diff --git a/.codespell/ignore-words.txt b/.codespell/ignore-words.txt index 87abbcf8e3..fc8feaca97 100644 --- a/.codespell/ignore-words.txt +++ b/.codespell/ignore-words.txt @@ -24,3 +24,5 @@ numer arithmetics ftbfs straightaway +ftbs +ftb diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 0ffa4fcfd9..7b63f7549d 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,4 +1,7 @@ -#all: Reformat remaining C code that doesn't have a space after a comma. +# top: Update Python formatting to black "2023 stable style". +8b2748269244304854b3462cb8902952b4dcb892 + +# all: Reformat remaining C code that doesn't have a space after a comma. 5b700b0af90591d6b1a2c087bb8de6b7f1bfdd2d # ports: Reformat more C and Python source code. diff --git a/.github/actions/mpy_cross/action.yml b/.github/actions/mpy_cross/action.yml index d9fe54fdc7..a2ac41b968 100644 --- a/.github/actions/mpy_cross/action.yml +++ b/.github/actions/mpy_cross/action.yml @@ -5,6 +5,9 @@ inputs: required: false default: true type: boolean + cp-version: + required: true + type: string runs: using: composite @@ -16,17 +19,19 @@ runs: uses: actions/download-artifact@v3 with: name: mpy-cross - path: mpy-cross + path: mpy-cross/build - name: Make mpy-cross executable if: inputs.download == 'true' && steps.download-mpy-cross.outcome == 'success' - run: sudo chmod +x mpy-cross/mpy-cross + run: sudo chmod +x mpy-cross/build/mpy-cross shell: bash - name: Build mpy-cross if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure' run: make -C mpy-cross -j2 shell: bash + env: + CP_VERSION: ${{ inputs.cp-version }} - name: Upload mpy-cross if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure' @@ -34,4 +39,4 @@ runs: uses: actions/upload-artifact@v3 with: name: mpy-cross - path: mpy-cross/mpy-cross + path: mpy-cross/build/mpy-cross diff --git a/.github/workflows/build-boards.yml b/.github/workflows/build-boards.yml index 85e789bf87..e3d3324cd3 100644 --- a/.github/workflows/build-boards.yml +++ b/.github/workflows/build-boards.yml @@ -49,6 +49,8 @@ jobs: - name: Set up mpy-cross if: steps.set-up-submodules.outputs.frozen == 'True' uses: ./.github/actions/mpy_cross + with: + cp-version: ${{ inputs.cp-version }} - name: Versions run: | diff --git a/.github/workflows/build-mpy-cross.yml b/.github/workflows/build-mpy-cross.yml index f60ef6cb3d..5ef13dae29 100644 --- a/.github/workflows/build-mpy-cross.yml +++ b/.github/workflows/build-mpy-cross.yml @@ -64,11 +64,11 @@ jobs: uses: actions/upload-artifact@v3 with: name: mpy-cross.${{ env.EX }} - path: mpy-cross/mpy-cross.${{ env.EX }} + path: mpy-cross/build-${{ matrix.mpy-cross }}/mpy-cross.${{ env.EX }} - name: Upload to S3 uses: ./.github/actions/upload_aws with: - source: mpy-cross/mpy-cross.${{ env.EX }} + source: mpy-cross/build-${{ matrix.mpy-cross }}/mpy-cross.${{ env.EX }} destination: mpy-cross/${{ env.OS }}/mpy-cross-${{ env.OS }}-${{ env.CP_VERSION }}.${{ env.EX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 730f03a15d..05d91910bc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,6 +51,7 @@ jobs: - name: Set up mpy-cross uses: ./.github/actions/mpy_cross with: + cp-version: ${{ steps.set-up-submodules.outputs.version }} download: false - name: Get last commit with checks id: get-last-commit-with-checks @@ -127,15 +128,15 @@ jobs: - uses: actions/upload-artifact@v3 with: name: mpy-cross-macos-11-x64 - path: mpy-cross/mpy-cross + path: mpy-cross/build/mpy-cross - name: Build mpy-cross (arm64) run: make -C mpy-cross -j2 -f Makefile.m1 V=2 - uses: actions/upload-artifact@v3 with: name: mpy-cross-macos-11-arm64 - path: mpy-cross/mpy-cross-arm64 + path: mpy-cross/build-arm64/mpy-cross-arm64 - name: Make universal binary - run: lipo -create -output mpy-cross-macos-universal mpy-cross/mpy-cross mpy-cross/mpy-cross-arm64 + run: lipo -create -output mpy-cross-macos-universal mpy-cross/build/mpy-cross mpy-cross/build-arm64/mpy-cross-arm64 - name: Upload artifact uses: actions/upload-artifact@v3 with: @@ -147,8 +148,8 @@ jobs: (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested')) run: | [ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross-macos-universal s3://adafruit-circuit-python/bin/mpy-cross/macos-11/mpy-cross-macos-11-${{ env.CP_VERSION }}-universal --no-progress --region us-east-1 - [ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross-arm64 s3://adafruit-circuit-python/bin/mpy-cross/macos-11/mpy-cross-macos-11-${{ env.CP_VERSION }}-arm64 --no-progress --region us-east-1 - [ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross s3://adafruit-circuit-python/bin/mpy-cross/macos-11/mpy-cross-macos-11-${{ env.CP_VERSION }}-x64 --no-progress --region us-east-1 + [ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/build-arm64/mpy-cross-arm64 s3://adafruit-circuit-python/bin/mpy-cross/macos-11/mpy-cross-macos-11-${{ env.CP_VERSION }}-arm64 --no-progress --region us-east-1 + [ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/build/mpy-cross s3://adafruit-circuit-python/bin/mpy-cross/macos-11/mpy-cross-macos-11-${{ env.CP_VERSION }}-x64 --no-progress --region us-east-1 env: AWS_PAGER: '' AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} diff --git a/.github/workflows/custom-board-build.yml b/.github/workflows/custom-board-build.yml index aa8044b0d2..8152a8f27b 100644 --- a/.github/workflows/custom-board-build.yml +++ b/.github/workflows/custom-board-build.yml @@ -65,6 +65,7 @@ jobs: if: steps.set-up-submodules.outputs.frozen == 'True' uses: ./.github/actions/mpy_cross with: + cp-version: ${{ steps.set-up-submodules.outputs.version }} download: false - name: Versions run: | diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 71f10339f3..3e9493fa0c 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -17,7 +17,7 @@ jobs: env: CP_VERSION: ${{ inputs.cp-version }} MICROPY_CPYTHON3: python3.8 - MICROPY_MICROPYTHON: ../ports/unix/micropython-coverage + MICROPY_MICROPYTHON: ../ports/unix/build-coverage/micropython TEST_all: TEST_mpy: --via-mpy -d basics float micropython TEST_native: --emit native @@ -41,6 +41,8 @@ jobs: uses: ./.github/actions/deps/external - name: Set up mpy-cross uses: ./.github/actions/mpy_cross + with: + cp-version: ${{ inputs.cp-version }} - name: Build unix port run: make -C ports/unix VARIANT=coverage -j2 - name: Run tests diff --git a/.gitmodules b/.gitmodules index 75f1d5f233..0f8ded62a3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -345,6 +345,9 @@ path = ports/raspberrypi/lib/Pico-PIO-USB url = https://github.com/sekigon-gonnoc/Pico-PIO-USB.git branch = main +[submodule "lib/micropython-lib"] + path = lib/micropython-lib + url = https://github.com/micropython/micropython-lib.git [submodule "lib/certificates"] path = lib/certificates url = https://github.com/adafruit/certificates diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 942a51afdc..dc8382f220 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,10 @@ repos: exclude: | (?x)^( locale/| - lib/ + lib/| + tests/unicode/data/utf-8_invalid.txt| + tests/extmod/data/qr.pgm| + tests/basics/bytearray_byte_operations.py ) - repo: local hooks: diff --git a/LICENSE b/LICENSE index 5b8797814f..aec1da6017 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -MIT License +The MIT License (MIT) -Copyright (c) 2013-2022 Damien P. George and others +Copyright (c) 2013-2023 Damien P. George Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,8 +9,8 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, diff --git a/conf.py b/conf.py index efcd455e01..11a589dd3b 100644 --- a/conf.py +++ b/conf.py @@ -202,7 +202,8 @@ exclude_patterns = ["**/build*", "ports/cxd56/spresense-exported-sdk", "ports/espressif/certificates", "ports/espressif/esp-idf", - "ports/espressif/esp32-camera", + "ports/espressif/esp-camera", + "ports/espressif/esp-protocols", "ports/espressif/.idf_tools", "ports/espressif/peripherals", "ports/litex/hw", diff --git a/devices/ble_hci/common-hal/_bleio/att.c b/devices/ble_hci/common-hal/_bleio/att.c index 9dfe9eb26c..08d37c0feb 100644 --- a/devices/ble_hci/common-hal/_bleio/att.c +++ b/devices/ble_hci/common-hal/_bleio/att.c @@ -44,7 +44,6 @@ #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" #include "supervisor/shared/tick.h" -#include "supervisor/shared/translate/translate.h" STATIC uint16_t max_mtu = BT_ATT_DEFAULT_LE_MTU; // 23 STATIC unsigned long timeout = 5000; diff --git a/docs/index.rst b/docs/index.rst index ba40d18ec4..6d73b1837a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -33,7 +33,6 @@ Full Table of Contents design_guide porting common_hal - reference/mpyfiles.rst reference/glossary.rst .. toctree:: diff --git a/docs/library/array.rst b/docs/library/array.rst index a78ba82404..a7a3b5952e 100644 --- a/docs/library/array.rst +++ b/docs/library/array.rst @@ -27,3 +27,55 @@ Classes Append new elements as contained in `iterable` to the end of array, growing it. + + .. method:: __getitem__(index) + + Indexed read of the array, called as ``a[index]`` (where ``a`` is an ``array``). + Returns a value if *index* is an ``int`` and an ``array`` if *index* is a slice. + Negative indices count from the end and ``IndexError`` is thrown if the index is + out of range. + + **Note:** ``__getitem__`` cannot be called directly (``a.__getitem__(index)`` fails) and + is not present in ``__dict__``, however ``a[index]`` does work. + + .. method:: __setitem__(index, value) + + Indexed write into the array, called as ``a[index] = value`` (where ``a`` is an ``array``). + ``value`` is a single value if *index* is an ``int`` and an ``array`` if *index* is a slice. + Negative indices count from the end and ``IndexError`` is thrown if the index is out of range. + + **Note:** ``__setitem__`` cannot be called directly (``a.__setitem__(index, value)`` fails) and + is not present in ``__dict__``, however ``a[index] = value`` does work. + + .. method:: __len__() + + Returns the number of items in the array, called as ``len(a)`` (where ``a`` is an ``array``). + + **Note:** ``__len__`` cannot be called directly (``a.__len__()`` fails) and the + method is not present in ``__dict__``, however ``len(a)`` does work. + + .. method:: __add__(other) + + Return a new ``array`` that is the concatenation of the array with *other*, called as + ``a + other`` (where ``a`` and *other* are both ``arrays``). + + **Note:** ``__add__`` cannot be called directly (``a.__add__(other)`` fails) and + is not present in ``__dict__``, however ``a + other`` does work. + + .. method:: __iadd__(other) + + Concatenates the array with *other* in-place, called as ``a += other`` (where ``a`` and *other* + are both ``arrays``). Equivalent to ``extend(other)``. + + **Note:** ``__iadd__`` cannot be called directly (``a.__iadd__(other)`` fails) and + is not present in ``__dict__``, however ``a += other`` does work. + + .. method:: __repr__() + + Returns the string representation of the array, called as ``str(a)`` or ``repr(a)``` + (where ``a`` is an ``array``). Returns the string ``"array(, [])"``, + where ```` is the type code letter for the array and ```` is a comma + separated list of the elements of the array. + + **Note:** ``__repr__`` cannot be called directly (``a.__repr__()`` fails) and + is not present in ``__dict__``, however ``str(a)`` and ``repr(a)`` both work. diff --git a/docs/reference/glossary.rst b/docs/reference/glossary.rst index fe65ddaa14..6ec613a315 100644 --- a/docs/reference/glossary.rst +++ b/docs/reference/glossary.rst @@ -52,7 +52,7 @@ Glossary cross-compiler Also known as ``mpy-cross``. This tool runs on your PC and converts a :term:`.py file` containing MicroPython code into a :term:`.mpy file` - containing MicroPython bytecode. This means it loads faster (the board + containing MicroPython :term:`bytecode`. This means it loads faster (the board doesn't have to compile the code), and uses less space on flash (the bytecode is more space efficient). @@ -112,6 +112,24 @@ Glossary require much less power. MicroPython is designed to be small and optimized enough to run on an average modern microcontroller. + micropython-lib + MicroPython is (usually) distributed as a single executable/binary + file with just few builtin modules. There is no extensive standard + library comparable with :term:`CPython`'s. Instead, there is a related, + but separate project `micropython-lib + `_ which provides + implementations for many modules from CPython's standard library. + + Some of the modules are are implemented in pure Python, and are able to + be used on all ports. However, the majority of these modules use + :term:`FFI` to access operating system functionality, and as such can + only be used on the :term:`MicroPython Unix port` (with limited support + for Windows). + + Unlike the :term:`CPython` stdlib, micropython-lib modules are + intended to be installed individually - either using manual copying or + using :term:`mip`. + MicroPython port MicroPython supports different :term:`boards `, RTOSes, and OSes, and can be relatively easily adapted to new systems. MicroPython @@ -133,16 +151,26 @@ Glossary machine-independent features. It can also function in a similar way to :term:`CPython`'s ``python`` executable. + mip + A package installer for MicroPython (mip - "mip installs packages"). It + installs MicroPython packages either from :term:`micropython-lib`, + GitHub, or arbitrary URLs. mip can be used on-device on + network-capable boards, and internally by tools such + as :term:`mpremote`. + + mpremote + A tool for interacting with a MicroPython device. + .mpy file The output of the :term:`cross-compiler`. A compiled form of a - :term:`.py file` that contains MicroPython bytecode instead of Python - source code. + :term:`.py file` that contains MicroPython :term:`bytecode` instead of + Python source code. native Usually refers to "native code", i.e. machine code for the target microcontroller (such as ARM Thumb, Xtensa, x86/x64). The ``@native`` decorator can be applied to a MicroPython function to generate native - code instead of bytecode for that function, which will likely be + code instead of :term:`bytecode` for that function, which will likely be faster but use more RAM. port @@ -173,3 +201,12 @@ Glossary peripheral that sends data over a pair of pins (TX & RX). Many boards include a way to make at least one of the UARTs available to a host PC as a serial port over USB. + + upip + A now-obsolete package manager for MicroPython, inspired + by :term:`CPython`'s pip, but much smaller and with reduced + functionality. See its replacement, :term:`mip`. + + webrepl + A way of connecting to the REPL (and transferring files) on a device + over the internet from a browser. See https://micropython.org/webrepl diff --git a/docs/reference/mpyfiles.rst b/docs/reference/mpyfiles.rst deleted file mode 100644 index b65f62f9ca..0000000000 --- a/docs/reference/mpyfiles.rst +++ /dev/null @@ -1,199 +0,0 @@ -.. _mpy_files: - -MicroPython .mpy files -====================== - -MicroPython defines the concept of an .mpy file which is a binary container -file format that holds precompiled code, and which can be imported like a -normal .py module. The file ``foo.mpy`` can be imported via ``import foo``, -as long as ``foo.mpy`` can be found in the usual way by the import machinery. -Usually, each directory listed in ``sys.path`` is searched in order. When -searching a particular directory ``foo.py`` is looked for first and if that -is not found then ``foo.mpy`` is looked for, then the search continues in the -next directory if neither is found. As such, ``foo.py`` will take precedence -over ``foo.mpy``. - -These .mpy files can contain bytecode which is usually generated from Python -source files (.py files) via the ``mpy-cross`` program. For some architectures -an .mpy file can also contain native machine code, which can be generated in -a variety of ways, most notably from C source code. - -Versioning and compatibility of .mpy files ------------------------------------------- - -A given .mpy file may or may not be compatible with a given MicroPython system. -Compatibility is based on the following: - -* Version of the .mpy file: the version of the file must match the version - supported by the system loading it. - -* Sub-version of the .mpy file: if the .mpy file contains native machine code - then the sub-version of the file must match the version support by the - system loading it. Otherwise, if there is no native machine code in the .mpy - file, then the sub-version is ignored when loading. - -* Small integer bits: the .mpy file will require a minimum number of bits in - a small integer and the system loading it must support at least this many - bits. - -* Native architecture: if the .mpy file contains native machine code then - it will specify the architecture of that machine code and the system - loading it must support execution of that architecture's code. - -If a MicroPython system supports importing .mpy files then the -``sys.implementation._mpy`` field will exist and return an integer which -encodes the version (lower 8 bits), features and native architecture. - -Trying to import an .mpy file that fails one of the first four tests will -raise ``ValueError('incompatible .mpy file')``. Trying to import an .mpy -file that fails the native architecture test (if it contains native machine -code) will raise ``ValueError('incompatible .mpy arch')``. - -If importing an .mpy file fails then try the following: - -* Determine the .mpy version and flags supported by your MicroPython system - by executing:: - - import sys - sys_mpy = sys.implementation._mpy - arch = [None, 'x86', 'x64', - 'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp', - 'xtensa', 'xtensawin'][sys_mpy >> 10] - print('mpy version:', sys_mpy & 0xff) - print('mpy flags:', end='') - if arch: - print(' -march=' + arch, end='') - print() - -* Check the validity of the .mpy file by inspecting the first two bytes of - the file. The first byte should be an uppercase 'C' and the second byte - will be the version number, which should match the system version from above. - If it doesn't match then rebuild the .mpy file. - -* Check if the system .mpy version matches the version emitted by ``mpy-cross`` - that was used to build the .mpy file, found by ``mpy-cross --version``. - If it doesn't match then recompile ``mpy-cross`` from the Git repository - checked out at the tag (or hash) reported by ``mpy-cross --version``. - -* Make sure you are using the correct ``mpy-cross`` flags, found by the code - above, or by inspecting the ``MPY_CROSS_FLAGS`` Makefile variable for the - port that you are using. - -The following table shows the correspondence between MicroPython release -and .mpy version. - -=================== ============ -MicroPython release .mpy version -=================== ============ -v1.19 and up 6 -v1.12 - v1.18 5 -v1.11 4 -v1.9.3 - v1.10 3 -v1.9 - v1.9.2 2 -v1.5.1 - v1.8.7 0 -=================== ============ - -For completeness, the next table shows the Git commit of the main -MicroPython repository at which the .mpy version was changed. - -=================== ======================================== -.mpy version change Git commit -=================== ======================================== -5 to 6 f2040bfc7ee033e48acef9f289790f3b4e6b74e5 -4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517 -3 to 4 9a5f92ea72754c01cc03e5efcdfe94021120531e -2 to 3 ff93fd4f50321c6190e1659b19e64fef3045a484 -1 to 2 dd11af209d226b7d18d5148b239662e30ed60bad -0 to 1 6a11048af1d01c78bdacddadd1b72dc7ba7c6478 -initial version 0 d8c834c95d506db979ec871417de90b7951edc30 -=================== ======================================== - -Binary encoding of .mpy files ------------------------------ - -MicroPython .mpy files are a binary container format with code objects (bytecode -and native machine code) stored internally in a nested hierarchy. The code for -the outer module is stored first, and then its children follow. Each child may -have further children, for example in the case of a class having methods, or a -function defining a lambda or comprehension. To keep files small while still -providing a large range of possible values it uses the concept of a -variably-encoded-unsigned-integer (vuint) in many places. Similar to utf-8 -encoding, this encoding stores 7 bits per byte with the 8th bit (MSB) set -if one or more bytes follow. The bits of the unsigned integer are stored -in the vuint in LSB form. - -The top-level of an .mpy file consists of three parts: - -* The header. - -* The global qstr and constant tables. - -* The raw-code for the outer scope of the module. - This outer scope is executed when the .mpy file is imported. - -You can inspect the contents of a .mpy file by using ``mpy-tool.py``, for -example (run from the root of the main MicroPython repository):: - - $ ./tools/mpy-tool.py -xd myfile.mpy - -The header -~~~~~~~~~~ - -The .mpy header is: - -====== ================================ -size field -====== ================================ -byte value 0x43 (ASCII 'C') -byte .mpy version number -byte feature flags -byte number of bits in a small int -====== ================================ - -The global qstr and constant tables -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -An .mpy file contains a single qstr table, and a single constant object table. -These are global to the .mpy file, they are referenced by all nested raw-code -objects. The qstr table maps internal qstr number (internal to the .mpy file) -to the resolved qstr number of the runtime that the .mpy file is imported into. -This links the .mpy file with the rest of the system that it executes within. -The constant object table is populated with references to all constant objects -that the .mpy file needs. - -====== ================================ -size field -====== ================================ -vuint number of qstrs -vuint number of constant objects -... qstr data -... encoded constant objects -====== ================================ - -Raw code elements -~~~~~~~~~~~~~~~~~ - -A raw-code element contains code, either bytecode or native machine code. Its -contents are: - -====== ================================ -size field -====== ================================ -vuint type, size and whether there are sub-raw-code elements -... code (bytecode or machine code) -vuint number of sub-raw-code elements (only if non-zero) -... sub-raw-code elements -====== ================================ - -The first vuint in a raw-code element encodes the type of code stored in this -element (the two least-significant bits), whether this raw-code has any -children (the third least-significant bit), and the length of the code that -follows (the amount of RAM to allocate for it). - -Following the vuint comes the code itself. Unless the code type is viper code -with relocations, this code is constant data and does not need to be modified. - -If this raw-code has any children (as indicated by a bit in the first vuint), -following the code comes a vuint counting the number of sub-raw-code elements. - -Finally any sub-raw-code elements are stored, recursively. diff --git a/docs/static/custom.css b/docs/static/custom.css new file mode 100644 index 0000000000..b0a7f746fc --- /dev/null +++ b/docs/static/custom.css @@ -0,0 +1,5 @@ +/* Workaround to force Sphinx to render tables to 100% and wordwrap */ +/* See https://stackoverflow.com/questions/69359978/grid-table-does-not-word-wrap for more details */ +.wy-table-responsive table td, .wy-table-responsive table th { + white-space: inherit; +} diff --git a/examples/natmod/ure/ure.c b/examples/natmod/ure/ure.c index 175b93e395..d4bd680abd 100644 --- a/examples/natmod/ure/ure.c +++ b/examples/natmod/ure/ure.c @@ -32,8 +32,8 @@ void *memmove(void *dest, const void *src, size_t n) { return mp_fun_table.memmove_(dest, src, n); } -mp_obj_type_t match_type; -mp_obj_type_t re_type; +mp_obj_full_type_t match_type; +mp_obj_full_type_t re_type; #include "extmod/modure.c" @@ -54,21 +54,21 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a match_type.base.type = (void*)&mp_fun_table.type_type; match_type.name = MP_QSTR_match; - match_type.print = match_print; + MP_OBJ_TYPE_SET_SLOT(&match_type, print, match_print, 0); match_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_group), MP_OBJ_FROM_PTR(&match_group_obj) }; match_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_groups), MP_OBJ_FROM_PTR(&match_groups_obj) }; match_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_span), MP_OBJ_FROM_PTR(&match_span_obj) }; match_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_start), MP_OBJ_FROM_PTR(&match_start_obj) }; match_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_OBJ_FROM_PTR(&match_end_obj) }; - match_type.locals_dict = (void*)&match_locals_dict; + MP_OBJ_TYPE_SET_SLOT(&match_type, locals_dict, (void*)&match_locals_dict, 1); re_type.base.type = (void*)&mp_fun_table.type_type; re_type.name = MP_QSTR_ure; - re_type.print = re_print; + MP_OBJ_TYPE_SET_SLOT(&re_type, print, re_print, 0); re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) }; re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) }; re_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_split), MP_OBJ_FROM_PTR(&re_split_obj) }; - re_type.locals_dict = (void*)&re_locals_dict; + MP_OBJ_TYPE_SET_SLOT(&re_type, locals_dict, (void*)&re_locals_dict, 1); mp_store_global(MP_QSTR_compile, MP_OBJ_FROM_PTR(&mod_re_compile_obj)); mp_store_global(MP_QSTR_match, MP_OBJ_FROM_PTR(&re_match_obj)); diff --git a/examples/natmod/uzlib/uzlib.c b/examples/natmod/uzlib/uzlib.c index 6df9944d6a..9cf58b10e7 100644 --- a/examples/natmod/uzlib/uzlib.c +++ b/examples/natmod/uzlib/uzlib.c @@ -9,7 +9,6 @@ void *memset(void *s, int c, size_t n) { #endif mp_obj_full_type_t decompio_type; -mp_stream_p_t decompio_stream_p; #include "extmod/moduzlib.c" @@ -19,18 +18,14 @@ STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table); mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { MP_DYNRUNTIME_INIT_ENTRY - decompio_stream_p.name = MP_QSTR_protocol_stream; - decompio_stream_p.read = decompio_read; - decompio_type.base.type = mp_fun_table.type_type; - decompio_type.flags = MP_TYPE_FLAG_EXTENDED; decompio_type.name = MP_QSTR_DecompIO; - decompio_type.make_new = decompio_make_new; - decompio_type.ext[0].protocol = &decompio_stream_p; + MP_OBJ_TYPE_SET_SLOT(&decompio_type, make_new, &decompio_make_new, 0); + MP_OBJ_TYPE_SET_SLOT(&decompio_type, protocol, &decompio_stream_p, 1); decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) }; decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) }; decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) }; - decompio_type.locals_dict = (void*)&decompio_locals_dict; + MP_OBJ_TYPE_SET_SLOT(&decompio_type, locals_dict, (void*)&decompio_locals_dict, 2); mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uzlib)); mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_uzlib_decompress_obj)); diff --git a/examples/usercmodule/cexample/examplemodule.c b/examples/usercmodule/cexample/examplemodule.c index 93a58be2ed..ccce03bcbd 100644 --- a/examples/usercmodule/cexample/examplemodule.c +++ b/examples/usercmodule/cexample/examplemodule.c @@ -1,6 +1,9 @@ // Include MicroPython API. #include "py/runtime.h" +// Used to get the time in the Timer class example. +#include "py/mphal.h" + // This is the function which will be called from Python as cexample.add_ints(a, b). STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) { // Extract the ints from the micropython input objects. @@ -13,6 +16,58 @@ STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) { // Define a Python reference to the function above. STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints); +// This structure represents Timer instance objects. +typedef struct _example_Timer_obj_t { + // All objects start with the base. + mp_obj_base_t base; + // Everything below can be thought of as instance attributes, but they + // cannot be accessed by MicroPython code directly. In this example we + // store the time at which the object was created. + mp_uint_t start_time; +} example_Timer_obj_t; + +// This is the Timer.time() method. After creating a Timer object, this +// can be called to get the time elapsed since creating the Timer. +STATIC mp_obj_t example_Timer_time(mp_obj_t self_in) { + // The first argument is self. It is cast to the *example_Timer_obj_t + // type so we can read its attributes. + example_Timer_obj_t *self = MP_OBJ_TO_PTR(self_in); + + // Get the elapsed time and return it as a MicroPython integer. + mp_uint_t elapsed = mp_hal_ticks_ms() - self->start_time; + return mp_obj_new_int_from_uint(elapsed); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(example_Timer_time_obj, example_Timer_time); + +// This represents Timer.__new__ and Timer.__init__, which is called when +// the user instantiates a Timer object. +STATIC mp_obj_t example_Timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // Allocates the new object and sets the type. + example_Timer_obj_t *self = mp_obj_malloc(example_Timer_obj_t, type); + + // Initializes the time for this Timer instance. + self->start_time = mp_hal_ticks_ms(); + + // The make_new function always returns self. + return MP_OBJ_FROM_PTR(self); +} + +// This collects all methods and other static class attributes of the Timer. +// The table structure is similar to the module table, as detailed below. +STATIC const mp_rom_map_elem_t example_Timer_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&example_Timer_time_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(example_Timer_locals_dict, example_Timer_locals_dict_table); + +// This defines the type(Timer) object. +MP_DEFINE_CONST_OBJ_TYPE( + example_type_Timer, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + make_new, example_Timer_make_new, + locals_dict, &example_Timer_locals_dict + ); + // Define all properties of the module. // Table entries are key/value pairs of the attribute name (a string) // and the MicroPython object reference. @@ -21,6 +76,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints); STATIC const mp_rom_map_elem_t example_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cexample) }, { MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) }, + { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&example_type_Timer) }, }; STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table); diff --git a/extmod/extmod.mk b/extmod/extmod.mk index 83b1854c1e..a1de6c6fe4 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -1,4 +1,41 @@ -# This makefile fragment provides rules to build 3rd-party components for extmod modules +# This makefile fragment adds the source code files for the core extmod modules +# and provides rules to build 3rd-party components for extmod modules. + +SRC_EXTMOD_C += \ + extmod/moduasyncio.c \ + extmod/modubinascii.c \ + extmod/moductypes.c \ + extmod/moduhashlib.c \ + extmod/moduheapq.c \ + extmod/modujson.c \ + extmod/moduos.c \ + extmod/moduplatform.c\ + extmod/modurandom.c \ + extmod/modure.c \ + extmod/moduselect.c \ + extmod/moduzlib.c \ + extmod/utime_mphal.c \ + extmod/vfs.c \ + extmod/vfs_blockdev.c \ + extmod/vfs_fat.c \ + extmod/vfs_fat_diskio.c \ + extmod/vfs_fat_file.c \ + extmod/vfs_lfs.c \ + extmod/vfs_posix.c \ + extmod/vfs_posix_file.c \ + extmod/vfs_reader.c \ + extmod/virtpin.c \ + shared/libc/abort_.c \ + shared/libc/printf.c \ + +SRC_THIRDPARTY_C += \ + +PY_O += $(addprefix $(BUILD)/, $(SRC_EXTMOD_C:.c=.o)) +PY_O += $(addprefix $(BUILD)/, $(SRC_THIRDPARTY_C:.c=.o)) +SRC_QSTR += $(SRC_EXTMOD_C) + +CFLAGS += $(CFLAGS_EXTMOD) $(CFLAGS_THIRDPARTY) +LDFLAGS += $(LDFLAGS_EXTMOD) $(LDFLAGS_THIRDPARTY) ################################################################################ # VFS FAT FS @@ -6,11 +43,11 @@ OOFATFS_DIR = lib/oofatfs # this sets the config file for FatFs -CFLAGS_MOD += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\" +CFLAGS_THIRDPARTY += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\" ifeq ($(MICROPY_VFS_FAT),1) -CFLAGS_MOD += -DMICROPY_VFS_FAT=1 -SRC_MOD += $(addprefix $(OOFATFS_DIR)/,\ +CFLAGS_EXTMOD += -DMICROPY_VFS_FAT=1 +SRC_THIRDPARTY_C += $(addprefix $(OOFATFS_DIR)/,\ ff.c \ ffunicode.c \ ) @@ -22,18 +59,18 @@ endif LITTLEFS_DIR = lib/littlefs ifeq ($(MICROPY_VFS_LFS1),1) -CFLAGS_MOD += -DMICROPY_VFS_LFS1=1 -CFLAGS_MOD += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT -SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\ +CFLAGS_EXTMOD += -DMICROPY_VFS_LFS1=1 +CFLAGS_THIRDPARTY += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT +SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\ lfs1.c \ lfs1_util.c \ ) endif ifeq ($(MICROPY_VFS_LFS2),1) -CFLAGS_MOD += -DMICROPY_VFS_LFS2=1 -CFLAGS_MOD += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT -SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\ +CFLAGS_EXTMOD += -DMICROPY_VFS_LFS2=1 +CFLAGS_THIRDPARTY += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT +SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\ lfs2.c \ lfs2_util.c \ ) @@ -45,12 +82,14 @@ endif # ussl ifeq ($(MICROPY_PY_USSL),1) -CFLAGS_MOD += -DMICROPY_PY_USSL=1 +CFLAGS_EXTMOD += -DMICROPY_PY_USSL=1 ifeq ($(MICROPY_SSL_AXTLS),1) CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include AXTLS_DIR = lib/axtls +GIT_SUBMODULES += $(AXTLS_DIR) +CFLAGS_EXTMOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include $(BUILD)/$(AXTLS_DIR)/%.o: CFLAGS += -Wno-all -Wno-unused-parameter -Wno-uninitialized -Wno-sign-compare -Wno-old-style-definition -Dmp_stream_errno=errno $(AXTLS_DEFS_EXTRA) -SRC_MOD += $(addprefix $(AXTLS_DIR)/,\ +SRC_THIRDPARTY_C += $(addprefix $(AXTLS_DIR)/,\ ssl/asn1.c \ ssl/loader.c \ ssl/tls1.c \ @@ -67,8 +106,12 @@ SRC_MOD += $(addprefix $(AXTLS_DIR)/,\ ) else ifeq ($(MICROPY_SSL_MBEDTLS),1) MBEDTLS_DIR = lib/mbedtls -CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include -SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\ +MBEDTLS_CONFIG_FILE ?= \"mbedtls/mbedtls_config.h\" +GIT_SUBMODULES += $(MBEDTLS_DIR) +CFLAGS_EXTMOD += -DMBEDTLS_CONFIG_FILE=$(MBEDTLS_CONFIG_FILE) +CFLAGS_EXTMOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include +SRC_THIRDPARTY_C += lib/mbedtls_errors/mp_mbedtls_errors.c +SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\ aes.c \ aesni.c \ arc4.c \ @@ -96,7 +139,6 @@ SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\ ecp_curves.c \ entropy.c \ entropy_poll.c \ - error.c \ gcm.c \ havege.c \ hmac_drbg.c \ @@ -148,13 +190,14 @@ endif # lwip ifeq ($(MICROPY_PY_LWIP),1) +GIT_SUBMODULES += lib/lwip # A port should add an include path where lwipopts.h can be found (eg extmod/lwip-include) LWIP_DIR = lib/lwip/src INC += -I$(TOP)/$(LWIP_DIR)/include -CFLAGS_MOD += -DMICROPY_PY_LWIP=1 -$(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS_MOD += -Wno-address -SRC_MOD += extmod/modlwip.c shared/netutils/netutils.c -SRC_MOD += $(addprefix $(LWIP_DIR)/,\ +CFLAGS_EXTMOD += -DMICROPY_PY_LWIP=1 +$(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS += -Wno-address +SRC_THIRDPARTY_C += shared/netutils/netutils.c +SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\ apps/mdns/mdns.c \ core/def.c \ core/dns.c \ @@ -193,8 +236,8 @@ SRC_MOD += $(addprefix $(LWIP_DIR)/,\ netif/ethernet.c \ ) ifeq ($(MICROPY_PY_LWIP_SLIP),1) -CFLAGS_MOD += -DMICROPY_PY_LWIP_SLIP=1 -SRC_MOD += $(LWIP_DIR)/netif/slipif.c +CFLAGS_EXTMOD += -DMICROPY_PY_LWIP_SLIP=1 +SRC_THIRDPARTY_C += $(LWIP_DIR)/netif/slipif.c endif endif @@ -205,8 +248,7 @@ ifeq ($(MICROPY_PY_BTREE),1) BTREE_DIR = lib/berkeley-db-1.xx BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA) INC += -I$(TOP)/$(BTREE_DIR)/PORT/include -SRC_MOD += extmod/modbtree.c -SRC_MOD += $(addprefix $(BTREE_DIR)/,\ +SRC_THIRDPARTY_C += $(addprefix $(BTREE_DIR)/,\ btree/bt_close.c \ btree/bt_conv.c \ btree/bt_debug.c \ @@ -222,9 +264,79 @@ SRC_MOD += $(addprefix $(BTREE_DIR)/,\ btree/bt_utils.c \ mpool/mpool.c \ ) -CFLAGS_MOD += -DMICROPY_PY_BTREE=1 +CFLAGS_EXTMOD += -DMICROPY_PY_BTREE=1 # we need to suppress certain warnings to get berkeley-db to compile cleanly # and we have separate BTREE_DEFS so the definitions don't interfere with other source code $(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS) $(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS) endif + +################################################################################ +# networking + +ifeq ($(MICROPY_PY_NETWORK_CYW43),1) +CYW43_DIR = lib/cyw43-driver +GIT_SUBMODULES += $(CYW43_DIR) +CFLAGS_EXTMOD += -DMICROPY_PY_NETWORK_CYW43=1 +SRC_THIRDPARTY_C += $(addprefix $(CYW43_DIR)/src/,\ + cyw43_ctrl.c \ + cyw43_lwip.c \ + cyw43_ll.c \ + cyw43_sdio.c \ + cyw43_stats.c \ + ) +ifeq ($(MICROPY_PY_BLUETOOTH),1) +DRIVERS_SRC_C += drivers/cyw43/cywbt.c +endif + +$(BUILD)/$(CYW43_DIR)/src/cyw43_%.o: CFLAGS += -std=c11 +endif # MICROPY_PY_NETWORK_CYW43 + +ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),) +ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),0) +WIZNET5K_DIR=lib/wiznet5k +GIT_SUBMODULES += lib/wiznet5k +INC += -I$(TOP)/$(WIZNET5K_DIR) -I$(TOP)/$(WIZNET5K_DIR)/Ethernet +CFLAGS += -DMICROPY_PY_NETWORK_WIZNET5K=$(MICROPY_PY_NETWORK_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_NETWORK_WIZNET5K) +CFLAGS_THIRDPARTY += -DWIZCHIP_PREFIXED_EXPORTS=1 +ifeq ($(MICROPY_PY_LWIP),1) +# When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket +CFLAGS_THIRDPARTY += -DWIZCHIP_USE_MAX_BUFFER +endif +SRC_THIRDPARTY_C += $(addprefix $(WIZNET5K_DIR)/,\ + Ethernet/W$(MICROPY_PY_NETWORK_WIZNET5K)/w$(MICROPY_PY_NETWORK_WIZNET5K).c \ + Ethernet/wizchip_conf.c \ + Ethernet/socket.c \ + Internet/DNS/dns.c \ + Internet/DHCP/dhcp.c \ + ) +endif +endif + +################################################################################ +# bluetooth + +ifeq ($(MICROPY_PY_BLUETOOTH),1) +CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH=1 + +ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) +ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) +$(error Cannot enable both NimBLE and BTstack at the same time) +endif +endif + +ifneq ($(MICROPY_BLUETOOTH_NIMBLE),1) +ifneq ($(MICROPY_BLUETOOTH_BTSTACK),1) +$(error Must enable one of MICROPY_BLUETOOTH_NIMBLE or MICROPY_BLUETOOTH_BTSTACK) +endif +endif + +ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) +include $(TOP)/extmod/nimble/nimble.mk +endif + +ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) +include $(TOP)/extmod/btstack/btstack.mk +endif + +endif diff --git a/extmod/moduasyncio.c b/extmod/moduasyncio.c index 4bd612d37b..80e673c94a 100644 --- a/extmod/moduasyncio.c +++ b/extmod/moduasyncio.c @@ -35,8 +35,6 @@ #include "shared-bindings/supervisor/__init__.h" #endif -#include "supervisor/shared/translate/translate.h" - // Used when task cannot be guaranteed to be non-NULL. #define TASK_PAIRHEAP(task) ((task) ? &(task)->pairheap : NULL) @@ -65,32 +63,19 @@ STATIC const mp_obj_type_t task_queue_type; STATIC const mp_obj_type_t task_type; STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); -STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); /******************************************************************************/ // Ticks for task ordering in pairing heap -// CIRCUITPY-style ticks -#define _TICKS_PERIOD (1lu << 29) -#define _TICKS_MAX (_TICKS_PERIOD - 1) -#define _TICKS_HALFPERIOD (_TICKS_PERIOD >> 1) -#if !CIRCUITPY || (defined(__unix__) || defined(__APPLE__)) STATIC mp_obj_t ticks(void) { - return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & _TICKS_MAX); + return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1)); } -#else -// We don't share the implementation above because our supervisor_ticks_ms -// starts the epoch about 65 seconds before the first overflow (see -// shared-bindings/supervisor/__init__.c). We assume/require that -// supervisor.ticks_ms is picked as the ticks implementation under -// CircuitPython for the Python-coded bits of asyncio. -#define ticks() supervisor_ticks_ms() -#endif STATIC mp_int_t ticks_diff(mp_obj_t t1_in, mp_obj_t t0_in) { mp_uint_t t0 = MP_OBJ_SMALL_INT_VALUE(t0_in); mp_uint_t t1 = MP_OBJ_SMALL_INT_VALUE(t1_in); - mp_int_t diff = ((t1 - t0 + _TICKS_HALFPERIOD) & _TICKS_MAX) - _TICKS_HALFPERIOD; + mp_int_t diff = ((t1 - t0 + MICROPY_PY_UTIME_TICKS_PERIOD / 2) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1)) + - MICROPY_PY_UTIME_TICKS_PERIOD / 2; return diff; } @@ -161,19 +146,20 @@ STATIC const mp_rom_map_elem_t task_queue_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&task_queue_pop_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&task_queue_remove_obj) }, - // CIRCUITPYTHON: remove these after the bundle need not support 8.x + // CIRCUITPYTHON: Remove these in CircuitPython 10.0.0 { MP_ROM_QSTR(MP_QSTR_push_head), MP_ROM_PTR(&task_queue_push_obj) }, { MP_ROM_QSTR(MP_QSTR_push_sorted), MP_ROM_PTR(&task_queue_push_obj) }, { MP_ROM_QSTR(MP_QSTR_pop_head), MP_ROM_PTR(&task_queue_pop_obj) }, }; STATIC MP_DEFINE_CONST_DICT(task_queue_locals_dict, task_queue_locals_dict_table); -STATIC const mp_obj_type_t task_queue_type = { - { &mp_type_type }, - .name = MP_QSTR_TaskQueue, - .make_new = task_queue_make_new, - .locals_dict = (mp_obj_dict_t *)&task_queue_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + task_queue_type, + MP_QSTR_TaskQueue, + MP_TYPE_FLAG_NONE, + make_new, task_queue_make_new, + locals_dict, &task_queue_locals_dict + ); /******************************************************************************/ // Task class @@ -248,6 +234,8 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_cancel_obj, task_cancel); // CIRCUITPY provides __await__(). +STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); + STATIC mp_obj_t task_await(mp_obj_t self_in) { return task_getiter(self_in, NULL); } @@ -271,7 +259,6 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { dest[1] = self_in; } else if (attr == MP_QSTR_ph_key) { dest[0] = self->ph_key; - // CIRCUITPY provides __await__(). } else if (attr == MP_QSTR___await__) { dest[0] = MP_OBJ_FROM_PTR(&task_await_obj); dest[1] = self_in; @@ -307,7 +294,6 @@ STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { STATIC mp_obj_t task_iternext(mp_obj_t self_in) { mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in); if (TASK_IS_DONE(self)) { - // CIRCUITPY if (self->data == mp_const_none) { // Task finished but has already been sent to the loop's exception handler. mp_raise_StopIteration(MP_OBJ_NULL); @@ -326,27 +312,25 @@ STATIC mp_obj_t task_iternext(mp_obj_t self_in) { return mp_const_none; } -STATIC const mp_obj_type_t task_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Task, - .make_new = task_make_new, - .attr = task_attr, - MP_TYPE_EXTENDED_FIELDS( - .getiter = task_getiter, - .iternext = task_iternext, - ), +STATIC const mp_getiter_iternext_custom_t task_getiter_iternext = { + .getiter = task_getiter, + .iternext = task_iternext, }; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + task_type, + MP_QSTR_Task, + MP_TYPE_FLAG_ITER_IS_CUSTOM, + make_new, task_make_new, + attr, task_attr, + iter, &task_getiter_iternext + ); + /******************************************************************************/ // C-level uasyncio module STATIC const mp_rom_map_elem_t mp_module_uasyncio_globals_table[] = { - #if CIRCUITPY - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__asyncio) }, - #else { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__uasyncio) }, - #endif { MP_ROM_QSTR(MP_QSTR_TaskQueue), MP_ROM_PTR(&task_queue_type) }, { MP_ROM_QSTR(MP_QSTR_Task), MP_ROM_PTR(&task_type) }, }; diff --git a/extmod/modubinascii.c b/extmod/modubinascii.c index 6346b23e62..59af21ace1 100644 --- a/extmod/modubinascii.c +++ b/extmod/modubinascii.c @@ -30,8 +30,9 @@ #include "py/runtime.h" #include "py/binary.h" +#include "py/objstr.h" -#include "supervisor/shared/translate/translate.h" +#include "lib/uzlib/tinf.h" #if MICROPY_PY_UBINASCII @@ -42,76 +43,19 @@ static void check_not_unicode(const mp_obj_t arg) { } #endif } -STATIC mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) { - // First argument is the data to convert. - // Second argument is an optional separator to be used between values. - const char *sep = NULL; - mp_buffer_info_t bufinfo; - check_not_unicode(args[0]); - mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); - // Code below assumes non-zero buffer length when computing size with - // separator, so handle the zero-length case here. - if (bufinfo.len == 0) { - return mp_const_empty_bytes; - } - - vstr_t vstr; - size_t out_len = bufinfo.len * 2; - if (n_args > 1) { - // 1-char separator between hex numbers - out_len += bufinfo.len - 1; - sep = mp_obj_str_get_str(args[1]); - } - vstr_init_len(&vstr, out_len); - byte *in = bufinfo.buf, *out = (byte *)vstr.buf; - for (mp_uint_t i = bufinfo.len; i--;) { - byte d = (*in >> 4); - if (d > 9) { - d += 'a' - '9' - 1; - } - *out++ = d + '0'; - d = (*in++ & 0xf); - if (d > 9) { - d += 'a' - '9' - 1; - } - *out++ = d + '0'; - if (sep != NULL && i != 0) { - *out++ = *sep; - } - } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +#if MICROPY_PY_BUILTINS_BYTES_HEX +STATIC mp_obj_t bytes_hex_as_bytes(size_t n_args, const mp_obj_t *args) { + return mp_obj_bytes_hex(n_args, args, &mp_type_bytes); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj, 1, 2, mod_binascii_hexlify); -STATIC mp_obj_t mod_binascii_unhexlify(mp_obj_t data) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_hex_as_bytes_obj, 1, 2, bytes_hex_as_bytes); - if ((bufinfo.len & 1) != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("odd-length string")); - } - vstr_t vstr; - vstr_init_len(&vstr, bufinfo.len / 2); - byte *in = bufinfo.buf, *out = (byte *)vstr.buf; - byte hex_byte = 0; - for (mp_uint_t i = bufinfo.len; i--;) { - byte hex_ch = *in++; - if (unichar_isxdigit(hex_ch)) { - hex_byte += unichar_xdigit_value(hex_ch); - } else { - mp_raise_ValueError(MP_ERROR_TEXT("non-hex digit found")); - } - if (i & 1) { - hex_byte <<= 4; - } else { - *out++ = hex_byte; - hex_byte = 0; - } - } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +STATIC mp_obj_t bytes_fromhex_bytes(mp_obj_t data) { + return mp_obj_bytes_fromhex(MP_OBJ_FROM_PTR(&mp_type_bytes), data); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj, mod_binascii_unhexlify); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bytes_fromhex_obj, bytes_fromhex_bytes); +#endif // If ch is a character in the base64 alphabet, and is not a pad character, then // the corresponding integer between 0 and 63, inclusively, is returned. @@ -171,7 +115,7 @@ STATIC mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) { mp_raise_ValueError(MP_ERROR_TEXT("incorrect padding")); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64); @@ -184,6 +128,7 @@ STATIC mp_obj_t mod_binascii_b2a_base64(size_t n_args, const mp_obj_t *pos_args, mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); uint8_t newline = args[ARG_newline].u_bool; + // CIRCUITPY check_not_unicode(pos_args[0]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(pos_args[0], &bufinfo, MP_BUFFER_READ); @@ -234,7 +179,7 @@ STATIC mp_obj_t mod_binascii_b2a_base64(size_t n_args, const mp_obj_t *pos_args, if (newline) { *out = '\n'; } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_binascii_b2a_base64_obj, 1, mod_binascii_b2a_base64); @@ -274,53 +219,30 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_binascii_b2a_base64_obj, 1, mod_binascii_b * any source distribution. */ -/* - * CRC32 algorithm taken from the zlib source, which is - * Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler - */ - - -static const unsigned int tinf_crc32tab[16] = { - 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, - 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, - 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, - 0xbdbdf21c -}; - -/* crc is previous value for incremental computation, 0xffffffff initially */ -static uint32_t from_uzlib_crc32(const void *data, unsigned int length, uint32_t crc) { - const unsigned char *buf = (const unsigned char *)data; - unsigned int i; - - for (i = 0; i < length; ++i) - { - crc ^= buf[i]; - crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4); - crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4); - } - - // return value suitable for passing in next time, for final value invert it - return crc /* ^ 0xffffffff*/; -} - +#if MICROPY_PY_UBINASCII_CRC32 STATIC mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; + // CIRCUITPY check_not_unicode(args[0]); mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); uint32_t crc = (n_args > 1) ? mp_obj_get_int_truncated(args[1]) : 0; - crc = from_uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff); + crc = uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff); return mp_obj_new_int_from_uint(crc ^ 0xffffffff); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32); - +#endif STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_binascii) }, - { MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&mod_binascii_hexlify_obj) }, - { MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&mod_binascii_unhexlify_obj) }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubinascii) }, + #if MICROPY_PY_BUILTINS_BYTES_HEX + { MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&bytes_hex_as_bytes_obj) }, + { MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&bytes_fromhex_obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) }, { MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) }, + #if MICROPY_PY_UBINASCII_CRC32 { MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&mod_binascii_crc32_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table); diff --git a/extmod/moductypes.c b/extmod/moductypes.c index 78cf44a17a..15c36290a9 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -32,8 +32,6 @@ #include "py/objtuple.h" #include "py/binary.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_UCTYPES // The uctypes module allows defining the layout of a raw data structure (using @@ -192,7 +190,7 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_ // but scalar structure field is lowered into native Python int, so all // type info is lost. So, we cannot say if it's scalar type description, // or such lowered scalar. - mp_raise_TypeError(MP_ERROR_TEXT("cannot unambiguously get sizeof scalar")); + mp_raise_TypeError(MP_ERROR_TEXT("can't unambiguously get sizeof scalar")); } syntax_error(); } @@ -504,8 +502,8 @@ STATIC void uctypes_struct_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_obj_t value) { - mp_obj_uctypes_struct_t *self = mp_obj_cast_to_native_base(base_in, &uctypes_struct_type); +STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { + mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in); if (value == MP_OBJ_NULL) { // delete @@ -561,7 +559,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_ob } } else if (agg_type == PTR) { - byte *p = *(void **)(void *)self->addr; + byte *p = *(void **)self->addr; if (mp_obj_is_small_int(t->items[1])) { uint val_type = GET_TYPE(MP_OBJ_SMALL_INT_VALUE(t->items[1]), VAL_TYPE_BITS); return get_aligned(val_type, p, index); @@ -590,7 +588,7 @@ STATIC mp_obj_t uctypes_struct_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]); uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS); if (agg_type == PTR) { - byte *p = *(void **)(void *)self->addr; + byte *p = *(void **)self->addr; return mp_obj_new_int((mp_int_t)(uintptr_t)p); } } @@ -636,19 +634,17 @@ STATIC mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) { } MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at); -STATIC const mp_obj_type_t uctypes_struct_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_struct, - .print = uctypes_struct_print, - .make_new = uctypes_struct_make_new, - .attr = uctypes_struct_attr, - MP_TYPE_EXTENDED_FIELDS( - .subscr = uctypes_struct_subscr, - .unary_op = uctypes_struct_unary_op, - .buffer_p = { .get_buffer = uctypes_get_buffer }, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + uctypes_struct_type, + MP_QSTR_struct, + MP_TYPE_FLAG_NONE, + make_new, uctypes_struct_make_new, + print, uctypes_struct_print, + attr, uctypes_struct_attr, + subscr, uctypes_struct_subscr, + unary_op, uctypes_struct_unary_op, + buffer, uctypes_get_buffer + ); STATIC const mp_rom_map_elem_t mp_module_uctypes_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uctypes) }, diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c index 64100bb499..6850434129 100644 --- a/extmod/moduhashlib.c +++ b/extmod/moduhashlib.c @@ -29,8 +29,6 @@ #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_UHASHLIB #if MICROPY_SSL_MBEDTLS @@ -111,7 +109,7 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) { vstr_t vstr; vstr_init_len(&vstr, 32); mbedtls_sha256_finish_ret((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #else @@ -154,7 +152,7 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) { vstr_t vstr; vstr_init_len(&vstr, SHA256_BLOCK_SIZE); sha256_final((CRYAL_SHA256_CTX *)self->state, (byte *)vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #endif @@ -168,12 +166,13 @@ STATIC const mp_rom_map_elem_t uhashlib_sha256_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(uhashlib_sha256_locals_dict, uhashlib_sha256_locals_dict_table); -STATIC const mp_obj_type_t uhashlib_sha256_type = { - { &mp_type_type }, - .name = MP_QSTR_sha256, - .make_new = uhashlib_sha256_make_new, - .locals_dict = (void *)&uhashlib_sha256_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + uhashlib_sha256_type, + MP_QSTR_sha256, + MP_TYPE_FLAG_NONE, + make_new, uhashlib_sha256_make_new, + locals_dict, &uhashlib_sha256_locals_dict + ); #endif #if MICROPY_PY_UHASHLIB_SHA1 @@ -207,7 +206,7 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) { vstr_t vstr; vstr_init_len(&vstr, SHA1_SIZE); SHA1_Final((byte *)vstr.buf, (SHA1_CTX *)self->state); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #endif @@ -248,7 +247,7 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) { vstr_init_len(&vstr, 20); mbedtls_sha1_finish_ret((mbedtls_sha1_context *)self->state, (byte *)vstr.buf); mbedtls_sha1_free((mbedtls_sha1_context *)self->state); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #endif @@ -261,12 +260,13 @@ STATIC const mp_rom_map_elem_t uhashlib_sha1_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(uhashlib_sha1_locals_dict, uhashlib_sha1_locals_dict_table); -STATIC const mp_obj_type_t uhashlib_sha1_type = { - { &mp_type_type }, - .name = MP_QSTR_sha1, - .make_new = uhashlib_sha1_make_new, - .locals_dict = (void *)&uhashlib_sha1_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + uhashlib_sha1_type, + MP_QSTR_sha1, + MP_TYPE_FLAG_NONE, + make_new, uhashlib_sha1_make_new, + locals_dict, &uhashlib_sha1_locals_dict + ); #endif #if MICROPY_PY_UHASHLIB_MD5 @@ -300,7 +300,7 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) { vstr_t vstr; vstr_init_len(&vstr, MD5_SIZE); MD5_Final((byte *)vstr.buf, (MD5_CTX *)self->state); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #endif // MICROPY_SSL_AXTLS @@ -341,7 +341,7 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) { vstr_init_len(&vstr, 16); mbedtls_md5_finish_ret((mbedtls_md5_context *)self->state, (byte *)vstr.buf); mbedtls_md5_free((mbedtls_md5_context *)self->state); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #endif // MICROPY_SSL_MBEDTLS @@ -354,12 +354,13 @@ STATIC const mp_rom_map_elem_t uhashlib_md5_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(uhashlib_md5_locals_dict, uhashlib_md5_locals_dict_table); -STATIC const mp_obj_type_t uhashlib_md5_type = { - { &mp_type_type }, - .name = MP_QSTR_md5, - .make_new = uhashlib_md5_make_new, - .locals_dict = (void *)&uhashlib_md5_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + uhashlib_md5_type, + MP_QSTR_md5, + MP_TYPE_FLAG_NONE, + make_new, uhashlib_md5_make_new, + locals_dict, &uhashlib_md5_locals_dict + ); #endif // MICROPY_PY_UHASHLIB_MD5 STATIC const mp_rom_map_elem_t mp_module_uhashlib_globals_table[] = { diff --git a/extmod/moduheapq.c b/extmod/moduheapq.c index c102e830ff..a2317fb120 100644 --- a/extmod/moduheapq.c +++ b/extmod/moduheapq.c @@ -27,8 +27,6 @@ #include "py/objlist.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_UHEAPQ // the algorithm here is modelled on CPython's heapq.py diff --git a/extmod/modujson.c b/extmod/modujson.c index 26241fa230..5234ecfd0e 100644 --- a/extmod/modujson.c +++ b/extmod/modujson.c @@ -34,8 +34,6 @@ #include "py/runtime.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_UJSON #if MICROPY_PY_UJSON_SEPARATORS @@ -71,7 +69,7 @@ STATIC mp_obj_t mod_ujson_dump_helper(size_t n_args, const mp_obj_t *pos_args, m vstr_t vstr; vstr_init_print(&vstr, 8, &print_ext.base); mp_obj_print_helper(&print_ext.base, pos_args[0], PRINT_JSON); - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_utf8_vstr(&vstr); } else { // dump(obj, stream) print_ext.base.data = MP_OBJ_TO_PTR(pos_args[1]); @@ -107,7 +105,7 @@ STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) { mp_print_t print; vstr_init_print(&vstr, 8, &print); mp_obj_print_helper(&print, obj, PRINT_JSON); - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_utf8_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps); #endif @@ -178,6 +176,9 @@ STATIC mp_uint_t ujson_python_readinto(mp_obj_t obj, void *buf, mp_uint_t size, } s->start = 0; s->end = mp_obj_get_int(ret); + if (s->end == 0) { + return 0; + } } *((uint8_t *)buf) = ((uint8_t *)s->bytearray_obj.items)[s->start]; @@ -332,7 +333,7 @@ STATIC mp_obj_t _mod_ujson_load(mp_obj_t stream_obj, bool return_first_json) { S_NEXT(s); } if (flt) { - next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false, NULL); + next = mp_parse_num_float(vstr.buf, vstr.len, false, NULL); } else { next = mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL); } diff --git a/extmod/moduplatform.h b/extmod/moduplatform.h index d52ad7da7d..3597f7559f 100644 --- a/extmod/moduplatform.h +++ b/extmod/moduplatform.h @@ -37,11 +37,11 @@ #if defined(__ARM_ARCH) #define MICROPY_PLATFORM_ARCH "arm" -#elif defined(__x86_64__) || defined(_WIN64) +#elif defined(__x86_64__) || defined(_M_X64) #define MICROPY_PLATFORM_ARCH "x86_64" #elif defined(__i386__) || defined(_M_IX86) #define MICROPY_PLATFORM_ARCH "x86" -#elif defined(__xtensa__) || defined(_M_IX86) +#elif defined(__xtensa__) #define MICROPY_PLATFORM_ARCH "xtensa" #else #define MICROPY_PLATFORM_ARCH "" diff --git a/extmod/modure.c b/extmod/modure.c index 7ad6ccabce..9e6ac76ecb 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -33,16 +33,17 @@ #include "py/objstr.h" #include "py/stackctrl.h" +#if MICROPY_PY_BUILTINS_STR_UNICODE +#include "py/unicode.h" +#endif + #if MICROPY_PY_URE #define re1_5_stack_chk() MP_STACK_CHECK() #include "lib/re1.5/re1.5.h" -// CIRCUITPY -#if MICROPY_PY_URE_DEBUG #define FLAG_DEBUG 0x1000 -#endif typedef struct _mp_obj_re_t { mp_obj_base_t base; @@ -124,6 +125,18 @@ STATIC void match_span_helper(size_t n_args, const mp_obj_t *args, mp_obj_t span e = self->caps[no * 2 + 1] - begin; } + #if MICROPY_PY_BUILTINS_STR_UNICODE + if (mp_obj_get_type(self->str) == &mp_type_str) { + const byte *begin = (const byte *)mp_obj_str_get_str(self->str); + if (s != -1) { + s = utf8_ptr_to_index(begin, begin + s); + } + if (e != -1) { + e = utf8_ptr_to_index(begin, begin + e); + } + } + #endif + span[0] = mp_obj_new_int(s); span[1] = mp_obj_new_int(e); } @@ -166,12 +179,13 @@ STATIC const mp_rom_map_elem_t match_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table); -STATIC const mp_obj_type_t match_type = { - { &mp_type_type }, - .name = MP_QSTR_match, - .print = match_print, - .locals_dict = (void *)&match_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + match_type, + MP_QSTR_match, + MP_TYPE_FLAG_NONE, + print, match_print, + locals_dict, &match_locals_dict + ); #endif STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -183,7 +197,7 @@ STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { (void)n_args; mp_obj_re_t *self; - if (mp_obj_is_type(args[0], &re_type)) { + if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) { self = MP_OBJ_TO_PTR(args[0]); } else { self = MP_OBJ_TO_PTR(mod_re_compile(1, args)); @@ -232,7 +246,7 @@ STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { return mp_const_none; } - match->base.type = &match_type; + match->base.type = (mp_obj_type_t *)&match_type; match->num_matches = caps_num / 2; // caps_num counts start and end pointers match->str = args[1]; return MP_OBJ_FROM_PTR(match); @@ -277,7 +291,7 @@ STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) { mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte *)subj.begin, caps[0] - subj.begin); mp_obj_list_append(retval, s); if (self->re.sub > 0) { - mp_raise_NotImplementedError(MP_ERROR_TEXT("Splitting with sub-captures")); + mp_raise_NotImplementedError(MP_ERROR_TEXT("splitting with sub-captures")); } subj.begin = caps[1]; if (maxsplit > 0 && --maxsplit == 0) { @@ -297,7 +311,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_split_obj, 2, 3, re_split); STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) { mp_obj_re_t *self; - if (mp_obj_is_type(args[0], &re_type)) { + if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) { self = MP_OBJ_TO_PTR(args[0]); } else { self = MP_OBJ_TO_PTR(mod_re_compile(1, args)); @@ -320,7 +334,7 @@ STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) { vstr_t vstr_return; vstr_return.buf = NULL; // We'll init the vstr after the first match mp_obj_match_t *match = mp_local_alloc(sizeof(mp_obj_match_t) + caps_num * sizeof(char *)); - match->base.type = &match_type; + match->base.type = (mp_obj_type_t *)&match_type; match->num_matches = caps_num / 2; // caps_num counts start and end pointers match->str = where; @@ -405,7 +419,11 @@ STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) { // Add post-match string vstr_add_strn(&vstr_return, subj.begin, subj.end - subj.begin); - return mp_obj_new_str_from_vstr(mp_obj_get_type(where), &vstr_return); + if (mp_obj_get_type(where) == &mp_type_str) { + return mp_obj_new_str_from_utf8_vstr(&vstr_return); + } else { + return mp_obj_new_bytes_from_vstr(&vstr_return); + } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_sub_obj, 3, 5, re_sub_helper); @@ -424,16 +442,17 @@ STATIC const mp_rom_map_elem_t re_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table); -STATIC const mp_obj_type_t re_type = { - { &mp_type_type }, +STATIC MP_DEFINE_CONST_OBJ_TYPE( + re_type, #if CIRCUITPY - .name = MP_QSTR_re, + MP_QSTR_re, #else - .name = MP_QSTR_ure, + MP_QSTR_ure, #endif - .print = re_print, - .locals_dict = (void *)&re_locals_dict, -}; + MP_TYPE_FLAG_NONE, + print, re_print, + locals_dict, &re_locals_dict + ); #endif STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { @@ -443,14 +462,12 @@ STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { if (size == -1) { goto error; } - mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, &re_type); + mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, (mp_obj_type_t *)&re_type); #if MICROPY_PY_URE_DEBUG int flags = 0; if (n_args > 1) { flags = mp_obj_get_int(args[1]); } - #else - (void)n_args; #endif int error = re1_5_compilecode(&o->re, re_str); if (error != 0) { diff --git a/extmod/moduselect.c b/extmod/moduselect.c index e41adbc791..a1513835b2 100644 --- a/extmod/moduselect.c +++ b/extmod/moduselect.c @@ -30,7 +30,6 @@ #include -#include "py/stream.h" #include "py/runtime.h" #include "py/obj.h" #include "py/objlist.h" @@ -343,16 +342,13 @@ STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); -STATIC const mp_obj_type_t mp_type_poll = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_poll, - .locals_dict = (void *)&poll_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = poll_iternext, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_poll, + MP_QSTR_poll, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + iter, poll_iternext, + locals_dict, &poll_locals_dict + ); // poll() STATIC mp_obj_t select_poll(void) { diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c index 4276c366cd..c2046fd93d 100644 --- a/extmod/moduzlib.c +++ b/extmod/moduzlib.c @@ -31,8 +31,6 @@ #include "py/stream.h" #include "py/mperrno.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_UZLIB #define UZLIB_CONF_PARANOID_CHECKS (1) @@ -138,22 +136,19 @@ STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table); #endif -#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_stream_p_t decompio_stream_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = decompio_read, }; -STATIC const mp_obj_type_t decompio_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_DecompIO, - .make_new = decompio_make_new, - .locals_dict = (void *)&decompio_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &decompio_stream_p, - ), -}; +#if !MICROPY_ENABLE_DYNRUNTIME +STATIC MP_DEFINE_CONST_OBJ_TYPE( + decompio_type, + MP_QSTR_DecompIO, + MP_TYPE_FLAG_NONE, + make_new, decompio_make_new, + protocol, &decompio_stream_p, + locals_dict, &decompio_locals_dict + ); #endif STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) { diff --git a/extmod/ulab b/extmod/ulab index 84f99f17fc..2df210f87a 160000 --- a/extmod/ulab +++ b/extmod/ulab @@ -1 +1 @@ -Subproject commit 84f99f17fc02b03c13f99485d9cf68bc9d17c600 +Subproject commit 2df210f87a79deedc9003b1bbd6015a2fea7c03e diff --git a/extmod/utime_mphal.c b/extmod/utime_mphal.c index 3d1cdfd820..9cd5d938d0 100644 --- a/extmod/utime_mphal.c +++ b/extmod/utime_mphal.c @@ -95,6 +95,19 @@ STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) { // we assume that first argument come from ticks_xx so is small int mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in); mp_uint_t delta = mp_obj_get_int(delta_in); + + // Check that delta does not overflow the range that ticks_diff can handle. + // This ensures the following: + // - ticks_diff(ticks_add(T, delta), T) == delta + // - ticks_diff(T, ticks_add(T, delta)) == -delta + // The latter requires excluding delta=-TICKS_PERIOD/2. + // + // This unsigned comparison is equivalent to a signed comparison of: + // delta <= -TICKS_PERIOD/2 || delta >= TICKS_PERIOD/2 + if (delta + MICROPY_PY_UTIME_TICKS_PERIOD / 2 - 1 >= MICROPY_PY_UTIME_TICKS_PERIOD - 1) { + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("ticks interval overflow")); + } + return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1)); } MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add); diff --git a/extmod/vfs.c b/extmod/vfs.c index 61d85b293b..125370b588 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -96,11 +96,12 @@ mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out) { STATIC mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_out) { const char *path = mp_obj_str_get_str(path_in); const char *p_out; - *path_out = mp_const_none; mp_vfs_mount_t *vfs = mp_vfs_lookup_path(path, &p_out); if (vfs != MP_VFS_NONE && vfs != MP_VFS_ROOT) { *path_out = mp_obj_new_str_of_type(mp_obj_get_type(path_in), (const byte *)p_out, strlen(p_out)); + } else { + *path_out = MP_OBJ_NULL; } return vfs; } @@ -131,8 +132,9 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) { } // If the mounted object has the VFS protocol, call its import_stat helper - const mp_vfs_proto_t *proto = (mp_vfs_proto_t *)mp_proto_get(MP_QSTR_protocol_vfs, vfs->obj); - if (proto != NULL) { + const mp_obj_type_t *type = mp_obj_get_type(vfs->obj); + if (MP_OBJ_TYPE_HAS_SLOT(type, protocol)) { + const mp_vfs_proto_t *proto = MP_OBJ_TYPE_GET_SLOT(type, protocol); return proto->import_stat(MP_OBJ_TO_PTR(vfs->obj), path_out); } @@ -171,7 +173,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { #if MICROPY_VFS_LFS1 if (memcmp(&buf[32], "littlefs", 8) == 0) { // LFS1 - mp_obj_t vfs = mp_type_vfs_lfs1.make_new(&mp_type_vfs_lfs1, 1, 0, &bdev_obj); + mp_obj_t vfs = MP_OBJ_TYPE_GET_SLOT(&mp_type_vfs_lfs1, make_new)(&mp_type_vfs_lfs1, 1, 0, &bdev_obj); nlr_pop(); return vfs; } @@ -179,7 +181,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { #if MICROPY_VFS_LFS2 if (memcmp(&buf[0], "littlefs", 8) == 0) { // LFS2 - mp_obj_t vfs = mp_type_vfs_lfs2.make_new(&mp_type_vfs_lfs2, 1, 0, &bdev_obj); + mp_obj_t vfs = MP_OBJ_TYPE_GET_SLOT(&mp_type_vfs_lfs2, make_new)(&mp_type_vfs_lfs2, 1, 0, &bdev_obj); nlr_pop(); return vfs; } @@ -192,7 +194,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { #endif #if MICROPY_VFS_FAT - return mp_fat_vfs_type.make_new(&mp_fat_vfs_type, 1, 0, &bdev_obj); + return MP_OBJ_TYPE_GET_SLOT(&mp_fat_vfs_type, make_new)(&mp_fat_vfs_type, 1, 0, &bdev_obj); #endif // no filesystem found @@ -311,7 +313,7 @@ mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) #if defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX // If the file is an integer then delegate straight to the POSIX handler if (mp_obj_is_small_int(args[ARG_file].u_obj)) { - return mp_vfs_posix_file_open(&mp_type_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj); + return mp_vfs_posix_file_open(&mp_type_vfs_posix_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj); } #endif @@ -359,10 +361,11 @@ mp_obj_t mp_vfs_getcwd(void) { if (!(cwd[0] == '/' && cwd[1] == 0)) { vstr_add_str(&vstr, cwd); } - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj, mp_vfs_getcwd); +// CIRCUITPY: accessible from shared-module/os/__init__.c mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in) { mp_vfs_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); if (self->is_iter) { @@ -402,7 +405,7 @@ mp_obj_t mp_vfs_ilistdir(size_t n_args, const mp_obj_t *args) { path_in = MP_OBJ_NEW_QSTR(MP_QSTR_); } - mp_obj_t path_out = mp_const_none; + mp_obj_t path_out; mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); if (vfs == MP_VFS_ROOT) { @@ -535,4 +538,7 @@ int mp_vfs_mount_and_chdir_protected(mp_obj_t bdev, mp_obj_t mount_point) { return ret; } +MP_REGISTER_ROOT_POINTER(struct _mp_vfs_mount_t *vfs_cur); +MP_REGISTER_ROOT_POINTER(struct _mp_vfs_mount_t *vfs_mount_table); + #endif // MICROPY_VFS diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 4d4e7e881a..9c0da3cda6 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -28,6 +28,10 @@ #include "py/mpconfig.h" #if MICROPY_VFS_FAT +#if !MICROPY_ENABLE_FINALISER +#error "MICROPY_VFS_FAT requires MICROPY_ENABLE_FINALISER" +#endif + #if !MICROPY_VFS #error "with MICROPY_VFS_FAT enabled, must also enable MICROPY_VFS" #endif @@ -41,7 +45,6 @@ #include "extmod/vfs_fat.h" #include "shared/timeutils/timeutils.h" #include "supervisor/filesystem.h" -#include "supervisor/shared/translate/translate.h" #if FF_MAX_SS == FF_MIN_SS #define SECSIZE(fs) (FF_MIN_SS) @@ -133,6 +136,7 @@ STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mk typedef struct _mp_vfs_fat_ilistdir_it_t { mp_obj_base_t base; mp_fun_1_t iternext; + mp_fun_1_t finaliser; bool is_str; FF_DIR dir; } mp_vfs_fat_ilistdir_it_t; @@ -177,6 +181,13 @@ STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) { return MP_OBJ_STOP_ITERATION; } +STATIC mp_obj_t mp_vfs_fat_ilistdir_it_del(mp_obj_t self_in) { + mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); + // ignore result / error because we may be closing a second time. + f_closedir(&self->dir); + return mp_const_none; +} + STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]); bool is_str_type = true; @@ -191,8 +202,10 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) { } // Create a new iterator object to list the dir - mp_vfs_fat_ilistdir_it_t *iter = mp_obj_malloc(mp_vfs_fat_ilistdir_it_t, &mp_type_polymorph_iter); + mp_vfs_fat_ilistdir_it_t *iter = m_new_obj_with_finaliser(mp_vfs_fat_ilistdir_it_t); + iter->base.type = &mp_type_polymorph_iter_with_finaliser; iter->iternext = mp_vfs_fat_ilistdir_it_iternext; + iter->finaliser = mp_vfs_fat_ilistdir_it_del; iter->is_str = is_str_type; FRESULT res = f_opendir(&self->fatfs, &iter->dir, path); if (res != FR_OK) { @@ -524,16 +537,13 @@ STATIC const mp_vfs_proto_t fat_vfs_proto = { .import_stat = fat_vfs_import_stat, }; -const mp_obj_type_t mp_fat_vfs_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_VfsFat, - .make_new = fat_vfs_make_new, - .locals_dict = (mp_obj_dict_t *)&fat_vfs_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &fat_vfs_proto, - ), - -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_fat_vfs_type, + MP_QSTR_VfsFat, + MP_TYPE_FLAG_NONE, + make_new, fat_vfs_make_new, + protocol, &fat_vfs_proto, + locals_dict, &fat_vfs_locals_dict + ); #endif // MICROPY_VFS_FAT diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index 36070f1011..72b712ab71 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -148,19 +148,64 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, } } -// Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO, -// but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor -STATIC const mp_arg_t file_open_args[] = { - { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} }, - { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r)} }, - { MP_QSTR_encoding, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} }, +// TODO gc hook to close the file if not already closed + +STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, + { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) }, }; #define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args) -// CIRCUITPY is more careful about validating the open mode. -STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_arg_val_t *args) { +STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table); + +STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = { + .read = file_obj_read, + .write = file_obj_write, + .ioctl = file_obj_ioctl, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_fat_fileio, + MP_QSTR_FileIO, + MP_TYPE_FLAG_ITER_IS_STREAM, + print, file_obj_print, + protocol, &vfs_fat_fileio_stream_p, + locals_dict, &vfs_fat_rawfile_locals_dict + ); + +STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { + .read = file_obj_read, + .write = file_obj_write, + .ioctl = file_obj_ioctl, + .is_text = true, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_fat_textio, + MP_QSTR_TextIOWrapper, + MP_TYPE_FLAG_ITER_IS_STREAM, + print, file_obj_print, + protocol, &vfs_fat_textio_stream_p, + locals_dict, &vfs_fat_rawfile_locals_dict + ); + +// Factory function for I/O stream classes +STATIC mp_obj_t fat_vfs_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { + fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); + + const mp_obj_type_t *type = &mp_type_vfs_fat_textio; int mode = 0; - const char *mode_s = mp_obj_str_get_str(args[1].u_obj); + const char *mode_s = mp_obj_str_get_str(mode_in); uint32_t rwxa_count = 0; uint32_t bt_count = 0; uint32_t plus_count = 0; @@ -187,12 +232,10 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar mode |= FA_READ | FA_WRITE; plus_count++; break; - #if MICROPY_PY_IO_FILEIO case 'b': bt_count++; type = &mp_type_vfs_fat_fileio; break; - #endif case 't': bt_count++; type = &mp_type_vfs_fat_textio; @@ -207,8 +250,8 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar mp_arg_error_invalid(MP_QSTR_mode); } - assert(vfs != NULL); - if ((mode & FA_WRITE) != 0 && !filesystem_is_writable_by_python(vfs)) { + assert(self != NULL); + if ((mode & FA_WRITE) != 0 && !filesystem_is_writable_by_python(self)) { mp_raise_OSError(MP_EROFS); } @@ -216,12 +259,13 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar pyb_file_obj_t *o = m_new_obj_with_finaliser(pyb_file_obj_t); o->base.type = type; - const char *fname = mp_obj_str_get_str(args[0].u_obj); - FRESULT res = f_open(&vfs->fatfs, &o->fp, fname, mode); + const char *fname = mp_obj_str_get_str(path_in); + FRESULT res = f_open(&self->fatfs, &o->fp, fname, mode); if (res != FR_OK) { m_del_obj(pyb_file_obj_t, o); - mp_raise_OSError_errno_str(fresult_to_errno_table[res], args[0].u_obj); + mp_raise_OSError_errno_str(fresult_to_errno_table[res], path_in); } + // CIRCUITPY does fast seek. // If we're reading, turn on fast seek. if (mode == FA_READ) { // One call to determine how much space we need. @@ -249,87 +293,6 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar return MP_OBJ_FROM_PTR(o); } - -STATIC mp_obj_t file_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, FILE_OPEN_NUM_ARGS, file_open_args, arg_vals); - return file_open(NULL, type, arg_vals); -} - -// TODO gc hook to close the file if not already closed - -STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, - { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, - { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, - { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table); - -#if MICROPY_PY_IO_FILEIO -STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) - .read = file_obj_read, - .write = file_obj_write, - .ioctl = file_obj_ioctl, -}; - -const mp_obj_type_t mp_type_vfs_fat_fileio = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_FileIO, - .print = file_obj_print, - .make_new = file_obj_make_new, - .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &vfs_fat_fileio_stream_p, - ), -}; -#endif - -STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) - .read = file_obj_read, - .write = file_obj_write, - .ioctl = file_obj_ioctl, - .is_text = true, -}; - -const mp_obj_type_t mp_type_vfs_fat_textio = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_TextIOWrapper, - .print = file_obj_print, - .make_new = file_obj_make_new, - .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &vfs_fat_textio_stream_p, - ), -}; - -// Factory function for I/O stream classes -STATIC mp_obj_t fatfs_builtin_open_self(mp_obj_t self_in, mp_obj_t path, mp_obj_t mode) { - // TODO: analyze buffering args and instantiate appropriate type - fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); - mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; - arg_vals[0].u_obj = path; - arg_vals[1].u_obj = mode; - arg_vals[2].u_obj = mp_const_none; - return file_open(self, &mp_type_vfs_fat_textio, arg_vals); -} -MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fatfs_builtin_open_self); +MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fat_vfs_open); #endif // MICROPY_VFS && MICROPY_VFS_FAT diff --git a/extmod/vfs_lfs.c b/extmod/vfs_lfs.c index f6a9a24623..4fb86b89b7 100644 --- a/extmod/vfs_lfs.c +++ b/extmod/vfs_lfs.c @@ -26,12 +26,13 @@ #include "py/runtime.h" #include "py/mphal.h" + +#if MICROPY_VFS && (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) + #include "shared/timeutils/timeutils.h" #include "extmod/vfs.h" #include "extmod/vfs_lfs.h" -#if MICROPY_VFS && (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) - enum { LFS_MAKE_ARG_bdev, LFS_MAKE_ARG_readsize, LFS_MAKE_ARG_progsize, LFS_MAKE_ARG_lookahead, LFS_MAKE_ARG_mtime }; static const mp_arg_t lfs_make_allowed_args[] = { diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index 0cd3295faf..de1f421977 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -24,6 +24,9 @@ * THE SOFTWARE. */ +// This file should be compiled when included from vfs_lfs.c. +#if defined(LFS_BUILD_VERSION) + #include #include @@ -36,6 +39,10 @@ #include "extmod/vfs.h" #include "shared/timeutils/timeutils.h" +#if !MICROPY_ENABLE_FINALISER +#error "MICROPY_VFS_LFS requires MICROPY_ENABLE_FINALISER" +#endif + STATIC int MP_VFS_LFSx(dev_ioctl)(const struct LFSx_API (config) * c, int cmd, int arg, bool must_return_int) { mp_obj_t ret = mp_vfs_blockdev_ioctl(c->context, cmd, arg); int ret_i = 0; @@ -155,6 +162,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(open_obj), MP_VFS_LFSx(file_open)); typedef struct MP_VFS_LFSx (_ilistdir_it_t) { mp_obj_base_t base; mp_fun_1_t iternext; + mp_fun_1_t finaliser; bool is_str; MP_OBJ_VFS_LFSx *vfs; LFSx_API(dir_t) dir; @@ -163,11 +171,16 @@ typedef struct MP_VFS_LFSx (_ilistdir_it_t) { STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) { MP_VFS_LFSx(ilistdir_it_t) * self = MP_OBJ_TO_PTR(self_in); + if (self->vfs == NULL) { + return MP_OBJ_STOP_ITERATION; + } + struct LFSx_API (info) info; for (;;) { int ret = LFSx_API(dir_read)(&self->vfs->lfs, &self->dir, &info); if (ret == 0) { LFSx_API(dir_close)(&self->vfs->lfs, &self->dir); + self->vfs = NULL; return MP_OBJ_STOP_ITERATION; } if (!(info.name[0] == '.' && (info.name[1] == '\0' @@ -190,6 +203,14 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) { return MP_OBJ_FROM_PTR(t); } +STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_del)(mp_obj_t self_in) { + MP_VFS_LFSx(ilistdir_it_t) * self = MP_OBJ_TO_PTR(self_in); + if (self->vfs != NULL) { + LFSx_API(dir_close)(&self->vfs->lfs, &self->dir); + } + return mp_const_none; +} + STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(args[0]); bool is_str_type = true; @@ -203,14 +224,17 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) path = vstr_null_terminated_str(&self->cur_dir); } - MP_VFS_LFSx(ilistdir_it_t) * iter = mp_obj_malloc(MP_VFS_LFSx(ilistdir_it_t), &mp_type_polymorph_iter); + MP_VFS_LFSx(ilistdir_it_t) * iter = m_new_obj_with_finaliser(MP_VFS_LFSx(ilistdir_it_t)); + iter->base.type = &mp_type_polymorph_iter_with_finaliser; + iter->iternext = MP_VFS_LFSx(ilistdir_it_iternext); + iter->finaliser = MP_VFS_LFSx(ilistdir_it_del); iter->is_str = is_str_type; - iter->vfs = self; int ret = LFSx_API(dir_open)(&self->lfs, &iter->dir, path); if (ret < 0) { mp_raise_OSError(-ret); } + iter->vfs = self; return MP_OBJ_FROM_PTR(iter); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(MP_VFS_LFSx(ilistdir_obj), 1, 2, MP_VFS_LFSx(ilistdir_func)); @@ -481,17 +505,21 @@ STATIC const mp_vfs_proto_t MP_VFS_LFSx(proto) = { .import_stat = MP_VFS_LFSx(import_stat), }; -const mp_obj_type_t MP_TYPE_VFS_LFSx = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - #if LFS_BUILD_VERSION == 1 - .name = MP_QSTR_VfsLfs1, - #else - .name = MP_QSTR_VfsLfs2, - #endif - .make_new = MP_VFS_LFSx(make_new), - .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(locals_dict), - MP_TYPE_EXTENDED_FIELDS( - .protocol = &MP_VFS_LFSx(proto), - ), -}; +#if LFS_BUILD_VERSION == 1 +#define VFS_LFSx_QSTR MP_QSTR_VfsLfs1 +#else +#define VFS_LFSx_QSTR MP_QSTR_VfsLfs2 +#endif + +MP_DEFINE_CONST_OBJ_TYPE( + MP_TYPE_VFS_LFSx, + VFS_LFSx_QSTR, + MP_TYPE_FLAG_NONE, + make_new, MP_VFS_LFSx(make_new), + protocol, &MP_VFS_LFSx(proto), + locals_dict, &MP_VFS_LFSx(locals_dict) + ); + +#undef VFS_LFSx_QSTR + +#endif // defined(LFS_BUILD_VERSION) diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c index da0c1405f1..5f0155d3c5 100644 --- a/extmod/vfs_lfsx_file.c +++ b/extmod/vfs_lfsx_file.c @@ -24,6 +24,9 @@ * THE SOFTWARE. */ +// This file should be compiled when included from vfs_lfs.c. +#if defined(LFS_BUILD_VERSION) + #include #include @@ -68,11 +71,9 @@ mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mod case '+': flags |= LFSx_MACRO(_O_RDWR); break; - #if MICROPY_PY_IO_FILEIO case 'b': type = &MP_TYPE_VFS_LFSx_(_fileio); break; - #endif case 't': type = &MP_TYPE_VFS_LFSx_(_textio); break; @@ -216,45 +217,35 @@ STATIC const mp_rom_map_elem_t MP_VFS_LFSx(file_locals_dict_table)[] = { }; STATIC MP_DEFINE_CONST_DICT(MP_VFS_LFSx(file_locals_dict), MP_VFS_LFSx(file_locals_dict_table)); -#if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t MP_VFS_LFSx(fileio_stream_p) = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = MP_VFS_LFSx(file_read), .write = MP_VFS_LFSx(file_write), .ioctl = MP_VFS_LFSx(file_ioctl), }; -const mp_obj_type_t MP_TYPE_VFS_LFSx_(_fileio) = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_FileIO, - .print = MP_VFS_LFSx(file_print), - .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict), - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &MP_VFS_LFSx(fileio_stream_p), - ), -}; -#endif +MP_DEFINE_CONST_OBJ_TYPE( + MP_TYPE_VFS_LFSx_(_fileio), + MP_QSTR_FileIO, + MP_TYPE_FLAG_ITER_IS_STREAM, + print, MP_VFS_LFSx(file_print), + protocol, &MP_VFS_LFSx(fileio_stream_p), + locals_dict, &MP_VFS_LFSx(file_locals_dict) + ); STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = MP_VFS_LFSx(file_read), .write = MP_VFS_LFSx(file_write), .ioctl = MP_VFS_LFSx(file_ioctl), .is_text = true, }; -const mp_obj_type_t MP_TYPE_VFS_LFSx_(_textio) = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_TextIOWrapper, - .print = MP_VFS_LFSx(file_print), - .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict), - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &MP_VFS_LFSx(textio_stream_p), - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + MP_TYPE_VFS_LFSx_(_textio), + MP_QSTR_TextIOWrapper, + MP_TYPE_FLAG_ITER_IS_STREAM, + print, MP_VFS_LFSx(file_print), + protocol, &MP_VFS_LFSx(textio_stream_p), + locals_dict, &MP_VFS_LFSx(file_locals_dict) + ); + +#endif // defined(LFS_BUILD_VERSION) diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index 4e73acea6f..9b856e1f01 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -31,11 +31,17 @@ #include "extmod/vfs.h" #include "extmod/vfs_posix.h" -#if defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX +#if MICROPY_VFS_POSIX +#if !MICROPY_ENABLE_FINALISER +#error "MICROPY_VFS_POSIX requires MICROPY_ENABLE_FINALISER" +#endif + +#include #include #include #include +#include #include #ifdef _MSC_VER #include // For mkdir etc. @@ -138,7 +144,7 @@ STATIC mp_obj_t vfs_posix_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode if (!mp_obj_is_small_int(path_in)) { path_in = vfs_posix_get_path_obj(self, path_in); } - return mp_vfs_posix_file_open(&mp_type_textio, path_in, mode_in); + return mp_vfs_posix_file_open(&mp_type_vfs_posix_textio, path_in, mode_in); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_open_obj, vfs_posix_open); @@ -162,6 +168,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd); typedef struct _vfs_posix_ilistdir_it_t { mp_obj_base_t base; mp_fun_1_t iternext; + mp_fun_1_t finaliser; bool is_str; DIR *dir; } vfs_posix_ilistdir_it_t; @@ -185,7 +192,7 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) { MP_THREAD_GIL_ENTER(); const char *fn = dirent->d_name; - if (fn[0] == '.' && (fn[1] == 0 || fn[1] == '.')) { + if (fn[0] == '.' && (fn[1] == 0 || (fn[1] == '.' && fn[2] == 0))) { // skip . and .. continue; } @@ -226,10 +233,22 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) { } } +STATIC mp_obj_t vfs_posix_ilistdir_it_del(mp_obj_t self_in) { + vfs_posix_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); + if (self->dir != NULL) { + MP_THREAD_GIL_EXIT(); + closedir(self->dir); + MP_THREAD_GIL_ENTER(); + } + return mp_const_none; +} + STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); - vfs_posix_ilistdir_it_t *iter = mp_obj_malloc(vfs_posix_ilistdir_it_t, &mp_type_polymorph_iter); + vfs_posix_ilistdir_it_t *iter = m_new_obj_with_finaliser(vfs_posix_ilistdir_it_t); + iter->base.type = &mp_type_polymorph_iter_with_finaliser; iter->iternext = vfs_posix_ilistdir_it_iternext; + iter->finaliser = vfs_posix_ilistdir_it_del; iter->is_str = mp_obj_get_type(path_in) == &mp_type_str; const char *path = vfs_posix_get_path_str(self, path_in); if (path[0] == '\0') { @@ -378,19 +397,16 @@ STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(vfs_posix_locals_dict, vfs_posix_locals_dict_table); STATIC const mp_vfs_proto_t vfs_posix_proto = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_vfs) .import_stat = mp_vfs_posix_import_stat, }; -const mp_obj_type_t mp_type_vfs_posix = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_VfsPosix, - .locals_dict = (mp_obj_dict_t *)&vfs_posix_locals_dict, - .make_new = vfs_posix_make_new, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &vfs_posix_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_posix, + MP_QSTR_VfsPosix, + MP_TYPE_FLAG_NONE, + make_new, vfs_posix_make_new, + protocol, &vfs_posix_proto, + locals_dict, &vfs_posix_locals_dict + ); #endif // MICROPY_VFS_POSIX diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 534b11c08c..ea19de7fd0 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -29,9 +29,8 @@ #include "py/runtime.h" #include "py/stream.h" #include "extmod/vfs_posix.h" -#include "supervisor/shared/translate/translate.h" -#if (defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX) || (defined(MICROPY_VFS_POSIX_FILE) && MICROPY_VFS_POSIX_FILE) +#if MICROPY_VFS_POSIX #include #include @@ -47,7 +46,7 @@ typedef struct _mp_obj_vfs_posix_file_t { int fd; } mp_obj_vfs_posix_file_t; -#ifdef MICROPY_CPYTHON_COMPAT +#if MICROPY_CPYTHON_COMPAT STATIC void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) { if (o->fd < 0) { mp_raise_ValueError(MP_ERROR_TEXT("I/O operation on closed file")); @@ -60,11 +59,11 @@ STATIC void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) { STATIC void vfs_posix_file_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_vfs_posix_file_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "", mp_obj_get_type_qstr(self_in), self->fd); + mp_printf(print, "", mp_obj_get_type_str(self_in), self->fd); } mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in) { - mp_obj_vfs_posix_file_t *o = m_new_obj(mp_obj_vfs_posix_file_t); + mp_obj_vfs_posix_file_t *o = m_new_obj_with_finaliser(mp_obj_vfs_posix_file_t); const char *mode_s = mp_obj_str_get_str(mode_in); int mode_rw = 0, mode_x = 0; @@ -84,15 +83,12 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_ case '+': mode_rw = O_RDWR; break; - #if MICROPY_PY_IO_FILEIO - // If we don't have io.FileIO, then files are in text mode implicitly case 'b': type = &mp_type_vfs_posix_fileio; break; case 't': type = &mp_type_vfs_posix_textio; break; - #endif } } @@ -112,17 +108,6 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_ return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t vfs_posix_file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - static const mp_arg_t allowed_args[] = { - { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} }, - { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} }, - }; - - mp_arg_val_t arg_vals[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, arg_vals); - return mp_vfs_posix_file_open(type, arg_vals[0].u_obj, arg_vals[1].u_obj); -} - STATIC mp_obj_t vfs_posix_file_fileno(mp_obj_t self_in) { mp_obj_vfs_posix_file_t *self = MP_OBJ_TO_PTR(self_in); check_fd_is_open(self); @@ -150,6 +135,12 @@ STATIC mp_uint_t vfs_posix_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, i STATIC mp_uint_t vfs_posix_file_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); + #if MICROPY_PY_OS_DUPTERM + if (o->fd <= STDERR_FILENO) { + mp_hal_stdout_tx_strn(buf, size); + return size; + } + #endif ssize_t r; MP_HAL_RETRY_SYSCALL(r, write(o->fd, buf, size), { *errcode = err; @@ -194,12 +185,12 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_ return 0; } case MP_STREAM_CLOSE: - MP_THREAD_GIL_EXIT(); - close(o->fd); - MP_THREAD_GIL_ENTER(); - #ifdef MICROPY_CPYTHON_COMPAT + if (o->fd >= 0) { + MP_THREAD_GIL_EXIT(); + close(o->fd); + MP_THREAD_GIL_ENTER(); + } o->fd = -1; - #endif return 0; case MP_STREAM_GET_FILENO: return o->fd; @@ -246,59 +237,46 @@ STATIC const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&vfs_posix_file___exit___obj) }, }; STATIC MP_DEFINE_CONST_DICT(vfs_posix_rawfile_locals_dict, vfs_posix_rawfile_locals_dict_table); -#if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t vfs_posix_fileio_stream_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = vfs_posix_file_read, .write = vfs_posix_file_write, .ioctl = vfs_posix_file_ioctl, }; -const mp_obj_type_t mp_type_vfs_posix_fileio = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_FileIO, - .print = vfs_posix_file_print, - .make_new = vfs_posix_file_make_new, - .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &vfs_posix_fileio_stream_p, - ), -}; -#endif +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_posix_fileio, + MP_QSTR_FileIO, + MP_TYPE_FLAG_ITER_IS_STREAM, + print, vfs_posix_file_print, + protocol, &vfs_posix_fileio_stream_p, + locals_dict, &vfs_posix_rawfile_locals_dict + ); STATIC const mp_stream_p_t vfs_posix_textio_stream_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = vfs_posix_file_read, .write = vfs_posix_file_write, .ioctl = vfs_posix_file_ioctl, .is_text = true, }; -const mp_obj_type_t mp_type_vfs_posix_textio = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_TextIOWrapper, - .print = vfs_posix_file_print, - .make_new = vfs_posix_file_make_new, - .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &vfs_posix_textio_stream_p, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_posix_textio, + MP_QSTR_TextIOWrapper, + MP_TYPE_FLAG_ITER_IS_STREAM, + print, vfs_posix_file_print, + protocol, &vfs_posix_textio_stream_p, + locals_dict, &vfs_posix_rawfile_locals_dict + ); -const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_textio}, STDIN_FILENO}; -const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_textio}, STDOUT_FILENO}; -const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_textio}, STDERR_FILENO}; +const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_vfs_posix_textio}, STDIN_FILENO}; +const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_vfs_posix_textio}, STDOUT_FILENO}; +const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_vfs_posix_textio}, STDERR_FILENO}; -#endif // MICROPY_VFS_POSIX || MICROPY_VFS_POSIX_FILE +#endif // MICROPY_VFS_POSIX diff --git a/extmod/virtpin.c b/extmod/virtpin.c index 510ba8dbaf..cd0b9f92f8 100644 --- a/extmod/virtpin.c +++ b/extmod/virtpin.c @@ -25,16 +25,15 @@ */ #include "extmod/virtpin.h" -#include "py/proto.h" int mp_virtual_pin_read(mp_obj_t pin) { mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(pin); - const mp_pin_p_t *pin_p = mp_proto_get(MP_QSTR_protocol_pin, s); + mp_pin_p_t *pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol); return pin_p->ioctl(pin, MP_PIN_READ, 0, NULL); } void mp_virtual_pin_write(mp_obj_t pin, int value) { mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(pin); - const mp_pin_p_t *pin_p = mp_proto_get(MP_QSTR_protocol_pin, s); + mp_pin_p_t *pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol); pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL); } diff --git a/frozen/Adafruit_CircuitPython_asyncio b/frozen/Adafruit_CircuitPython_asyncio index 7c25d09be0..c277db5ae8 160000 --- a/frozen/Adafruit_CircuitPython_asyncio +++ b/frozen/Adafruit_CircuitPython_asyncio @@ -1 +1 @@ -Subproject commit 7c25d09be04a2979bcfb43b801de57594112808d +Subproject commit c277db5ae86805006f563b782e0a85832a5c3450 diff --git a/lib/libm/thumb_vfp_sqrtf.c b/lib/libm/thumb_vfp_sqrtf.c index 12ffebf827..25b8823163 100644 --- a/lib/libm/thumb_vfp_sqrtf.c +++ b/lib/libm/thumb_vfp_sqrtf.c @@ -3,7 +3,7 @@ #include float sqrtf(float x) { - asm volatile ( + __asm__ volatile ( "vsqrt.f32 %[r], %[x]\n" : [r] "=t" (x) : [x] "t" (x)); diff --git a/lib/libm_dbl/thumb_vfp_sqrt.c b/lib/libm_dbl/thumb_vfp_sqrt.c index dd37a07b05..ccd33e9796 100644 --- a/lib/libm_dbl/thumb_vfp_sqrt.c +++ b/lib/libm_dbl/thumb_vfp_sqrt.c @@ -2,7 +2,7 @@ double sqrt(double x) { double ret; - asm volatile ( + __asm__ volatile ( "vsqrt.f64 %P0, %P1\n" : "=w" (ret) : "w" (x)); diff --git a/lib/micropython-lib b/lib/micropython-lib new file mode 160000 index 0000000000..e6b89eafa3 --- /dev/null +++ b/lib/micropython-lib @@ -0,0 +1 @@ +Subproject commit e6b89eafa3b86d2e8e405450377d459600a30cd6 diff --git a/lib/oofatfs/ffconf.h b/lib/oofatfs/ffconf.h index fbb568f7c4..f22fbee932 100644 --- a/lib/oofatfs/ffconf.h +++ b/lib/oofatfs/ffconf.h @@ -72,8 +72,8 @@ #define FF_USE_MKFS 1 /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ -#ifdef MICROPY_FF_MKFS_FAT32 -#define FF_MKFS_FAT32 MICROPY_FF_MKFS_FAT32 +#ifdef MICROPY_FATFS_MKFS_FAT32 +#define FF_MKFS_FAT32 MICROPY_FATFS_MKFS_FAT32 #else #define FF_MKFS_FAT32 0 #endif diff --git a/lib/re1.5/charclass.c b/lib/re1.5/charclass.c index 7f6388c93d..2553b40530 100644 --- a/lib/re1.5/charclass.c +++ b/lib/re1.5/charclass.c @@ -6,7 +6,15 @@ int _re1_5_classmatch(const char *pc, const char *sp) int is_positive = (pc[-1] == Class); int cnt = *pc++; while (cnt--) { - if (*sp >= *pc && *sp <= pc[1]) return is_positive; + if (*pc == RE15_CLASS_NAMED_CLASS_INDICATOR) { + if (_re1_5_namedclassmatch(pc + 1, sp)) { + return is_positive; + } + } else { + if (*sp >= *pc && *sp <= pc[1]) { + return is_positive; + } + } pc += 2; } return !is_positive; diff --git a/lib/re1.5/compilecode.c b/lib/re1.5/compilecode.c index 936f6ed28a..081c57441e 100644 --- a/lib/re1.5/compilecode.c +++ b/lib/re1.5/compilecode.c @@ -4,6 +4,9 @@ #include "re1.5.h" +// Matches: DSWdsw +#define MATCH_NAMED_CLASS_CHAR(c) (((c) | 0x20) == 'd' || ((c) | 0x24) == 'w') + #define INSERT_CODE(at, num, pc) \ ((code ? memmove(code + at + num, code + at, pc - at) : 0), pc += num) #define REL(at, to) (to - at - 2) @@ -32,7 +35,6 @@ static char unescape(char c) { } } - static void _emit_checked(int at, char *code, int val, bool *err) { *err |= val != (int8_t)val; if (code) { @@ -54,7 +56,7 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode) re++; if (!*re) return NULL; // Trailing backslash term = PC; - if ((*re | 0x20) == 'd' || (*re | 0x20) == 's' || (*re | 0x20) == 'w') { + if (MATCH_NAMED_CLASS_CHAR(*re)) { EMIT(PC++, NamedClass); EMIT(PC++, *re); } else { @@ -87,27 +89,24 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode) PC++; // Skip # of pair byte prog->len++; for (cnt = 0; *re != ']'; re++, cnt++) { - if (!*re) return NULL; - const char *b = re; - if (*re == '\\') { - re += 1; - if (!*re) return NULL; // Trailing backslash - EMIT(PC++, unescape(*re)); - } else { - EMIT(PC++, *re); + char c = *re; + if (c == '\\') { + ++re; + c = *re; + if (MATCH_NAMED_CLASS_CHAR(c)) { + c = RE15_CLASS_NAMED_CLASS_INDICATOR; + goto emit_char_pair; + } else { + c = unescape(c); + } } + if (!c) return NULL; if (re[1] == '-' && re[2] != ']') { re += 2; - } else { - re = b; - } - if (*re == '\\') { - re += 1; - if (!*re) return NULL; // Trailing backslash - EMIT(PC++, unescape(*re)); - } else { - EMIT(PC++, *re); } + emit_char_pair: + EMIT(PC++, c); + EMIT(PC++, *re); } EMIT_CHECKED(term + 1, cnt); break; @@ -255,6 +254,7 @@ int re1_5_compilecode(ByteProg *prog, const char *re) return 0; } +// CIRCUITPY debug as main program #if defined(DEBUG_COMPILECODE) #include void re1_5_fatal(char *x) { diff --git a/lib/re1.5/re1.5.h b/lib/re1.5/re1.5.h index 43a0416160..68ec27e389 100644 --- a/lib/re1.5/re1.5.h +++ b/lib/re1.5/re1.5.h @@ -140,6 +140,7 @@ struct Subject { #define NON_ANCHORED_PREFIX 5 #define HANDLE_ANCHORED(bytecode, is_anchored) ((is_anchored) ? (bytecode) + NON_ANCHORED_PREFIX : (bytecode)) +#define RE15_CLASS_NAMED_CLASS_INDICATOR 0 int re1_5_backtrack(ByteProg*, Subject*, const char**, int, int); int re1_5_pikevm(ByteProg*, Subject*, const char**, int, int); diff --git a/locale/ID.po b/locale/ID.po index 2a218084b9..299a4c53fc 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -142,7 +142,7 @@ msgstr "" msgid "%q in use" msgstr "%q sedang digunakan" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "%q indeks di luar batas" @@ -229,7 +229,7 @@ msgstr "" msgid "%q must be of type %q or %q, not %q" msgstr "" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -282,6 +282,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -633,7 +638,7 @@ msgid "Below minimum frame rate" msgstr "Di bawah frame rate minimum" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -1110,8 +1115,6 @@ msgstr "" msgid "Generic Failure" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1980,10 +1983,6 @@ msgstr "Buffer sumber dan tujuan harus memiliki panjang yang sama" msgid "Specify exactly one of data0 or data_pins" msgstr "" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "Memisahkan dengan menggunakan sub-captures" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "" @@ -2422,7 +2421,8 @@ msgid "__init__() should return None" msgstr "__init __() harus mengembalikan None" #: py/objtype.c -msgid "__init__() should return None, not '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" msgstr "" #: py/objobject.c @@ -2512,8 +2512,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "berusaha mendapatkan argmin/argmax dari urutan kosong" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "atribut belum didukung" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2640,7 +2640,7 @@ msgstr "tidak dapat menetapkan ke ekspresi" msgid "can't cancel self" msgstr "" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2658,10 +2658,18 @@ msgstr "" msgid "can't convert '%q' object to %q implicitly" msgstr "" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "" + #: py/obj.c msgid "can't convert to complex" msgstr "" @@ -2690,14 +2698,14 @@ msgstr "tidak bisa menghapus ekspresi" msgid "can't do binary op between '%q' and '%q'" msgstr "" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "" @@ -2748,6 +2756,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2780,18 +2796,10 @@ msgstr "" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" - #: py/emitnative.c msgid "casting" msgstr "" @@ -2840,6 +2848,10 @@ msgstr "" msgid "comparison of int and uint" msgstr "" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "" @@ -3412,8 +3424,8 @@ msgid "join expects a list of str/bytes objects consistent with self object" msgstr "" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" -msgstr "argumen keyword belum diimplementasi - gunakan args normal" +msgid "keyword argument(s) not implemented - use normal args instead" +msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3423,10 +3435,6 @@ msgstr "" msgid "label redefined" msgstr "label didefinis ulang" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "" @@ -3513,6 +3521,10 @@ msgstr "" msgid "memory allocation failed, heap is locked" msgstr "" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3561,6 +3573,10 @@ msgstr "" msgid "name not defined" msgstr "" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3635,7 +3651,7 @@ msgstr "" msgid "non-default argument follows default argument" msgstr "argumen non-default mengikuti argumen standar(default)" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "digit non-hex ditemukan" @@ -3725,7 +3741,7 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "panjang data string memiliki keganjilan (odd-length)" @@ -3745,11 +3761,6 @@ msgstr "" msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -#, fuzzy -msgid "offset out of bounds" -msgstr "modul tidak ditemukan" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -3998,10 +4009,6 @@ msgstr "" msgid "sleep length must be non-negative" msgstr "" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4046,6 +4053,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" @@ -4058,8 +4069,17 @@ msgstr "" msgid "stream operation not supported" msgstr "" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" msgstr "" #: extmod/moductypes.c @@ -4090,6 +4110,10 @@ msgstr "sintaksis error pada JSON" msgid "syntax error in uctypes descriptor" msgstr "sintaksis error pada pendeskripsi uctypes" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "" @@ -4363,6 +4387,19 @@ msgstr "zi harus berjenis float" msgid "zi must be of shape (n_section, 2)" msgstr "Zi harus berbentuk (n_section, 2)" +#~ msgid "Splitting with sub-captures" +#~ msgstr "Memisahkan dengan menggunakan sub-captures" + +#~ msgid "attributes not supported yet" +#~ msgstr "atribut belum didukung" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "argumen keyword belum diimplementasi - gunakan args normal" + +#, fuzzy +#~ msgid "offset out of bounds" +#~ msgstr "modul tidak ditemukan" + #~ msgid "ADC2 is being used by WiFi" #~ msgstr "ADC2 sedang digunakan oleh WiFi" diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index d2ec2e2f6c..24d0fc6be8 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -139,7 +139,7 @@ msgstr "" msgid "%q in use" msgstr "" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "" @@ -226,7 +226,7 @@ msgstr "" msgid "%q must be of type %q or %q, not %q" msgstr "" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -279,6 +279,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -628,7 +633,7 @@ msgid "Below minimum frame rate" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -1100,8 +1105,6 @@ msgstr "" msgid "Generic Failure" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1956,10 +1959,6 @@ msgstr "" msgid "Specify exactly one of data0 or data_pins" msgstr "" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "" @@ -2396,7 +2395,8 @@ msgid "__init__() should return None" msgstr "" #: py/objtype.c -msgid "__init__() should return None, not '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" msgstr "" #: py/objobject.c @@ -2486,7 +2486,7 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "" #: py/objstr.c -msgid "attributes not supported yet" +msgid "attributes not supported" msgstr "" #: extmod/ulab/code/ulab_tools.c @@ -2614,7 +2614,7 @@ msgstr "" msgid "can't cancel self" msgstr "" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2632,10 +2632,18 @@ msgstr "" msgid "can't convert '%q' object to %q implicitly" msgstr "" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "" + #: py/obj.c msgid "can't convert to complex" msgstr "" @@ -2664,14 +2672,14 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "" @@ -2722,6 +2730,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2754,18 +2770,10 @@ msgstr "" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" - #: py/emitnative.c msgid "casting" msgstr "" @@ -2814,6 +2822,10 @@ msgstr "" msgid "comparison of int and uint" msgstr "" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "" @@ -3386,7 +3398,7 @@ msgid "join expects a list of str/bytes objects consistent with self object" msgstr "" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -3397,10 +3409,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "" @@ -3487,6 +3495,10 @@ msgstr "" msgid "memory allocation failed, heap is locked" msgstr "" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3535,6 +3547,10 @@ msgstr "" msgid "name not defined" msgstr "" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3609,7 +3625,7 @@ msgstr "" msgid "non-default argument follows default argument" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "" @@ -3699,7 +3715,7 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "" @@ -3719,10 +3735,6 @@ msgstr "" msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -3971,10 +3983,6 @@ msgstr "" msgid "sleep length must be non-negative" msgstr "" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4019,6 +4027,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" @@ -4031,8 +4043,17 @@ msgstr "" msgid "stream operation not supported" msgstr "" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" msgstr "" #: extmod/moductypes.c @@ -4063,6 +4084,10 @@ msgstr "" msgid "syntax error in uctypes descriptor" msgstr "" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "" diff --git a/locale/cs.po b/locale/cs.po index 74dd9ad140..750331d20c 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-10-03 15:21+0000\n" +"PO-Revision-Date: 2023-10-13 20:08+0000\n" "Last-Translator: Vladimír Smitka \n" "Language-Team: LANGUAGE \n" "Language: cs\n" @@ -150,7 +150,7 @@ msgstr "%q v %q musí být typu %q, ne %q" msgid "%q in use" msgstr "%q se právÄ› používá" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "Index %q je mimo rozsah" @@ -216,7 +216,6 @@ msgid "%q must be >= %d" msgstr "%q musí být >= %d" #: shared-bindings/analogbufio/BufferedIn.c -#, fuzzy msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "%q musí být bytearray nebo pole typu 'H' nebo 'B'" @@ -238,7 +237,7 @@ msgstr "%q musí být pole typu 'h'" msgid "%q must be of type %q or %q, not %q" msgstr "%q musí být typu %q nebo %q, ne %q" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q musí být typu %q, ne %q" @@ -265,7 +264,7 @@ msgstr "%q krok nemůže být nula" #: py/bc.c py/objnamedtuple.c msgid "%q() takes %d positional arguments but %d were given" -msgstr "%q() vyžaduje %d poziÄních argumentů, ale %d jich bylo zadáno" +msgstr "%q() vyžaduje %d poziÄních argumentů, ale pouze %d jich bylo zadáno" #: shared-bindings/usb_hid/Device.c msgid "%q, %q, and %q must all be the same length" @@ -289,6 +288,11 @@ msgstr "%q[%u] používá extra pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "%q[%u] waits on input outside of count" +msgstr "%q[%u] Äeká na vstup mimo rozsah" + +#: py/runtime.c +#, c-format +msgid "%s" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c @@ -319,7 +323,7 @@ msgstr "Objekt '%q' není iterovatelný" #: py/emitinlinethumb.c py/emitinlinextensa.c #, c-format msgid "'%s' expects a label" -msgstr "'%s' oÄekává popisek" +msgstr "'%s' oÄekává label" #: py/emitinlinethumb.c py/emitinlinextensa.c #, c-format @@ -349,7 +353,7 @@ msgstr "'%s' oÄekává integer (celé Äíslo)" #: py/emitinlinethumb.c #, c-format msgid "'%s' expects at most r%d" -msgstr "'%s' oÄekává nejvíce r%d" +msgstr "'%s' oÄekává nanejvýš r%d" #: py/emitinlinethumb.c #, c-format @@ -387,7 +391,7 @@ msgstr "'%s' objekt není vložitelný" #: py/objstr.c msgid "'=' alignment not allowed in string format specifier" -msgstr "" +msgstr "Specifikátor zarovnání '=' není ve formátovacím Å™etÄ›zci povolen" #: shared-module/struct/__init__.c msgid "'S' and 'O' are not supported format types" @@ -407,11 +411,11 @@ msgstr "'await', 'async for' nebo 'async' je volán mimo async" #: py/compile.c msgid "'break' outside loop" -msgstr "'break' je volán vnÄ› cyklu" +msgstr "'break' je volán mimo cyklus" #: py/compile.c msgid "'continue' outside loop" -msgstr "'continue' je volán vnÄ› cyklu" +msgstr "'continue' je volán mimo cyklus" #: py/compile.c msgid "'data' requires at least 2 arguments" @@ -439,11 +443,11 @@ msgstr "'yield' je volán mimo funkci" #: py/compile.c msgid "* arg after **" -msgstr "" +msgstr "* arg po **" #: py/compile.c msgid "*x must be assignment target" -msgstr "" +msgstr "∗x musí být cíl pÅ™iÅ™azení" #: py/obj.c msgid ", in %q\n" @@ -451,7 +455,7 @@ msgstr ", v% q\n" #: py/objcomplex.c msgid "0.0 to a complex power" -msgstr "" +msgstr "0.0 na komplexní mocninu" #: py/modbuiltins.c msgid "3-arg pow() not supported" @@ -480,7 +484,7 @@ msgstr "Adresní rozsah není povolen" #: shared-bindings/memorymap/AddressRange.c msgid "Address range wraps around" -msgstr "" +msgstr "Adresní rozsah se pÅ™eklápí pÅ™es maximální možnou adresu" #: ports/espressif/common-hal/canio/CAN.c msgid "All CAN peripherals are in use" @@ -557,7 +561,7 @@ msgstr "VÅ¡echny ÄasovaÄe pro tento pin jsou používány" #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c #: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" -msgstr "VÅ¡echny ÄasovaÄe jsou použity" +msgstr "VÅ¡echny ÄasovaÄe jsou používány" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nrf/common-hal/_bleio/Adapter.c @@ -566,7 +570,7 @@ msgstr "Již propagujeme." #: ports/atmel-samd/common-hal/canio/Listener.c msgid "Already have all-matches listener" -msgstr "" +msgstr "Již existuje posluchaÄ pro vÅ¡echny zprávy" #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c @@ -583,7 +587,7 @@ msgstr "Již skenuje wifi sítÄ›" #: shared-module/os/getenv.c #, c-format msgid "An error occurred while retrieving '%s':\n" -msgstr "" +msgstr "DoÅ¡lo k chybÄ› pÅ™i naÄítání '%s'\n" #: ports/stm/common-hal/audiopwmio/PWMAudioOut.c msgid "Another PWMAudioOut is already active" @@ -642,8 +646,8 @@ msgid "Below minimum frame rate" msgstr "Pod minimální obnovovací frekvencí" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" -msgstr "Bitové hodiny a výbÄ›r slov musí být sekvenÄní piny" +msgid "Bit clock and word select must be sequential GPIO pins" +msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -658,7 +662,6 @@ msgid "Bitmap size and bits per value must match" msgstr "Velikost bitmapy a poÄet bitů na hodnotu se musí shodovat" #: supervisor/shared/safe_mode.c -#, fuzzy msgid "Boot device must be first (interface #0)." msgstr "Bootovací zařízení musí být první (rozhraní #0)." @@ -727,7 +730,7 @@ msgstr "SbÄ›rnicový pin %d je již používán" #: shared-bindings/_bleio/UUID.c msgid "Byte buffer must be 16 bytes." -msgstr "Bajtový buffer musí být 16 bajtů." +msgstr "Buffer musí být dlouhý 16 bajtů." #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" @@ -751,15 +754,18 @@ msgstr "Inizializace kamery" #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Can only alarm on RTC IO from deep sleep." -msgstr "" +msgstr "Alarm z IO RTC je možné generovat pouze z hlubokého spánku." #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Can only alarm on one low pin while others alarm high from deep sleep." msgstr "" +"Lze nastavit alarm na jednom pinu ve stavu low pÅ™i hlubokém spánku, ostatní " +"musí být ve stavu high." #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Can only alarm on two low pins from deep sleep." msgstr "" +"Lze nastavit alarm na maximálnÄ› dvou pinech ve stavu low pÅ™i hlubokém spánku." #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -790,7 +796,7 @@ msgstr "Nelze získat ve výstupním režimu" #: ports/nrf/common-hal/microcontroller/Processor.c msgid "Cannot get temperature" -msgstr "Nelze získat teplotu" +msgstr "Nelze získat teplotu (°C)" #: shared-bindings/_bleio/Adapter.c msgid "Cannot have scan responses for extended, connectable advertisements." @@ -798,7 +804,7 @@ msgstr "" #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Cannot pull on input-only pin." -msgstr "" +msgstr "Nelze aktivovat pull rezistor na pinu, který je pouze pro vstup." #: shared-bindings/audiobusio/PDMIn.c msgid "Cannot record to a file" @@ -869,7 +875,7 @@ msgstr "" #: shared-bindings/bitmaptools/__init__.c msgid "Coordinate arrays have different lengths" -msgstr "" +msgstr "Pole souÅ™adnic mají různé délky" #: shared-bindings/bitmaptools/__init__.c msgid "Coordinate arrays types have different sizes" @@ -919,7 +925,7 @@ msgstr "Datový blok musí následovat fmt blok" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data not supported with directed advertising" -msgstr "" +msgstr "Data nejsou podporována s cíleným oznamováním" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nrf/common-hal/_bleio/Adapter.c @@ -929,6 +935,7 @@ msgstr "Data jsou příliÅ¡ velká pro propagovaný paket" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Deep sleep pins must use a rising edge with pulldown" msgstr "" +"Piny pro hluboký spánek musí používat náběžnou hranu s pulldown rezistorem" #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." @@ -968,7 +975,7 @@ msgstr "ECB operuje najednou pouze 16 bajtů" #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c msgid "ESP-IDF memory allocation failed" -msgstr "" +msgstr "ESP-IDF alokace pamÄ›ti selhala" #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/ps2io/Ps2.c @@ -983,15 +990,15 @@ msgstr "Chyba v regulárním výrazu" #: supervisor/shared/safe_mode.c msgid "Error in safemode.py." -msgstr "" +msgstr "Chyba v safemode.py." #: shared-bindings/socketpool/Socket.c shared-bindings/ssl/SSLSocket.c msgid "Error: Failure to bind" -msgstr "" +msgstr "Chyba: nepodaÅ™ilo se nabindovat port" #: shared-bindings/alarm/__init__.c msgid "Expected a kind of %q" -msgstr "" +msgstr "OÄekáván typ %q" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nrf/common-hal/_bleio/Adapter.c @@ -1000,7 +1007,7 @@ msgstr "" #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "FFT is defined for ndarrays only" -msgstr "" +msgstr "FFT lze použít pouze pro ndarrays" #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "FFT is implemented for linear arrays only" @@ -1008,7 +1015,7 @@ msgstr "FFT je implementován pouze pro lineární pole" #: ports/espressif/common-hal/ssl/SSLSocket.c msgid "Failed SSL handshake" -msgstr "" +msgstr "SSL handshake selhal" #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." @@ -1017,7 +1024,7 @@ msgstr "NepodaÅ™ilo se odeslat příkaz." #: ports/nrf/sd_mutex.c #, c-format msgid "Failed to acquire mutex, err 0x%04x" -msgstr "" +msgstr "NepodaÅ™ilo se získat mutex, err 0x%04x" #: shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" @@ -1029,11 +1036,11 @@ msgstr "Chyba alokace pamÄ›ti WiFi" #: ports/espressif/common-hal/wifi/ScannedNetworks.c msgid "Failed to allocate wifi scan memory" -msgstr "" +msgstr "NepodaÅ™ilo se alokovat paměť pro wifi scan" #: ports/stm/common-hal/audiopwmio/PWMAudioOut.c msgid "Failed to buffer the sample" -msgstr "" +msgstr "NepodaÅ™ilo se nabufferovat sample" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nrf/common-hal/_bleio/Adapter.c @@ -1051,7 +1058,7 @@ msgstr "Soubor MP3 se nepodaÅ™ilo analyzovat" #: ports/nrf/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" -msgstr "" +msgstr "NepodaÅ™ilo se uvolnit mutex, err 0x%04x" #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." @@ -1063,33 +1070,33 @@ msgstr "soubor existuje" #: shared-module/os/getenv.c msgid "File not found" -msgstr "" +msgstr "Soubor nenalezen" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" -msgstr "" +msgstr "Filtry jsou příliÅ¡ komplexní" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is duplicate" -msgstr "" +msgstr "Firmware je duplicitní" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is invalid" -msgstr "" +msgstr "Firmware není validní" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is too big" -msgstr "" +msgstr "Firmware je příliÅ¡ velký" #: shared-bindings/bitmaptools/__init__.c msgid "For L8 colorspace, input bitmap must have 8 bits per pixel" -msgstr "" +msgstr "Pro barevný prostor L8 musí mít vstupní bitmapa 8 bitů na pixel" #: shared-bindings/bitmaptools/__init__.c msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" -msgstr "" +msgstr "Pro barevný prostor RGB musí mít vstupní bitmapa 16 bitů na pixel" #: ports/cxd56/common-hal/camera/Camera.c msgid "Format not supported" @@ -1119,8 +1126,6 @@ msgstr "Inicializace GNSS" msgid "Generic Failure" msgstr "Základní chyba" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1132,11 +1137,11 @@ msgstr "Skupina již byla použita" #: ports/mimxrt10xx/common-hal/busio/SPI.c ports/nrf/common-hal/busio/SPI.c #: ports/raspberrypi/common-hal/busio/SPI.c msgid "Half duplex SPI is not implemented" -msgstr "" +msgstr "Poloduplexní SPI není implementované" #: supervisor/shared/safe_mode.c msgid "Hard fault: memory access or instruction error." -msgstr "" +msgstr "Fatální chyba: přístup k pamÄ›ti nebo chyba instrukce." #: ports/mimxrt10xx/common-hal/busio/SPI.c #: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/I2C.c @@ -1147,16 +1152,17 @@ msgstr "Hardware je používán, zkuste alternativní piny" #: supervisor/shared/safe_mode.c msgid "Heap allocation when VM not running." -msgstr "" +msgstr "Alokace heapu pÅ™i neběžícím VM." #: supervisor/shared/safe_mode.c msgid "" "Heap was corrupted because the stack was too small. Increase stack size." msgstr "" +"Heap byl poÅ¡kozen, protože je stack příliÅ¡ malý. NavyÅ¡ velikost stacku." #: extmod/vfs_posix_file.c py/objstringio.c msgid "I/O operation on closed file" -msgstr "" +msgstr "I/O operace nad zavÅ™eným souborem" #: ports/stm/common-hal/busio/I2C.c msgid "I2C init error" @@ -1169,7 +1175,7 @@ msgstr "Periférie I2C je používána" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "In-buffer elements must be <= 4 bytes long" -msgstr "" +msgstr "Elementy v bufferu musí být <= 4 bajty" #: shared-bindings/_pew/PewPew.c msgid "Incorrect buffer size" @@ -1177,7 +1183,7 @@ msgstr "Nesprávná velikost vyrovnávací pamÄ›ti" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Init program size invalid" -msgstr "" +msgstr "Velikost init programu není správná" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Initial set pin direction conflicts with initial out pin direction" @@ -1198,7 +1204,7 @@ msgstr "Vstup trval příliÅ¡ dlouho" #: ports/espressif/common-hal/neopixel_write/__init__.c py/moduerrno.c msgid "Input/output error" -msgstr "VstupnÄ›/výstupní chyba" +msgstr "Chyba vstupu/výstupu" #: ports/nrf/common-hal/_bleio/__init__.c msgid "Insufficient authentication" @@ -1210,11 +1216,11 @@ msgstr "NedostateÄné Å¡ifrování" #: ports/espressif/common-hal/wifi/Radio.c msgid "Interface must be started" -msgstr "" +msgstr "Rozhraní musí být nastartováno" #: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c msgid "Internal audio buffer too small" -msgstr "" +msgstr "Interní audio buffer je příliÅ¡ malý" #: ports/stm/common-hal/busio/UART.c msgid "Internal define error" @@ -1232,11 +1238,11 @@ msgstr "VnitÅ™ní chyba #%d" #: supervisor/shared/safe_mode.c msgid "Internal watchdog timer expired." -msgstr "" +msgstr "Interní watchdog timer expiroval." #: supervisor/shared/safe_mode.c msgid "Interrupt error." -msgstr "" +msgstr "Chyba pÅ™eruÅ¡ení." #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c @@ -1245,7 +1251,7 @@ msgstr "" #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" -msgstr "" +msgstr "Å patný %s" #: ports/atmel-samd/common-hal/microcontroller/Pin.c #: ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c @@ -1269,7 +1275,7 @@ msgstr "Chybné BSSID" #: main.c msgid "Invalid CIRCUITPY_PYSTACK_SIZE\n" -msgstr "" +msgstr "Å patný CIRCUITPY_PYSTACK_SIZE\n" #: shared-bindings/wifi/Radio.c msgid "Invalid MAC address" @@ -1286,7 +1292,7 @@ msgstr "" #: shared-module/os/getenv.c #, c-format msgid "Invalid byte %.*s" -msgstr "" +msgstr "Å patný byte %.*s" #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format @@ -1295,7 +1301,7 @@ msgstr "Chybný data_pin[%d]" #: shared-module/msgpack/__init__.c msgid "Invalid format" -msgstr "" +msgstr "Å patný formát" #: shared-module/audiocore/WaveFile.c msgid "Invalid format chunk size" @@ -1303,7 +1309,7 @@ msgstr "Neplatná velikost bloku" #: shared-bindings/wifi/Radio.c msgid "Invalid hex password" -msgstr "" +msgstr "Å patné heslo v hex" #: ports/espressif/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" @@ -1324,7 +1330,7 @@ msgstr "Chybný stav" #: shared-module/os/getenv.c msgid "Invalid unicode escape" -msgstr "" +msgstr "Neplatná unicode escape sekvence" #: shared-bindings/aesio/aes.c msgid "Key must be 16, 24, or 32 bytes long" @@ -1332,7 +1338,7 @@ msgstr "KlÃ­Ä musí být dlouhý 16, 24 nebo 32 bajtů" #: shared-module/os/getenv.c msgid "Key not found" -msgstr "" +msgstr "KlÃ­Ä nenalezen" #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" @@ -1344,11 +1350,11 @@ msgstr "" #: shared-module/displayio/Group.c msgid "Layer already in a group" -msgstr "" +msgstr "Vrstva již v groupÄ› je" #: shared-module/displayio/Group.c msgid "Layer must be a Group or TileGrid subclass" -msgstr "" +msgstr "Vrstva musí být Group nebo TileGrid" #: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" @@ -1365,39 +1371,39 @@ msgstr "" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" -msgstr "" +msgstr "Nekorespondující velikost dat" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched swap flag" -msgstr "" +msgstr "Nekorespondující swap flag" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_in_pin. %q[%u] reads pin(s)" -msgstr "" +msgstr "Chybí first_in_pin. %q[%u] Äte z pinu(ů)" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_in_pin. %q[%u] shifts in from pin(s)" -msgstr "" +msgstr "Chybí first_in_pin. %q[%u] posunuje z pinu(ů)" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_in_pin. %q[%u] waits based on pin" -msgstr "" +msgstr "Chybí first_in_pin. %q[%u] Äeká na základÄ› pinu" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_out_pin. %q[%u] shifts out to pin(s)" -msgstr "" +msgstr "Chybí first_out_pin. %q[%u] posunuje do pinu(ů)" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_out_pin. %q[%u] writes pin(s)" -msgstr "" +msgstr "Chybí first_out_pin. %q[%u] zapisuje do pinu(ů)" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_set_pin. %q[%u] sets pin(s)" -msgstr "" +msgstr "Chybí first_set_pin. %q[%u] nastavuje pin(y)" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing jmp_pin. %q[%u] jumps on pin" -msgstr "" +msgstr "Chybí jmp_pin. %q[%u] skáÄe na pin" #: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c msgid "Must be a %q subclass." @@ -1405,7 +1411,7 @@ msgstr "Musí být podtřída %q." #: ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c msgid "Must provide 5/6/5 RGB pins" -msgstr "" +msgstr "Je tÅ™eba poskytnout 5/6/5 RGB piny" #: ports/mimxrt10xx/common-hal/busio/SPI.c shared-bindings/busio/SPI.c msgid "Must provide MISO or MOSI pin" @@ -1418,7 +1424,7 @@ msgstr "Je nutné použít nÄ›kolik kolíků 6 rgb, nikoli %d" #: supervisor/shared/safe_mode.c msgid "NLR jump failed. Likely memory corruption." -msgstr "" +msgstr "NLR skok selhal. PravdÄ›podobnÄ› poÅ¡kozením pamÄ›ti." #: ports/espressif/common-hal/nvm/ByteArray.c msgid "NVS Error" @@ -1426,7 +1432,7 @@ msgstr "Chyba NVS" #: shared-bindings/socketpool/SocketPool.c msgid "Name or service not known" -msgstr "" +msgstr "Jméno nebo služba není známa" #: py/qstr.c msgid "Name too long" @@ -1480,7 +1486,7 @@ msgstr "Žádné I2C zařízení na adrese: 0x%x" #: supervisor/shared/web_workflow/web_workflow.c msgid "No IP" -msgstr "" +msgstr "Není IP" #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c msgid "No available clocks" @@ -1488,11 +1494,11 @@ msgstr "Žádné dostupné hodiny" #: ports/espressif/common-hal/imagecapture/ParallelImageCapture.c msgid "No capture in progress" -msgstr "" +msgstr "Žádné aktivní zachytávání" #: shared-module/usb/core/Device.c msgid "No configuration set" -msgstr "" +msgstr "Konfigurace není nastavena" #: shared-bindings/_bleio/PacketBuffer.c msgid "No connection: length cannot be determined" @@ -1512,15 +1518,15 @@ msgstr "" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in in program" -msgstr "" +msgstr "V programu není vstup" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in or out in program" -msgstr "" +msgstr "V programu není vstup nebo výstup" #: py/objint.c shared-bindings/time/__init__.c msgid "No long integer support" -msgstr "" +msgstr "Není podpora long integer" #: shared-bindings/wifi/Radio.c msgid "No network with that ssid" @@ -1528,14 +1534,14 @@ msgstr "Žádná síť s takovým SSID" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No out in program" -msgstr "" +msgstr "V programu není výstup" #: ports/atmel-samd/common-hal/busio/I2C.c #: ports/espressif/common-hal/busio/I2C.c #: ports/mimxrt10xx/common-hal/busio/I2C.c ports/nrf/common-hal/busio/I2C.c #: ports/raspberrypi/common-hal/busio/I2C.c msgid "No pull up found on SDA or SCL; check your wiring" -msgstr "" +msgstr "SDA nebo SCL zÅ™ejmÄ› nemá pull up; zkontroluj zapojení" #: shared-module/touchio/TouchIn.c msgid "No pulldown on pin; 1Mohm recommended" @@ -1559,11 +1565,11 @@ msgstr "Není k dispozici žádný ÄasovaÄ" #: shared-module/usb/core/Device.c msgid "No usb host port initialized" -msgstr "" +msgstr "Žádný USB host port není inicializován" #: ports/nrf/common-hal/_bleio/__init__.c msgid "Nordic system firmware out of memory" -msgstr "" +msgstr "Nordic system firmware - nedostatek pamÄ›ti" #: shared-bindings/ipaddress/IPv4Address.c shared-bindings/ipaddress/__init__.c msgid "Not a valid IP string" @@ -1597,11 +1603,11 @@ msgstr "" #: supervisor/shared/bluetooth/bluetooth.c msgid "Off" -msgstr "" +msgstr "Vypnuto" #: supervisor/shared/bluetooth/bluetooth.c msgid "Ok" -msgstr "" +msgstr "Ok" #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c @@ -1630,11 +1636,11 @@ msgstr "" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Only edge detection is available on this hardware" -msgstr "" +msgstr "Na tomto hardware je dostupná pouze detekce hrany" #: shared-bindings/ipaddress/__init__.c msgid "Only int or string supported for ip" -msgstr "" +msgstr "Pro IP je podporován pouze int nebo string" #: shared-module/displayio/OnDiskBitmap.c #, c-format @@ -1642,59 +1648,61 @@ msgid "" "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " "%d bpp given" msgstr "" +"Podporovány jsou pouze Äernobílé, indexované 4 bpp nebo 8 bpp a 16 bpp nebo " +"vyšší BMP: bitmapa má %d bpp" #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." -msgstr "" +msgstr "Pouze jeden %q lze nastavit v hlubokém spánku." #: ports/espressif/common-hal/espulp/ULPAlarm.c msgid "Only one %q can be set." -msgstr "" +msgstr "Lze nastavit pouze jeden %q ." #: ports/espressif/common-hal/i2ctarget/I2CTarget.c #: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c msgid "Only one address is allowed" -msgstr "" +msgstr "Je povolena pouze jedna adresa" #: ports/atmel-samd/common-hal/alarm/time/TimeAlarm.c #: ports/nrf/common-hal/alarm/time/TimeAlarm.c #: ports/stm/common-hal/alarm/time/TimeAlarm.c msgid "Only one alarm.time alarm can be set" -msgstr "" +msgstr "Lze nastavit pouze jeden alarm typu alarm.time" #: ports/espressif/common-hal/alarm/time/TimeAlarm.c #: ports/raspberrypi/common-hal/alarm/time/TimeAlarm.c msgid "Only one alarm.time alarm can be set." -msgstr "" +msgstr "Může být nastaven pouze jeden alarm typu alarm.time." #: shared-module/displayio/ColorConverter.c msgid "Only one color can be transparent at a time" -msgstr "" +msgstr "Pouze jedna barva může být nastavena jako transparentní" #: py/moduerrno.c msgid "Operation not permitted" -msgstr "" +msgstr "Operace není povolena" #: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" -msgstr "" +msgstr "Operace nebo funkce není podporována" #: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" -msgstr "" +msgstr "ÄŒasový limit operace vyprÅ¡el" #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Out of MDNS service slots" -msgstr "" +msgstr "DoÅ¡ly mDNS sloty" #: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" -msgstr "" +msgstr "DoÅ¡la paměť" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c msgid "Out of sockets" -msgstr "" +msgstr "DoÅ¡ly sockety" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Out-buffer elements must be <= 4 bytes long" @@ -1711,44 +1719,44 @@ msgstr "" #: ports/stm/common-hal/pwmio/PWMOut.c msgid "PWM restart" -msgstr "" +msgstr "Restart PWM" #: ports/raspberrypi/common-hal/countio/Counter.c msgid "PWM slice already in use" -msgstr "" +msgstr "PWM kanál je již využíván" #: ports/raspberrypi/common-hal/countio/Counter.c msgid "PWM slice channel A already in use" -msgstr "" +msgstr "PWM kanál A je již využíván" #: ports/espressif/common-hal/audiobusio/__init__.c msgid "Peripheral in use" -msgstr "" +msgstr "Periférie je používána" #: py/moduerrno.c msgid "Permission denied" -msgstr "" +msgstr "Přístup odepÅ™en" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Pin cannot wake from Deep Sleep" -msgstr "" +msgstr "Z Deep Sleep nelze probudit pinem" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Pin count too large" -msgstr "" +msgstr "PoÄet pinů je příliÅ¡ velký" #: ports/stm/common-hal/alarm/pin/PinAlarm.c #: ports/stm/common-hal/pulseio/PulseIn.c msgid "Pin interrupt already in use" -msgstr "" +msgstr "PÅ™eruÅ¡ení od pinu je již používáno" #: shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c msgid "Pin is input only" -msgstr "" +msgstr "Pin je pouze vstupní" #: ports/raspberrypi/common-hal/countio/Counter.c msgid "Pin must be on PWM Channel B" -msgstr "" +msgstr "Pin musí být na PWM kanálu B" #: ports/atmel-samd/common-hal/countio/Counter.c msgid "Pin must support hardware interrupts" @@ -1780,15 +1788,15 @@ msgstr "" #: py/builtinhelp.c msgid "Plus any modules on the filesystem\n" -msgstr "" +msgstr "Plus vÅ¡echny moduly na filesystému\n" #: shared-module/vectorio/Polygon.c msgid "Polygon needs at least 3 points" -msgstr "" +msgstr "Polygon potÅ™ebuje nejménÄ› 3 body" #: supervisor/shared/safe_mode.c msgid "Power dipped. Make sure you are providing enough power." -msgstr "" +msgstr "Pokles napájení. Zkontroluj, zda je k dispozici dostateÄné napájení." #: shared-bindings/_bleio/Adapter.c msgid "Prefix buffer must be on the heap" @@ -1806,19 +1814,19 @@ msgstr "PÅ™edstírám hluboký spánek do alarmu, CTRL-C nebo zápisu souboru.\n #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Program does IN without loading ISR" -msgstr "" +msgstr "Program provedl IN bez naÄtení ISR" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Program does OUT without loading OSR" -msgstr "" +msgstr "Program provedl OUT bez naÄtení OSR" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Program size invalid" -msgstr "" +msgstr "Velikost programu je nesprávná" #: ports/espressif/common-hal/espulp/ULP.c msgid "Program too long" -msgstr "" +msgstr "Program je příliÅ¡ dlouhý" #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." @@ -1826,7 +1834,7 @@ msgstr "" #: ports/raspberrypi/common-hal/countio/Counter.c msgid "RISE_AND_FALL not available on this chip" -msgstr "" +msgstr "RISE_AND_FALL není na tomto Äipu k dispozici" #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" @@ -1839,7 +1847,7 @@ msgstr "" #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nrf/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" -msgstr "" +msgstr "RS485" #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -1848,88 +1856,88 @@ msgstr "" #: shared-bindings/alarm/time/TimeAlarm.c shared-bindings/time/__init__.c msgid "RTC is not supported on this board" -msgstr "" +msgstr "RTC není na této desce podporován" #: ports/stm/common-hal/os/__init__.c msgid "Random number generation error" -msgstr "" +msgstr "Chyba generování náhodných Äísel" #: shared-bindings/_bleio/__init__.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c shared-module/bitmaptools/__init__.c #: shared-module/displayio/Bitmap.c msgid "Read-only" -msgstr "" +msgstr "Pouze pro Ätení" #: extmod/vfs_fat.c py/moduerrno.c msgid "Read-only filesystem" -msgstr "" +msgstr "Filesystém pouze pro Ätení" #: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" -msgstr "" +msgstr "PÅ™ijatá odpovÄ›Ä nebyla validní" #: supervisor/shared/bluetooth/bluetooth.c msgid "Reconnecting" -msgstr "" +msgstr "OpÄ›tovné pÅ™ipojování" #: shared-bindings/displayio/EPaperDisplay.c msgid "Refresh too soon" -msgstr "" +msgstr "Pokus o obnovení příliÅ¡ brzo" #: shared-bindings/canio/RemoteTransmissionRequest.c msgid "RemoteTransmissionRequests limited to 8 bytes" -msgstr "" +msgstr "RemoteTransmissionRequests je limitován na 8 bajtů" #: shared-bindings/aesio/aes.c msgid "Requested AES mode is unsupported" -msgstr "" +msgstr "Požadovaný režim AES je nepodporovaný" #: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" -msgstr "" +msgstr "Požadovaný zdroj nebyl nalezen" #: ports/atmel-samd/common-hal/audioio/AudioOut.c msgid "Right channel unsupported" -msgstr "" +msgstr "Pravý kanál nepodporován" #: main.c msgid "Running in safe mode! Not running saved code.\n" -msgstr "" +msgstr "BÄ›h v nouzovém režimu! Uložený kód není zpracováván.\n" #: shared-module/sdcardio/SDCard.c msgid "SD card CSD format not supported" -msgstr "" +msgstr "CSD formát SD karty není podporován" #: ports/cxd56/common-hal/sdioio/SDCard.c msgid "SDCard init" -msgstr "" +msgstr "Inicializace SD karty" #: ports/stm/common-hal/sdioio/SDCard.c #, c-format msgid "SDIO GetCardInfo Error %d" -msgstr "" +msgstr "SDIO GetCardInfo chyba %d" #: ports/stm/common-hal/sdioio/SDCard.c #, c-format msgid "SDIO Init Error %d" -msgstr "" +msgstr "Inicializace SDIO chyba %d" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" -msgstr "" +msgstr "Konfigurace SPI selhala" #: ports/stm/common-hal/busio/SPI.c msgid "SPI init error" -msgstr "" +msgstr "Chyba inicializace SPI" #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" -msgstr "" +msgstr "SPI periferie je používána" #: ports/stm/common-hal/busio/SPI.c msgid "SPI re-init" -msgstr "" +msgstr "OpÄ›tovná inicializace SPI" #: shared-bindings/is31fl3741/FrameBuffer.c msgid "Scale dimensions must divide by 3" @@ -1938,7 +1946,7 @@ msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nrf/common-hal/_bleio/Adapter.c msgid "Scan already in progress. Stop with stop_scan." -msgstr "" +msgstr "Scan již probíhá. Lze zastavit pomocí stop_scan." #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -1951,7 +1959,7 @@ msgstr "" #: ports/cxd56/common-hal/camera/Camera.c msgid "Size not supported" -msgstr "" +msgstr "Velikost není podporována" #: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c #: shared-bindings/nvm/ByteArray.c @@ -1968,51 +1976,47 @@ msgstr "" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" -msgstr "" +msgstr "SocketPool je možné použít pouze s wifi.radio" #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" -msgstr "" +msgstr "Zdrojové a cílové buffery musí být stejné délky" #: shared-bindings/paralleldisplay/ParallelBus.c msgid "Specify exactly one of data0 or data_pins" -msgstr "" - -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "" +msgstr "Specifikuj pÅ™esnÄ› jeden z data0 nebo data_pins" #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" -msgstr "" +msgstr "Levý stereo kanál musí být na PWM kanálu A" #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo right must be on PWM channel B" -msgstr "" +msgstr "Pravý stereo kanál musí být na PWM kanálu B" #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" -msgstr "" +msgstr "Musíš definovat monotonic_time nebo epoch_time" #: shared-bindings/gnss/GNSS.c msgid "System entry must be gnss.SatelliteSystem" -msgstr "" +msgstr "Parametr \"system\" musí být gnss.SatelliteSystem" #: ports/stm/common-hal/microcontroller/Processor.c msgid "Temperature read timed out" -msgstr "" +msgstr "ÄŒas pro Ätení teploty vyprÅ¡el" #: supervisor/shared/safe_mode.c msgid "The `microcontroller` module was used to boot into safe mode." -msgstr "" +msgstr "Modul `microcontroller` byl použit pro spuÅ¡tÄ›ní do nouzového režimu." #: py/obj.c msgid "The above exception was the direct cause of the following exception:" -msgstr "" +msgstr "Výše uvedená výjimka byla přímá příÄina následující výjimky:" #: shared-bindings/rgbmatrix/RGBMatrix.c msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" -msgstr "" +msgstr "PoÄet prvků rgb_pin musí být 6, 12, 18, 24, nebo 30" #: shared-module/audiomixer/MixerVoice.c msgid "The sample's bits_per_sample does not match the mixer's" @@ -2032,11 +2036,11 @@ msgstr "" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." -msgstr "" +msgstr "Fatální chyby firmware tÅ™etí strany." #: shared-module/imagecapture/ParallelImageCapture.c msgid "This microcontroller does not support continuous capture." -msgstr "" +msgstr "Tento mikrokontrolér nepodporuje kontinuální snímání." #: shared-module/paralleldisplay/ParallelBus.c msgid "" @@ -2058,17 +2062,17 @@ msgstr "" #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." -msgstr "" +msgstr "ÄŒas je v minulosti." #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Timeout is too long: Maximum timeout length is %d seconds" -msgstr "" +msgstr "ÄŒasový limit je příliÅ¡ dlouhý: maximální limit je %d vteÅ™in" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" -msgstr "" +msgstr "V samplu je příliÅ¡ mnoho kanálů" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample." @@ -2077,21 +2081,22 @@ msgstr "" #: shared-module/displayio/__init__.c msgid "Too many display busses; forgot displayio.release_displays() ?" msgstr "" +"PříliÅ¡ mnoho sbÄ›rnic displaye; nezapomnÄ›l si na displayio.release_displays()?" #: shared-module/displayio/__init__.c msgid "Too many displays" -msgstr "" +msgstr "PříliÅ¡ mnoho displejů" #: ports/espressif/common-hal/_bleio/PacketBuffer.c #: ports/nrf/common-hal/_bleio/PacketBuffer.c msgid "Total data to write is larger than %q" -msgstr "" +msgstr "Velikost dat k zápisu je vÄ›tší než %q" #: ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.c #: ports/raspberrypi/common-hal/alarm/touch/TouchAlarm.c #: ports/stm/common-hal/alarm/touch/TouchAlarm.c msgid "Touch alarms not available" -msgstr "" +msgstr "Touch alarmy nejsou dostupné" #: py/obj.c msgid "Traceback (most recent call last):\n" @@ -2103,60 +2108,60 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c msgid "UART de-init" -msgstr "" +msgstr "De-inicializace UART" #: ports/cxd56/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c #: ports/stm/common-hal/busio/UART.c msgid "UART init" -msgstr "" +msgstr "Inicializace UART" #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" -msgstr "" +msgstr "UART periférie je používána" #: ports/stm/common-hal/busio/UART.c msgid "UART re-init" -msgstr "" +msgstr "OpÄ›tovná inicializace UART" #: ports/stm/common-hal/busio/UART.c msgid "UART write" -msgstr "" +msgstr "Zápis na UART" #: main.c msgid "UID:" -msgstr "" +msgstr "UID:" #: shared-module/usb_hid/Device.c msgid "USB busy" -msgstr "" +msgstr "USB zaneprázdnÄ›no" #: supervisor/shared/safe_mode.c msgid "USB devices need more endpoints than are available." -msgstr "" +msgstr "USB zařízení potÅ™ebují více endpointů než je k dispozici." #: supervisor/shared/safe_mode.c msgid "USB devices specify too many interface names." -msgstr "" +msgstr "USB zařízení používají příliÅ¡ mnoho názvů rozhraní." #: shared-module/usb_hid/Device.c msgid "USB error" -msgstr "" +msgstr "Chyba USB" #: shared-bindings/_bleio/UUID.c msgid "UUID integer value must be 0-0xffff" -msgstr "" +msgstr "UUID integer musí být 0-0xffff" #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" -msgstr "" +msgstr "UUID Å™etÄ›zec neodpovídá 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" #: shared-bindings/_bleio/UUID.c msgid "UUID value is not str, int or byte buffer" -msgstr "" +msgstr "Hodnota UUID není str, int ani byte buffer" #: ports/raspberrypi/common-hal/memorymap/AddressRange.c msgid "Unable to access unaligned IO register" -msgstr "" +msgstr "Nelze pÅ™istupovat k nezarovnanému IO registru" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audioio/AudioOut.c @@ -2167,21 +2172,21 @@ msgstr "" #: supervisor/shared/safe_mode.c msgid "Unable to allocate the heap." -msgstr "" +msgstr "Nelze alokovat heap." #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" -msgstr "" +msgstr "Není možné vytvoÅ™it zámek" #: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c #, c-format msgid "Unable to find I2C Display at %x" -msgstr "" +msgstr "I2C display nenalezen na %x" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Unable to find free GCLK" -msgstr "" +msgstr "Nelze najít volný GCLK" #: py/parse.c msgid "Unable to init parser" @@ -2189,24 +2194,24 @@ msgstr "" #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" -msgstr "" +msgstr "Nelze Äíst data palety barev" #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" -msgstr "" +msgstr "NepodaÅ™ilo se zaÄít mDNS dotaz" #: shared-bindings/nvm/ByteArray.c msgid "Unable to write to nvm." -msgstr "" +msgstr "Není možné zapisovat do nvm." #: ports/raspberrypi/common-hal/memorymap/AddressRange.c msgid "Unable to write to read-only memory" -msgstr "" +msgstr "Není možné zapisovat do pamÄ›ti jen pro Ätení" #: shared-bindings/alarm/SleepMemory.c msgid "Unable to write to sleep_memory." -msgstr "" +msgstr "Nelze zapsat do sleep_memory." #: ports/nrf/common-hal/_bleio/UUID.c msgid "Unexpected nrfx uuid type" @@ -2215,27 +2220,27 @@ msgstr "" #: ports/espressif/common-hal/ssl/SSLSocket.c #, c-format msgid "Unhandled ESP TLS error %d %d %x %d" -msgstr "" +msgstr "NeoÅ¡etÅ™ená chyba ESP TLS: %d %d %x %d" #: ports/espressif/common-hal/_bleio/__init__.c #, c-format msgid "Unknown BLE error at %s:%d: %d" -msgstr "" +msgstr "Neznámá chyba BLE na %s:%d: %d" #: ports/espressif/common-hal/_bleio/__init__.c #, c-format msgid "Unknown BLE error: %d" -msgstr "" +msgstr "Neznámá chyba BLE: %d" #: ports/raspberrypi/common-hal/wifi/__init__.c #, c-format msgid "Unknown error code %d" -msgstr "" +msgstr "Neznámý chybový kód %d" #: shared-bindings/wifi/Radio.c #, c-format msgid "Unknown failure %d" -msgstr "" +msgstr "Neznámé selhání %d" #: ports/nrf/common-hal/_bleio/__init__.c #, c-format @@ -2245,27 +2250,27 @@ msgstr "" #: ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c #: supervisor/shared/safe_mode.c msgid "Unknown reason." -msgstr "" +msgstr "Neznámý důvod." #: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Unknown security error: 0x%04x" -msgstr "" +msgstr "Neznámá bezpeÄnostní chyba: 0x%04x" #: ports/espressif/common-hal/_bleio/__init__.c #, c-format msgid "Unknown system firmware error at %s:%d: %d" -msgstr "" +msgstr "Neznámá chyba firmwaru na %s:%d: %d" #: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Unknown system firmware error: %04x" -msgstr "" +msgstr "Neznámá chyba firmwaru: %04x" #: ports/espressif/common-hal/_bleio/__init__.c #, c-format msgid "Unknown system firmware error: %d" -msgstr "" +msgstr "Neznámá chyba firmwaru: %d" #: shared-bindings/adafruit_pixelbuf/PixelBuf.c #: shared-module/_pixelmap/PixelMap.c @@ -2281,23 +2286,23 @@ msgstr "" #: shared-bindings/bitmaptools/__init__.c msgid "Unsupported colorspace" -msgstr "" +msgstr "Nepodporovaný barevný prostor" #: shared-module/displayio/display_core.c msgid "Unsupported display bus type" -msgstr "" +msgstr "Nepodporovaná sbÄ›rnice dispalye" #: shared-module/audiocore/WaveFile.c msgid "Unsupported format" -msgstr "" +msgstr "Nepodporovaný formát" #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" -msgstr "" +msgstr "Nepodporovaný hash algoritmus" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Update Failed" -msgstr "" +msgstr "Aktualizace selhala" #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/espressif/common-hal/_bleio/Descriptor.c @@ -2315,19 +2320,19 @@ msgstr "" #: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" -msgstr "" +msgstr "Verze byla neplatná" #: ports/stm/common-hal/microcontroller/Processor.c msgid "Voltage read timed out" -msgstr "" +msgstr "ÄŒasový limit Ätení napÄ›tí vyprÅ¡el" #: main.c msgid "WARNING: Your code filename has two extensions\n" -msgstr "" +msgstr "UPOZORNÄšNÃ: Název souboru vaÅ¡eho kódu má dvÄ› koncovky\n" #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "WatchDogTimer cannot be deinitialized once mode is set to RESET" -msgstr "" +msgstr "WatchDogTimer nelze deaktivovat v režimu RESET" #: py/builtinhelp.c #, c-format @@ -2338,18 +2343,23 @@ msgid "" "\n" "To list built-in modules type `help(\"modules\")`.\n" msgstr "" +"Vítejte v Adafruit CircuitPython %s!\n" +"\n" +"Pro více informací navÅ¡tivte circuitpython.org.\n" +"\n" +"Seznam vestavÄ›ných modulů můžete vypsat pomocí `help(\"modules\")`.\n" #: supervisor/shared/web_workflow/web_workflow.c msgid "Wi-Fi: " -msgstr "" +msgstr "Wi-Fi: " #: ports/raspberrypi/common-hal/wifi/Radio.c msgid "Wifi is not enabled" -msgstr "" +msgstr "Wifi není povoleno" #: main.c msgid "Woken up by alarm.\n" -msgstr "" +msgstr "Probuzen alarmem.\n" #: ports/espressif/common-hal/_bleio/PacketBuffer.c #: ports/nrf/common-hal/_bleio/PacketBuffer.c @@ -2361,64 +2371,65 @@ msgstr "" #: ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h #: ports/atmel-samd/boards/meowmeow/mpconfigboard.h msgid "You pressed both buttons at start up." -msgstr "" +msgstr "PÅ™i spuÅ¡tÄ›ní jsi stiskl obÄ› tlaÄítka." #: ports/espressif/boards/m5stack_core_basic/mpconfigboard.h #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h msgid "You pressed button A at start up." -msgstr "" +msgstr "PÅ™i spuÅ¡tÄ›ní jsi stiskl tlaÄítko A." #: ports/espressif/boards/m5stack_m5paper/mpconfigboard.h msgid "You pressed button DOWN at start up." -msgstr "" +msgstr "PÅ™i spuÅ¡tÄ›ní jsi stiskl tlaÄítko DOWN." #: supervisor/shared/safe_mode.c msgid "You pressed the BOOT button at start up" -msgstr "" +msgstr "PÅ™i spuÅ¡tÄ›ní jsi stiskl tlaÄítko BOOT" #: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h msgid "You pressed the GPIO0 button at start up." -msgstr "" +msgstr "PÅ™i spuÅ¡tÄ›ní jsi stiskl tlaÄítko na pinu GPIO0." #: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h msgid "You pressed the Rec button at start up." -msgstr "" +msgstr "PÅ™i spuÅ¡tÄ›ní jsi stiskl tlaÄítko Rec." #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." -msgstr "" +msgstr "PÅ™i spuÅ¡tÄ›ní jsi stiskl tlaÄítko SW38." #: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h msgid "You pressed the VOLUME button at start up." -msgstr "" +msgstr "PÅ™i spuÅ¡tÄ›ní jsi stiskl tlaÄítko VOLUME." #: ports/espressif/boards/m5stack_atom_echo/mpconfigboard.h #: ports/espressif/boards/m5stack_atom_lite/mpconfigboard.h #: ports/espressif/boards/m5stack_atom_matrix/mpconfigboard.h #: ports/espressif/boards/m5stack_atom_u/mpconfigboard.h msgid "You pressed the central button at start up." -msgstr "" +msgstr "PÅ™i spuÅ¡tÄ›ní jsi stiskl stÅ™edové tlaÄítko." #: ports/nrf/boards/aramcon2_badge/mpconfigboard.h msgid "You pressed the left button at start up." -msgstr "" +msgstr "PÅ™i spuÅ¡tÄ›ní jsi stiskl tlaÄítko doleva." #: supervisor/shared/safe_mode.c msgid "You pressed the reset button during boot." -msgstr "" +msgstr "PÅ™i spuÅ¡tÄ›ní jsi stiskl tlaÄítko reset." #: supervisor/shared/micropython.c msgid "[truncated due to length]" -msgstr "" +msgstr "[zkráceno kvůli délce]" #: py/objtype.c msgid "__init__() should return None" msgstr "" #: py/objtype.c -msgid "__init__() should return None, not '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" msgstr "" #: py/objobject.c @@ -2435,7 +2446,7 @@ msgstr "" #: py/compile.c msgid "annotation must be an identifier" -msgstr "" +msgstr "anotace musí být identifikátor" #: extmod/ulab/code/numpy/create.c msgid "arange: cannot compute length" @@ -2455,7 +2466,7 @@ msgstr "" #: extmod/ulab/code/numpy/numerical.c msgid "argsort is not implemented for flattened arrays" -msgstr "" +msgstr "argsort není implementován pro zploÅ¡tÄ›ná pole" #: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" @@ -2463,7 +2474,7 @@ msgstr "" #: py/compile.c msgid "argument name reused" -msgstr "" +msgstr "jméno argumentu znovupoužito" #: py/argcheck.c shared-bindings/_stage/__init__.c #: shared-bindings/digitalio/DigitalInOut.c @@ -2480,15 +2491,15 @@ msgstr "" #: extmod/ulab/code/ndarray.c msgid "array and index length must be equal" -msgstr "" +msgstr "Pole a index musí mít stejnou délku" #: extmod/ulab/code/numpy/io/io.c msgid "array has too many dimensions" -msgstr "" +msgstr "pole má příliÅ¡ mnoho dimenzí" #: extmod/ulab/code/ndarray.c msgid "array is too big" -msgstr "" +msgstr "pole je příliÅ¡ velké" #: py/objarray.c shared-bindings/alarm/SleepMemory.c #: shared-bindings/memorymap/AddressRange.c shared-bindings/nvm/ByteArray.c @@ -2497,31 +2508,31 @@ msgstr "" #: py/asmxtensa.c msgid "asm overflow" -msgstr "" +msgstr "pÅ™eteÄení v asm" #: extmod/ulab/code/numpy/numerical.c msgid "attempt to get (arg)min/(arg)max of empty sequence" -msgstr "" +msgstr "pokus o získání (arg)min/(arg)max z prázdné sekvence" #: extmod/ulab/code/numpy/numerical.c msgid "attempt to get argmin/argmax of an empty sequence" msgstr "" #: py/objstr.c -msgid "attributes not supported yet" +msgid "attributes not supported" msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" -msgstr "" +msgstr "osa je mimo rozsah" #: extmod/ulab/code/numpy/numerical.c extmod/ulab/code/ulab_tools.c msgid "axis must be None, or an integer" -msgstr "" +msgstr "osa musí být None nebo integer" #: extmod/ulab/code/numpy/numerical.c msgid "axis too long" -msgstr "" +msgstr "osa je příliÅ¡ dlouhá" #: shared-bindings/bitmaptools/__init__.c msgid "background value out of range of target" @@ -2549,11 +2560,11 @@ msgstr "" #: shared-bindings/bitmaptools/__init__.c msgid "bitmap sizes must match" -msgstr "" +msgstr "velikosti bitmapy musí odpovídat" #: extmod/modurandom.c msgid "bits must be 32 or less" -msgstr "" +msgstr "poÄet bitů nesmí pÅ™esáhnout 32" #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" @@ -2565,11 +2576,11 @@ msgstr "" #: extmod/ulab/code/numpy/create.c extmod/ulab/code/utils/utils.c msgid "buffer is smaller than requested size" -msgstr "" +msgstr "buffer je menší než požadovaná velikost" #: extmod/ulab/code/numpy/create.c extmod/ulab/code/utils/utils.c msgid "buffer size must be a multiple of element size" -msgstr "" +msgstr "velikost bufferu musí být násobkem velikosti elementu" #: shared-module/struct/__init__.c msgid "buffer size must match format" @@ -2585,15 +2596,15 @@ msgstr "" #: shared-bindings/socketpool/Socket.c shared-bindings/ssl/SSLSocket.c msgid "buffer too small for requested bytes" -msgstr "" +msgstr "buffer je příliÅ¡ malý pro poÄet požadovaných bajtů" #: py/emitbc.c msgid "bytecode overflow" -msgstr "" +msgstr "pÅ™eteÄení bytecode" #: py/objarray.c msgid "bytes length not a multiple of item size" -msgstr "" +msgstr "PoÄet bajtů není násobkem velikosti prvku" #: py/objstr.c msgid "bytes value out of range" @@ -2610,7 +2621,7 @@ msgstr "" #: shared-module/vectorio/Circle.c shared-module/vectorio/Polygon.c #: shared-module/vectorio/Rectangle.c msgid "can only have one parent" -msgstr "" +msgstr "může mít pouze jednoho rodiÄe" #: py/emitinlinethumb.c msgid "can only have up to 4 parameters to Thumb assembly" @@ -2634,41 +2645,49 @@ msgstr "" #: extmod/moduasyncio.c msgid "can't cancel self" -msgstr "" +msgstr "nelze zruÅ¡it sám sebe" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" -msgstr "" +msgstr "není možné pÅ™evést %q na %q" #: py/obj.c #, c-format msgid "can't convert %s to complex" -msgstr "" +msgstr "nelze pÅ™evést %s na complex" #: py/obj.c #, c-format msgid "can't convert %s to float" -msgstr "" +msgstr "nelze pÅ™evést %s na float" #: py/objstr.c msgid "can't convert '%q' object to %q implicitly" msgstr "" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" +msgstr "nelze pÅ™evést complex na float" + +#: py/objint.c +msgid "can't convert inf to int" msgstr "" #: py/obj.c msgid "can't convert to complex" -msgstr "" +msgstr "nelze pÅ™evést na complex" #: py/obj.c msgid "can't convert to float" -msgstr "" +msgstr "nelze pÅ™evést na float" #: py/runtime.c msgid "can't convert to int" -msgstr "" +msgstr "nelze pÅ™evést na int" #: py/objstr.c msgid "can't convert to str implicitly" @@ -2686,14 +2705,14 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "" @@ -2704,7 +2723,7 @@ msgstr "" #: py/builtinimport.c msgid "can't perform relative import" -msgstr "" +msgstr "nelze provést relativní import" #: py/objgenerator.c msgid "can't send non-None value to a just-started generator" @@ -2712,7 +2731,7 @@ msgstr "" #: shared-module/sdcardio/SDCard.c msgid "can't set 512 block size" -msgstr "" +msgstr "nelze nastavit velikost bloku 512" #: py/objexcept.c py/objnamedtuple.c msgid "can't set attribute" @@ -2720,7 +2739,7 @@ msgstr "" #: py/runtime.c shared-bindings/supervisor/Runtime.c msgid "can't set attribute '%q'" -msgstr "" +msgstr "nelze nastavit atribut '%q'" #: py/emitnative.c msgid "can't store '%q'" @@ -2744,13 +2763,21 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" -msgstr "" +msgstr "nelze Äekat" #: extmod/ulab/code/ndarray.c msgid "cannot assign new shape" -msgstr "" +msgstr "nelze pÅ™iÅ™adit nový tvar" #: extmod/ulab/code/ndarray_operators.c msgid "cannot cast output with casting rule" @@ -2758,11 +2785,11 @@ msgstr "" #: extmod/ulab/code/ndarray.c msgid "cannot convert complex to dtype" -msgstr "" +msgstr "nelze pÅ™evést complex na dtype" #: extmod/ulab/code/ndarray.c msgid "cannot convert complex type" -msgstr "" +msgstr "nelze pÅ™evést typ complex" #: py/objtype.c msgid "cannot create '%q' instances" @@ -2774,19 +2801,11 @@ msgstr "" #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" -msgstr "" - -#: py/runtime.c -msgid "cannot import name %q" -msgstr "" +msgstr "nelze smazat prvky pole" #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" -msgstr "" - -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" +msgstr "nelze zmÄ›nit rozmÄ›ry pole" #: py/emitnative.c msgid "casting" @@ -2794,7 +2813,7 @@ msgstr "" #: ports/stm/common-hal/pwmio/PWMOut.c msgid "channel re-init" -msgstr "" +msgstr "opÄ›tovná inicializace kanálu" #: shared-bindings/_stage/Text.c msgid "chars buffer too small" @@ -2814,7 +2833,7 @@ msgstr "" #: shared-bindings/msgpack/ExtType.c msgid "code outside range 0~127" -msgstr "" +msgstr "kód mimo rozsah 0~127" #: shared-bindings/displayio/Palette.c msgid "color buffer must be 3 bytes (RGB) or 4 bytes (RGB + pad byte)" @@ -2834,6 +2853,10 @@ msgstr "" #: py/emitnative.c msgid "comparison of int and uint" +msgstr "porovnání int a uint" + +#: py/objcomplex.c +msgid "complex divide by zero" msgstr "" #: py/objfloat.c py/parsenum.c @@ -2862,7 +2885,7 @@ msgstr "" #: extmod/ulab/code/numpy/io/io.c msgid "corrupted file" -msgstr "" +msgstr "poÅ¡kozený soubor" #: extmod/ulab/code/numpy/poly.c msgid "could not invert Vandermonde matrix" @@ -2870,7 +2893,7 @@ msgstr "" #: shared-module/sdcardio/SDCard.c msgid "couldn't determine SD card version" -msgstr "" +msgstr "nelze zjistit verzi SD karty" #: extmod/ulab/code/numpy/numerical.c msgid "cross is defined for 1D arrays of length 3" @@ -2878,20 +2901,20 @@ msgstr "" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "data must be iterable" -msgstr "" +msgstr "data musí být iterovatelná" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "data must be of equal length" -msgstr "" +msgstr "data musí mít stejnou délku" #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "data pin #%d in use" -msgstr "" +msgstr "datový pin #%d je používán" #: extmod/ulab/code/ndarray.c msgid "data type not understood" -msgstr "" +msgstr "datový typ nebyl rozpoznán" #: py/parsenum.c msgid "decimal numbers not supported" @@ -2928,15 +2951,15 @@ msgstr "" #: extmod/ulab/code/numpy/transform.c msgid "dimensions do not match" -msgstr "" +msgstr "dimenze nesouhlasí" #: py/emitnative.c msgid "div/mod not implemented for uint" -msgstr "" +msgstr "div/mod nejsou implementované pro uint" #: extmod/ulab/code/numpy/create.c msgid "divide by zero" -msgstr "" +msgstr "dÄ›lení nulou" #: py/runtime.c msgid "division by zero" @@ -2944,7 +2967,7 @@ msgstr "" #: extmod/ulab/code/numpy/vector.c msgid "dtype must be float, or complex" -msgstr "" +msgstr "dtype musí být float nebo complex" #: py/objdeque.c msgid "empty" @@ -2952,7 +2975,7 @@ msgstr "" #: extmod/ulab/code/numpy/io/io.c msgid "empty file" -msgstr "" +msgstr "prázdný soubor" #: extmod/moduasyncio.c extmod/moduheapq.c msgid "empty heap" @@ -2972,7 +2995,7 @@ msgstr "" #: shared-bindings/alarm/time/TimeAlarm.c msgid "epoch_time not supported on this board" -msgstr "" +msgstr "epoch_time není podporován na této desce" #: ports/nrf/common-hal/busio/UART.c #, c-format @@ -2984,6 +3007,8 @@ msgid "" "espcamera.Camera requires reserved PSRAM to be configured. See the " "documentation for instructions." msgstr "" +"espcamera.Camera vyžaduje reservovanou PSRAM. V dokumentaci nalezneÅ¡ " +"instrukce." #: py/runtime.c msgid "exceptions must derive from BaseException" @@ -3033,7 +3058,7 @@ msgstr "" #: shared-bindings/traceback/__init__.c msgid "file write is not available" -msgstr "" +msgstr "zápis do souboru není dostupný" #: shared-bindings/storage/__init__.c msgid "filesystem must provide mount method" @@ -3041,15 +3066,15 @@ msgstr "" #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" -msgstr "" +msgstr "První argument musí být zavolatelný" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "first argument must be a function" -msgstr "" +msgstr "první argument musí být funkce" #: extmod/ulab/code/numpy/create.c msgid "first argument must be a tuple of ndarrays" -msgstr "" +msgstr "první argument musí být tuple nebo ndarray" #: extmod/ulab/code/numpy/transform.c extmod/ulab/code/numpy/vector.c msgid "first argument must be an ndarray" @@ -3061,7 +3086,7 @@ msgstr "" #: extmod/ulab/code/scipy/linalg/linalg.c msgid "first two arguments must be ndarrays" -msgstr "" +msgstr "první dva argumenty musí být ndarray" #: extmod/ulab/code/ndarray.c msgid "flattening order must be either 'C', or 'F'" @@ -3077,7 +3102,7 @@ msgstr "" #: py/nativeglue.c msgid "float unsupported" -msgstr "" +msgstr "float není podporován" #: shared-bindings/_stage/Text.c msgid "font must be 2048 bytes long" @@ -3110,29 +3135,29 @@ msgstr "" #: extmod/ulab/code/ndarray.c msgid "function is defined for ndarrays only" -msgstr "" +msgstr "funkce je definována pouze pro ndarraye" #: extmod/ulab/code/numpy/carray/carray.c msgid "function is implemented for ndarrays only" -msgstr "" +msgstr "funkce je implementována jen pro ndarraye" #: py/argcheck.c #, c-format msgid "function missing %d required positional arguments" -msgstr "" +msgstr "funkci chybí %d povinné poziÄní argumenty" #: py/bc.c msgid "function missing keyword-only argument" -msgstr "" +msgstr "funkci chybí argument pouze pro klíÄové slovo" #: py/bc.c msgid "function missing required keyword argument '%q'" -msgstr "" +msgstr "funkci chybí argument specifikovaný klíÄovým slovem" #: py/bc.c #, c-format msgid "function missing required positional argument #%d" -msgstr "" +msgstr "funkci chybí požadovaný argument na pozici #%d" #: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c #, c-format @@ -3153,7 +3178,7 @@ msgstr "" #: py/objgenerator.c py/runtime.c msgid "generator raised StopIteration" -msgstr "" +msgstr "generátor způsobil StopIteration" #: shared-bindings/_stage/Layer.c msgid "graphic must be 2048 bytes long" @@ -3161,7 +3186,7 @@ msgstr "" #: extmod/moduhashlib.c msgid "hash is final" -msgstr "" +msgstr "hash je koneÄný" #: extmod/moduheapq.c msgid "heap must be a list" @@ -3181,11 +3206,11 @@ msgstr "" #: py/persistentcode.c msgid "incompatible .mpy arch" -msgstr "" +msgstr "nekopmatibilní architektura .mpy" #: py/persistentcode.c msgid "incompatible .mpy file" -msgstr "" +msgstr "nekompatibilní .mpy soubor" #: py/objstr.c msgid "incomplete format" @@ -3205,7 +3230,7 @@ msgstr "" #: shared-bindings/_pixelmap/PixelMap.c msgid "index must be tuple or int" -msgstr "" +msgstr "index musí být tuple nebo int" #: extmod/ulab/code/numpy/numerical.c extmod/ulab/code/ulab_tools.c #: ports/espressif/common-hal/pulseio/PulseIn.c @@ -3223,15 +3248,15 @@ msgstr "" #: ports/espressif/common-hal/busio/I2C.c msgid "init I2C" -msgstr "" +msgstr "inicializace I2C" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" -msgstr "" +msgstr "výchozí hodnoty musí být iterovatelné" #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c msgid "initial_value length is wrong" -msgstr "" +msgstr "délka initial_value je chybná" #: py/compile.c msgid "inline assembler must be a function" @@ -3239,15 +3264,15 @@ msgstr "" #: extmod/ulab/code/numpy/vector.c msgid "input and output dimensions differ" -msgstr "" +msgstr "dimenze vstupu a výstupu se liší" #: extmod/ulab/code/numpy/vector.c msgid "input and output shapes differ" -msgstr "" +msgstr "vstupní a výstupní tvar je růzmý" #: extmod/ulab/code/numpy/create.c msgid "input argument must be an integer, a tuple, or a list" -msgstr "" +msgstr "vstupní argument musí být integer, tuple nebo list" #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "input array length must be power of 2" @@ -3255,7 +3280,7 @@ msgstr "" #: extmod/ulab/code/numpy/create.c msgid "input arrays are not compatible" -msgstr "" +msgstr "vstupní pole nejsou kompatibilní" #: extmod/ulab/code/numpy/poly.c msgid "input data must be an iterable" @@ -3263,11 +3288,11 @@ msgstr "" #: extmod/ulab/code/numpy/vector.c msgid "input dtype must be float or complex" -msgstr "" +msgstr "vstupní dtype musí být float nebo complex" #: extmod/ulab/code/numpy/poly.c msgid "input is not iterable" -msgstr "" +msgstr "vstup není iterovatelný" #: extmod/ulab/code/numpy/linalg/linalg.c msgid "input matrix is asymmetric" @@ -3280,27 +3305,27 @@ msgstr "" #: extmod/ulab/code/numpy/create.c msgid "input must be 1- or 2-d" -msgstr "" +msgstr "vstup musí být 1- nebo 2-d" #: extmod/ulab/code/numpy/carray/carray.c msgid "input must be a 1D ndarray" -msgstr "" +msgstr "vstup musí být 1D ndarray" #: extmod/ulab/code/scipy/linalg/linalg.c extmod/ulab/code/user/user.c msgid "input must be a dense ndarray" -msgstr "" +msgstr "vstup musí být hustý ndarray" #: extmod/ulab/code/user/user.c msgid "input must be an ndarray" -msgstr "" +msgstr "vstup musí být ndarray" #: extmod/ulab/code/numpy/carray/carray.c msgid "input must be an ndarray, or a scalar" -msgstr "" +msgstr "vstup musí být ndarray nebo scalar" #: extmod/ulab/code/scipy/signal/signal.c msgid "input must be one-dimensional" -msgstr "" +msgstr "vstup musí být jednorozmÄ›rný" #: extmod/ulab/code/ulab_tools.c msgid "input must be square matrix" @@ -3325,16 +3350,16 @@ msgstr "" #: py/compile.c msgid "invalid architecture" -msgstr "" +msgstr "Å¡patná architektura" #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid bits_per_pixel %d, must be, 1, 2, 4, 8, 16, 24, or 32" -msgstr "" +msgstr "chybné bits_per_pixel %d, musí být 1, 2, 4, 8, 16, 24, or 32" #: ports/raspberrypi/common-hal/ssl/SSLSocket.c msgid "invalid cert" -msgstr "" +msgstr "Å¡patný certifikár" #: shared-bindings/bitmaptools/__init__.c #, c-format @@ -3344,11 +3369,11 @@ msgstr "" #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid element_size %d, must be, 1, 2, or 4" -msgstr "" +msgstr "chybná element_size %d, musí být 1, 2, nebo 4" #: shared-bindings/traceback/__init__.c msgid "invalid exception" -msgstr "" +msgstr "Å¡patná výjimka" #: py/objstr.c msgid "invalid format specifier" @@ -3356,11 +3381,11 @@ msgstr "" #: shared-bindings/wifi/Radio.c msgid "invalid hostname" -msgstr "" +msgstr "Å¡patný hostname" #: ports/raspberrypi/common-hal/ssl/SSLSocket.c msgid "invalid key" -msgstr "" +msgstr "Å¡patný klíÄ" #: py/compile.c msgid "invalid micropython decorator" @@ -3368,7 +3393,7 @@ msgstr "" #: ports/espressif/common-hal/espcamera/Camera.c msgid "invalid setting" -msgstr "" +msgstr "neplatné nastavení" #: shared-bindings/random/__init__.c msgid "invalid step" @@ -3408,7 +3433,7 @@ msgid "join expects a list of str/bytes objects consistent with self object" msgstr "" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -3419,10 +3444,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "" @@ -3450,12 +3471,12 @@ msgstr "" #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "mDNS already initialized" -msgstr "" +msgstr "mDNS je již inicializováno" #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "mDNS only works with built-in WiFi" -msgstr "" +msgstr "mDNS pracuje pouze s vestavÄ›nou WiFi" #: py/parse.c msgid "malformed f-string" @@ -3482,7 +3503,7 @@ msgstr "" #: extmod/ulab/code/ndarray.c msgid "maximum number of dimensions is " -msgstr "" +msgstr "maximální poÄet dimenzí je " #: py/runtime.c msgid "maximum recursion depth exceeded" @@ -3490,11 +3511,11 @@ msgstr "" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "maxiter must be > 0" -msgstr "" +msgstr "maxiter musí být > 0" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "maxiter should be > 0" -msgstr "" +msgstr "maxiter by mÄ›l být > 0" #: extmod/ulab/code/numpy/numerical.c msgid "median argument must be an ndarray" @@ -3510,9 +3531,13 @@ msgid "memory allocation failed, heap is locked" msgstr "" #: py/objarray.c -msgid "memoryview: length is not a multiple of itemsize" +msgid "memoryview offset too large" msgstr "" +#: py/objarray.c +msgid "memoryview: length is not a multiple of itemsize" +msgstr "memoryview: délka není násobkem velikosti položky" + #: extmod/ulab/code/numpy/linalg/linalg.c msgid "mode must be complete, or reduced" msgstr "" @@ -3557,6 +3582,10 @@ msgstr "" msgid "name not defined" msgstr "" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3567,7 +3596,7 @@ msgstr "" #: extmod/ulab/code/ndarray.c msgid "ndarray length overflows" -msgstr "" +msgstr "délka ndarray pÅ™etekla" #: py/runtime.c #, c-format @@ -3576,7 +3605,7 @@ msgstr "" #: py/modmath.c msgid "negative factorial" -msgstr "" +msgstr "záporný faktoriál" #: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative power with no float support" @@ -3592,7 +3621,7 @@ msgstr "" #: shared-module/sdcardio/SDCard.c msgid "no SD card" -msgstr "" +msgstr "není vložena SD karta" #: py/vm.c msgid "no active exception to reraise" @@ -3616,7 +3645,7 @@ msgstr "" #: shared-module/sdcardio/SDCard.c msgid "no response from SD card" -msgstr "" +msgstr "žádná odpovÄ›Ä z SD karty" #: ports/espressif/common-hal/espcamera/Camera.c py/objobject.c py/runtime.c msgid "no such attribute" @@ -3631,17 +3660,17 @@ msgstr "" msgid "non-default argument follows default argument" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "" #: ports/nrf/common-hal/_bleio/Adapter.c msgid "non-zero timeout must be > 0.01" -msgstr "" +msgstr "nenulový timeout musí být > 0.01" #: shared-bindings/_bleio/Adapter.c msgid "non-zero timeout must be >= interval" -msgstr "" +msgstr "nenulový timeout musí být >= interval" #: shared-bindings/_bleio/UUID.c msgid "not a 128-bit UUID" @@ -3649,7 +3678,7 @@ msgstr "" #: py/parse.c msgid "not a constant" -msgstr "" +msgstr "není konstanta" #: py/objstr.c msgid "not all arguments converted during string formatting" @@ -3661,11 +3690,11 @@ msgstr "" #: extmod/ulab/code/numpy/carray/carray_tools.c msgid "not implemented for complex dtype" -msgstr "" +msgstr "není implementováno pro komplexní dtype" #: extmod/ulab/code/numpy/bitwise.c msgid "not supported for input types" -msgstr "" +msgstr "není podporováno pro vstupní typy" #: extmod/ulab/code/numpy/create.c msgid "number of points must be at least 2" @@ -3673,12 +3702,12 @@ msgstr "" #: py/builtinhelp.c msgid "object " -msgstr "" +msgstr "objekt " #: py/obj.c #, c-format msgid "object '%s' isn't a tuple or list" -msgstr "" +msgstr "objekt '%s' není tuple or nebo list" #: py/obj.c msgid "object doesn't support item assignment" @@ -3715,36 +3744,32 @@ msgstr "" #: py/obj.c #, c-format msgid "object of type '%s' has no len()" -msgstr "" +msgstr "objekt typu '%s' nemá len()" #: py/obj.c msgid "object with buffer protocol required" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "" #: supervisor/shared/web_workflow/web_workflow.c msgid "off" -msgstr "" +msgstr "vypnuto" #: extmod/ulab/code/utils/utils.c msgid "offset is too large" -msgstr "" +msgstr "offset je příliÅ¡ velký" #: shared-bindings/dualbank/__init__.c msgid "offset must be >= 0" -msgstr "" +msgstr "offset musí být >= 0" #: extmod/ulab/code/numpy/create.c msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -3752,15 +3777,15 @@ msgstr "" #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only mono is supported" -msgstr "" +msgstr "je podporováno pouze mono" #: extmod/ulab/code/numpy/create.c msgid "only ndarrays can be concatenated" -msgstr "" +msgstr "pouze ndarraye mohou být spojeny" #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only oversample=64 is supported" -msgstr "" +msgstr "je podporován pouze oversampling 64" #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c @@ -3775,7 +3800,7 @@ msgstr "" #: py/vm.c msgid "opcode" -msgstr "" +msgstr "opcode" #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/bitwise.c #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/vector.c @@ -3784,15 +3809,15 @@ msgstr "" #: extmod/ulab/code/numpy/linalg/linalg.c msgid "operation is defined for 2D arrays only" -msgstr "" +msgstr "operace je definována pouze pro 2D pole" #: extmod/ulab/code/numpy/linalg/linalg.c msgid "operation is defined for ndarrays only" -msgstr "" +msgstr "operace je definována pouze pro ndarray pole" #: extmod/ulab/code/ndarray.c msgid "operation is implemented for 1D Boolean arrays only" -msgstr "" +msgstr "operace je immplementována pouze pro 1D boolean pole" #: extmod/ulab/code/numpy/numerical.c msgid "operation is not implemented on ndarrays" @@ -3813,7 +3838,7 @@ msgstr "" #: extmod/ulab/code/utils/utils.c msgid "out array is too small" -msgstr "" +msgstr "výstupní pole je příliÅ¡ malé" #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" @@ -3879,11 +3904,11 @@ msgstr "" #: ports/stm/common-hal/pulseio/PulseIn.c py/objdict.c py/objlist.c py/objset.c #: shared-bindings/ps2io/Ps2.c msgid "pop from empty %q" -msgstr "" +msgstr "pop z prázdného %q" #: shared-bindings/socketpool/Socket.c shared-bindings/ssl/SSLSocket.c msgid "port must be >= 0" -msgstr "" +msgstr "port musí být >= 0" #: py/compile.c msgid "positional arg after **" @@ -3907,7 +3932,7 @@ msgstr "" #: py/parse.c msgid "raw f-strings are not supported" -msgstr "" +msgstr "surové f-stringy nesjou podporované" #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "real and imaginary parts must be of equal length" @@ -3967,11 +3992,11 @@ msgstr "" #: py/nativeglue.c msgid "set unsupported" -msgstr "" +msgstr "set neoodporován" #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" -msgstr "" +msgstr "tvar musí být integer nebo tuple integerů" #: shared-module/msgpack/__init__.c msgid "short read" @@ -3993,10 +4018,6 @@ msgstr "" msgid "sleep length must be non-negative" msgstr "" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4027,7 +4048,7 @@ msgstr "" #: shared-bindings/bitmaptools/__init__.c msgid "source palette too large" -msgstr "" +msgstr "zdrojová paleta je příliÅ¡ velká" #: shared-bindings/bitmaptools/__init__.c msgid "source_bitmap must have value_count of 2 or 65536" @@ -4041,6 +4062,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" @@ -4053,8 +4078,17 @@ msgstr "" msgid "stream operation not supported" msgstr "" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" msgstr "" #: extmod/moductypes.c @@ -4085,13 +4119,17 @@ msgstr "" msgid "syntax error in uctypes descriptor" msgstr "" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" -msgstr "" +msgstr "timeout pÅ™ekroÄil maximální podporovanou hodnotu" #: ports/nrf/common-hal/_bleio/Adapter.c msgid "timeout must be < 655.35 secs" -msgstr "" +msgstr "timeout musí být < 655.35 s" #: shared-module/sdcardio/SDCard.c msgid "timeout waiting for v1 card" @@ -4103,7 +4141,7 @@ msgstr "" #: ports/stm/common-hal/pwmio/PWMOut.c msgid "timer re-init" -msgstr "" +msgstr "opÄ›tovný init timeru" #: shared-bindings/time/__init__.c msgid "timestamp out of range for platform time_t" @@ -4115,11 +4153,11 @@ msgstr "" #: py/compile.c msgid "too many args" -msgstr "" +msgstr "příliÅ¡ mnoho argumentů" #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/create.c msgid "too many dimensions" -msgstr "" +msgstr "příliÅ¡ mnoho dimenzí" #: extmod/ulab/code/ndarray.c msgid "too many indices" @@ -4144,7 +4182,7 @@ msgstr "" #: py/obj.c msgid "tuple/list has wrong length" -msgstr "" +msgstr "tuple/list má Å¡patnou délku" #: ports/espressif/common-hal/canio/CAN.c #, c-format @@ -4186,7 +4224,7 @@ msgstr "" #: py/parse.c msgid "unexpected indent" -msgstr "" +msgstr "neoÄekávané odsazení" #: py/bc.c msgid "unexpected keyword argument" @@ -4216,16 +4254,16 @@ msgstr "" #: py/compile.c msgid "unknown type" -msgstr "" +msgstr "neznámý typ" #: py/compile.c msgid "unknown type '%q'" -msgstr "" +msgstr "neznámý typ '%q'" #: py/objstr.c #, c-format msgid "unmatched '%c' in format" -msgstr "" +msgstr "neshoduje se '%c' ve formátu" #: py/objtype.c py/runtime.c msgid "unreadable attribute" @@ -4233,7 +4271,7 @@ msgstr "" #: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" -msgstr "" +msgstr "nepodporovaný typ% q" #: py/emitinlinethumb.c #, c-format @@ -4298,7 +4336,7 @@ msgstr "" #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" -msgstr "" +msgstr "wifi.Monitor není dostupný" #: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" @@ -4314,11 +4352,11 @@ msgstr "" #: extmod/ulab/code/numpy/io/io.c msgid "wrong dtype" -msgstr "" +msgstr "Å¡patný dtype" #: extmod/ulab/code/numpy/transform.c msgid "wrong index type" -msgstr "" +msgstr "Å¡patný typ indexu" #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/create.c #: extmod/ulab/code/numpy/io/io.c extmod/ulab/code/numpy/transform.c @@ -4358,6 +4396,15 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "__init__() should return None, not '%q'" +#~ msgstr "__init__() by mÄ›l vracet hodnotu None, nikoli '%q'" + +#~ msgid "cannot unambiguously get sizeof scalar" +#~ msgstr "velikost scalar nelze jednoznaÄnÄ› urÄit" + +#~ msgid "Bit clock and word select must be sequential pins" +#~ msgstr "Bitové hodiny a výbÄ›r slov musí být sekvenÄní piny" + #~ msgid "ADC2 is being used by WiFi" #~ msgstr "WiFi používá ADC2" diff --git a/locale/de_DE.po b/locale/de_DE.po index d94b51ff92..469f41a67c 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -148,7 +148,7 @@ msgstr "%q in %q muss von Typ %q sein, nicht %q" msgid "%q in use" msgstr "%q in Benutzung" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "Der Index %q befindet sich außerhalb des Bereiches" @@ -236,7 +236,7 @@ msgstr "%q muss ein Array vom Typ 'h' sein" msgid "%q must be of type %q or %q, not %q" msgstr "%q muss von Typ %q oder %q sein, nicht %q" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q muss von Typ %q sein, nicht %q" @@ -290,6 +290,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -641,8 +646,8 @@ msgid "Below minimum frame rate" msgstr "Unterhalb der minimalen Frame Rate" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" -msgstr "Bit clock und word select müssen geordnete Pins sein" +msgid "Bit clock and word select must be sequential GPIO pins" +msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -1126,8 +1131,6 @@ msgstr "GNSS-Initialisierung" msgid "Generic Failure" msgstr "Generischer Fehler" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -2000,10 +2003,6 @@ msgstr "Quell- und Zielpuffer müssen gleich lang sein" msgid "Specify exactly one of data0 or data_pins" msgstr "Gib genau einen von data0 oder data_pins an" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "Splitting mit sub-captures" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "Stereo links muss sich auf PWM-Kanal A befinden" @@ -2459,8 +2458,9 @@ msgid "__init__() should return None" msgstr "__init__() sollte None zurückgeben" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "__init__() sollte None zurückgeben, nicht '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "__init__() sollte None zurückgeben, nicht '%s'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2549,8 +2549,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "Versuch, argmin/argmax einer leeren Sequenz zu ermitteln" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "Attribute werden noch nicht unterstützt" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2679,7 +2679,7 @@ msgstr "kann keinem Ausdruck zuweisen" msgid "can't cancel self" msgstr "kann self nicht abbrechen" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "kann %q nicht zu %q konvertieren" @@ -2697,10 +2697,18 @@ msgstr "kann %s nicht nach float konvertieren" msgid "can't convert '%q' object to %q implicitly" msgstr "Kann '%q' Objekt nicht implizit nach %q konvertieren" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "kann NaN nicht nach int konvertieren" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "Complex kann nicht in Float konvertiert werden" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "kann inf nicht nach int konvertieren" + #: py/obj.c msgid "can't convert to complex" msgstr "kann nicht nach complex konvertieren" @@ -2729,14 +2737,14 @@ msgstr "Ausdruck kann nicht gelöscht werden" msgid "can't do binary op between '%q' and '%q'" msgstr "Eine binäre Operation zwischen '%q' und '%q' ist nicht möglich" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "kann mit einer komplexen Zahl keine abgeschnittene Division ausführen" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "Kann '%q' nicht implizit nach 'bool' konvertieren" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "Laden von '%q' nicht möglich" @@ -2793,6 +2801,14 @@ msgstr "" "kann nicht von der manuellen Feldspezifikation zur automatischen " "Feldnummerierung wechseln" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2825,18 +2841,10 @@ msgstr "Kann Instanz nicht erstellen" msgid "cannot delete array elements" msgstr "Array-Elemente können nicht gelöscht werden" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "Name %q kann nicht importiert werden" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "Array kann nicht umgeformt werden" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "Kann nicht eindeutig die Größe (sizeof) des Skalars ermitteln" - #: py/emitnative.c msgid "casting" msgstr "Umwandlung (cast)" @@ -2887,6 +2895,10 @@ msgstr "Farbe muss zwischen 0x000000 und 0xffffff liegen" msgid "comparison of int and uint" msgstr "Vergleich von int und uint" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "Komplexe Zahlen nicht unterstützt" @@ -3467,10 +3479,8 @@ msgstr "" "übereinstimmen" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" -"Schlüsselwort-Argument(e) noch nicht implementiert - verwende stattdessen " -"normale Argumente" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3480,10 +3490,6 @@ msgstr "Label '%q' nicht definiert" msgid "label redefined" msgstr "Label neu definiert" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "Für diesen Typ ist length nicht zulässig" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "Der Pegel muss zwischen 0 und 1 liegen" @@ -3572,6 +3578,10 @@ msgstr "Speicherzuordnung fehlgeschlagen, Zuweisung von %u Bytes" msgid "memory allocation failed, heap is locked" msgstr "Speicherzuweisung fehlgeschlagen, der Heap ist gesperrt" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "memoryview: length ist kein Vielfaches von itemize" @@ -3620,6 +3630,10 @@ msgstr "Name '%q' ist nirgends definiert worden (Schreibweise kontrollieren)" msgid "name not defined" msgstr "Dieser Name ist nirgends definiert worden (Schreibweise kontrollieren)" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "native Methode zu groß" @@ -3694,7 +3708,7 @@ msgstr "Nicht-UUID in service_uuids_whitelist gefunden" msgid "non-default argument follows default argument" msgstr "ein non-default argument folgt auf ein default argument" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "eine nicht-hex zahl wurde gefunden" @@ -3786,7 +3800,7 @@ msgstr "Objekt vom Typ '%s' hat keine len()" msgid "object with buffer protocol required" msgstr "Objekt mit Pufferprotokoll (buffer protocol) erforderlich" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "String mit ungerader Länge" @@ -3807,10 +3821,6 @@ msgid "offset must be non-negative and no greater than buffer length" msgstr "" "Offset muss nicht negativ sein und darf nicht größer als die Pufferlänge sein" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "offset außerhalb der Grenzen" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -4062,10 +4072,6 @@ msgstr "Größe ist nur für ndarrays definiert" msgid "sleep length must be non-negative" msgstr "Die Schlafdauer darf nicht negativ sein" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "Slice-Schritt darf nicht Null sein" - #: py/nativeglue.c msgid "slice unsupported" msgstr "Slice nicht unterstützt" @@ -4110,6 +4116,10 @@ msgstr "source_bitmap muss value_count von 65536 haben" msgid "source_bitmap must have value_count of 8" msgstr "source_bitmap muss value_count von 8 haben" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "start/end Indizes" @@ -4122,9 +4132,18 @@ msgstr "stop ist von start aus nicht erreichbar" msgid "stream operation not supported" msgstr "stream operation ist nicht unterstützt" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" -msgstr "Zeichenfolgen werden nicht unterstützt; verwende bytes oder bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "String index außerhalb des Bereiches" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "String indizes müssen Integer sein, nicht %s" #: extmod/moductypes.c msgid "struct: can't index" @@ -4154,6 +4173,10 @@ msgstr "Syntaxfehler in JSON" msgid "syntax error in uctypes descriptor" msgstr "Syntaxfehler in uctypes Deskriptor" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "Das Zeitlimit hat den maximal zulässigen Wert überschritten" @@ -4429,6 +4452,46 @@ msgstr "zi muss eine Gleitkommazahl sein" msgid "zi must be of shape (n_section, 2)" msgstr "zi muss die Form (n_section, 2) haben" +#~ msgid "Splitting with sub-captures" +#~ msgstr "Splitting mit sub-captures" + +#~ msgid "__init__() should return None, not '%q'" +#~ msgstr "__init__() sollte None zurückgeben, nicht '%q'" + +#~ msgid "attributes not supported yet" +#~ msgstr "Attribute werden noch nicht unterstützt" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "" +#~ "kann mit einer komplexen Zahl keine abgeschnittene Division ausführen" + +#~ msgid "cannot import name %q" +#~ msgstr "Name %q kann nicht importiert werden" + +#~ msgid "cannot unambiguously get sizeof scalar" +#~ msgstr "Kann nicht eindeutig die Größe (sizeof) des Skalars ermitteln" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "" +#~ "Schlüsselwort-Argument(e) noch nicht implementiert - verwende stattdessen " +#~ "normale Argumente" + +#~ msgid "length argument not allowed for this type" +#~ msgstr "Für diesen Typ ist length nicht zulässig" + +#~ msgid "offset out of bounds" +#~ msgstr "offset außerhalb der Grenzen" + +#~ msgid "slice step can't be zero" +#~ msgstr "Slice-Schritt darf nicht Null sein" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "" +#~ "Zeichenfolgen werden nicht unterstützt; verwende bytes oder bytearray" + +#~ msgid "Bit clock and word select must be sequential pins" +#~ msgstr "Bit clock und word select müssen geordnete Pins sein" + #~ msgid "Initialization failed due to lack of memory" #~ msgstr "Initialisierung aufgrund von Speichermangel fehlgeschlagen" @@ -5804,21 +5867,12 @@ msgstr "zi muss die Form (n_section, 2) haben" #~ msgid "Running in safe mode! Auto-reload is off.\n" #~ msgstr "Sicherheitsmodus aktiv! Automatisches Neuladen ist deaktiviert.\n" -#~ msgid "__init__() should return None, not '%s'" -#~ msgstr "__init__() sollte None zurückgeben, nicht '%s'" - #~ msgid "can't convert %s to int" #~ msgstr "kann %s nicht nach int konvertieren" -#~ msgid "can't convert NaN to int" -#~ msgstr "kann NaN nicht nach int konvertieren" - #~ msgid "can't convert address to int" #~ msgstr "kann Adresse nicht in int konvertieren" -#~ msgid "can't convert inf to int" -#~ msgstr "kann inf nicht nach int konvertieren" - #~ msgid "object '%s' is not a tuple or list" #~ msgstr "Objekt '%s' ist weder tupel noch list" @@ -5831,12 +5885,6 @@ msgstr "zi muss die Form (n_section, 2) haben" #~ msgid "popitem(): dictionary is empty" #~ msgstr "popitem(): dictionary ist leer" -#~ msgid "string index out of range" -#~ msgstr "String index außerhalb des Bereiches" - -#~ msgid "string indices must be integers, not %s" -#~ msgstr "String indizes müssen Integer sein, nicht %s" - #~ msgid "unknown format code '%c' for object of type '%s'" #~ msgstr "unbekannter Formatcode '%c' für Objekt vom Typ '%s'" diff --git a/locale/el.po b/locale/el.po index b362f61284..da0c7d7f2a 100644 --- a/locale/el.po +++ b/locale/el.po @@ -151,7 +151,7 @@ msgstr "%q στο %q Ï€Ïέπει να είναι Ï„Ïπου %q, όχι %q" msgid "%q in use" msgstr "%q είναι σε χÏήση" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "%q δείκτης εκτός εμβέλειας" @@ -238,7 +238,7 @@ msgstr "%q Ï€Ïέπει να είναι λίστα Ï„Ïπου 'h'" msgid "%q must be of type %q or %q, not %q" msgstr "%q Ï€Ïέπει να είναι Ï„Ïπου %q ή %q, όχι %q" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -291,6 +291,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -642,8 +647,8 @@ msgid "Below minimum frame rate" msgstr "ΧαμηλότεÏο από το ελάχιστο frame rate" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" -msgstr "Ρολόι bit και word select Ï€Ïέπει να είναι διαδοχικά pins" +msgid "Bit clock and word select must be sequential GPIO pins" +msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -1124,8 +1129,6 @@ msgstr "" msgid "Generic Failure" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1982,10 +1985,6 @@ msgstr "" msgid "Specify exactly one of data0 or data_pins" msgstr "" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "" @@ -2422,7 +2421,8 @@ msgid "__init__() should return None" msgstr "" #: py/objtype.c -msgid "__init__() should return None, not '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" msgstr "" #: py/objobject.c @@ -2512,7 +2512,7 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "" #: py/objstr.c -msgid "attributes not supported yet" +msgid "attributes not supported" msgstr "" #: extmod/ulab/code/ulab_tools.c @@ -2640,7 +2640,7 @@ msgstr "" msgid "can't cancel self" msgstr "" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2658,10 +2658,18 @@ msgstr "" msgid "can't convert '%q' object to %q implicitly" msgstr "" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "" + #: py/obj.c msgid "can't convert to complex" msgstr "" @@ -2690,14 +2698,14 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "" @@ -2748,6 +2756,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2780,18 +2796,10 @@ msgstr "" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" - #: py/emitnative.c msgid "casting" msgstr "" @@ -2840,6 +2848,10 @@ msgstr "" msgid "comparison of int and uint" msgstr "" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "" @@ -3412,7 +3424,7 @@ msgid "join expects a list of str/bytes objects consistent with self object" msgstr "" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -3423,10 +3435,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "" @@ -3513,6 +3521,10 @@ msgstr "" msgid "memory allocation failed, heap is locked" msgstr "" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3561,6 +3573,10 @@ msgstr "" msgid "name not defined" msgstr "" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3635,7 +3651,7 @@ msgstr "" msgid "non-default argument follows default argument" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "" @@ -3725,7 +3741,7 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "" @@ -3745,10 +3761,6 @@ msgstr "" msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -3997,10 +4009,6 @@ msgstr "" msgid "sleep length must be non-negative" msgstr "" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4045,6 +4053,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" @@ -4057,8 +4069,17 @@ msgstr "" msgid "stream operation not supported" msgstr "" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" msgstr "" #: extmod/moductypes.c @@ -4089,6 +4110,10 @@ msgstr "" msgid "syntax error in uctypes descriptor" msgstr "" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "" @@ -4362,6 +4387,9 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "Bit clock and word select must be sequential pins" +#~ msgstr "Ρολόι bit και word select Ï€Ïέπει να είναι διαδοχικά pins" + #~ msgid "ADC2 is being used by WiFi" #~ msgstr "Το ADC2 χÏησιμοποιείται απο το WIFI" diff --git a/locale/en_GB.po b/locale/en_GB.po index a73c431037..8b2a074513 100644 --- a/locale/en_GB.po +++ b/locale/en_GB.po @@ -152,7 +152,7 @@ msgstr "%q in %q must be of type %q, not %q" msgid "%q in use" msgstr "%q in use" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "%q index out of range" @@ -239,7 +239,7 @@ msgstr "%q must be array of type 'h'" msgid "%q must be of type %q or %q, not %q" msgstr "%q must be of type %q or %q, not %q" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q must be of type %q, not %q" @@ -292,6 +292,11 @@ msgstr "%q[%u] uses extra pin" msgid "%q[%u] waits on input outside of count" msgstr "%q[%u] waits on input outside of count" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -643,8 +648,8 @@ msgid "Below minimum frame rate" msgstr "Below minimum frame rate" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" -msgstr "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" +msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -1118,8 +1123,6 @@ msgstr "GNSS init" msgid "Generic Failure" msgstr "Generic Failure" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1983,10 +1986,6 @@ msgstr "Source and destination buffers must be the same length" msgid "Specify exactly one of data0 or data_pins" msgstr "Specify exactly one of data0 or data_pins" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "Splitting with sub-captures" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "Stereo left must be on PWM channel A" @@ -2432,8 +2431,9 @@ msgid "__init__() should return None" msgstr "__init__() should return None" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "__init__() should return None, not '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2522,8 +2522,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "attempt to get argmin/argmax of an empty sequence" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "attributes not supported yet" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2650,7 +2650,7 @@ msgstr "Can't assign to expression" msgid "can't cancel self" msgstr "can't cancel self" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "Can't convert %q to %q" @@ -2668,10 +2668,18 @@ msgstr "can't convert %s to float" msgid "can't convert '%q' object to %q implicitly" msgstr "Can't convert '%q' object to %q implicitly" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "can't convert complex to float" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "" + #: py/obj.c msgid "can't convert to complex" msgstr "can't convert to complex" @@ -2700,14 +2708,14 @@ msgstr "Can't delete expression" msgid "can't do binary op between '%q' and '%q'" msgstr "Can't do binary op between '%q' and '%q'" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "Can't do truncated division of a complex number" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "can't implicitly convert '%q' to 'bool'" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "can't load from '%q'" @@ -2760,6 +2768,14 @@ msgid "" msgstr "" "can't switch from manual field specification to automatic field numbering" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "can't wait" @@ -2792,18 +2808,10 @@ msgstr "can't create instance" msgid "cannot delete array elements" msgstr "cannot delete array elements" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "can't import name %q" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "cannot reshape array" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "cannot unambiguously get sizeof scalar" - #: py/emitnative.c msgid "casting" msgstr "casting" @@ -2852,6 +2860,10 @@ msgstr "colour must be between 0x000000 and 0xffffff" msgid "comparison of int and uint" msgstr "comparison of int and uint" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "complex values not supported" @@ -3427,8 +3439,8 @@ msgid "join expects a list of str/bytes objects consistent with self object" msgstr "join expects a list of str/bytes objects consistent with self object" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" -msgstr "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" +msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3438,10 +3450,6 @@ msgstr "label '%q' not defined" msgid "label redefined" msgstr "label redefined" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "length argument not allowed for this type" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "level must be between 0 and 1" @@ -3528,6 +3536,10 @@ msgstr "memory allocation failed, allocating %u bytes" msgid "memory allocation failed, heap is locked" msgstr "memory allocation failed, heap is locked" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "memoryview: length is not a multiple of itemsize" @@ -3576,6 +3588,10 @@ msgstr "name '%q' is not defined" msgid "name not defined" msgstr "name not defined" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "native method too big" @@ -3650,7 +3666,7 @@ msgstr "non-UUID found in service_uuids_whitelist" msgid "non-default argument follows default argument" msgstr "non-default argument follows default argument" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "non-hex digit found" @@ -3740,7 +3756,7 @@ msgstr "object of type '%s' has no len()" msgid "object with buffer protocol required" msgstr "object with buffer protocol required" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "odd-length string" @@ -3760,10 +3776,6 @@ msgstr "offset must be >= 0" msgid "offset must be non-negative and no greater than buffer length" msgstr "offset must be non-negative and not greater than buffer length" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "offset out of bounds" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -4012,10 +4024,6 @@ msgstr "size is defined for ndarrays only" msgid "sleep length must be non-negative" msgstr "sleep length must be non-negative" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "slice step can't be zero" - #: py/nativeglue.c msgid "slice unsupported" msgstr "slice unsupported" @@ -4060,6 +4068,10 @@ msgstr "source_bitmap must have value_count of 65536" msgid "source_bitmap must have value_count of 8" msgstr "source_bitmap must have value_count of 8" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "start/end indices" @@ -4072,9 +4084,18 @@ msgstr "stop not reachable from start" msgid "stream operation not supported" msgstr "stream operation not supported" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" -msgstr "string not supported; use bytes or bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "" #: extmod/moductypes.c msgid "struct: can't index" @@ -4104,6 +4125,10 @@ msgstr "syntax error in JSON" msgid "syntax error in uctypes descriptor" msgstr "syntax error in uctypes descriptor" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "timeout duration exceeded the maximum supported value" @@ -4377,6 +4402,42 @@ msgstr "zi must be of float type" msgid "zi must be of shape (n_section, 2)" msgstr "zi must be of shape (n_section, 2)" +#~ msgid "Splitting with sub-captures" +#~ msgstr "Splitting with sub-captures" + +#~ msgid "__init__() should return None, not '%q'" +#~ msgstr "__init__() should return None, not '%q'" + +#~ msgid "attributes not supported yet" +#~ msgstr "attributes not supported yet" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "Can't do truncated division of a complex number" + +#~ msgid "cannot import name %q" +#~ msgstr "can't import name %q" + +#~ msgid "cannot unambiguously get sizeof scalar" +#~ msgstr "cannot unambiguously get sizeof scalar" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "keyword argument(s) not yet implemented - use normal args instead" + +#~ msgid "length argument not allowed for this type" +#~ msgstr "length argument not allowed for this type" + +#~ msgid "offset out of bounds" +#~ msgstr "offset out of bounds" + +#~ msgid "slice step can't be zero" +#~ msgstr "slice step can't be zero" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "string not supported; use bytes or bytearray" + +#~ msgid "Bit clock and word select must be sequential pins" +#~ msgstr "Bit clock and word select must be sequential pins" + #~ msgid "Initialization failed due to lack of memory" #~ msgstr "Initialisation failed due to lack of memory" diff --git a/locale/es.po b/locale/es.po index c36dfbe627..3474f84ff9 100644 --- a/locale/es.po +++ b/locale/es.po @@ -154,7 +154,7 @@ msgstr "%q en %q debe ser del tipo %q, no %q" msgid "%q in use" msgstr "%q está siendo utilizado" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "%q índice fuera de rango" @@ -241,7 +241,7 @@ msgstr "%q debe ser una matriz de tipo 'h'" msgid "%q must be of type %q or %q, not %q" msgstr "%q debe ser del tipo %q o %q, y no %q" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q debe ser del tipo %q, y no %q" @@ -294,6 +294,11 @@ msgstr "%q[%u] usa un pin extra" msgid "%q[%u] waits on input outside of count" msgstr "%q[%u] espera entrada fuera del contador" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -647,8 +652,8 @@ msgid "Below minimum frame rate" msgstr "Por debajo de la tasa mínima de refrescamiento" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" -msgstr "Los pines \"clock\" y \"word-select\" deben ser consecutivos" +msgid "Bit clock and word select must be sequential GPIO pins" +msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -1135,8 +1140,6 @@ msgstr "Inicialización GNSS" msgid "Generic Failure" msgstr "Fallo Genérico" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -2015,10 +2018,6 @@ msgstr "Los buffers de fuente y destino deben ser del mismo tamaño" msgid "Specify exactly one of data0 or data_pins" msgstr "Especifique exactamente uno de data0 or data_pins" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "Dividiendo con sub-capturas" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "Estéreo izquierdo debe estar en el canal PWM A" @@ -2469,8 +2468,9 @@ msgid "__init__() should return None" msgstr "__init__() deberia devolver None" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "__init__() debe retornar None, no '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "__init__() deberia devolver None, no '%s'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2559,8 +2559,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "intento de obtener argmin/argmax de una secuencia vacía" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "atributos aún no soportados" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2687,7 +2687,7 @@ msgstr "no se puede asignar a la expresión" msgid "can't cancel self" msgstr "no se puede cancelar a si mismo" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "no puede convertir %q a %q" @@ -2705,10 +2705,18 @@ msgstr "no se puede convertir %s a float" msgid "can't convert '%q' object to %q implicitly" msgstr "no se puede convertir el objeto '%q' a %q implícitamente" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "no se puede convertir Nan a int" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "no se puede convertir complejo a float" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "no se puede convertir inf en int" + #: py/obj.c msgid "can't convert to complex" msgstr "no se puede convertir a complejo" @@ -2737,14 +2745,14 @@ msgstr "no se puede borrar la expresión" msgid "can't do binary op between '%q' and '%q'" msgstr "no se puede hacer una operacion binaria entre '%q' y '%q'" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "no se puede hacer la división truncada de un número complejo" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "no se puede convertir implícitamente '%q' a 'bool'" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "no se puede cargar desde '%q'" @@ -2800,6 +2808,14 @@ msgstr "" "no se puede cambiar de especificación de campo manual a numeración " "automática de campos" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "no se puede esperar" @@ -2832,18 +2848,10 @@ msgstr "no se puede crear instancia" msgid "cannot delete array elements" msgstr "no se pudo eliminar elementos del array" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "no se puede importar name '%q'" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "no puede remodelar la matriz" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "no se puede sin ambiguedades traer el sizeof del escalar" - #: py/emitnative.c msgid "casting" msgstr "convirtiendo tipo" @@ -2892,6 +2900,10 @@ msgstr "color debe estar entre 0x000000 y 0xffffff" msgid "comparison of int and uint" msgstr "comparación entre int y uint" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "valores complejos no soportados" @@ -3469,10 +3481,8 @@ msgstr "" "join espera una lista de objetos str/bytes consistentes con el mismo objeto" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" -"argumento(s) por palabra clave aún no implementados - usa argumentos " -"normales en su lugar" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3482,10 +3492,6 @@ msgstr "etiqueta '%q' no definida" msgid "label redefined" msgstr "etiqueta redefinida" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "argumento length no permitido para este tipo" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "el nivel debe ser entre 0 y 1" @@ -3572,6 +3578,10 @@ msgstr "la asignación de memoria falló, asignando %u bytes" msgid "memory allocation failed, heap is locked" msgstr "la asignación de memoria falló, el heap está bloqueado" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3621,6 +3631,10 @@ msgstr "name '%q' no esta definido" msgid "name not defined" msgstr "name no definido" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "método nativo muy grande" @@ -3695,7 +3709,7 @@ msgstr "no UUID encontrado en service_uuids_whitelist" msgid "non-default argument follows default argument" msgstr "argumento no predeterminado sigue argumento predeterminado" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "digito non-hex encontrado" @@ -3786,7 +3800,7 @@ msgstr "el objeto de tipo '%s' no tiene len()" msgid "object with buffer protocol required" msgstr "objeto con protocolo de buffer requerido" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "string de longitud impar" @@ -3806,10 +3820,6 @@ msgstr "offset debe ser >= 0" msgid "offset must be non-negative and no greater than buffer length" msgstr "offset debe ser non-negative y no mayo que la longitud del buffer" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "offset fuera de límites" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -4058,10 +4068,6 @@ msgstr "el tamaño se define solo para ndarrays" msgid "sleep length must be non-negative" msgstr "la longitud de sleep no puede ser negativa" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "el tamaño de la división no puede ser cero" - #: py/nativeglue.c msgid "slice unsupported" msgstr "sin capacidades para rebanado" @@ -4106,6 +4112,10 @@ msgstr "source_bitmap debe tener value_count de 65536" msgid "source_bitmap must have value_count of 8" msgstr "source_bitmap debe tener value_count de 8" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "índices inicio/final" @@ -4118,9 +4128,18 @@ msgstr "stop no se puede alcanzar del principio" msgid "stream operation not supported" msgstr "operación stream no soportada" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" -msgstr "string no soportado; usa bytes o bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "string index fuera de rango" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "índices de string deben ser enteros, no %s" #: extmod/moductypes.c msgid "struct: can't index" @@ -4150,6 +4169,10 @@ msgstr "error de sintaxis en JSON" msgid "syntax error in uctypes descriptor" msgstr "error de sintaxis en el descriptor uctypes" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "" @@ -4424,6 +4447,44 @@ msgstr "zi debe ser de tipo flotante" msgid "zi must be of shape (n_section, 2)" msgstr "zi debe ser una forma (n_section,2)" +#~ msgid "Splitting with sub-captures" +#~ msgstr "Dividiendo con sub-capturas" + +#~ msgid "__init__() should return None, not '%q'" +#~ msgstr "__init__() debe retornar None, no '%q'" + +#~ msgid "attributes not supported yet" +#~ msgstr "atributos aún no soportados" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "no se puede hacer la división truncada de un número complejo" + +#~ msgid "cannot import name %q" +#~ msgstr "no se puede importar name '%q'" + +#~ msgid "cannot unambiguously get sizeof scalar" +#~ msgstr "no se puede sin ambiguedades traer el sizeof del escalar" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "" +#~ "argumento(s) por palabra clave aún no implementados - usa argumentos " +#~ "normales en su lugar" + +#~ msgid "length argument not allowed for this type" +#~ msgstr "argumento length no permitido para este tipo" + +#~ msgid "offset out of bounds" +#~ msgstr "offset fuera de límites" + +#~ msgid "slice step can't be zero" +#~ msgstr "el tamaño de la división no puede ser cero" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "string no soportado; usa bytes o bytearray" + +#~ msgid "Bit clock and word select must be sequential pins" +#~ msgstr "Los pines \"clock\" y \"word-select\" deben ser consecutivos" + #~ msgid "Initialization failed due to lack of memory" #~ msgstr "Inicializacion fallida por falta de memoria" @@ -5870,21 +5931,12 @@ msgstr "zi debe ser una forma (n_section,2)" #~ msgid "Running in safe mode! Auto-reload is off.\n" #~ msgstr "Ejecutando en modo seguro! La auto-recarga esta deshabilitada.\n" -#~ msgid "__init__() should return None, not '%s'" -#~ msgstr "__init__() deberia devolver None, no '%s'" - #~ msgid "can't convert %s to int" #~ msgstr "no se puede convertir %s a int" -#~ msgid "can't convert NaN to int" -#~ msgstr "no se puede convertir Nan a int" - #~ msgid "can't convert address to int" #~ msgstr "no se puede convertir address a int" -#~ msgid "can't convert inf to int" -#~ msgstr "no se puede convertir inf en int" - #~ msgid "object '%s' is not a tuple or list" #~ msgstr "el objeto '%s' no es una tupla o lista" @@ -5897,12 +5949,6 @@ msgstr "zi debe ser una forma (n_section,2)" #~ msgid "popitem(): dictionary is empty" #~ msgstr "popitem(): diccionario vacío" -#~ msgid "string index out of range" -#~ msgstr "string index fuera de rango" - -#~ msgid "string indices must be integers, not %s" -#~ msgstr "índices de string deben ser enteros, no %s" - #~ msgid "unknown format code '%c' for object of type '%s'" #~ msgstr "codigo format desconocido '%c' para el typo de objeto '%s'" diff --git a/locale/fil.po b/locale/fil.po index 73cc68180b..544f37dbb7 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -140,7 +140,7 @@ msgstr "" msgid "%q in use" msgstr "%q ay ginagamit" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "%q indeks wala sa sakop" @@ -227,7 +227,7 @@ msgstr "" msgid "%q must be of type %q or %q, not %q" msgstr "" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -281,6 +281,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -633,7 +638,7 @@ msgid "Below minimum frame rate" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -1110,8 +1115,6 @@ msgstr "" msgid "Generic Failure" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1970,10 +1973,6 @@ msgstr "" msgid "Specify exactly one of data0 or data_pins" msgstr "" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "Binibiyak gamit ang sub-captures" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "" @@ -2412,8 +2411,9 @@ msgid "__init__() should return None" msgstr "__init__() dapat magbalik na None" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "__init__() dapat magbalink na None, hindi '%s'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2502,8 +2502,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "attributes hindi sinusuportahan" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2632,7 +2632,7 @@ msgstr "hindi ma i-assign sa expression" msgid "can't cancel self" msgstr "" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2650,10 +2650,18 @@ msgstr "hindi ma-convert %s sa int" msgid "can't convert '%q' object to %q implicitly" msgstr "hindi maaaring i-convert ang '%q' na bagay sa %q nang walang pahiwatig" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "hindi ma i-convert NaN sa int" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "hindi ma i-convert inf sa int" + #: py/obj.c msgid "can't convert to complex" msgstr "hindi ma-convert sa complex" @@ -2682,15 +2690,14 @@ msgstr "hindi mabura ang expression" msgid "can't do binary op between '%q' and '%q'" msgstr "hindi magawa ang binary op sa gitna ng '%q' at '%q'" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "" -"hindi maaaring gawin ang truncated division ng isang kumplikadong numero" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "hindi maaaring ma-convert ang ' %q' sa 'bool'" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "hidi ma i-load galing sa '%q'" @@ -2745,6 +2752,14 @@ msgstr "" "hindi mapalitan ang manual field specification sa awtomatikong field " "numbering" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2777,18 +2792,10 @@ msgstr "hindi magawa ang instance" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "hindi ma-import ang name %q" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" - #: py/emitnative.c msgid "casting" msgstr "casting" @@ -2837,6 +2844,10 @@ msgstr "color ay dapat mula sa 0x000000 hangang 0xffffff" msgid "comparison of int and uint" msgstr "" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "kumplikadong values hindi sinusuportahan" @@ -3416,10 +3427,8 @@ msgstr "" "object" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" -"kindi pa ipinapatupad ang (mga) argument(s) ng keyword - gumamit ng normal " -"args" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3429,10 +3438,6 @@ msgstr "label '%d' kailangan na i-define" msgid "label redefined" msgstr "ang label ay na-define ulit" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "length argument ay walang pahintulot sa ganitong type" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "" @@ -3519,6 +3524,10 @@ msgstr "nabigo ang paglalaan ng memorya, paglalaan ng %u bytes" msgid "memory allocation failed, heap is locked" msgstr "abigo ang paglalaan ng memorya, ang heap ay naka-lock" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3567,6 +3576,10 @@ msgstr "name '%q' ay hindi defined" msgid "name not defined" msgstr "name hindi na define" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3641,7 +3654,7 @@ msgstr "" msgid "non-default argument follows default argument" msgstr "non-default argument sumusunod sa default argument" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "non-hex digit nahanap" @@ -3731,7 +3744,7 @@ msgstr "object na type '%s' walang len()" msgid "object with buffer protocol required" msgstr "object na may buffer protocol kinakailangan" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "odd-length string" @@ -3751,11 +3764,6 @@ msgstr "" msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -#, fuzzy -msgid "offset out of bounds" -msgstr "wala sa sakop ang address" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -4005,10 +4013,6 @@ msgstr "" msgid "sleep length must be non-negative" msgstr "sleep length ay dapat hindi negatibo" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4053,6 +4057,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "start/end indeks" @@ -4065,9 +4073,18 @@ msgstr "stop hindi maabot sa simula" msgid "stream operation not supported" msgstr "stream operation hindi sinusuportahan" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" -msgstr "string hindi supportado; gumamit ng bytes o kaya bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "indeks ng string wala sa sakop" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "ang indeks ng string ay dapat na integer, hindi %s" #: extmod/moductypes.c msgid "struct: can't index" @@ -4097,6 +4114,10 @@ msgstr "sintaks error sa JSON" msgid "syntax error in uctypes descriptor" msgstr "may pagkakamali sa sintaks sa uctypes descriptor" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "" @@ -4370,6 +4391,34 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "Splitting with sub-captures" +#~ msgstr "Binibiyak gamit ang sub-captures" + +#~ msgid "attributes not supported yet" +#~ msgstr "attributes hindi sinusuportahan" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "" +#~ "hindi maaaring gawin ang truncated division ng isang kumplikadong numero" + +#~ msgid "cannot import name %q" +#~ msgstr "hindi ma-import ang name %q" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "" +#~ "kindi pa ipinapatupad ang (mga) argument(s) ng keyword - gumamit ng " +#~ "normal args" + +#~ msgid "length argument not allowed for this type" +#~ msgstr "length argument ay walang pahintulot sa ganitong type" + +#, fuzzy +#~ msgid "offset out of bounds" +#~ msgstr "wala sa sakop ang address" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "string hindi supportado; gumamit ng bytes o kaya bytearray" + #~ msgid "queue overflow" #~ msgstr "puno na ang pila (overflow)" @@ -4815,21 +4864,12 @@ msgstr "" #~ msgid "Running in safe mode! Auto-reload is off.\n" #~ msgstr "Tumatakbo sa safe mode! Awtomatikong pag re-reload ay OFF.\n" -#~ msgid "__init__() should return None, not '%s'" -#~ msgstr "__init__() dapat magbalink na None, hindi '%s'" - #~ msgid "can't convert %s to int" #~ msgstr "hindi ma-convert %s sa int" -#~ msgid "can't convert NaN to int" -#~ msgstr "hindi ma i-convert NaN sa int" - #~ msgid "can't convert address to int" #~ msgstr "hindi ma i-convert ang address sa INT" -#~ msgid "can't convert inf to int" -#~ msgstr "hindi ma i-convert inf sa int" - #~ msgid "object '%s' is not a tuple or list" #~ msgstr "object '%s' ay hindi tuple o list" @@ -4842,12 +4882,6 @@ msgstr "" #~ msgid "popitem(): dictionary is empty" #~ msgstr "popitem(): dictionary ay walang laman" -#~ msgid "string index out of range" -#~ msgstr "indeks ng string wala sa sakop" - -#~ msgid "string indices must be integers, not %s" -#~ msgstr "ang indeks ng string ay dapat na integer, hindi %s" - #~ msgid "unknown format code '%c' for object of type '%s'" #~ msgstr "hindi alam ang format code '%c' para sa object na ang type ay '%s'" diff --git a/locale/fr.po b/locale/fr.po index 56bbcb466e..e893f4a200 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -151,7 +151,7 @@ msgstr "%q dans %q doit être de type %q, pas %q" msgid "%q in use" msgstr "%q en cours d'utilisation" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "index %q hors de portée" @@ -238,7 +238,7 @@ msgstr "%q doit être array de type 'h'" msgid "%q must be of type %q or %q, not %q" msgstr "%q doit être de type %q ou %q, pas %q" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q doit être de type %q, pas %q" @@ -293,6 +293,11 @@ msgstr "%q[%u] utilise des broches supplémentaires" msgid "%q[%u] waits on input outside of count" msgstr "%q[%u] attend sur une entrée hors du compte" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -644,10 +649,8 @@ msgid "Below minimum frame rate" msgstr "Au-dessous de la fréquence d'images minimale" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" -"La sélection du bit d'horloge et de mot doit être sur des broches " -"séquentielles" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -1141,8 +1144,6 @@ msgstr "Initialisation GNSS" msgid "Generic Failure" msgstr "Échec génerique" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -2021,10 +2022,6 @@ msgstr "Les tampons source et de destination doivent être de la même longueur" msgid "Specify exactly one of data0 or data_pins" msgstr "Spécifiez une unique broche parmi data0 ou data_pins" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "Fractionnement avec des sous-captures" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "Canal stéréo gauche doit être sur le canal PWM A" @@ -2478,8 +2475,9 @@ msgid "__init__() should return None" msgstr "__init__() doit retourner None" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "__init__() doit retourner None, pas '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "__init__() doit retourner None, pas '%s'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2568,8 +2566,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "tenter d'obtenir argmin / argmax d'une séquence vide" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "attribut pas encore supporté" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2697,7 +2695,7 @@ msgstr "ne peut pas assigner à une expression" msgid "can't cancel self" msgstr "ne peut pas s'annuler soi-même" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "impossible de convertir %q en %q" @@ -2715,10 +2713,18 @@ msgstr "ne peut convertir %s en nombre à virgule flottante 'float'" msgid "can't convert '%q' object to %q implicitly" msgstr "impossible de convertir l'objet '%q' en '%q' implicitement" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "on ne peut convertir NaN en entier 'int'" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "ne peut convertir un complexe en flottant" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "on ne peut convertir l'infini 'inf' en entier 'int'" + #: py/obj.c msgid "can't convert to complex" msgstr "ne peut convertir en nombre complexe" @@ -2747,14 +2753,14 @@ msgstr "ne peut pas supprimer l'expression" msgid "can't do binary op between '%q' and '%q'" msgstr "opération binaire impossible entre '%q' et '%q'" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "on ne peut pas faire de division tronquée de nombres complexes" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "impossible de convertir implicitement '%q' en 'bool'" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "impossible de charger depuis '%q'" @@ -2811,6 +2817,14 @@ msgstr "" "impossible de passer d'une spécification manuelle des champs à une " "énumération auto" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2843,18 +2857,10 @@ msgstr "ne peut pas créer une instance" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "ne peut pas importer le nom %q" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "ne peut récupérer sans ambigüité le sizeof d'un scalaire" - #: py/emitnative.c msgid "casting" msgstr "typage" @@ -2906,6 +2912,10 @@ msgstr "la couleur doit être entre 0x000000 et 0xffffff" msgid "comparison of int and uint" msgstr "comparaison entre int et uint" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "valeurs complexes non supportées" @@ -3488,10 +3498,8 @@ msgstr "" "'join' s'attend à une liste d'objets str/bytes cohérents avec l'objet self" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" -"argument(s) nommé(s) pas encore implémenté(s) - utilisez les arguments " -"normaux" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3501,10 +3509,6 @@ msgstr "label '%q' non supporté" msgid "label redefined" msgstr "étiquette redéfinie" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "paramètre 'length' non-permis pour ce type" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "le niveau doit être compris entre 0 et 1" @@ -3591,6 +3595,10 @@ msgstr "l'allocation de mémoire a échoué en allouant %u octets" msgid "memory allocation failed, heap is locked" msgstr "l'allocation de mémoire a échoué, le tas est vérrouillé" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "memoryview: length n'est pas un multiple de itemsize" @@ -3639,6 +3647,10 @@ msgstr "nom '%q' non défini" msgid "name not defined" msgstr "nom non défini" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "la méthode native est trop longue" @@ -3714,7 +3726,7 @@ msgid "non-default argument follows default argument" msgstr "" "un argument sans valeur par défaut suit un argument avec valeur par défaut" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "chiffre non-héxadécimale trouvé" @@ -3805,7 +3817,7 @@ msgstr "l'objet de type '%s' n'a pas de len()" msgid "object with buffer protocol required" msgstr "un objet avec un protocole de tampon est nécessaire" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "chaîne de longueur impaire" @@ -3826,10 +3838,6 @@ msgid "offset must be non-negative and no greater than buffer length" msgstr "" "offset ne doit pas être négatif, et pas plus grand que la taille du tampon" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "décalage hors limites" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -4079,10 +4087,6 @@ msgstr "la taille n'est définie que pour les ndarrays" msgid "sleep length must be non-negative" msgstr "la longueur de sleep ne doit pas être négative" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "le pas 'step' de la tranche ne peut être zéro" - #: py/nativeglue.c msgid "slice unsupported" msgstr "slice non-supporté" @@ -4127,6 +4131,10 @@ msgstr "source_bitmap doit avoir une value_count de 65536" msgid "source_bitmap must have value_count of 8" msgstr "source_bitmap doit avoir une value_count de 8" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "indices de début/fin" @@ -4139,10 +4147,18 @@ msgstr "stop n'est pas accessible au démarrage" msgid "stream operation not supported" msgstr "opération de flux non supportée" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" msgstr "" -"chaîne de carac. non supportée; utilisez des bytes ou une matrice de bytes" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "index de chaîne hors gamme" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "les indices de chaîne de caractères doivent être des entiers, pas %s" #: extmod/moductypes.c msgid "struct: can't index" @@ -4172,6 +4188,10 @@ msgstr "erreur de syntaxe JSON" msgid "syntax error in uctypes descriptor" msgstr "erreur de syntaxe dans le descripteur d'uctypes" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "le délai d'expiration a dépassé la valeur maximale prise en charge" @@ -4445,6 +4465,47 @@ msgstr "zi doit être de type float" msgid "zi must be of shape (n_section, 2)" msgstr "zi doit être de forme (n_section, 2)" +#~ msgid "Splitting with sub-captures" +#~ msgstr "Fractionnement avec des sous-captures" + +#~ msgid "__init__() should return None, not '%q'" +#~ msgstr "__init__() doit retourner None, pas '%q'" + +#~ msgid "attributes not supported yet" +#~ msgstr "attribut pas encore supporté" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "on ne peut pas faire de division tronquée de nombres complexes" + +#~ msgid "cannot import name %q" +#~ msgstr "ne peut pas importer le nom %q" + +#~ msgid "cannot unambiguously get sizeof scalar" +#~ msgstr "ne peut récupérer sans ambigüité le sizeof d'un scalaire" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "" +#~ "argument(s) nommé(s) pas encore implémenté(s) - utilisez les arguments " +#~ "normaux" + +#~ msgid "length argument not allowed for this type" +#~ msgstr "paramètre 'length' non-permis pour ce type" + +#~ msgid "offset out of bounds" +#~ msgstr "décalage hors limites" + +#~ msgid "slice step can't be zero" +#~ msgstr "le pas 'step' de la tranche ne peut être zéro" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "" +#~ "chaîne de carac. non supportée; utilisez des bytes ou une matrice de bytes" + +#~ msgid "Bit clock and word select must be sequential pins" +#~ msgstr "" +#~ "La sélection du bit d'horloge et de mot doit être sur des broches " +#~ "séquentielles" + #~ msgid "Initialization failed due to lack of memory" #~ msgstr "Échec d'initialisation par manque de mémoire" @@ -5920,21 +5981,12 @@ msgstr "zi doit être de forme (n_section, 2)" #~ msgid "Running in safe mode! Auto-reload is off.\n" #~ msgstr "Mode sans-échec ! Auto-chargement désactivé.\n" -#~ msgid "__init__() should return None, not '%s'" -#~ msgstr "__init__() doit retourner None, pas '%s'" - #~ msgid "can't convert %s to int" #~ msgstr "ne peut convertir %s en entier 'int'" -#~ msgid "can't convert NaN to int" -#~ msgstr "on ne peut convertir NaN en entier 'int'" - #~ msgid "can't convert address to int" #~ msgstr "ne peut convertir l'adresse en entier 'int'" -#~ msgid "can't convert inf to int" -#~ msgstr "on ne peut convertir l'infini 'inf' en entier 'int'" - #~ msgid "object '%s' is not a tuple or list" #~ msgstr "l'objet '%s' n'est pas un tuple ou une liste" @@ -5947,13 +5999,6 @@ msgstr "zi doit être de forme (n_section, 2)" #~ msgid "popitem(): dictionary is empty" #~ msgstr "popitem() : dictionnaire vide" -#~ msgid "string index out of range" -#~ msgstr "index de chaîne hors gamme" - -#~ msgid "string indices must be integers, not %s" -#~ msgstr "" -#~ "les indices de chaîne de caractères doivent être des entiers, pas %s" - #~ msgid "unknown format code '%c' for object of type '%s'" #~ msgstr "code de format '%c' inconnu pour un objet de type '%s'" diff --git a/locale/hi.po b/locale/hi.po index 2551d5b725..68f039aa3f 100644 --- a/locale/hi.po +++ b/locale/hi.po @@ -139,7 +139,7 @@ msgstr "" msgid "%q in use" msgstr "" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "" @@ -226,7 +226,7 @@ msgstr "" msgid "%q must be of type %q or %q, not %q" msgstr "" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -279,6 +279,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -628,7 +633,7 @@ msgid "Below minimum frame rate" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -1100,8 +1105,6 @@ msgstr "" msgid "Generic Failure" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1956,10 +1959,6 @@ msgstr "" msgid "Specify exactly one of data0 or data_pins" msgstr "" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "" @@ -2396,7 +2395,8 @@ msgid "__init__() should return None" msgstr "" #: py/objtype.c -msgid "__init__() should return None, not '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" msgstr "" #: py/objobject.c @@ -2486,7 +2486,7 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "" #: py/objstr.c -msgid "attributes not supported yet" +msgid "attributes not supported" msgstr "" #: extmod/ulab/code/ulab_tools.c @@ -2614,7 +2614,7 @@ msgstr "" msgid "can't cancel self" msgstr "" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2632,10 +2632,18 @@ msgstr "" msgid "can't convert '%q' object to %q implicitly" msgstr "" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "" + #: py/obj.c msgid "can't convert to complex" msgstr "" @@ -2664,14 +2672,14 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "" @@ -2722,6 +2730,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2754,18 +2770,10 @@ msgstr "" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" - #: py/emitnative.c msgid "casting" msgstr "" @@ -2814,6 +2822,10 @@ msgstr "" msgid "comparison of int and uint" msgstr "" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "" @@ -3386,7 +3398,7 @@ msgid "join expects a list of str/bytes objects consistent with self object" msgstr "" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -3397,10 +3409,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "" @@ -3487,6 +3495,10 @@ msgstr "" msgid "memory allocation failed, heap is locked" msgstr "" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3535,6 +3547,10 @@ msgstr "" msgid "name not defined" msgstr "" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3609,7 +3625,7 @@ msgstr "" msgid "non-default argument follows default argument" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "" @@ -3699,7 +3715,7 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "" @@ -3719,10 +3735,6 @@ msgstr "" msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -3971,10 +3983,6 @@ msgstr "" msgid "sleep length must be non-negative" msgstr "" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4019,6 +4027,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" @@ -4031,8 +4043,17 @@ msgstr "" msgid "stream operation not supported" msgstr "" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" msgstr "" #: extmod/moductypes.c @@ -4063,6 +4084,10 @@ msgstr "" msgid "syntax error in uctypes descriptor" msgstr "" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "" diff --git a/locale/it_IT.po b/locale/it_IT.po index f1cffe5e49..5e29b93b7d 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -143,7 +143,7 @@ msgstr "" msgid "%q in use" msgstr "%q in uso" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "indice %q fuori intervallo" @@ -230,7 +230,7 @@ msgstr "" msgid "%q must be of type %q or %q, not %q" msgstr "" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -283,6 +283,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -636,7 +641,7 @@ msgid "Below minimum frame rate" msgstr "Al di sotto del frame rate minimo" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -1112,8 +1117,6 @@ msgstr "" msgid "Generic Failure" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1977,10 +1980,6 @@ msgstr "" msgid "Specify exactly one of data0 or data_pins" msgstr "" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "Suddivisione con sotto-catture" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "" @@ -2419,8 +2418,9 @@ msgid "__init__() should return None" msgstr "__init__() deve ritornare None" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "__init__() deve ritornare None, non '%s'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2509,8 +2509,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "attributi non ancora supportati" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2641,7 +2641,7 @@ msgstr "impossibile assegnare all'espressione" msgid "can't cancel self" msgstr "" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2659,10 +2659,18 @@ msgstr "non è possibile convertire %s a float" msgid "can't convert '%q' object to %q implicitly" msgstr "impossibile convertire l'oggetto '%q' implicitamente in %q" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "impossibile convertire NaN in int" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "impossibile convertire inf in int" + #: py/obj.c msgid "can't convert to complex" msgstr "non è possibile convertire a complex" @@ -2691,14 +2699,14 @@ msgstr "impossibile cancellare l'espessione" msgid "can't do binary op between '%q' and '%q'" msgstr "impossibile eseguire operazione binaria tra '%q' e '%q'" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "impossibile fare il modulo di un numero complesso" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "non è possibile convertire implicitamente '%q' in 'bool'" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "impossibile caricare da '%q'" @@ -2749,6 +2757,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2781,18 +2797,10 @@ msgstr "impossibile creare un istanza" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "impossibile imporate il nome %q" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" - #: py/emitnative.c msgid "casting" msgstr "casting" @@ -2843,6 +2851,10 @@ msgstr "il colore deve essere compreso tra 0x000000 e 0xffffff" msgid "comparison of int and uint" msgstr "" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "valori complessi non supportai" @@ -3422,10 +3434,8 @@ msgstr "" "join prende una lista di oggetti str/byte consistenti con l'oggetto stesso" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" -"argomento(i) nominati non ancora implementati - usare invece argomenti " -"normali" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3435,10 +3445,6 @@ msgstr "etichetta '%q' non definita" msgid "label redefined" msgstr "etichetta ridefinita" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "" @@ -3525,6 +3531,10 @@ msgstr "allocazione di memoria fallita, allocando %u byte" msgid "memory allocation failed, heap is locked" msgstr "allocazione di memoria fallita, l'heap è bloccato" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3573,6 +3583,10 @@ msgstr "nome '%q'non definito" msgid "name not defined" msgstr "nome non definito" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3647,7 +3661,7 @@ msgstr "" msgid "non-default argument follows default argument" msgstr "argomento non predefinito segue argmoento predfinito" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "trovata cifra non esadecimale" @@ -3739,7 +3753,7 @@ msgstr "l'oggetto di tipo '%s' non implementa len()" msgid "object with buffer protocol required" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "stringa di lunghezza dispari" @@ -3759,11 +3773,6 @@ msgstr "" msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -#, fuzzy -msgid "offset out of bounds" -msgstr "indirizzo fuori limite" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -4015,10 +4024,6 @@ msgstr "" msgid "sleep length must be non-negative" msgstr "la lunghezza di sleed deve essere non negativa" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4063,6 +4068,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" @@ -4075,10 +4084,19 @@ msgstr "stop non raggiungibile dall'inizio" msgid "stream operation not supported" msgstr "operazione di stream non supportata" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" msgstr "" +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "indice della stringa fuori intervallo" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "indici della stringa devono essere interi, non %s" + #: extmod/moductypes.c msgid "struct: can't index" msgstr "" @@ -4107,6 +4125,10 @@ msgstr "errore di sintassi nel JSON" msgid "syntax error in uctypes descriptor" msgstr "errore di sintassi nel descrittore uctypes" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "" @@ -4380,6 +4402,27 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "Splitting with sub-captures" +#~ msgstr "Suddivisione con sotto-catture" + +#~ msgid "attributes not supported yet" +#~ msgstr "attributi non ancora supportati" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "impossibile fare il modulo di un numero complesso" + +#~ msgid "cannot import name %q" +#~ msgstr "impossibile imporate il nome %q" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "" +#~ "argomento(i) nominati non ancora implementati - usare invece argomenti " +#~ "normali" + +#, fuzzy +#~ msgid "offset out of bounds" +#~ msgstr "indirizzo fuori limite" + #~ msgid "ADC2 is being used by WiFi" #~ msgstr "ADC2 sta usando il WiFi" @@ -4874,21 +4917,12 @@ msgstr "" #~ msgid "Running in safe mode! Auto-reload is off.\n" #~ msgstr "Modalità sicura in esecuzione! Auto-reload disattivato.\n" -#~ msgid "__init__() should return None, not '%s'" -#~ msgstr "__init__() deve ritornare None, non '%s'" - #~ msgid "can't convert %s to int" #~ msgstr "non è possibile convertire %s a int" -#~ msgid "can't convert NaN to int" -#~ msgstr "impossibile convertire NaN in int" - #~ msgid "can't convert address to int" #~ msgstr "impossible convertire indirizzo in int" -#~ msgid "can't convert inf to int" -#~ msgstr "impossibile convertire inf in int" - #~ msgid "object '%s' is not a tuple or list" #~ msgstr "oggetto '%s' non è una tupla o una lista" @@ -4901,12 +4935,6 @@ msgstr "" #~ msgid "popitem(): dictionary is empty" #~ msgstr "popitem(): il dizionario è vuoto" -#~ msgid "string index out of range" -#~ msgstr "indice della stringa fuori intervallo" - -#~ msgid "string indices must be integers, not %s" -#~ msgstr "indici della stringa devono essere interi, non %s" - #~ msgid "unknown format code '%c' for object of type '%s'" #~ msgstr "codice di formattaione '%c' sconosciuto per oggetto di tipo '%s'" diff --git a/locale/ja.po b/locale/ja.po index 07e65422a6..0187d60a46 100644 --- a/locale/ja.po +++ b/locale/ja.po @@ -146,7 +146,7 @@ msgstr "" msgid "%q in use" msgstr "%qã¯ä½¿ç”¨ä¸­" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "%q インデックスã¯ç¯„囲外" @@ -233,7 +233,7 @@ msgstr "" msgid "%q must be of type %q or %q, not %q" msgstr "" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -286,6 +286,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -637,7 +642,7 @@ msgid "Below minimum frame rate" msgstr "最低ã®ãƒ•ãƒ¬ãƒ¼ãƒ ãƒ¬ãƒ¼ãƒˆæœªæº€" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -1111,8 +1116,6 @@ msgstr "" msgid "Generic Failure" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1970,10 +1973,6 @@ msgstr "ãƒãƒƒãƒ•ã‚¡ (å…ƒ/å…ˆ) ã¯åŒã˜é•·ã•ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“" msgid "Specify exactly one of data0 or data_pins" msgstr "" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "" @@ -2411,7 +2410,8 @@ msgid "__init__() should return None" msgstr "" #: py/objtype.c -msgid "__init__() should return None, not '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" msgstr "" #: py/objobject.c @@ -2501,8 +2501,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "属性ã¯æœªå¯¾å¿œã§ã™" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2629,7 +2629,7 @@ msgstr "å¼ã«ã¯ä»£å…¥ã§ãã¾ã›ã‚“" msgid "can't cancel self" msgstr "" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "%qã‚’%qã«å¤‰æ›ã§ãã¾ã›ã‚“" @@ -2647,10 +2647,18 @@ msgstr "" msgid "can't convert '%q' object to %q implicitly" msgstr "オブジェクト '%q' ã‚’ %q ã«æš—é»™ã«å¤‰æ›ã§ãã¾ã›ã‚“" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "" + #: py/obj.c msgid "can't convert to complex" msgstr "" @@ -2679,14 +2687,14 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "複素数ã®åˆ‡ã‚Šæ¨ã¦é™¤ç®—ã¯ã§ãã¾ã›ã‚“" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "" @@ -2737,6 +2745,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "手動ã¨è‡ªå‹•ã®ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰æŒ‡å®šã¯æ··åœ¨ã§ãã¾ã›ã‚“" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2769,18 +2785,10 @@ msgstr "インスタンスを作れã¾ã›ã‚“" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" - #: py/emitnative.c msgid "casting" msgstr "" @@ -2831,6 +2839,10 @@ msgstr "色ã¯0x000000ã‹ã‚‰0xffffffã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“" msgid "comparison of int and uint" msgstr "" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "" @@ -3406,8 +3418,8 @@ msgid "join expects a list of str/bytes objects consistent with self object" msgstr "joinã«ã¯ str/bytes (ã®ã†ã¡è‡ªèº«ã¨ä¸€è‡´ã—ãŸåž‹ã®) リストãŒå¿…è¦" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" -msgstr "キーワード引数ã¯æœªå®Ÿè£…。通常ã®å¼•æ•°ã‚’使ã£ã¦ãã ã•ã„" +msgid "keyword argument(s) not implemented - use normal args instead" +msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3417,10 +3429,6 @@ msgstr "ラベル'%q'ã¯å®šç¾©ã•ã‚Œã¦ã„ã¾ã›ã‚“" msgid "label redefined" msgstr "ラベルã®å†å®šç¾©" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "levelã¯0ã‹ã‚‰1ã®é–“ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“" @@ -3507,6 +3515,10 @@ msgstr "" msgid "memory allocation failed, heap is locked" msgstr "メモリ確ä¿ã«å¤±æ•—。ヒープãŒãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3555,6 +3567,10 @@ msgstr "åå‰ '%q' ã¯å®šç¾©ã•ã‚Œã¦ã„ã¾ã›ã‚“" msgid "name not defined" msgstr "åå‰ãŒå®šç¾©ã•ã‚Œã¦ã„ã¾ã›ã‚“" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3629,7 +3645,7 @@ msgstr "" msgid "non-default argument follows default argument" msgstr "デフォルト引数ã®å¾Œã«é€šå¸¸ã®å¼•æ•°ã¯ç½®ã‘ã¾ã›ã‚“" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "16進数以外ã®æ¡ãŒã‚ã‚Šã¾ã™" @@ -3719,7 +3735,7 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "奇数長ã®æ–‡å­—列" @@ -3739,10 +3755,6 @@ msgstr "" msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -3991,10 +4003,6 @@ msgstr "" msgid "sleep length must be non-negative" msgstr "sleepã®é•·ã•ã¯éžè² æ•°ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "スライスã®ã‚¹ãƒ†ãƒƒãƒ—ã¯0ã«ã§ãã¾ã›ã‚“" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4039,6 +4047,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" @@ -4051,9 +4063,18 @@ msgstr "" msgid "stream operation not supported" msgstr "ストリームæ“作ã¯éžå¯¾å¿œ" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" -msgstr "文字列ã§ã¯ãªãbytesã¾ãŸã¯bytesarrayãŒå¿…è¦" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "" #: extmod/moductypes.c msgid "struct: can't index" @@ -4083,6 +4104,10 @@ msgstr "JSONã«æ§‹æ–‡ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã™" msgid "syntax error in uctypes descriptor" msgstr "uctypedディスクリプタã®æ§‹æ–‡ã‚¨ãƒ©ãƒ¼" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "タイムアウト長ã¯å¯¾å¿œã™ã‚‹æœ€å¤§å€¤ã‚’超ãˆã¦ã„ã¾ã™" @@ -4356,6 +4381,21 @@ msgstr "ziã¯float値ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "attributes not supported yet" +#~ msgstr "属性ã¯æœªå¯¾å¿œã§ã™" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "複素数ã®åˆ‡ã‚Šæ¨ã¦é™¤ç®—ã¯ã§ãã¾ã›ã‚“" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "キーワード引数ã¯æœªå®Ÿè£…。通常ã®å¼•æ•°ã‚’使ã£ã¦ãã ã•ã„" + +#~ msgid "slice step can't be zero" +#~ msgstr "スライスã®ã‚¹ãƒ†ãƒƒãƒ—ã¯0ã«ã§ãã¾ã›ã‚“" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "文字列ã§ã¯ãªãbytesã¾ãŸã¯bytesarrayãŒå¿…è¦" + #~ msgid "WatchDogTimer is not currently running" #~ msgstr "WatchDogTimerã¯ç¾åœ¨å‹•ä½œã—ã¦ã„ã¾ã›ã‚“" diff --git a/locale/ko.po b/locale/ko.po index 28e233fcf0..0c99906e54 100644 --- a/locale/ko.po +++ b/locale/ko.po @@ -140,7 +140,7 @@ msgstr "" msgid "%q in use" msgstr "%q 사용 중입니다" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "%q ì¸ë±ìŠ¤ 범위를 벗어났습니다" @@ -227,7 +227,7 @@ msgstr "" msgid "%q must be of type %q or %q, not %q" msgstr "" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -280,6 +280,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -631,7 +636,7 @@ msgid "Below minimum frame rate" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -1103,8 +1108,6 @@ msgstr "" msgid "Generic Failure" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1959,10 +1962,6 @@ msgstr "" msgid "Specify exactly one of data0 or data_pins" msgstr "" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "" @@ -2400,7 +2399,8 @@ msgid "__init__() should return None" msgstr "" #: py/objtype.c -msgid "__init__() should return None, not '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" msgstr "" #: py/objobject.c @@ -2490,7 +2490,7 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "" #: py/objstr.c -msgid "attributes not supported yet" +msgid "attributes not supported" msgstr "" #: extmod/ulab/code/ulab_tools.c @@ -2618,7 +2618,7 @@ msgstr "" msgid "can't cancel self" msgstr "" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2636,10 +2636,18 @@ msgstr "" msgid "can't convert '%q' object to %q implicitly" msgstr "" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "" + #: py/obj.c msgid "can't convert to complex" msgstr "" @@ -2668,14 +2676,14 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "" @@ -2726,6 +2734,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2758,18 +2774,10 @@ msgstr "" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" - #: py/emitnative.c msgid "casting" msgstr "" @@ -2818,6 +2826,10 @@ msgstr "" msgid "comparison of int and uint" msgstr "" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "" @@ -3390,7 +3402,7 @@ msgid "join expects a list of str/bytes objects consistent with self object" msgstr "" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -3401,10 +3413,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "" @@ -3491,6 +3499,10 @@ msgstr "" msgid "memory allocation failed, heap is locked" msgstr "" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3539,6 +3551,10 @@ msgstr "" msgid "name not defined" msgstr "" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3613,7 +3629,7 @@ msgstr "" msgid "non-default argument follows default argument" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "" @@ -3703,7 +3719,7 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "" @@ -3723,10 +3739,6 @@ msgstr "" msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -3975,10 +3987,6 @@ msgstr "" msgid "sleep length must be non-negative" msgstr "" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4023,6 +4031,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" @@ -4035,8 +4047,17 @@ msgstr "" msgid "stream operation not supported" msgstr "" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" msgstr "" #: extmod/moductypes.c @@ -4067,6 +4088,10 @@ msgstr "" msgid "syntax error in uctypes descriptor" msgstr "" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "" diff --git a/locale/nl.po b/locale/nl.po index 84e4a981da..1e249dc534 100644 --- a/locale/nl.po +++ b/locale/nl.po @@ -139,7 +139,7 @@ msgstr "" msgid "%q in use" msgstr "%q in gebruik" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "%q index buiten bereik" @@ -226,7 +226,7 @@ msgstr "" msgid "%q must be of type %q or %q, not %q" msgstr "" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -279,6 +279,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -630,7 +635,7 @@ msgid "Below minimum frame rate" msgstr "Onder de minimum frame rate" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -1106,8 +1111,6 @@ msgstr "" msgid "Generic Failure" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1975,10 +1978,6 @@ msgstr "Bron en bestemming buffers moeten dezelfde lengte hebben" msgid "Specify exactly one of data0 or data_pins" msgstr "" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "Splitting met sub-captures" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "" @@ -2419,8 +2418,9 @@ msgid "__init__() should return None" msgstr "__init __() zou None moeten retourneren" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "__init__() moet None teruggeven, niet '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "__init __ () zou None moeten retouneren, niet '%s'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2509,8 +2509,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "poging om argmin/argmax van een lege sequentie te krijgen" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "attributen nog niet ondersteund" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2638,7 +2638,7 @@ msgstr "kan niet toewijzen aan expressie" msgid "can't cancel self" msgstr "" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "kan %q niet naar %q converteren" @@ -2656,10 +2656,18 @@ msgstr "kan %s niet omzetten naar een float" msgid "can't convert '%q' object to %q implicitly" msgstr "kan '%q' object niet omzetten naar %q impliciet" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "kan NaN niet omzetten naar int" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "kan inf niet omzetten naar int" + #: py/obj.c msgid "can't convert to complex" msgstr "kan niet omzetten naar complex" @@ -2688,14 +2696,14 @@ msgstr "kan expressie niet verwijderen" msgid "can't do binary op between '%q' and '%q'" msgstr "kan geen een binaire operatie doen tussen '%q' en '%q'" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "kan geen afgekapte deling doen van een comlex nummer" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "kan '%q niet impliciet converteren naar 'bool'" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "kan niet laden van '%q'" @@ -2746,6 +2754,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "kan niet schakelen tussen handmatige en automatische veld specificatie" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2778,18 +2794,10 @@ msgstr "kan geen instantie creëren" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "kan naam %q niet importeren" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" - #: py/emitnative.c msgid "casting" msgstr "casting" @@ -2838,6 +2846,10 @@ msgstr "kleur moet tussen 0x000000 en 0xffffff liggen" msgid "comparison of int and uint" msgstr "" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "complexe waardes niet ondersteund" @@ -3415,9 +3427,8 @@ msgstr "" "self-object" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" -"trefwoord argument(en) zijn niet geïmplementeerd, gebruik normale argumenten" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3427,10 +3438,6 @@ msgstr "label '%q' is niet gedefinieerd" msgid "label redefined" msgstr "label opnieuw gedefinieerd" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "voor dit type is length niet toegestaan" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "level moet tussen 0 en 1 liggen" @@ -3517,6 +3524,10 @@ msgstr "geheugentoewijzing mislukt, %u bytes worden toegewezen" msgid "memory allocation failed, heap is locked" msgstr "geheugentoewijzing mislukt, heap is vergrendeld" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3565,6 +3576,10 @@ msgstr "naam '%q' is niet gedefinieerd" msgid "name not defined" msgstr "naam is niet gedefinieerd" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3639,7 +3654,7 @@ msgstr "niet-UUID gevonden in service_uuids_whitelist" msgid "non-default argument follows default argument" msgstr "niet-standaard argument volgt op een standaard argument" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "er werd een niet-hexadecimaal cijfer gevonden" @@ -3729,7 +3744,7 @@ msgstr "object van type '%s' heeft geen len()" msgid "object with buffer protocol required" msgstr "object met buffer protocol vereist" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "string met oneven lengte" @@ -3749,10 +3764,6 @@ msgstr "compensatie moet groter of gelijk 0 zijn" msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "offset buiten bereik" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -4001,10 +4012,6 @@ msgstr "omvang is alleen voor ndarrays gedefinieerd" msgid "sleep length must be non-negative" msgstr "de slaapduur mag niet negatief zijn" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "segmentstap mag niet nul zijn" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4049,6 +4056,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "start/stop indices" @@ -4061,9 +4072,18 @@ msgstr "stop is niet bereikbaar vanaf start" msgid "stream operation not supported" msgstr "stream operatie niet ondersteund" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" -msgstr "string niet ondersteund; gebruik bytes of bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "string index buiten bereik" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "string indices moeten integer zijn, niet %s" #: extmod/moductypes.c msgid "struct: can't index" @@ -4093,6 +4113,10 @@ msgstr "syntaxisfout in JSON" msgid "syntax error in uctypes descriptor" msgstr "syntaxisfout in uctypes aanduiding" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "time-outduur is groter dan de ondersteunde maximale waarde" @@ -4366,6 +4390,38 @@ msgstr "zi moet van type float zijn" msgid "zi must be of shape (n_section, 2)" msgstr "zi moet vorm (n_section, 2) hebben" +#~ msgid "Splitting with sub-captures" +#~ msgstr "Splitting met sub-captures" + +#~ msgid "__init__() should return None, not '%q'" +#~ msgstr "__init__() moet None teruggeven, niet '%q'" + +#~ msgid "attributes not supported yet" +#~ msgstr "attributen nog niet ondersteund" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "kan geen afgekapte deling doen van een comlex nummer" + +#~ msgid "cannot import name %q" +#~ msgstr "kan naam %q niet importeren" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "" +#~ "trefwoord argument(en) zijn niet geïmplementeerd, gebruik normale " +#~ "argumenten" + +#~ msgid "length argument not allowed for this type" +#~ msgstr "voor dit type is length niet toegestaan" + +#~ msgid "offset out of bounds" +#~ msgstr "offset buiten bereik" + +#~ msgid "slice step can't be zero" +#~ msgstr "segmentstap mag niet nul zijn" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "string niet ondersteund; gebruik bytes of bytearray" + #~ msgid "Initialization failed due to lack of memory" #~ msgstr "De initialisatie is mislukt vanwege een gebrek aan geheugen" @@ -5435,21 +5491,12 @@ msgstr "zi moet vorm (n_section, 2) hebben" #~ msgid "Running in safe mode! Auto-reload is off.\n" #~ msgstr "Draaiende in veilige modus! Auto-herlaad is uit.\n" -#~ msgid "__init__() should return None, not '%s'" -#~ msgstr "__init __ () zou None moeten retouneren, niet '%s'" - #~ msgid "can't convert %s to int" #~ msgstr "kan %s niet omzetten naar een int" -#~ msgid "can't convert NaN to int" -#~ msgstr "kan NaN niet omzetten naar int" - #~ msgid "can't convert address to int" #~ msgstr "kan adres niet omzetten naar int" -#~ msgid "can't convert inf to int" -#~ msgstr "kan inf niet omzetten naar int" - #~ msgid "object '%s' is not a tuple or list" #~ msgstr "object '%s' is geen tuple of lijst" @@ -5462,12 +5509,6 @@ msgstr "zi moet vorm (n_section, 2) hebben" #~ msgid "popitem(): dictionary is empty" #~ msgstr "popitem(): dictionary is leeg" -#~ msgid "string index out of range" -#~ msgstr "string index buiten bereik" - -#~ msgid "string indices must be integers, not %s" -#~ msgstr "string indices moeten integer zijn, niet %s" - #~ msgid "unknown format code '%c' for object of type '%s'" #~ msgstr "onbekende formaatcode '%c' voor object van type '%s'" diff --git a/locale/pl.po b/locale/pl.po index 230e11033e..6d61250df3 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -141,7 +141,7 @@ msgstr "" msgid "%q in use" msgstr "%q w użyciu" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "%q poza zakresem" @@ -228,7 +228,7 @@ msgstr "" msgid "%q must be of type %q or %q, not %q" msgstr "" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -281,6 +281,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -632,7 +637,7 @@ msgid "Below minimum frame rate" msgstr "Poniżej minimalnej liczby klatek na sekundÄ™" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -1106,8 +1111,6 @@ msgstr "" msgid "Generic Failure" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1962,10 +1965,6 @@ msgstr "Bufory źródÅ‚owy i docelowy muszÄ… mieć takÄ… samÄ… dÅ‚ugość" msgid "Specify exactly one of data0 or data_pins" msgstr "" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "PodziaÅ‚ z podgrupami" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "" @@ -2402,8 +2401,9 @@ msgid "__init__() should return None" msgstr "__init__() powinien zwracać None" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "__init__() powinno zwrócić None, a nie '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "__init__() powinien zwracać None, nie '%s'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2492,8 +2492,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "atrybuty nie sÄ… jeszcze obsÅ‚ugiwane" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2620,7 +2620,7 @@ msgstr "przypisanie do wyrażenia" msgid "can't cancel self" msgstr "" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "nie można dokonać konwersji %q na %q" @@ -2638,10 +2638,18 @@ msgstr "nie można skonwertować %s do float" msgid "can't convert '%q' object to %q implicitly" msgstr "nie można automatycznie skonwertować '%q' do '%q'" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "nie można skonwertować NaN do int" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "nie można skonwertować inf do int" + #: py/obj.c msgid "can't convert to complex" msgstr "nie można skonwertować do complex" @@ -2670,14 +2678,14 @@ msgstr "nie można usunąć wyrażenia" msgid "can't do binary op between '%q' and '%q'" msgstr "nie można użyć operatora pomiÄ™dzy '%q' a '%q'" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "nie można wykonać dzielenia caÅ‚kowitego na liczbie zespolonej" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "nie można automatyczne skonwertować '%q' do 'bool'" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "nie można Å‚adować z '%q'" @@ -2728,6 +2736,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "nie można zmienić z rÄ™cznego numerowaniu pól do automatycznego" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2760,18 +2776,10 @@ msgstr "nie można stworzyć instancji" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "nie można zaimportować nazwy %q" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" - #: py/emitnative.c msgid "casting" msgstr "rzutowanie" @@ -2820,6 +2828,10 @@ msgstr "kolor musi być pomiÄ™dzy 0x000000 a 0xffffff" msgid "comparison of int and uint" msgstr "" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "wartoÅ›ci zespolone nieobsÅ‚ugiwane" @@ -3393,8 +3405,8 @@ msgid "join expects a list of str/bytes objects consistent with self object" msgstr "join oczekuje listy str/bytes zgodnych z self" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" -msgstr "argumenty nazwane nieobsÅ‚ugiwane - proszÄ™ użyć zwykÅ‚ych argumentów" +msgid "keyword argument(s) not implemented - use normal args instead" +msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3404,10 +3416,6 @@ msgstr "etykieta '%q' niezdefiniowana" msgid "label redefined" msgstr "etykieta przedefiniowana" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "ten typ nie pozawala na podanie dÅ‚ugoÅ›ci" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "" @@ -3494,6 +3502,10 @@ msgstr "alokacja pamiÄ™ci nie powiodÅ‚a siÄ™, alokowano %u bajtów" msgid "memory allocation failed, heap is locked" msgstr "alokacja pamiÄ™ci nie powiodÅ‚a siÄ™, sterta zablokowana" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3542,6 +3554,10 @@ msgstr "nazwa '%q' niezdefiniowana" msgid "name not defined" msgstr "nazwa niezdefiniowana" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3616,7 +3632,7 @@ msgstr "" msgid "non-default argument follows default argument" msgstr "argument z wartoÅ›ciÄ… domyÅ›lnÄ… przed argumentem bez" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "cyfra nieszesnastkowa" @@ -3706,7 +3722,7 @@ msgstr "obiekt typu '%s' nie ma len()" msgid "object with buffer protocol required" msgstr "wymagany obiekt z protokoÅ‚em buforu" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "Å‚aÅ„cuch o nieparzystej dÅ‚ugoÅ›ci" @@ -3726,10 +3742,6 @@ msgstr "" msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "offset poza zakresem" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -3978,10 +3990,6 @@ msgstr "" msgid "sleep length must be non-negative" msgstr "okres snu musi być nieujemny" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4026,6 +4034,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "poczÄ…tkowe/koÅ„cowe indeksy" @@ -4038,9 +4050,18 @@ msgstr "stop nie jest osiÄ…galne ze start" msgid "stream operation not supported" msgstr "operacja na strumieniu nieobsÅ‚ugiwana" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" -msgstr "Å‚aÅ„cuchy nieobsÅ‚ugiwane; użyj bytes lub bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "indeks Å‚aÅ„cucha poza zakresem" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "indeksy Å‚aÅ„cucha muszÄ… być caÅ‚kowite, nie %s" #: extmod/moductypes.c msgid "struct: can't index" @@ -4070,6 +4091,10 @@ msgstr "bÅ‚Ä…d skÅ‚adni w JSON" msgid "syntax error in uctypes descriptor" msgstr "bÅ‚Ä…d skÅ‚adni w deskryptorze uctypes" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "" @@ -4343,6 +4368,33 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "Splitting with sub-captures" +#~ msgstr "PodziaÅ‚ z podgrupami" + +#~ msgid "__init__() should return None, not '%q'" +#~ msgstr "__init__() powinno zwrócić None, a nie '%q'" + +#~ msgid "attributes not supported yet" +#~ msgstr "atrybuty nie sÄ… jeszcze obsÅ‚ugiwane" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "nie można wykonać dzielenia caÅ‚kowitego na liczbie zespolonej" + +#~ msgid "cannot import name %q" +#~ msgstr "nie można zaimportować nazwy %q" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "argumenty nazwane nieobsÅ‚ugiwane - proszÄ™ użyć zwykÅ‚ych argumentów" + +#~ msgid "length argument not allowed for this type" +#~ msgstr "ten typ nie pozawala na podanie dÅ‚ugoÅ›ci" + +#~ msgid "offset out of bounds" +#~ msgstr "offset poza zakresem" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "Å‚aÅ„cuchy nieobsÅ‚ugiwane; użyj bytes lub bytearray" + #~ msgid "Initialization failed due to lack of memory" #~ msgstr "Inicjalizacja nie powiodÅ‚a siÄ™ z powodu braku pamiÄ™ci" @@ -5038,21 +5090,12 @@ msgstr "" #~ msgid "Running in safe mode! Auto-reload is off.\n" #~ msgstr "Uruchomiony tryb bezpieczeÅ„stwa! Samo-przeÅ‚adowanie wyÅ‚Ä…czone.\n" -#~ msgid "__init__() should return None, not '%s'" -#~ msgstr "__init__() powinien zwracać None, nie '%s'" - #~ msgid "can't convert %s to int" #~ msgstr "nie można skonwertować %s do int" -#~ msgid "can't convert NaN to int" -#~ msgstr "nie można skonwertować NaN do int" - #~ msgid "can't convert address to int" #~ msgstr "nie można skonwertować adresu do int" -#~ msgid "can't convert inf to int" -#~ msgstr "nie można skonwertować inf do int" - #~ msgid "object '%s' is not a tuple or list" #~ msgstr "obiekt '%s' nie jest krotkÄ… ani listÄ…" @@ -5065,12 +5108,6 @@ msgstr "" #~ msgid "popitem(): dictionary is empty" #~ msgstr "popitem(): sÅ‚ownik jest pusty" -#~ msgid "string index out of range" -#~ msgstr "indeks Å‚aÅ„cucha poza zakresem" - -#~ msgid "string indices must be integers, not %s" -#~ msgstr "indeksy Å‚aÅ„cucha muszÄ… być caÅ‚kowite, nie %s" - #~ msgid "unknown format code '%c' for object of type '%s'" #~ msgstr "zÅ‚y kod formatowania '%c' dla obiektu typu '%s'" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index 644de87ae4..094e1ad2dc 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -152,7 +152,7 @@ msgstr "%q em %q deve ser do tipo %q e não %q" msgid "%q in use" msgstr "%q em uso" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "O índice %q está fora do intervalo" @@ -239,7 +239,7 @@ msgstr "%q deve ser uma matriz do tipo 'h'" msgid "%q must be of type %q or %q, not %q" msgstr "%q deve ser do tipo %q ou %q e não %q" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q deve ser do tipo %q e não %q" @@ -292,6 +292,11 @@ msgstr "%q[%u] usa pino extra" msgid "%q[%u] waits on input outside of count" msgstr "%q[%u] espera na entrada fora da contagem" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -647,8 +652,8 @@ msgid "Below minimum frame rate" msgstr "Abaixo da taxa mínima de quadros" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" -msgstr "O Bit clock e o word select devem ser pinos sequenciais" +msgid "Bit clock and word select must be sequential GPIO pins" +msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -1132,8 +1137,6 @@ msgstr "Inicialização do GNSS" msgid "Generic Failure" msgstr "Falha Genérica" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -2014,10 +2017,6 @@ msgstr "Os buffers da origem e do destino devem ter o mesmo comprimento" msgid "Specify exactly one of data0 or data_pins" msgstr "Especifique exatamente um do data0 ou do data_pins" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "Divisão com sub-capturas" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "O estéreo à esquerda deve estar no canal PWM A" @@ -2471,8 +2470,9 @@ msgid "__init__() should return None" msgstr "O __init__() deve retornar Nenhum" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "O __init__() deve retornar Nenhum, não '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "O __init__() deve retornar Nenhum, não '%s'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2561,8 +2561,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "tente obter argmin/argmax de uma sequência vazia" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "atributos ainda não suportados" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2689,7 +2689,7 @@ msgstr "a expressão não pode ser atribuída" msgid "can't cancel self" msgstr "não é possível cancelar a si mesmo" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "não é possível converter %q para %q" @@ -2707,10 +2707,18 @@ msgstr "Não é possível converter %s para float" msgid "can't convert '%q' object to %q implicitly" msgstr "não é possível converter implicitamente o objeto '%q' para %q" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "Não é possível converter NaN para int" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "não foi possível converter complexo em flutuante" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "não é possível converter inf para int" + #: py/obj.c msgid "can't convert to complex" msgstr "não é possível converter para complex" @@ -2739,14 +2747,14 @@ msgstr "não é possível excluir a expressão" msgid "can't do binary op between '%q' and '%q'" msgstr "não é possível executar uma operação binária entre '%q' e '%q'" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "não é possível fazer a divisão truncada de um número complexo" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "não é possível converter implicitamente '%q' em 'bool'" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "não é possível carregar a partir de '%q'" @@ -2801,6 +2809,14 @@ msgid "" msgstr "" "não é possível alternar da especificação de campo manual para a automática" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "não vejo a hora" @@ -2833,18 +2849,10 @@ msgstr "não é possível criar instância" msgid "cannot delete array elements" msgstr "não é possível excluir os elementos da matriz" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "não pode importar nome %q" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "não é possível remodelar a matriz" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "Não é possível obter de forma inequívoca a escala do sizeof" - #: py/emitnative.c msgid "casting" msgstr "fundição" @@ -2895,6 +2903,10 @@ msgstr "cor deve estar entre 0x000000 e 0xffffff" msgid "comparison of int and uint" msgstr "comparação de int e uint" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "os valores complexos não compatíveis" @@ -3474,10 +3486,8 @@ msgstr "" "join espera uma lista de objetos str/bytes consistentes com o próprio objeto" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" -"o(s) argumento(s) de palavra-chave ainda não foi implementado - em vez " -"disso, use argumentos normais" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3487,10 +3497,6 @@ msgstr "o rótulo '%q' não foi definido" msgid "label redefined" msgstr "o rótulo foi redefinido" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "o argumento de comprimento não é permitido para este tipo" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "o nível deve estar entre 0 e 1" @@ -3579,6 +3585,10 @@ msgstr "" "falha na alocação de memória, a área de alocação dinâmica de variáveis " "(heap) está bloqueada" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "memoryview: o comprimento não é um múltiplo do tamanho dos itens" @@ -3627,6 +3637,10 @@ msgstr "o nome '%q' não está definido" msgid "name not defined" msgstr "nome não definido" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "o método nativo é grande demais" @@ -3701,7 +3715,7 @@ msgstr "um não UUID foi encontrado na lista service_uuids_whitelist" msgid "non-default argument follows default argument" msgstr "o argumento não predefinido segue o argumento predefinido" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "um dígito não hexadecimal foi encontrado" @@ -3791,7 +3805,7 @@ msgstr "O objeto do tipo '%s' não possui len()" msgid "object with buffer protocol required" msgstr "é necessário objeto com protocolo do buffer" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "sequência com comprimento ímpar" @@ -3811,10 +3825,6 @@ msgstr "o offset deve ser >= 0" msgid "offset must be non-negative and no greater than buffer length" msgstr "o offset deve ser positivo e não maior do que o comprimento do buffer" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "desvio fora dos limites" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -4068,10 +4078,6 @@ msgstr "o tamanho é definido apenas para os ndarrays" msgid "sleep length must be non-negative" msgstr "a duração do sleep não deve ser negativo" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "a etapa da fatia não pode ser zero" - #: py/nativeglue.c msgid "slice unsupported" msgstr "fatia não suportada" @@ -4116,6 +4122,10 @@ msgstr "o source_bitmap deve ter o value_count de 65536" msgid "source_bitmap must have value_count of 8" msgstr "o source_bitmap deve ter o value_count de 8" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "os índices de início/fim" @@ -4128,9 +4138,18 @@ msgstr "stop não está acessível a partir do início" msgid "stream operation not supported" msgstr "a operação do fluxo não é compatível" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" -msgstr "a string não é compatível; use bytes ou bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "o índice da string está fora do intervalo" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "o índices das string devem ser números inteiros, não %s" #: extmod/moductypes.c msgid "struct: can't index" @@ -4160,6 +4179,10 @@ msgstr "erro de sintaxe no JSON" msgid "syntax error in uctypes descriptor" msgstr "houve um erro de sintaxe no descritor uctypes" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "a duração do tempo limite excedeu o valor máximo suportado" @@ -4433,6 +4456,44 @@ msgstr "zi deve ser de um tipo float" msgid "zi must be of shape (n_section, 2)" msgstr "zi deve estar na forma (n_section, 2)" +#~ msgid "Splitting with sub-captures" +#~ msgstr "Divisão com sub-capturas" + +#~ msgid "__init__() should return None, not '%q'" +#~ msgstr "O __init__() deve retornar Nenhum, não '%q'" + +#~ msgid "attributes not supported yet" +#~ msgstr "atributos ainda não suportados" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "não é possível fazer a divisão truncada de um número complexo" + +#~ msgid "cannot import name %q" +#~ msgstr "não pode importar nome %q" + +#~ msgid "cannot unambiguously get sizeof scalar" +#~ msgstr "Não é possível obter de forma inequívoca a escala do sizeof" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "" +#~ "o(s) argumento(s) de palavra-chave ainda não foi implementado - em vez " +#~ "disso, use argumentos normais" + +#~ msgid "length argument not allowed for this type" +#~ msgstr "o argumento de comprimento não é permitido para este tipo" + +#~ msgid "offset out of bounds" +#~ msgstr "desvio fora dos limites" + +#~ msgid "slice step can't be zero" +#~ msgstr "a etapa da fatia não pode ser zero" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "a string não é compatível; use bytes ou bytearray" + +#~ msgid "Bit clock and word select must be sequential pins" +#~ msgstr "O Bit clock e o word select devem ser pinos sequenciais" + #~ msgid "Initialization failed due to lack of memory" #~ msgstr "A inicialização falhou devido à falta de memória" @@ -5989,21 +6050,12 @@ msgstr "zi deve estar na forma (n_section, 2)" #~ msgid "Running in safe mode! Auto-reload is off.\n" #~ msgstr "Rodando em modo seguro! Atualização automática está desligada.\n" -#~ msgid "__init__() should return None, not '%s'" -#~ msgstr "O __init__() deve retornar Nenhum, não '%s'" - #~ msgid "can't convert %s to int" #~ msgstr "Não é possível converter %s para int" -#~ msgid "can't convert NaN to int" -#~ msgstr "Não é possível converter NaN para int" - #~ msgid "can't convert address to int" #~ msgstr "não é possível converter o endereço para int" -#~ msgid "can't convert inf to int" -#~ msgstr "não é possível converter inf para int" - #~ msgid "object '%s' is not a tuple or list" #~ msgstr "o objeto '%s' não é uma tupla ou uma lista" @@ -6016,12 +6068,6 @@ msgstr "zi deve estar na forma (n_section, 2)" #~ msgid "popitem(): dictionary is empty" #~ msgstr "popitem(): o dicionário está vazio" -#~ msgid "string index out of range" -#~ msgstr "o índice da string está fora do intervalo" - -#~ msgid "string indices must be integers, not %s" -#~ msgstr "o índices das string devem ser números inteiros, não %s" - #~ msgid "unknown format code '%c' for object of type '%s'" #~ msgstr "código de formato desconhecido '%c' para o objeto do tipo '%s'" diff --git a/locale/ru.po b/locale/ru.po index 2ccbb57ec4..aae08acd69 100644 --- a/locale/ru.po +++ b/locale/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2023-09-10 08:50+0000\n" +"PO-Revision-Date: 2023-10-13 20:08+0000\n" "Last-Translator: xXx \n" "Language-Team: none\n" "Language: ru\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 5.0.1-dev\n" +"X-Generator: Weblate 5.1-dev\n" #: main.c msgid "" @@ -154,7 +154,7 @@ msgstr "%q в %q должно быть типа %q, а не %q" msgid "%q in use" msgstr "%q иÑпользуетÑÑ" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "Ð˜Ð½Ð´ÐµÐºÑ %q вне диапазона" @@ -213,7 +213,7 @@ msgstr "%q должно быть <= %d" #: ports/espressif/common-hal/watchdog/WatchDogTimer.c msgid "%q must be <= %u" -msgstr "" +msgstr "%q должно быть <= %u" #: py/argcheck.c msgid "%q must be >= %d" @@ -241,7 +241,7 @@ msgstr "%q должен быть маÑÑивом типа 'h \"" msgid "%q must be of type %q or %q, not %q" msgstr "%q должно быть типа%q или%q, а не%q" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q должно быть типа %q, а не %q" @@ -294,6 +294,11 @@ msgstr "%q[%u] иÑпользует дополнительный контакт" msgid "%q[%u] waits on input outside of count" msgstr "%q [%u] ожидает ввода за пределами графа" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -646,9 +651,8 @@ msgid "Below minimum frame rate" msgstr "Ðиже минимальной чаÑтоты кадров" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" +msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" -"Битовый тактовый генератор и выбор Ñлова должны быть поÑледовательными пинами" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -1141,8 +1145,6 @@ msgstr "Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ GNSS" msgid "Generic Failure" msgstr "Общий Ñбой" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -2019,10 +2021,6 @@ msgstr "ИÑходный и конечный буферы должны имет msgid "Specify exactly one of data0 or data_pins" msgstr "Укажите точно один из data0 или data_pins" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "Разделение Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñубзахватов" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "Стерео Ñлева должно быть на PWM-канале A" @@ -2474,8 +2472,9 @@ msgid "__init__() should return None" msgstr "__init__() должен возвращать значение None" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "__init__() должен возвращать None, а не '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2568,8 +2567,8 @@ msgstr "" "поÑледовательноÑти" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "Ðтрибуты пока не поддерживаютÑÑ" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2697,7 +2696,7 @@ msgstr "Ðе удаетÑÑ Ð½Ð°Ð·Ð½Ð°Ñ‡Ð¸Ñ‚ÑŒ выражение" msgid "can't cancel self" msgstr "Ðе могу отменить ÑебÑ" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "Ðе удаетÑÑ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ñ‚ÑŒ %q в %q" @@ -2715,10 +2714,18 @@ msgstr "не могу преобразовать %s в чиÑло Ñ Ð¿Ð»Ð°Ð²Ð° msgid "can't convert '%q' object to %q implicitly" msgstr "не может конвертировать «%q» в% q коÑвенно" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "Ðе может преобразовать Ñложный в плавающий" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "" + #: py/obj.c msgid "can't convert to complex" msgstr "не может быть преобразован в Ñложный" @@ -2747,14 +2754,14 @@ msgstr "Ðе удаетÑÑ ÑƒÐ´Ð°Ð»Ð¸Ñ‚ÑŒ выражение" msgid "can't do binary op between '%q' and '%q'" msgstr "Ðе могу выполнить двоичную операцию между '%q' и '%q'" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "Ðе могу Ñделать уÑеченное деление комплекÑного чиÑла" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "не может неÑвно преобразовать '%q' в 'bool'" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "Ðе удаетÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ из '%q'" @@ -2809,6 +2816,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "не может переключатьÑÑ Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ Ð¿Ð¾Ð»Ñ Ð½Ð° автоматичеÑкую нумерацию полÑ" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "не может ждать" @@ -2841,18 +2856,10 @@ msgstr "Ðе удаетÑÑ Ñоздать ÑкземплÑÑ€" msgid "cannot delete array elements" msgstr "Ðе удаетÑÑ ÑƒÐ´Ð°Ð»Ð¸Ñ‚ÑŒ Ñлементы маÑÑива" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "Ðе удаетÑÑ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ Ð¸Ð¼Ñ %Q" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "Ðе удаетÑÑ Ð¸Ð·Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ форму маÑÑива" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "не может однозначно получить размер ÑкалÑра" - #: py/emitnative.c msgid "casting" msgstr "каÑтинг" @@ -2904,6 +2911,10 @@ msgstr "Цвет должен быть от 0x000000 до 0xffffff" msgid "comparison of int and uint" msgstr "Ñравнение int и uint" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "КомплекÑные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð½Ðµ поддерживаютÑÑ" @@ -3483,10 +3494,8 @@ msgstr "" "Ñамообъектом" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" -"Ðргументы ключевого Ñлова еще не реализованы - вмеÑто Ñтого иÑпользуйте " -"обычные аргументы" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3496,10 +3505,6 @@ msgstr "Метка '%q' не определена" msgid "label redefined" msgstr "Метка переопределена" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "аргумент длины не допуÑкаетÑÑ Ð´Ð»Ñ Ñтого типа" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "уровень должен быть между 0 и 1" @@ -3588,6 +3593,10 @@ msgstr "Сбой Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¼Ñти, выделение %u байт msgid "memory allocation failed, heap is locked" msgstr "Ðе удалоÑÑŒ выделить памÑÑ‚ÑŒ, куча заблокирована" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "вид памÑти: длина не ÑвлÑетÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑтвом Ñлементов" @@ -3636,6 +3645,10 @@ msgstr "Ð˜Ð¼Ñ '%q' не определено" msgid "name not defined" msgstr "Ð˜Ð¼Ñ Ð½Ðµ определено" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "родной метод Ñлишком большой" @@ -3712,7 +3725,7 @@ msgstr "" "Ðргумент отличный от аргумента по умолчанию Ñледует за аргументом по " "умолчанию" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "Ðенайдена шеÑÑ‚Ð½Ð°Ð´Ñ†Ð°Ñ‚ÐµÑ€Ð¸Ñ‡Ð½Ð°Ñ Ñ†Ð¸Ñ„Ñ€Ð°" @@ -3802,7 +3815,7 @@ msgstr "объект типа «%s» не имеет len()" msgid "object with buffer protocol required" msgstr "Объект Ñ Ð¾Ð±Ñзательным буферным протоколом" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "Строка нечетной длины" @@ -3822,10 +3835,6 @@ msgstr "Смещение должно быть >= 0" msgid "offset must be non-negative and no greater than buffer length" msgstr "Смещение должно быть неотрицательным и не превышать длину буфера" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "Смещение за пределы" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -4074,10 +4083,6 @@ msgstr "размер определен только Ð´Ð»Ñ Ð¼Ð°ÑÑива ndarr msgid "sleep length must be non-negative" msgstr "ПродолжительноÑÑ‚ÑŒ Ñна должна быть неотрицательной" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "Шаг Ñреза не может быть равен нулю" - #: py/nativeglue.c msgid "slice unsupported" msgstr "Фрагмент не поддерживаетÑÑ" @@ -4122,6 +4127,10 @@ msgstr "source_bitmap должен иметь значение_Ñчет 65536" msgid "source_bitmap must have value_count of 8" msgstr "source_bitmap должен иметь значение_Ñчет 8" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "Ðачальные/конечные индекÑÑ‹" @@ -4134,9 +4143,18 @@ msgstr "ОÑтановка недоÑтупна Ñ Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð¾Ð³Ð¾ запу msgid "stream operation not supported" msgstr "ÐŸÐ¾Ñ‚Ð¾ÐºÐ¾Ð²Ð°Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ поддерживаетÑÑ" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" -msgstr "Ñтрока не поддерживаетÑÑ; ИÑпользование байтов или маÑÑива байтов" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "" #: extmod/moductypes.c msgid "struct: can't index" @@ -4166,6 +4184,10 @@ msgstr "ÑинтакÑÐ¸Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° в JSON" msgid "syntax error in uctypes descriptor" msgstr "СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° в деÑкрипторе UCTYPES" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "" @@ -4441,6 +4463,46 @@ msgstr "zi должно быть типа float" msgid "zi must be of shape (n_section, 2)" msgstr "zi должен иметь форму (n_section, 2)" +#~ msgid "Splitting with sub-captures" +#~ msgstr "Разделение Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñубзахватов" + +#~ msgid "__init__() should return None, not '%q'" +#~ msgstr "__init__() должен возвращать None, а не '%q'" + +#~ msgid "attributes not supported yet" +#~ msgstr "Ðтрибуты пока не поддерживаютÑÑ" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "Ðе могу Ñделать уÑеченное деление комплекÑного чиÑла" + +#~ msgid "cannot import name %q" +#~ msgstr "Ðе удаетÑÑ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ Ð¸Ð¼Ñ %Q" + +#~ msgid "cannot unambiguously get sizeof scalar" +#~ msgstr "не может однозначно получить размер ÑкалÑра" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "" +#~ "Ðргументы ключевого Ñлова еще не реализованы - вмеÑто Ñтого иÑпользуйте " +#~ "обычные аргументы" + +#~ msgid "length argument not allowed for this type" +#~ msgstr "аргумент длины не допуÑкаетÑÑ Ð´Ð»Ñ Ñтого типа" + +#~ msgid "offset out of bounds" +#~ msgstr "Смещение за пределы" + +#~ msgid "slice step can't be zero" +#~ msgstr "Шаг Ñреза не может быть равен нулю" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "Ñтрока не поддерживаетÑÑ; ИÑпользование байтов или маÑÑива байтов" + +#~ msgid "Bit clock and word select must be sequential pins" +#~ msgstr "" +#~ "Битовый тактовый генератор и выбор Ñлова должны быть поÑледовательными " +#~ "пинами" + #~ msgid "Initialization failed due to lack of memory" #~ msgstr "Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ðµ удалаÑÑŒ из-за нехватки памÑти" diff --git a/locale/sv.po b/locale/sv.po index c4d00bd3d6..64c2aff41e 100644 --- a/locale/sv.po +++ b/locale/sv.po @@ -151,7 +151,7 @@ msgstr "%q i %q mÃ¥ste vara av typen %q, inte %q" msgid "%q in use" msgstr "%q används redan" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "Index %q ligger utanför intervallet" @@ -240,7 +240,7 @@ msgstr "%q mÃ¥ste vara en matris av typen 'h'" msgid "%q must be of type %q or %q, not %q" msgstr "%q mÃ¥ste vara av typen %q eller %q, inte %q" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q mÃ¥ste vara av typen %q, inte %q" @@ -293,6 +293,11 @@ msgstr "%q[%u] använder extra pinnar" msgid "%q[%u] waits on input outside of count" msgstr "%q[%u] väntar pÃ¥ input utanför count" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -644,8 +649,8 @@ msgid "Below minimum frame rate" msgstr "Under minsta bildfrekvens" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" -msgstr "Bitklocka och word select mÃ¥ste vara sekventiella pinnar" +msgid "Bit clock and word select must be sequential GPIO pins" +msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -1123,8 +1128,6 @@ msgstr "GNSS start" msgid "Generic Failure" msgstr "Allmänt fel" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1994,10 +1997,6 @@ msgstr "Käll- och mÃ¥lbuffertar mÃ¥ste ha samma längd" msgid "Specify exactly one of data0 or data_pins" msgstr "Ange en av data0 eller data_pins" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "Splitting med sub-captures" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "Vänster stereokanal mÃ¥ste använda PWM kanal A" @@ -2443,8 +2442,9 @@ msgid "__init__() should return None" msgstr "__init __() ska returnera None" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "__init__() ska returnera None, inte '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "__init __ () ska returnera None, inte '%s'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2533,8 +2533,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "försök att fÃ¥ argmin/argmax för en tom sekvens" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "attribut stöds inte än" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2661,7 +2661,7 @@ msgstr "kan inte tilldela uttryck" msgid "can't cancel self" msgstr "kan inte avbryta sig själv" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "kan inte konvertera %q till %q" @@ -2679,10 +2679,18 @@ msgstr "kan inte konvertera %s till float" msgid "can't convert '%q' object to %q implicitly" msgstr "kan inte konvertera '%q' objekt implicit till %q" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "kan inte konvertera NaN till int" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "kan inte konvertera complex till float" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "kan inte konvertera inf till int" + #: py/obj.c msgid "can't convert to complex" msgstr "kan inte konvertera till komplex" @@ -2711,14 +2719,14 @@ msgstr "kan inte ta bort uttryck" msgid "can't do binary op between '%q' and '%q'" msgstr "kan inte göra binära op mellan '%q' och '%q'" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "kan inte göra trunkerad division av komplext tal" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "kan inte implicit konvertera '%q' till 'bool'" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "kan inte ladda frÃ¥n '%q'" @@ -2771,6 +2779,14 @@ msgid "" msgstr "" "kan inte byta frÃ¥n manuell fältspecifikation till automatisk fältnumrering" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "kan inte vänta" @@ -2803,18 +2819,10 @@ msgstr "kan inte skapa instans" msgid "cannot delete array elements" msgstr "kan inte ta bort arrayelement" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "kan inte importera namn %q" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "kan inte omforma matris" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "Kan inte entydigt fÃ¥ sizeof scalar" - #: py/emitnative.c msgid "casting" msgstr "casting inte implementerad" @@ -2863,6 +2871,10 @@ msgstr "färg mÃ¥ste vara mellan 0x000000 och 0xffffff" msgid "comparison of int and uint" msgstr "jämförelse av int och uint" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "komplexa värden stöds inte" @@ -3442,9 +3454,8 @@ msgstr "" "objektet self" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" -"nyckelordsargument är ännu inte implementerade - använd vanliga argument" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3454,10 +3465,6 @@ msgstr "etiketten '%q' har inte definierats" msgid "label redefined" msgstr "etiketten omdefinierad" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "argumentet length är inte är tillÃ¥ten för denna typ" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "level ska ligga mellan 0 och 1" @@ -3544,6 +3551,10 @@ msgstr "minnesallokering misslyckades, allokerar %u byte" msgid "memory allocation failed, heap is locked" msgstr "minnesallokeringen misslyckades, heapen är lÃ¥st" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "memoryview: längden är inte en multipel av itemsize" @@ -3592,6 +3603,10 @@ msgstr "namnet '%q' är inte definierat" msgid "name not defined" msgstr "namn inte definierat" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "inbyggd metod för stor" @@ -3666,7 +3681,7 @@ msgstr "icke-UUID hittades i service_uuids_whitelist" msgid "non-default argument follows default argument" msgstr "icke-standard argument följer standard argument" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "icke-hexnummer hittade" @@ -3756,7 +3771,7 @@ msgstr "objekt av typen '%s' har ingen len()" msgid "object with buffer protocol required" msgstr "objekt med buffertprotokoll krävs" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "sträng har udda längd" @@ -3776,10 +3791,6 @@ msgstr "offset mÃ¥ste vara >= 0" msgid "offset must be non-negative and no greater than buffer length" msgstr "offset mÃ¥ste vara icke-negativt och inte längre än buffertlängd" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "offset utanför gränserna" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -4028,10 +4039,6 @@ msgstr "storlek är enbart definierad ndarrays" msgid "sleep length must be non-negative" msgstr "värdet för sleep mÃ¥ste vara positivt" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "segmentsteg kan inte vara noll" - #: py/nativeglue.c msgid "slice unsupported" msgstr "slice stöds inte" @@ -4076,6 +4083,10 @@ msgstr "source_bitmap mÃ¥ste ha value_count av 65536" msgid "source_bitmap must have value_count of 8" msgstr "source_bitmap mÃ¥ste ha value_count av 8" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "start-/slutindex" @@ -4088,9 +4099,18 @@ msgstr "stop kan inte nÃ¥s frÃ¥n start" msgid "stream operation not supported" msgstr "stream-Ã¥tgärd stöds inte" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" -msgstr "sträng stöds inte; använd bytes eller bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "strängindex utanför intervallet" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "strängindex mÃ¥ste vara heltal, inte %s" #: extmod/moductypes.c msgid "struct: can't index" @@ -4120,6 +4140,10 @@ msgstr "syntaxfel i JSON" msgid "syntax error in uctypes descriptor" msgstr "syntaxfel i uctypes deskriptor" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "timeout-längd överskred det maximala värde som stöds" @@ -4393,6 +4417,43 @@ msgstr "zi mÃ¥ste vara av typ float" msgid "zi must be of shape (n_section, 2)" msgstr "zi mÃ¥ste vara i formen (n_section, 2)" +#~ msgid "Splitting with sub-captures" +#~ msgstr "Splitting med sub-captures" + +#~ msgid "__init__() should return None, not '%q'" +#~ msgstr "__init__() ska returnera None, inte '%q'" + +#~ msgid "attributes not supported yet" +#~ msgstr "attribut stöds inte än" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "kan inte göra trunkerad division av komplext tal" + +#~ msgid "cannot import name %q" +#~ msgstr "kan inte importera namn %q" + +#~ msgid "cannot unambiguously get sizeof scalar" +#~ msgstr "Kan inte entydigt fÃ¥ sizeof scalar" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "" +#~ "nyckelordsargument är ännu inte implementerade - använd vanliga argument" + +#~ msgid "length argument not allowed for this type" +#~ msgstr "argumentet length är inte är tillÃ¥ten för denna typ" + +#~ msgid "offset out of bounds" +#~ msgstr "offset utanför gränserna" + +#~ msgid "slice step can't be zero" +#~ msgstr "segmentsteg kan inte vara noll" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "sträng stöds inte; använd bytes eller bytearray" + +#~ msgid "Bit clock and word select must be sequential pins" +#~ msgstr "Bitklocka och word select mÃ¥ste vara sekventiella pinnar" + #~ msgid "Initialization failed due to lack of memory" #~ msgstr "Initieringen misslyckades pÃ¥ grund av minnesbrist" @@ -5922,21 +5983,12 @@ msgstr "zi mÃ¥ste vara i formen (n_section, 2)" #~ msgid "Running in safe mode! Auto-reload is off.\n" #~ msgstr "Kör i säkert läge! Autoladdning är avstängd.\n" -#~ msgid "__init__() should return None, not '%s'" -#~ msgstr "__init __ () ska returnera None, inte '%s'" - #~ msgid "can't convert %s to int" #~ msgstr "kan inte konvertera %s till int" -#~ msgid "can't convert NaN to int" -#~ msgstr "kan inte konvertera NaN till int" - #~ msgid "can't convert address to int" #~ msgstr "kan inte konvertera address till int" -#~ msgid "can't convert inf to int" -#~ msgstr "kan inte konvertera inf till int" - #~ msgid "object '%s' is not a tuple or list" #~ msgstr "objektet '%s' är inte en tupel eller lista" @@ -5949,12 +6001,6 @@ msgstr "zi mÃ¥ste vara i formen (n_section, 2)" #~ msgid "popitem(): dictionary is empty" #~ msgstr "popitem(): ordlistan är tom" -#~ msgid "string index out of range" -#~ msgstr "strängindex utanför intervallet" - -#~ msgid "string indices must be integers, not %s" -#~ msgstr "strängindex mÃ¥ste vara heltal, inte %s" - #~ msgid "unknown format code '%c' for object of type '%s'" #~ msgstr "okänt format '%c' för objekt av typ '%s'" diff --git a/locale/tr.po b/locale/tr.po index eb715370e8..c8a54faf29 100644 --- a/locale/tr.po +++ b/locale/tr.po @@ -147,7 +147,7 @@ msgstr "" msgid "%q in use" msgstr "%q kullanımda" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "%q indeksi aralık dışında" @@ -234,7 +234,7 @@ msgstr "" msgid "%q must be of type %q or %q, not %q" msgstr "" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -287,6 +287,11 @@ msgstr "" msgid "%q[%u] waits on input outside of count" msgstr "" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -639,8 +644,8 @@ msgid "Below minimum frame rate" msgstr "Minimum kare hızından altında" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" -msgstr "Bit saati ve kelime seçimi pinleri sıralı olmalıdır" +msgid "Bit clock and word select must be sequential GPIO pins" +msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -1116,8 +1121,6 @@ msgstr "GNSS init" msgid "Generic Failure" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1976,10 +1979,6 @@ msgstr "" msgid "Specify exactly one of data0 or data_pins" msgstr "" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "" @@ -2416,7 +2415,8 @@ msgid "__init__() should return None" msgstr "" #: py/objtype.c -msgid "__init__() should return None, not '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" msgstr "" #: py/objobject.c @@ -2506,7 +2506,7 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "" #: py/objstr.c -msgid "attributes not supported yet" +msgid "attributes not supported" msgstr "" #: extmod/ulab/code/ulab_tools.c @@ -2634,7 +2634,7 @@ msgstr "" msgid "can't cancel self" msgstr "" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2652,10 +2652,18 @@ msgstr "" msgid "can't convert '%q' object to %q implicitly" msgstr "" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "" + #: py/obj.c msgid "can't convert to complex" msgstr "" @@ -2684,14 +2692,14 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "" @@ -2742,6 +2750,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "" @@ -2774,18 +2790,10 @@ msgstr "" msgid "cannot delete array elements" msgstr "" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "" - #: py/emitnative.c msgid "casting" msgstr "" @@ -2834,6 +2842,10 @@ msgstr "" msgid "comparison of int and uint" msgstr "" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "" @@ -3406,7 +3418,7 @@ msgid "join expects a list of str/bytes objects consistent with self object" msgstr "" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" +msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -3417,10 +3429,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "" @@ -3507,6 +3515,10 @@ msgstr "" msgid "memory allocation failed, heap is locked" msgstr "" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "" @@ -3555,6 +3567,10 @@ msgstr "" msgid "name not defined" msgstr "" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "" @@ -3629,7 +3645,7 @@ msgstr "" msgid "non-default argument follows default argument" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "" @@ -3719,7 +3735,7 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "" @@ -3739,10 +3755,6 @@ msgstr "" msgid "offset must be non-negative and no greater than buffer length" msgstr "" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -3991,10 +4003,6 @@ msgstr "" msgid "sleep length must be non-negative" msgstr "" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "" - #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4039,6 +4047,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" @@ -4051,8 +4063,17 @@ msgstr "" msgid "stream operation not supported" msgstr "" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" msgstr "" #: extmod/moductypes.c @@ -4083,6 +4104,10 @@ msgstr "" msgid "syntax error in uctypes descriptor" msgstr "" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "" @@ -4356,6 +4381,9 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "Bit clock and word select must be sequential pins" +#~ msgstr "Bit saati ve kelime seçimi pinleri sıralı olmalıdır" + #~ msgid "Initialization failed due to lack of memory" #~ msgstr "Bellek yetersizliÄŸi nedeniyle baÅŸlatma baÅŸarısız oldu" diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index 27499137aa..7eb79a0ed4 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: circuitpython-cn\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-09-13 17:49+0000\n" +"PO-Revision-Date: 2023-10-16 23:54+0000\n" "Last-Translator: hexthat \n" "Language-Team: Chinese Hanyu Pinyin\n" "Language: zh_Latn_pinyin\n" @@ -15,7 +15,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.0.1-dev\n" +"X-Generator: Weblate 5.1\n" #: main.c msgid "" @@ -153,7 +153,7 @@ msgstr "%q zhÅng de %q bì xÅ« shì %q lèi xíng, ér bù shì %q" msgid "%q in use" msgstr "%q zhèngzài bèi shÇyòng" -#: py/objstr.c py/objstrunicode.c +#: py/objstr.c msgid "%q index out of range" msgstr "%q suÇ’yÇn chÄochÅ« fànwéi" @@ -212,7 +212,7 @@ msgstr "%q bìxÅ« <= %d" #: ports/espressif/common-hal/watchdog/WatchDogTimer.c msgid "%q must be <= %u" -msgstr "" +msgstr "%q bì xÅ« <= %u" #: py/argcheck.c msgid "%q must be >= %d" @@ -241,7 +241,7 @@ msgstr "%q bìxÅ« shì lèixíng wéi 'h' de shùzÇ”" msgid "%q must be of type %q or %q, not %q" msgstr "%q de lèi xíng bì xÅ« shì %q huò %q, ér bù shì %q" -#: py/argcheck.c py/objstrunicode.c shared-module/synthio/__init__.c +#: py/argcheck.c shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q de lèi xíng bì xÅ« shì %q, ér bù shì %q" @@ -294,6 +294,11 @@ msgstr "%q[%u] shÇyòng éwài de yÇnjiÇŽo" msgid "%q[%u] waits on input outside of count" msgstr "%q[%u] dÄ›ngdài jìshù zhÄ«wài de shÅ«rù" +#: py/runtime.c +#, c-format +msgid "%s" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" @@ -645,8 +650,8 @@ msgid "Below minimum frame rate" msgstr "dÄ«yú zuìdÄ« zhÄ“nlÇœ" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c -msgid "Bit clock and word select must be sequential pins" -msgstr "wèi shízhÅng hé zì xuÇŽnzé bìxÅ« shì liánxù de yÇn jiÇŽo" +msgid "Bit clock and word select must be sequential GPIO pins" +msgstr "wèi shízhÅng hézì xuÇŽnzé bìxÅ« shì shùnxù GPIO yÇnjiÇŽo" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -1126,8 +1131,6 @@ msgstr "GNSS chÅ«shÇhuà" msgid "Generic Failure" msgstr "tÅng yòng gù zhàng" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1997,10 +2000,6 @@ msgstr "Yuán huÇŽnchÅng qÅ« hé mùbiÄo huÇŽnchÅng qÅ« de chángdù bìxÅ« x msgid "Specify exactly one of data0 or data_pins" msgstr "zhÇ dìng data0 huò data_pins zhÅng de yí gè" -#: extmod/modure.c -msgid "Splitting with sub-captures" -msgstr "YÇ” zi bÇ”huò fÄ“nliè" - #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Stereo left must be on PWM channel A" msgstr "lì tÇ shÄ“ng zuÇ’ bì xÅ« shì zài PWM tÅng dào A" @@ -2446,8 +2445,9 @@ msgid "__init__() should return None" msgstr "__init__() fÇŽnhuí not" #: py/objtype.c -msgid "__init__() should return None, not '%q'" -msgstr "__Init __() yÄ«nggÄi fÇŽnhuí None, ér bùshì '%q'" +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "__Init__() yÄ«nggÄi fÇŽnhuí not, ér bùshì '%s'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2536,8 +2536,8 @@ msgid "attempt to get argmin/argmax of an empty sequence" msgstr "chángshì huòqÇ” kÅng xùliè de argmin/ argmax" #: py/objstr.c -msgid "attributes not supported yet" -msgstr "shÇ”xìng shàngwèi zhÄ«chí" +msgid "attributes not supported" +msgstr "" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" @@ -2664,7 +2664,7 @@ msgstr "bùnéng fÄ“npèi dào biÇŽodá shì" msgid "can't cancel self" msgstr "bù néng qÇ” xiÄo zì wÇ’" -#: py/objint.c py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/runtime.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "WúfÇŽ jiÄng %q zhuÇŽnhuàn wèi %q" @@ -2682,10 +2682,18 @@ msgstr "wúfÇŽ zhuÇŽnhuàn %s dào fú diÇŽn xíng biànliàng" msgid "can't convert '%q' object to %q implicitly" msgstr "wúfÇŽ jiÄng '%q' duìxiàng zhuÇŽnhuàn wèi %q yÇn hán" +#: py/objint.c +msgid "can't convert NaN to int" +msgstr "wúfÇŽ jiÄng dÇŽoháng zhuÇŽnhuàn wèi int" + #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" msgstr "wú fÇŽ jiÄng fù zá zhuÇŽn huàn wéi fú dòng" +#: py/objint.c +msgid "can't convert inf to int" +msgstr "bùnéng jiÄng inf zhuÇŽnhuàn wèi int" + #: py/obj.c msgid "can't convert to complex" msgstr "bùnéng zhuÇŽnhuàn wèi fùzá" @@ -2714,14 +2722,14 @@ msgstr "bùnéng shÄnchú biÇŽodá shì" msgid "can't do binary op between '%q' and '%q'" msgstr "bùnéng zài '%q' hé '%q' zhÄ« jiÄn jìnxíng èr yuán yùnsuàn" -#: py/objcomplex.c -msgid "can't do truncated division of a complex number" -msgstr "bùnéng fÄ“njiÄ› fùzá de shùzì" - #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "bùnéng yÇn hán de jiÄng '%q' zhuÇŽnhuàn wèi 'bool'" +#: py/runtime.c +msgid "can't import name %q" +msgstr "" + #: py/emitnative.c msgid "can't load from '%q'" msgstr "wúfÇŽ cóng '%q' jiÄzài" @@ -2772,6 +2780,14 @@ msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "wúfÇŽ cóng shÇ’udòng zìduàn guÄ«gé qiÄ“huàn dào zìdòng zìduàn biÄnhào" +#: py/objcomplex.c +msgid "can't truncate-divide a complex number" +msgstr "" + +#: extmod/moductypes.c +msgid "can't unambiguously get sizeof scalar" +msgstr "" + #: extmod/moduasyncio.c msgid "can't wait" msgstr "dÄ›ngbùjí" @@ -2805,18 +2821,10 @@ msgstr "wúfÇŽ chuàngjiàn shílì" msgid "cannot delete array elements" msgstr "wúfÇŽ shÄnchú shùzÇ” yuánsù" -#: py/runtime.c -msgid "cannot import name %q" -msgstr "wúfÇŽ dÇŽorù míngchÄ“ng %q" - #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "wúfÇŽ chóngsù zhènliè xíngzhuàng" -#: extmod/moductypes.c -msgid "cannot unambiguously get sizeof scalar" -msgstr "bù néng háo bù hán hu de dé dào dà xiÇŽo de lín" - #: py/emitnative.c msgid "casting" msgstr "tóuyÇng" @@ -2868,6 +2876,10 @@ msgstr "yánsè bìxÅ« jiè yú 0x000000 hé 0xffffff zhÄ« jiÄn" msgid "comparison of int and uint" msgstr "yÄ«n tè hé wÅ« yÄ«n tè de bÇ jiào" +#: py/objcomplex.c +msgid "complex divide by zero" +msgstr "" + #: py/objfloat.c py/parsenum.c msgid "complex values not supported" msgstr "bù zhÄ«chí fùzá de zhí" @@ -3445,8 +3457,8 @@ msgstr "" "tiÄnjiÄ yÄ«gè fúhé zìshÄ“n duìxiàng de zìfú chuàn/zì jié duìxiàng lièbiÇŽo" #: py/argcheck.c -msgid "keyword argument(s) not yet implemented - use normal args instead" -msgstr "guÄnjiàn zì cÄnshù shàngwèi shíxiàn - qÇng shÇyòng chángguÄ« cÄnshù" +msgid "keyword argument(s) not implemented - use normal args instead" +msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3456,10 +3468,6 @@ msgstr "biÄoqiÄn '%q' wèi dìngyì" msgid "label redefined" msgstr "biÄoqiÄn chóngxÄ«n dìngyì" -#: py/stream.c -msgid "length argument not allowed for this type" -msgstr "bù yÇ”nxÇ” gÄi lèixíng de chángdù cÄnshù" - #: shared-bindings/audiomixer/MixerVoice.c msgid "level must be between 0 and 1" msgstr "Level bìxÅ« jiè yú 0 hé 1 zhÄ« jiÄn" @@ -3546,6 +3554,10 @@ msgstr "nèicún fÄ“npèi shÄ«bài, fÄ“npèi %u zì jié" msgid "memory allocation failed, heap is locked" msgstr "jìyì tÇ fÄ“npèi shÄ«bài, duÄ« bèi suÇ’dìng" +#: py/objarray.c +msgid "memoryview offset too large" +msgstr "" + #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" msgstr "nèi cún shì tú: cháng dù bú shì xiàng mù huà de bèi shù" @@ -3594,6 +3606,10 @@ msgstr "míngchÄ“ng '%q' wèi dìngyì" msgid "name not defined" msgstr "míngchÄ“ng wèi dìngyì" +#: py/persistentcode.c +msgid "native code in .mpy unsupported" +msgstr "" + #: py/asmthumb.c msgid "native method too big" msgstr "yuán shÄ“ng fÄng fÇŽ tài dà" @@ -3668,7 +3684,7 @@ msgstr "Zài service_uuids bái míngdÄn zhÅng zhÇŽodào fÄ“i UUID" msgid "non-default argument follows default argument" msgstr "bùshì mòrèn cÄnshù zÅ«nxún mòrèn cÄnshù" -#: extmod/modubinascii.c +#: py/objstr.c msgid "non-hex digit found" msgstr "zhÇŽodào fÄ“i shíliù jìn zhì shùzì" @@ -3758,7 +3774,7 @@ msgstr "lèixíng '%s' de duìxiàng méiyÇ’u chángdù" msgid "object with buffer protocol required" msgstr "xÅ«yào huÇŽnchÅng qÅ« xiéyì de duìxiàng" -#: extmod/modubinascii.c +#: py/objstr.c msgid "odd-length string" msgstr "jÄ«shù zìfú chuàn" @@ -3778,10 +3794,6 @@ msgstr "piÄn yí liàng bì xÅ« >= 0" msgid "offset must be non-negative and no greater than buffer length" msgstr "piÄn yí liàng bì xÅ« wéi fÄ“i fù shù qiÄ› bù dà yú huÇŽn chÅng qÅ« cháng dù" -#: py/objstr.c py/objstrunicode.c -msgid "offset out of bounds" -msgstr "piÄnlí biÄnjiè" - #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" @@ -4030,10 +4042,6 @@ msgstr "dàxiÇŽo jÇn wèi ndarrays dìngyì" msgid "sleep length must be non-negative" msgstr "shuìmián chángdù bìxÅ« shìfÄ“i fùshù" -#: extmod/ulab/code/ndarray.c -msgid "slice step can't be zero" -msgstr "qiÄ“piàn bù cháng bùnéng wéi líng" - #: py/nativeglue.c msgid "slice unsupported" msgstr "qiÄ“ piàn bù shòu zhÄ« chí" @@ -4081,6 +4089,10 @@ msgstr "" msgid "source_bitmap must have value_count of 8" msgstr "yuán wèi tú (source_bitmap) de zhí de shù mù (value_count) bì xÅ« shì 8" +#: extmod/modure.c +msgid "splitting with sub-captures" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "kÄishÇ/jiéshù zhÇshù" @@ -4093,9 +4105,18 @@ msgstr "tíngzhÇ wúfÇŽ cóng kÄishÇ zhÅng zhÇŽodào" msgid "stream operation not supported" msgstr "bù zhÄ«chí liú cÄozuò" -#: py/stream.c -msgid "string not supported; use bytes or bytearray" -msgstr "zìfú chuàn bù zhÄ«chí; shÇyòng zì jié huò zì jié zÇ”" +#: py/objarray.c py/objstr.c +msgid "string argument without an encoding" +msgstr "" + +#: py/objstrunicode.c +msgid "string index out of range" +msgstr "zìfú chuàn suÇ’yÇn chÄochÅ« fànwéi" + +#: py/objstrunicode.c +#, c-format +msgid "string indices must be integers, not %s" +msgstr "zìfú chuàn zhÇshù bìxÅ« shì zhÄ›ngshù, ér bùshì %s" #: extmod/moductypes.c msgid "struct: can't index" @@ -4125,6 +4146,10 @@ msgstr "JSON yÇ”fÇŽ cuòwù" msgid "syntax error in uctypes descriptor" msgstr "uctypes miáoshù fú zhÅng de yÇ”fÇŽ cuòwù" +#: extmod/utime_mphal.c +msgid "ticks interval overflow" +msgstr "" + #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" msgstr "chÄoshí shíjiÄn chÄoguò zuìdà zhÄ«chí zhí" @@ -4398,6 +4423,42 @@ msgstr "zi bìxÅ« wèi fú diÇŽn xíng" msgid "zi must be of shape (n_section, 2)" msgstr "zi bìxÅ« jùyÇ’u xíngzhuàng (n_section,2)" +#~ msgid "Splitting with sub-captures" +#~ msgstr "YÇ” zi bÇ”huò fÄ“nliè" + +#~ msgid "__init__() should return None, not '%q'" +#~ msgstr "__Init __() yÄ«nggÄi fÇŽnhuí None, ér bùshì '%q'" + +#~ msgid "attributes not supported yet" +#~ msgstr "shÇ”xìng shàngwèi zhÄ«chí" + +#~ msgid "can't do truncated division of a complex number" +#~ msgstr "bùnéng fÄ“njiÄ› fùzá de shùzì" + +#~ msgid "cannot import name %q" +#~ msgstr "wúfÇŽ dÇŽorù míngchÄ“ng %q" + +#~ msgid "cannot unambiguously get sizeof scalar" +#~ msgstr "bù néng háo bù hán hu de dé dào dà xiÇŽo de lín" + +#~ msgid "keyword argument(s) not yet implemented - use normal args instead" +#~ msgstr "guÄnjiàn zì cÄnshù shàngwèi shíxiàn - qÇng shÇyòng chángguÄ« cÄnshù" + +#~ msgid "length argument not allowed for this type" +#~ msgstr "bù yÇ”nxÇ” gÄi lèixíng de chángdù cÄnshù" + +#~ msgid "offset out of bounds" +#~ msgstr "piÄnlí biÄnjiè" + +#~ msgid "slice step can't be zero" +#~ msgstr "qiÄ“piàn bù cháng bùnéng wéi líng" + +#~ msgid "string not supported; use bytes or bytearray" +#~ msgstr "zìfú chuàn bù zhÄ«chí; shÇyòng zì jié huò zì jié zÇ”" + +#~ msgid "Bit clock and word select must be sequential pins" +#~ msgstr "wèi shízhÅng hé zì xuÇŽnzé bìxÅ« shì liánxù de yÇn jiÇŽo" + #~ msgid "Initialization failed due to lack of memory" #~ msgstr "yóu yú nèi cún bù zú, chÅ« shÇ huà shÄ« bài" @@ -5872,21 +5933,12 @@ msgstr "zi bìxÅ« jùyÇ’u xíngzhuàng (n_section,2)" #~ msgid "Running in safe mode! Auto-reload is off.\n" #~ msgstr "Zài Änquán móshì xià yùnxíng! Zìdòng chóngxÄ«n jiÄzài yÇ guÄnbì.\n" -#~ msgid "__init__() should return None, not '%s'" -#~ msgstr "__Init__() yÄ«nggÄi fÇŽnhuí not, ér bùshì '%s'" - #~ msgid "can't convert %s to int" #~ msgstr "wúfÇŽ zhuÇŽnhuàn%s dào int" -#~ msgid "can't convert NaN to int" -#~ msgstr "wúfÇŽ jiÄng dÇŽoháng zhuÇŽnhuàn wèi int" - #~ msgid "can't convert address to int" #~ msgstr "wúfÇŽ jiÄng dìzhÇ zhuÇŽnhuàn wèi int" -#~ msgid "can't convert inf to int" -#~ msgstr "bùnéng jiÄng inf zhuÇŽnhuàn wèi int" - #~ msgid "object '%s' is not a tuple or list" #~ msgstr "duìxiàng '%s' bùshì yuán zÇ” huò lièbiÇŽo" @@ -5899,12 +5951,6 @@ msgstr "zi bìxÅ« jùyÇ’u xíngzhuàng (n_section,2)" #~ msgid "popitem(): dictionary is empty" #~ msgstr "dànchÅ« xiàngmù (): ZìdiÇŽn wèi kÅng" -#~ msgid "string index out of range" -#~ msgstr "zìfú chuàn suÇ’yÇn chÄochÅ« fànwéi" - -#~ msgid "string indices must be integers, not %s" -#~ msgstr "zìfú chuàn zhÇshù bìxÅ« shì zhÄ›ngshù, ér bùshì %s" - #, fuzzy #~ msgid "unknown format code '%c' for object of type '%s'" #~ msgstr "lèixíng '%s' duìxiàng wèizhÄ« de géshì dàimÇŽ '%c'" diff --git a/main.c b/main.c index 3d4d665beb..c593739a04 100644 --- a/main.c +++ b/main.c @@ -58,7 +58,6 @@ #include "supervisor/shared/status_leds.h" #include "supervisor/shared/tick.h" #include "supervisor/shared/traceback.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/workflow.h" #include "supervisor/usb.h" #include "supervisor/workflow.h" diff --git a/mpy-cross/.gitignore b/mpy-cross/.gitignore deleted file mode 100644 index 6daeea5040..0000000000 --- a/mpy-cross/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) -# -# SPDX-License-Identifier: MIT - -/build-* -/mpy-cross -/mpy-cross.static -/mpy-cross.static.exe -/mpy-cross.static-raspbian -/mpy-cross.fuzz -/pitools diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile index 4858cb25c7..4064ce21d2 100644 --- a/mpy-cross/Makefile +++ b/mpy-cross/Makefile @@ -1,24 +1,68 @@ -# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) -# -# SPDX-License-Identifier: MIT +include ../py/mkenv.mk -# The following is a temporary hack to forefully undefine vars that might have -# be defined by a calling Makefile (from recursive make). -# TODO: Find a better way to be able to call this Makefile recursively. -ifneq ($(findstring undefine,$(.FEATURES)),) -override undefine COPT -override undefine CFLAGS_EXTRA -override undefine LDFLAGS_EXTRA -override undefine MICROPY_FORCE_32BIT -override undefine CROSS_COMPILE -override undefine FROZEN_DIR -override undefine FROZEN_MPY_DIR -override undefine USER_C_MODULES -override undefine SRC_MOD -override undefine BUILD -override undefine PROG +# define main target +PROG ?= mpy-cross + +# qstr definitions (must come before including py.mk) +QSTR_DEFS = qstrdefsport.h + +# OS name, for simple autoconfig +UNAME_S := $(shell uname -s) + +# include py core make definitions +include $(TOP)/py/py.mk + +INC += -I. +INC += -I$(BUILD) +INC += -I$(TOP) + +# compiler settings +CWARN = -Wall -Werror +CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith +CFLAGS += $(INC) $(CWARN) -std=gnu99 $(COPT) $(CFLAGS_EXTRA) +CFLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables +CFLAGS += -DCIRCUITPY + +# Debugging/Optimization +ifdef DEBUG +CFLAGS += -g +COPT = -O0 +else +COPT = -Os #-DNDEBUG endif -include mpy-cross.mk -CFLAGS += -g -STRIP = : +# On OSX, 'gcc' is a symlink to clang unless a real gcc is installed. +# The unix port of MicroPython on OSX must be compiled with clang, +# while cross-compile ports require gcc, so we test here for OSX and +# if necessary override the value of 'CC' set in py/mkenv.mk +ifeq ($(UNAME_S),Darwin) +CC = clang +# Use clang syntax for map file +LDFLAGS_ARCH = -Wl,-map,$@.map -Wl,-dead_strip +else +# Use gcc syntax for map file +LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections +endif +LDFLAGS += $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) + +# source files +SRC_C = \ + main.c \ + gccollect.c \ + shared/runtime/gchelper_generic.c \ + supervisor/stub/safe_mode.c \ + supervisor/stub/stack.c \ + supervisor/shared/translate/translate.c + +# Add fmode when compiling with mingw gcc +COMPILER_TARGET := $(shell $(CC) -dumpmachine) +ifneq (,$(findstring mingw,$(COMPILER_TARGET))) + SRC_C += windows-fmode.c +endif + +OBJ = $(PY_CORE_O) +OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) + +$(BUILD)/supervisor/shared/translate/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/compressed_translations.generated.h + +include $(TOP)/py/mkrules.mk diff --git a/mpy-cross/Makefile.fuzz b/mpy-cross/Makefile.fuzz index 0fbbe9b647..30fc4e543a 100644 --- a/mpy-cross/Makefile.fuzz +++ b/mpy-cross/Makefile.fuzz @@ -6,4 +6,4 @@ PROG=mpy-cross.fuzz BUILD=build-static STATIC_BUILD=1 CC=afl-clang-fast -include mpy-cross.mk +include Makefile diff --git a/mpy-cross/Makefile.m1 b/mpy-cross/Makefile.m1 index 13431f708b..d81925abe2 100644 --- a/mpy-cross/Makefile.m1 +++ b/mpy-cross/Makefile.m1 @@ -5,6 +5,6 @@ PROG=mpy-cross-arm64 BUILD=build-arm64 -include mpy-cross.mk +include Makefile # Because mpy-cross.mk unconditionally overwrites CC for Darwin, we must set it BELOW the inclusion CC := $(shell xcrun --find clang) -isysroot $(shell xcrun --show-sdk-path) -target arm64-apple-macos11 diff --git a/mpy-cross/Makefile.static b/mpy-cross/Makefile.static index ac2a8079bb..1dad474510 100644 --- a/mpy-cross/Makefile.static +++ b/mpy-cross/Makefile.static @@ -6,4 +6,4 @@ PROG=mpy-cross.static BUILD=build-static STATIC_BUILD=1 -include mpy-cross.mk +include Makefile diff --git a/mpy-cross/Makefile.static-aarch64 b/mpy-cross/Makefile.static-aarch64 index e59ba8331f..50daeef788 100644 --- a/mpy-cross/Makefile.static-aarch64 +++ b/mpy-cross/Makefile.static-aarch64 @@ -7,4 +7,4 @@ BUILD=build-static-aarch64 STATIC_BUILD=1 CROSS_COMPILE = aarch64-linux-gnu- -include mpy-cross.mk +include Makefile diff --git a/mpy-cross/Makefile.static-mingw b/mpy-cross/Makefile.static-mingw index bcd2b6a9f2..3c4b29e112 100644 --- a/mpy-cross/Makefile.static-mingw +++ b/mpy-cross/Makefile.static-mingw @@ -7,4 +7,4 @@ CROSS_COMPILE = x86_64-w64-mingw32- BUILD=build-static-mingw STATIC_BUILD=1 -include mpy-cross.mk +include Makefile diff --git a/mpy-cross/Makefile.static-raspbian b/mpy-cross/Makefile.static-raspbian index 8fe78b0aff..bb16c52676 100644 --- a/mpy-cross/Makefile.static-raspbian +++ b/mpy-cross/Makefile.static-raspbian @@ -8,4 +8,4 @@ STATIC_BUILD=1 $(shell if ! [ -d pitools ]; then echo 1>&2 "Fetching pi build tools. This may take awhile."; git clone -q https://github.com/raspberrypi/tools.git --depth=1 pitools; fi) CROSS_COMPILE = pitools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- -include mpy-cross.mk +include Makefile diff --git a/mpy-cross/main.c b/mpy-cross/main.c index 88d84915f8..67e73e0eba 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -73,8 +73,9 @@ STATIC int compile_and_save(const char *file, const char *output_file, const cha #endif mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); - mp_module_context_t *ctx = m_new_obj(mp_module_context_t); - mp_compiled_module_t cm = mp_compile_to_raw_code(&parse_tree, source_name, false, ctx); + mp_compiled_module_t cm; + cm.context = m_new_obj(mp_module_context_t); + mp_compile_to_raw_code(&parse_tree, source_name, false, &cm); vstr_t vstr; vstr_init(&vstr, 16); @@ -181,6 +182,15 @@ STATIC void pre_process_options(int argc, char **argv) { } } +STATIC char *backslash_to_forwardslash(char *path) { + for (char *p = path; p != NULL && *p != '\0'; ++p) { + if (*p == '\\') { + *p = '/'; + } + } + return path; +} + MP_NOINLINE int main_(int argc, char **argv) { mp_stack_set_limit(40000 * (sizeof(void *) / 4)); @@ -203,19 +213,9 @@ MP_NOINLINE int main_(int argc, char **argv) { // set default compiler configuration mp_dynamic_compiler.small_int_bits = 31; - #if defined(__i386__) - mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86; - mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_X86; - #elif defined(__x86_64__) - mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X64; - mp_dynamic_compiler.nlr_buf_num_regs = MAX(MICROPY_NLR_NUM_REGS_X64, MICROPY_NLR_NUM_REGS_X64_WIN); - #elif defined(__arm__) && !defined(__thumb2__) - mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6; - mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; - #else + // don't support native emitter unless -march is specified mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_NONE; mp_dynamic_compiler.nlr_buf_num_regs = 0; - #endif const char *input_file = NULL; const char *output_file = NULL; @@ -228,7 +228,7 @@ MP_NOINLINE int main_(int argc, char **argv) { a += 1; } else if (strcmp(argv[a], "--version") == 0) { printf("CircuitPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE - "; mpy-cross emitting mpy v" MP_STRINGIFY(MPY_VERSION) "-CircuitPython\n"); + "; mpy-cross emitting mpy v" MP_STRINGIFY(MPY_VERSION) "." MP_STRINGIFY(MPY_SUB_VERSION) "\n"); return 0; } else if (strcmp(argv[a], "-v") == 0) { mp_verbose_flag++; @@ -251,7 +251,7 @@ MP_NOINLINE int main_(int argc, char **argv) { exit(usage(argv)); } a += 1; - source_file = argv[a]; + source_file = backslash_to_forwardslash(argv[a]); } else if (strncmp(argv[a], "-msmall-int-bits=", sizeof("-msmall-int-bits=") - 1) == 0) { char *end; mp_dynamic_compiler.small_int_bits = @@ -292,6 +292,20 @@ MP_NOINLINE int main_(int argc, char **argv) { } else if (strcmp(arch, "xtensawin") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_XTENSAWIN; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_XTENSAWIN; + } else if (strcmp(arch, "host") == 0) { + #if defined(__i386__) || defined(_M_IX86) + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86; + mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_X86; + #elif defined(__x86_64__) || defined(_M_X64) + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X64; + mp_dynamic_compiler.nlr_buf_num_regs = MAX(MICROPY_NLR_NUM_REGS_X64, MICROPY_NLR_NUM_REGS_X64_WIN); + #elif defined(__arm__) && !defined(__thumb2__) + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6; + mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; + #else + mp_printf(&mp_stderr_print, "unable to determine host architecture for -march=host\n"); + exit(1); + #endif } else { return usage(argv); } @@ -303,7 +317,7 @@ MP_NOINLINE int main_(int argc, char **argv) { mp_printf(&mp_stderr_print, "multiple input files\n"); exit(1); } - input_file = argv[a]; + input_file = backslash_to_forwardslash(argv[a]); } } @@ -339,7 +353,3 @@ void nlr_jump_fail(void *val) { fprintf(stderr, "FATAL: uncaught NLR %p\n", val); exit(1); } - -void serial_write(const char *text) { - printf("%s", text); -} diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h index 099c372fdd..d835e81b41 100644 --- a/mpy-cross/mpconfigport.h +++ b/mpy-cross/mpconfigport.h @@ -166,7 +166,7 @@ typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) (void)0 // We need to provide a declaration/definition of alloca() -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__NetBSD__) #include #elif defined(_WIN32) #include @@ -182,6 +182,7 @@ typedef long mp_off_t; #define MP_ENDIANNESS_LITTLE (1) #define NORETURN __declspec(noreturn) #define MP_NOINLINE __declspec(noinline) +#define MP_ALWAYSINLINE __forceinline #define MP_LIKELY(x) (x) #define MP_UNLIKELY(x) (x) #define MICROPY_PORT_CONSTANTS { MP_ROM_QSTR(MP_QSTR_dummy), MP_ROM_PTR(NULL) } diff --git a/mpy-cross/mpy-cross.mk b/mpy-cross/mpy-cross.mk deleted file mode 100644 index db93f17123..0000000000 --- a/mpy-cross/mpy-cross.mk +++ /dev/null @@ -1,85 +0,0 @@ -# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) -# -# SPDX-License-Identifier: MIT - -include ../py/mkenv.mk - -# define main target - -PROG ?= mpy-cross - -# qstr definitions (must come before including py.mk) -QSTR_DEFS = qstrdefsport.h - -# OS name, for simple autoconfig -UNAME_S := $(shell uname -s) - -# include py core make definitions -include $(TOP)/py/py.mk - -INC += -I. -INC += -I$(TOP) -INC += -I$(BUILD) - -# compiler settings -CWARN = -Wall -Werror -CWARN += -Wpointer-arith -Wuninitialized -CFLAGS = $(INC) $(CWARN) -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) -CFLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables - -# Build a static executable. -# Useful for Windows builds, etc., that must run on multiple operating system versions. -ifdef STATIC_BUILD -CFLAGS += -static -static-libgcc -static-libstdc++ -endif - - -# Debugging/Optimization -ifdef DEBUG -CFLAGS += -g -COPT = -O0 -else -COPT = -Os #-DNDEBUG -endif - -# On OSX, 'gcc' is a symlink to clang unless a real gcc is installed. -# The unix port of MicroPython on OSX must be compiled with clang, -# while cross-compile ports require gcc, so we test here for OSX and -# if necessary override the value of 'CC' set in py/mkenv.mk -ifeq ($(UNAME_S),Darwin) -CC = clang -# Use clang syntax for map file -LDFLAGS_ARCH = -Wl,-map,$@.map -Wl,-dead_strip -else -# Use gcc syntax for map file -LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections -endif -LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) - -ifdef STATIC_BUILD -LDFLAGS += -static -static-libgcc -static-libstdc++ -endif - -CFLAGS += -DCIRCUITPY=1 - -# source files -SRC_C += \ - main.c \ - gccollect.c \ - shared/runtime/gchelper_generic.c \ - supervisor/stub/safe_mode.c \ - supervisor/stub/stack.c \ - supervisor/shared/translate/translate.c - -# Add fmode when compiling with mingw gcc -COMPILER_TARGET := $(shell $(CC) -dumpmachine) -ifneq (,$(findstring mingw,$(COMPILER_TARGET))) - SRC_C += fmode.c -endif - -OBJ = $(PY_CORE_O) -OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) - -$(BUILD)/supervisor/shared/translate/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/compressed_translations.generated.h - -include $(TOP)/py/mkrules.mk diff --git a/mpy-cross/mpy-cross.vcxproj b/mpy-cross/mpy-cross.vcxproj index 53cb0fa1fe..322d8c25d1 100644 --- a/mpy-cross/mpy-cross.vcxproj +++ b/mpy-cross/mpy-cross.vcxproj @@ -24,7 +24,6 @@ True $(MSBuildThisFileDirectory)build\ $(MSBuildThisFileDirectory) - $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)..\ports\windows\msvc\ diff --git a/mpy-cross/mpy_cross/__init__.py b/mpy-cross/mpy_cross/__init__.py new file mode 100644 index 0000000000..8eadbc8352 --- /dev/null +++ b/mpy-cross/mpy_cross/__init__.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2022 Andrew Leech +# Copyright (c) 2022 Jim Mussared +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +from __future__ import print_function +import os +import re +import stat +import subprocess + +NATIVE_ARCHS = { + "NATIVE_ARCH_NONE": "", + "NATIVE_ARCH_X86": "x86", + "NATIVE_ARCH_X64": "x64", + "NATIVE_ARCH_ARMV6": "armv6", + "NATIVE_ARCH_ARMV6M": "armv6m", + "NATIVE_ARCH_ARMV7M": "armv7m", + "NATIVE_ARCH_ARMV7EM": "armv7em", + "NATIVE_ARCH_ARMV7EMSP": "armv7emsp", + "NATIVE_ARCH_ARMV7EMDP": "armv7emdp", + "NATIVE_ARCH_XTENSA": "xtensa", + "NATIVE_ARCH_XTENSAWIN": "xtensawin", +} + +globals().update(NATIVE_ARCHS) + +__all__ = ["version", "compile", "run", "CrossCompileError"] + list(NATIVE_ARCHS.keys()) + + +class CrossCompileError(Exception): + pass + + +_VERSION_RE = re.compile("mpy-cross emitting mpy v([0-9]+)(?:.([0-9]+))?") + + +def _find_mpy_cross_binary(mpy_cross): + if mpy_cross: + return mpy_cross + return os.path.abspath(os.path.join(os.path.dirname(__file__), "../build/mpy-cross")) + + +def mpy_version(mpy_cross=None): + """ + Get the version and sub-version of the .mpy file format generated by this version of mpy-cross. + + Returns: A tuple of `(mpy_version, mpy_sub_version)` + Optional keyword arguments: + - mpy_cross: Specific mpy-cross binary to use + """ + version_info = run(["--version"], mpy_cross=mpy_cross) + match = re.search(_VERSION_RE, version_info) + mpy_version, mpy_sub_version = int(match.group(1)), int(match.group(2) or "0") + return ( + mpy_version, + mpy_sub_version, + ) + + +def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None, extra_args=None): + """ + Compile the specified .py file with mpy-cross. + + Returns: Standard output from mpy-cross as a string. + + Required arguments: + - src: The path to the .py file + + Optional keyword arguments: + - dest: The output .mpy file. Defaults to `src` (with .mpy extension) + - src_path: The path to embed in the .mpy file (defaults to `src`) + - opt: Optimisation level (0-3, default 0) + - march: One of the `NATIVE_ARCH_*` constants (defaults to NATIVE_ARCH_NONE) + - mpy_cross: Specific mpy-cross binary to use + - extra_args: Additional arguments to pass to mpy-cross (e.g. `["-X", "emit=native"]`) + """ + if not src: + raise ValueError("src is required") + if not os.path.exists(src): + raise CrossCompileError("Input .py file not found: {}.".format(src_py)) + + args = [] + + if src_path: + args += ["-s", src_path] + + if dest: + args += ["-o", dest] + + if march: + args += ["-march=" + march] + + if opt is not None: + args += ["-O{}".format(opt)] + + if extra_args: + args += extra_args + + args += [src] + + run(args, mpy_cross) + + +def run(args, mpy_cross=None): + """ + Run mpy-cross with the specified command line arguments. + Prefer to use `compile()` instead. + + Returns: Standard output from mpy-cross as a string. + + Optional keyword arguments: + - mpy_cross: Specific mpy-cross binary to use + """ + mpy_cross = _find_mpy_cross_binary(mpy_cross) + + if not os.path.exists(mpy_cross): + raise CrossCompileError("mpy-cross binary not found at {}.".format(mpy_cross)) + + try: + st = os.stat(mpy_cross) + os.chmod(mpy_cross, st.st_mode | stat.S_IEXEC) + except OSError: + pass + + try: + return subprocess.check_output([mpy_cross] + args, stderr=subprocess.STDOUT).decode() + except subprocess.CalledProcessError as er: + raise CrossCompileError(er.output.decode()) diff --git a/mpy-cross/mpy_cross/__main__.py b/mpy-cross/mpy_cross/__main__.py new file mode 100644 index 0000000000..2b6b81c333 --- /dev/null +++ b/mpy-cross/mpy_cross/__main__.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2022 Andrew Leech +# Copyright (c) 2022 Jim Mussared +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +from __future__ import print_function +import argparse +import sys + +from . import run, CrossCompileError + +try: + print(run(sys.argv[1:])) +except CrossCompileError as er: + print(er.args[0], file=sys.stderr) + raise SystemExit(1) diff --git a/ports/litex/supervisor/internal_flash_root_pointers.h b/mpy-cross/windows-fmode.c similarity index 68% rename from ports/litex/supervisor/internal_flash_root_pointers.h rename to mpy-cross/windows-fmode.c index ae3e45e14c..a7976b87e3 100644 --- a/ports/litex/supervisor/internal_flash_root_pointers.h +++ b/mpy-cross/windows-fmode.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,9 +23,27 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_LITEX_INTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_LITEX_INTERNAL_FLASH_ROOT_POINTERS_H -#define FLASH_ROOT_POINTERS +#include "fmode.h" +#include "py/mpconfig.h" +#include +#include -#endif // MICROPY_INCLUDED_LITEX_INTERNAL_FLASH_ROOT_POINTERS_H +// Workaround for setting file translation mode: we must distinguish toolsets +// since mingw has no _set_fmode, and altering msvc's _fmode directly has no effect +STATIC int set_fmode_impl(int mode) { + #ifndef _MSC_VER + _fmode = mode; + return 0; + #else + return _set_fmode(mode); + #endif +} + +void set_fmode_binary(void) { + set_fmode_impl(O_BINARY); +} + +void set_fmode_text(void) { + set_fmode_impl(O_TEXT); +} diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 9457486959..ef6a4bd793 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -362,7 +362,7 @@ OBJ_EXTRA_ORDER_DEPS += $(HEADER_BUILD)/candata.h $(HEADER_BUILD)/candata.h: tools/mkcandata.py | $(HEADER_BUILD) $(Q)$(PYTHON) $< > $@ -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += peripherals/samd/$(PERIPHERALS_CHIP_FAMILY)/clocks.c diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c index 4dbb0a0006..3d5cbf6790 100644 --- a/ports/atmel-samd/audio_dma.c +++ b/ports/atmel-samd/audio_dma.c @@ -432,4 +432,6 @@ void audio_dma_evsys_handler(void) { } } +MP_REGISTER_ROOT_POINTER(mp_obj_t playing_audio[AUDIO_DMA_CHANNEL_COUNT]); + #endif diff --git a/ports/atmel-samd/bindings/samd/Clock.c b/ports/atmel-samd/bindings/samd/Clock.c index 00c1959ccf..fb8dd366d6 100644 --- a/ports/atmel-samd/bindings/samd/Clock.c +++ b/ports/atmel-samd/bindings/samd/Clock.c @@ -128,12 +128,13 @@ STATIC const mp_rom_map_elem_t samd_clock_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(samd_clock_locals_dict, samd_clock_locals_dict_table); -const mp_obj_type_t samd_clock_type = { - { &mp_type_type }, - .name = MP_QSTR_Clock, - .print = samd_clock_print, - .locals_dict = (mp_obj_t)&samd_clock_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + samd_clock_type, + MP_QSTR_Clock, + MP_TYPE_FLAG_NONE, + print, samd_clock_print, + locals_dict, &samd_clock_locals_dict + ); #ifdef SAMD21 diff --git a/ports/atmel-samd/common-hal/_pew/PewPew.c b/ports/atmel-samd/common-hal/_pew/PewPew.c index c4d94e3dbd..4d8d7ccb83 100644 --- a/ports/atmel-samd/common-hal/_pew/PewPew.c +++ b/ports/atmel-samd/common-hal/_pew/PewPew.c @@ -35,7 +35,6 @@ #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/util.h" #include "samd/timers.h" -#include "supervisor/shared/translate/translate.h" #include "timer_handler.h" diff --git a/ports/atmel-samd/common-hal/analogio/AnalogIn.c b/ports/atmel-samd/common-hal/analogio/AnalogIn.c index d15be8308a..f51f299bd3 100644 --- a/ports/atmel-samd/common-hal/analogio/AnalogIn.c +++ b/ports/atmel-samd/common-hal/analogio/AnalogIn.c @@ -37,7 +37,6 @@ #include "samd/adc.h" #include "shared-bindings/analogio/AnalogIn.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "atmel_start_pins.h" #include "hal/include/hal_adc_sync.h" diff --git a/ports/atmel-samd/common-hal/analogio/AnalogOut.c b/ports/atmel-samd/common-hal/analogio/AnalogOut.c index ec690e8ddb..dbf9d5e8dd 100644 --- a/ports/atmel-samd/common-hal/analogio/AnalogOut.c +++ b/ports/atmel-samd/common-hal/analogio/AnalogOut.c @@ -33,7 +33,6 @@ #include "shared-bindings/analogio/AnalogOut.h" #include "shared-bindings/audioio/AudioOut.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "atmel_start_pins.h" #include "hal/include/hal_dac_sync.h" diff --git a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c index 9c1a00c052..8ba18d7701 100644 --- a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c +++ b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -40,7 +40,6 @@ #include "shared-bindings/audiobusio/I2SOut.h" #include "shared-bindings/audiocore/RawSample.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "atmel_start_pins.h" #include "hal/include/hal_gpio.h" diff --git a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c index 6796fe03f8..b3c6f9df5e 100644 --- a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c +++ b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -37,7 +37,6 @@ #include "shared-bindings/audiobusio/PDMIn.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "atmel_start_pins.h" #include "hal/include/hal_gpio.h" diff --git a/ports/atmel-samd/common-hal/audioio/AudioOut.c b/ports/atmel-samd/common-hal/audioio/AudioOut.c index 7007672b3f..52cf8d422b 100644 --- a/ports/atmel-samd/common-hal/audioio/AudioOut.c +++ b/ports/atmel-samd/common-hal/audioio/AudioOut.c @@ -35,7 +35,6 @@ #include "shared-bindings/audioio/AudioOut.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "atmel_start_pins.h" #include "hal/include/hal_gpio.h" diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index 902e696408..b1e981fb31 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -35,7 +35,6 @@ #include "samd/sercom.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "common-hal/busio/__init__.h" diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index 02776928ca..1bc5152b52 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -33,7 +33,6 @@ #include "peripheral_clk_config.h" #include "supervisor/board.h" -#include "supervisor/shared/translate/translate.h" #include "common-hal/busio/__init__.h" #include "hal/include/hal_gpio.h" diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 36c7f020bc..424b16b75c 100644 --- a/ports/atmel-samd/common-hal/busio/UART.c +++ b/ports/atmel-samd/common-hal/busio/UART.c @@ -35,7 +35,6 @@ #include "py/mperrno.h" #include "py/runtime.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/tick.h" #include "hpl_sercom_config.h" diff --git a/ports/atmel-samd/common-hal/countio/Counter.c b/ports/atmel-samd/common-hal/countio/Counter.c index e3694615ab..6b280c1a60 100644 --- a/ports/atmel-samd/common-hal/countio/Counter.c +++ b/ports/atmel-samd/common-hal/countio/Counter.c @@ -7,7 +7,6 @@ #include "eic_handler.h" #include "samd/external_interrupts.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" void common_hal_countio_counter_construct(countio_counter_obj_t *self, const mcu_pin_obj_t *pin, countio_edge_t edge, digitalio_pull_t pull) { diff --git a/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c b/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c index 5e8381e337..3b68748e47 100644 --- a/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c +++ b/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c @@ -34,7 +34,6 @@ #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/digitalio/DigitalInOut.h" -#include "supervisor/shared/translate/translate.h" digitalinout_result_t common_hal_digitalio_digitalinout_construct( digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin) { diff --git a/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c b/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c index df26379170..da0230f60b 100644 --- a/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c +++ b/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c @@ -48,7 +48,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/time/__init__.h" #include "supervisor/shared/tick.h" -#include "supervisor/shared/translate/translate.h" #ifdef SAMD21 #include "hpl/gclk/hpl_gclk_base.h" diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.c b/ports/atmel-samd/common-hal/microcontroller/Pin.c index d70de33618..3db4ec4898 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.c +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.c @@ -27,7 +27,6 @@ #include "py/runtime.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "atmel_start_pins.h" #include "hal/include/hal_gpio.h" diff --git a/ports/atmel-samd/common-hal/microcontroller/__init__.c b/ports/atmel-samd/common-hal/microcontroller/__init__.c index 054d7ee7f8..c4b7c787b4 100644 --- a/ports/atmel-samd/common-hal/microcontroller/__init__.c +++ b/ports/atmel-samd/common-hal/microcontroller/__init__.c @@ -36,7 +36,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Processor.h" #include "supervisor/shared/safe_mode.h" -#include "supervisor/shared/translate/translate.h" void common_hal_mcu_delay_us(uint32_t delay) { mp_hal_delay_us(delay); diff --git a/ports/atmel-samd/common-hal/ps2io/Ps2.c b/ports/atmel-samd/common-hal/ps2io/Ps2.c index 43f40aa48e..bde2ecfac6 100644 --- a/ports/atmel-samd/common-hal/ps2io/Ps2.c +++ b/ports/atmel-samd/common-hal/ps2io/Ps2.c @@ -43,7 +43,6 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/ps2io/Ps2.h" #include "supervisor/port.h" -#include "supervisor/shared/translate/translate.h" #define STATE_IDLE 0 #define STATE_RECV 1 diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.c b/ports/atmel-samd/common-hal/pulseio/PulseIn.c index cc2c1f4fe0..69c6753c65 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseIn.c +++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.c @@ -44,7 +44,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/pulseio/PulseIn.h" #include "supervisor/shared/tick.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/port.h" // This timer is shared amongst all PulseIn objects as a higher resolution clock. diff --git a/ports/atmel-samd/common-hal/pulseio/PulseOut.c b/ports/atmel-samd/common-hal/pulseio/PulseOut.c index dc98e4bd18..282c6035cd 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseOut.c +++ b/ports/atmel-samd/common-hal/pulseio/PulseOut.c @@ -36,7 +36,6 @@ #include "py/gc.h" #include "py/runtime.h" #include "shared-bindings/pulseio/PulseOut.h" -#include "supervisor/shared/translate/translate.h" #include "timer_handler.h" // This timer is shared amongst all PulseOut objects under the assumption that diff --git a/ports/atmel-samd/common-hal/pwmio/PWMOut.c b/ports/atmel-samd/common-hal/pwmio/PWMOut.c index 1bb955fce8..e18420c457 100644 --- a/ports/atmel-samd/common-hal/pwmio/PWMOut.c +++ b/ports/atmel-samd/common-hal/pwmio/PWMOut.c @@ -38,7 +38,6 @@ #include "hal/utils/include/utils_repeat_macro.h" #include "samd/pins.h" #include "samd/timers.h" -#include "supervisor/shared/translate/translate.h" #undef ENABLE diff --git a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c index d253e0967e..d8d56e3172 100644 --- a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c +++ b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c @@ -33,7 +33,6 @@ #include "eic_handler.h" #include "samd/external_interrupts.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { diff --git a/ports/atmel-samd/common-hal/rtc/RTC.c b/ports/atmel-samd/common-hal/rtc/RTC.c index 0ebb61e11b..2da624494b 100644 --- a/ports/atmel-samd/common-hal/rtc/RTC.c +++ b/ports/atmel-samd/common-hal/rtc/RTC.c @@ -37,7 +37,6 @@ #include "shared-bindings/rtc/__init__.h" #include "shared-bindings/rtc/RTC.h" #include "supervisor/port.h" -#include "supervisor/shared/translate/translate.h" // This is the time in seconds since 2000 that the RTC was started. // TODO: Change the offset to ticks so that it can be a subsecond adjustment. diff --git a/ports/atmel-samd/common-hal/sdioio/SDCard.c b/ports/atmel-samd/common-hal/sdioio/SDCard.c index e641db75ac..3490015cbe 100644 --- a/ports/atmel-samd/common-hal/sdioio/SDCard.c +++ b/ports/atmel-samd/common-hal/sdioio/SDCard.c @@ -32,7 +32,6 @@ #include "shared-bindings/sdioio/SDCard.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/__init__.h" -#include "supervisor/shared/translate/translate.h" #include "genhdr/sdiodata.h" diff --git a/ports/atmel-samd/common-hal/touchio/TouchIn.c b/ports/atmel-samd/common-hal/touchio/TouchIn.c index c3fae041fb..8922dc50fb 100644 --- a/ports/atmel-samd/common-hal/touchio/TouchIn.c +++ b/ports/atmel-samd/common-hal/touchio/TouchIn.c @@ -33,7 +33,6 @@ #include "py/mphal.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/touchio/TouchIn.h" -#include "supervisor/shared/translate/translate.h" // Native touchio only exists for SAMD21 #ifdef SAMD21 diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 6fb969e47b..71219ebcef 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -62,7 +62,7 @@ #define MICROPY_FATFS_EXFAT (0) // FAT32 mkfs takes about 500 bytes. -#define MICROPY_FF_MKFS_FAT32 (0) +#define MICROPY_FATFS_MKFS_FAT32 (0) // Only support simpler HID descriptors on SAMD21. #define CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR (1) @@ -270,13 +270,4 @@ #include "peripherals/samd/dma.h" -#if CIRCUITPY_AUDIOCORE -#define MICROPY_PORT_ROOT_POINTERS \ - CIRCUITPY_COMMON_ROOT_POINTERS \ - mp_obj_t playing_audio[AUDIO_DMA_CHANNEL_COUNT]; -#else -#define MICROPY_PORT_ROOT_POINTERS \ - CIRCUITPY_COMMON_ROOT_POINTERS -#endif - #endif // __INCLUDED_MPCONFIGPORT_H diff --git a/ports/atmel-samd/supervisor/internal_flash_root_pointers.h b/ports/atmel-samd/supervisor/internal_flash_root_pointers.h deleted file mode 100644 index 3e9148ce0a..0000000000 --- a/ports/atmel-samd/supervisor/internal_flash_root_pointers.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_ROOT_POINTERS_H - -#define FLASH_ROOT_POINTERS - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/broadcom/Makefile b/ports/broadcom/Makefile index 7243091a42..be2dd788f8 100644 --- a/ports/broadcom/Makefile +++ b/ports/broadcom/Makefile @@ -128,7 +128,7 @@ endif CFLAGS += $(INC) -Wall -Werror -std=gnu11 $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) $(DISABLE_WARNINGS) -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) LDFLAGS += $(CFLAGS) -T peripherals/broadcom/link$(SUFFIX).ld -Wl,--gc-sections -Wl,-Map=$@.map # -Wl,--cref diff --git a/ports/broadcom/bindings/videocore/Framebuffer.c b/ports/broadcom/bindings/videocore/Framebuffer.c index 39c5e71467..7239456d3e 100644 --- a/ports/broadcom/bindings/videocore/Framebuffer.c +++ b/ports/broadcom/bindings/videocore/Framebuffer.c @@ -169,14 +169,12 @@ STATIC const framebuffer_p_t videocore_framebuffer_proto = { .deinit = videocore_framebuffer_deinit_proto, }; -const mp_obj_type_t videocore_framebuffer_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Framebuffer, - .locals_dict = (mp_obj_dict_t *)&videocore_framebuffer_locals_dict, - .make_new = videocore_framebuffer_make_new, - MP_TYPE_EXTENDED_FIELDS( - .buffer_p = { .get_buffer = common_hal_videocore_framebuffer_get_buffer, }, - .protocol = &videocore_framebuffer_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + videocore_framebuffer_type, + MP_QSTR_Framebuffer, + MP_TYPE_FLAG_NONE, + locals_dict, (mp_obj_dict_t *)&videocore_framebuffer_locals_dict, + make_new, videocore_framebuffer_make_new, + buffer, common_hal_videocore_framebuffer_get_buffer, + protocol, &videocore_framebuffer_proto + ); diff --git a/ports/broadcom/common-hal/digitalio/DigitalInOut.c b/ports/broadcom/common-hal/digitalio/DigitalInOut.c index 0dd74a8412..2173ac5684 100644 --- a/ports/broadcom/common-hal/digitalio/DigitalInOut.c +++ b/ports/broadcom/common-hal/digitalio/DigitalInOut.c @@ -32,7 +32,6 @@ #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/digitalio/DigitalInOut.h" -#include "supervisor/shared/translate/translate.h" #include "peripherals/broadcom/gpio.h" diff --git a/ports/broadcom/common-hal/sdioio/SDCard.c b/ports/broadcom/common-hal/sdioio/SDCard.c index cf8bfb1faa..041a06c036 100644 --- a/ports/broadcom/common-hal/sdioio/SDCard.c +++ b/ports/broadcom/common-hal/sdioio/SDCard.c @@ -35,7 +35,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/__init__.h" #include "supervisor/port.h" -#include "supervisor/shared/translate/translate.h" #include "peripherals/broadcom/cpu.h" #include "peripherals/broadcom/defines.h" diff --git a/ports/broadcom/mpconfigport.h b/ports/broadcom/mpconfigport.h index e77725cca3..453f126818 100644 --- a/ports/broadcom/mpconfigport.h +++ b/ports/broadcom/mpconfigport.h @@ -45,8 +45,8 @@ #define CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE (1920) #define CIRCUITPY_PROCESSOR_COUNT (4) -#define MICROPY_FF_MKFS_FAT32 (1) #define MICROPY_FATFS_EXFAT (1) +#define MICROPY_FATFS_MKFS_FAT32 (1) //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -57,7 +57,4 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// -#define MICROPY_PORT_ROOT_POINTERS \ - CIRCUITPY_COMMON_ROOT_POINTERS - #endif // __INCLUDED_MPCONFIGPORT_H diff --git a/ports/cxd56/Makefile b/ports/cxd56/Makefile index 9ec889e257..c6203350d1 100644 --- a/ports/cxd56/Makefile +++ b/ports/cxd56/Makefile @@ -72,6 +72,7 @@ CFLAGS += \ $(INC) \ -DCONFIG_WCHAR_BUILTIN \ -DCONFIG_HAVE_DOUBLE \ + -DNDEBUG \ -Dmain=spresense_main \ -D_estack=__stack \ -DCIRCUITPY_BOARD_ID="\"$(BOARD)\"" \ @@ -155,7 +156,7 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_CIRCUITPY_COMMON:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += diff --git a/ports/cxd56/mpconfigport.h b/ports/cxd56/mpconfigport.h index 3560e72855..a0f5c0c1e1 100644 --- a/ports/cxd56/mpconfigport.h +++ b/ports/cxd56/mpconfigport.h @@ -45,7 +45,4 @@ #define MICROPY_BYTES_PER_GC_BLOCK (32) -#define MICROPY_PORT_ROOT_POINTERS \ - CIRCUITPY_COMMON_ROOT_POINTERS \ - #endif // __INCLUDED_MPCONFIGPORT_H diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index 0622e67447..03435b53a4 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -369,7 +369,7 @@ $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os $(BUILD)/lib/protomatter/src/core.o: CFLAGS += -DESP32 # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # IDF build commands IDF_PATH = $(realpath ./esp-idf) diff --git a/ports/espressif/bindings/espcamera/Camera.c b/ports/espressif/bindings/espcamera/Camera.c index 109ed5cffe..aea4cc775b 100644 --- a/ports/espressif/bindings/espcamera/Camera.c +++ b/ports/espressif/bindings/espcamera/Camera.c @@ -992,9 +992,10 @@ STATIC const mp_rom_map_elem_t espcamera_camera_locals_table[] = { STATIC MP_DEFINE_CONST_DICT(espcamera_camera_locals_dict, espcamera_camera_locals_table); -const mp_obj_type_t espcamera_camera_type = { - .base = { &mp_type_type }, - .name = MP_QSTR_Camera, - .make_new = espcamera_camera_make_new, - .locals_dict = (mp_obj_t)&espcamera_camera_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + espcamera_camera_type, + MP_QSTR_Camera, + MP_TYPE_FLAG_NONE, + make_new, espcamera_camera_make_new, + locals_dict, &espcamera_camera_locals_dict + ); diff --git a/ports/espressif/bindings/espidf/__init__.c b/ports/espressif/bindings/espidf/__init__.c index 65b7f12a18..9f554f4512 100644 --- a/ports/espressif/bindings/espidf/__init__.c +++ b/ports/espressif/bindings/espidf/__init__.c @@ -104,14 +104,15 @@ STATIC void espidf_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr //| //| ... //| -const mp_obj_type_t mp_type_espidf_IDFError = { - { &mp_type_type }, - .name = MP_QSTR_IDFError, - .print = espidf_exception_print, - .make_new = mp_obj_exception_make_new, - .attr = mp_obj_exception_attr, - .parent = &mp_type_OSError, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_espidf_IDFError, + MP_QSTR_IDFError, + MP_TYPE_FLAG_NONE, + print, espidf_exception_print, + make_new, mp_obj_exception_make_new, + attr, mp_obj_exception_attr, + parent, &mp_type_OSError + ); //| class MemoryError(builtins.MemoryError): //| """Raised when an ``ESP-IDF`` memory allocation fails.""" @@ -122,14 +123,15 @@ NORETURN void mp_raise_espidf_MemoryError(void) { nlr_raise(mp_obj_new_exception(&mp_type_espidf_MemoryError)); } -const mp_obj_type_t mp_type_espidf_MemoryError = { - { &mp_type_type }, - .name = MP_QSTR_MemoryError, - .print = espidf_exception_print, - .make_new = mp_obj_exception_make_new, - .attr = mp_obj_exception_attr, - .parent = &mp_type_MemoryError, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_espidf_MemoryError, + MP_QSTR_MemoryError, + MP_TYPE_FLAG_NONE, + print, espidf_exception_print, + make_new, mp_obj_exception_make_new, + attr, mp_obj_exception_attr, + parent, &mp_type_MemoryError + ); //| def get_total_psram() -> int: //| """Returns the number of bytes of psram detected, or 0 if psram is not present or not configured""" @@ -168,3 +170,5 @@ const mp_obj_module_t espidf_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t *)&espidf_module_globals, }; + +MP_REGISTER_MODULE(MP_QSTR_espidf, espidf_module); diff --git a/ports/espressif/bindings/espnow/ESPNow.c b/ports/espressif/bindings/espnow/ESPNow.c index 6255e19f86..1f544758d1 100644 --- a/ports/espressif/bindings/espnow/ESPNow.c +++ b/ports/espressif/bindings/espnow/ESPNow.c @@ -359,14 +359,14 @@ STATIC mp_obj_t espnow_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } -const mp_obj_type_t espnow_type = { - { &mp_type_type }, - .name = MP_QSTR_ESPNow, - .make_new = espnow_make_new, - .locals_dict = (mp_obj_t)&espnow_locals_dict, - .flags = MP_TYPE_FLAG_EXTENDED, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &espnow_stream_p, - .unary_op = &espnow_unary_op - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + espnow_type, + MP_QSTR_ESPNow, + MP_TYPE_FLAG_NONE, + make_new, espnow_make_new, + locals_dict, &espnow_locals_dict, + protocol, &espnow_stream_p, + unary_op, &espnow_unary_op + ); + +MP_REGISTER_ROOT_POINTER(struct _espnow_obj_t *espnow_singleton); diff --git a/ports/espressif/bindings/espnow/ESPNowPacket.c b/ports/espressif/bindings/espnow/ESPNowPacket.c index f8bc8e8418..cefdb1e9e8 100644 --- a/ports/espressif/bindings/espnow/ESPNowPacket.c +++ b/ports/espressif/bindings/espnow/ESPNowPacket.c @@ -43,23 +43,7 @@ //| const mp_obj_namedtuple_type_t espnow_packet_type_obj = { - .base = { - .base = { - .type = &mp_type_type - }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_ESPNowPacket, - .print = namedtuple_print, - .parent = &mp_type_tuple, - .make_new = namedtuple_make_new, - .attr = namedtuple_attr, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - ), - }, + NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_ESPNowPacket), .n_fields = 4, .fields = { MP_QSTR_mac, diff --git a/ports/espressif/bindings/espnow/Peer.c b/ports/espressif/bindings/espnow/Peer.c index 6515cb4eeb..9f6b46ac8e 100644 --- a/ports/espressif/bindings/espnow/Peer.c +++ b/ports/espressif/bindings/espnow/Peer.c @@ -222,9 +222,10 @@ STATIC const mp_rom_map_elem_t espnow_peer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(espnow_peer_locals_dict, espnow_peer_locals_dict_table); -const mp_obj_type_t espnow_peer_type = { - { &mp_type_type }, - .name = MP_QSTR_Peer, - .make_new = espnow_peer_make_new, - .locals_dict = (mp_obj_t)&espnow_peer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + espnow_peer_type, + MP_QSTR_Peer, + MP_TYPE_FLAG_NONE, + make_new, espnow_peer_make_new, + locals_dict, &espnow_peer_locals_dict + ); diff --git a/ports/espressif/bindings/espnow/Peers.c b/ports/espressif/bindings/espnow/Peers.c index 096a5266a0..0606d3a94f 100644 --- a/ports/espressif/bindings/espnow/Peers.c +++ b/ports/espressif/bindings/espnow/Peers.c @@ -83,8 +83,7 @@ STATIC MP_DEFINE_CONST_DICT(espnow_peers_locals_dict, espnow_peers_locals_dict_t STATIC void espnow_peers_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { espnow_peers_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list); - return list->base.type->print(print, self->list, kind); + return MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(self->list), print)(print, self->list, kind); } /******************************************************************************/ @@ -92,8 +91,7 @@ STATIC void espnow_peers_print(const mp_print_t *print, mp_obj_t self_in, mp_pri STATIC mp_obj_t espnow_peers_unary_op(mp_unary_op_t op, mp_obj_t self_in) { espnow_peers_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list); - return list->base.type->ext->unary_op(op, self->list); + return MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(self->list), unary_op)(op, self->list); } /******************************************************************************/ @@ -104,8 +102,7 @@ STATIC mp_obj_t espnow_peers_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t v return MP_OBJ_NULL; // op not supported } espnow_peers_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list); - return list->base.type->ext->subscr(self->list, index, value); + return MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(self->list), subscr)(self->list, index, value); } /******************************************************************************/ @@ -113,8 +110,7 @@ STATIC mp_obj_t espnow_peers_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t v STATIC mp_obj_t espnow_peers_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { espnow_peers_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list); - return list->base.type->ext->getiter(self->list, iter_buf); + return ((mp_getiter_fun_t)MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(self->list), iter))(self->list, iter_buf); } espnow_peers_obj_t *espnow_peers_new(void) { @@ -123,15 +119,13 @@ espnow_peers_obj_t *espnow_peers_new(void) { return self; } -const mp_obj_type_t espnow_peers_type = { - { &mp_type_type }, - .name = MP_QSTR_Peers, - .print = espnow_peers_print, - .locals_dict = (mp_obj_t)&espnow_peers_locals_dict, - .flags = MP_TYPE_FLAG_EXTENDED, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = espnow_peers_unary_op, - .subscr = espnow_peers_subscr, - .getiter = espnow_peers_getiter, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + espnow_peers_type, + MP_QSTR_Peers, + MP_TYPE_FLAG_ITER_IS_GETITER, + print, espnow_peers_print, + locals_dict, &espnow_peers_locals_dict, + unary_op, espnow_peers_unary_op, + subscr, espnow_peers_subscr, + iter, espnow_peers_getiter + ); diff --git a/ports/espressif/bindings/espulp/ULP.c b/ports/espressif/bindings/espulp/ULP.c index 09453c9a09..4e9c331758 100644 --- a/ports/espressif/bindings/espulp/ULP.c +++ b/ports/espressif/bindings/espulp/ULP.c @@ -172,9 +172,10 @@ STATIC const mp_rom_map_elem_t espulp_ulp_locals_table[] = { }; STATIC MP_DEFINE_CONST_DICT(espulp_ulp_locals_dict, espulp_ulp_locals_table); -const mp_obj_type_t espulp_ulp_type = { - { &mp_type_type }, - .name = MP_QSTR_ULP, - .make_new = espulp_ulp_make_new, - .locals_dict = (mp_obj_t)&espulp_ulp_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + espulp_ulp_type, + MP_QSTR_ULP, + MP_TYPE_FLAG_NONE, + make_new, espulp_ulp_make_new, + locals_dict, &espulp_ulp_locals_dict + ); diff --git a/ports/espressif/bindings/espulp/ULPAlarm.c b/ports/espressif/bindings/espulp/ULPAlarm.c index b8b0a7c122..7c13e8cbca 100644 --- a/ports/espressif/bindings/espulp/ULPAlarm.c +++ b/ports/espressif/bindings/espulp/ULPAlarm.c @@ -59,8 +59,9 @@ STATIC mp_obj_t espulp_ulpalarm_make_new(const mp_obj_type_t *type, size_t n_arg return MP_OBJ_FROM_PTR(self); } -const mp_obj_type_t espulp_ulpalarm_type = { - { &mp_type_type }, - .name = MP_QSTR_ULPAlarm, - .make_new = espulp_ulpalarm_make_new, -}; +MP_DEFINE_CONST_OBJ_TYPE( + espulp_ulpalarm_type, + MP_QSTR_ULPAlarm, + MP_TYPE_FLAG_NONE, + make_new, espulp_ulpalarm_make_new + ); diff --git a/ports/espressif/boards/m5stack_atoms3/board.c b/ports/espressif/boards/m5stack_atoms3/board.c new file mode 100644 index 0000000000..ee8b6c8f4d --- /dev/null +++ b/ports/espressif/boards/m5stack_atoms3/board.c @@ -0,0 +1,106 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/displayio/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + +displayio_fourwire_obj_t board_display_obj; + +#define DELAY 0x80 + +// display init sequence according to ST7789 +uint8_t display_init_sequence[] = { + 0x01, 0 | DELAY, 0x96, // _SWRESET and Delay 150ms + 0x11, 0 | DELAY, 0xff, // _SLPOUT and Delay 500ms + 0x3A, 1 | DELAY, 0x55, 0x0a, // _COLMOD and Delay 10ms + 0x36, 0x01, 0x08, // _MADCTL + 0x21, 0x80, 0x0A, // _INVON Hack and Delay 10ms + 0x13, 0x80, 0x0A, // _NORON and Delay 10ms + 0x36, 0x01, 0xC0, // _MADCTL + 0x29, 0 | DELAY, 0xff // _DISPON and Delay 500ms +}; + + +void board_init(void) { + displayio_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + // busio_spi_obj_t *spi = common_hal_board_create_spi(0); + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO17, &pin_GPIO21, NULL, false); + common_hal_busio_spi_never_reset(spi); + bus->base.type = &displayio_fourwire_type; + + common_hal_displayio_fourwire_construct( + bus, + spi, + &pin_GPIO33, // DC + &pin_GPIO15, // CS + &pin_GPIO34, // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + displayio_display_obj_t *display = &allocate_display()->display; + display->base.type = &displayio_display_type; + + common_hal_displayio_display_construct( + display, + bus, + 128, // width (after rotation) + 128, // height (after rotation) + 2, // column start + 1, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO16, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 200 // backlight pwm frequency + ); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/cxd56/supervisor/internal_flash_root_pointers.h b/ports/espressif/boards/m5stack_atoms3/mpconfigboard.h similarity index 69% rename from ports/cxd56/supervisor/internal_flash_root_pointers.h rename to ports/espressif/boards/m5stack_atoms3/mpconfigboard.h index 126c6af097..e2e3e7f84f 100644 --- a/ports/cxd56/supervisor/internal_flash_root_pointers.h +++ b/ports/espressif/boards/m5stack_atoms3/mpconfigboard.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright 2019 Sony Semiconductor Solutions Corporation + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,9 +23,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_CXD56_INTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_CXD56_INTERNAL_FLASH_ROOT_POINTERS_H -#define FLASH_ROOT_POINTERS +// Micropython setup -#endif // MICROPY_INCLUDED_CXD56_INTERNAL_FLASH_ROOT_POINTERS_H +#define MICROPY_HW_BOARD_NAME "M5Stack AtomS3" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +// #define MICROPY_HW_NEOPIXEL (&pin_GPIO35) + +#define CIRCUITPY_BOARD_I2C (2) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO39, .sda = &pin_GPIO38}, \ + {.scl = &pin_GPIO1, .sda = &pin_GPIO2}} + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO17) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO21) diff --git a/ports/espressif/boards/m5stack_atoms3/mpconfigboard.mk b/ports/espressif/boards/m5stack_atoms3/mpconfigboard.mk new file mode 100644 index 0000000000..9bc53033a1 --- /dev/null +++ b/ports/espressif/boards/m5stack_atoms3/mpconfigboard.mk @@ -0,0 +1,11 @@ +USB_VID = 0x303A +USB_PID = 0x8120 +USB_PRODUCT = "M5Stack AtomS3" +USB_MANUFACTURER = "M5Stack" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB +CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_atoms3/pins.c b/ports/espressif/boards/m5stack_atoms3/pins.c new file mode 100644 index 0000000000..0936919131 --- /dev/null +++ b/ports/espressif/boards/m5stack_atoms3/pins.c @@ -0,0 +1,53 @@ +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(porta_i2c, i2c, 1) + +STATIC const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_PORTA_SCL), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_PORTA_SDA), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_D39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IMU_SCL), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_D38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IMU_SDA), MP_ROM_PTR(&pin_GPIO38) }, + + // lcd spi bus + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_BTN), MP_ROM_PTR(&pin_GPIO41) }, + + { MP_ROM_QSTR(MP_QSTR_IR_LED), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_I2C), MP_ROM_PTR(&board_porta_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} +}; + +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/m5stack_atoms3/sdkconfig b/ports/espressif/boards/m5stack_atoms3/sdkconfig new file mode 100644 index 0000000000..f5ef797681 --- /dev/null +++ b/ports/espressif/boards/m5stack_atoms3/sdkconfig @@ -0,0 +1,15 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/common-hal/_bleio/ble_events.c b/ports/espressif/common-hal/_bleio/ble_events.c index a072a80623..e5c4608cd7 100644 --- a/ports/espressif/common-hal/_bleio/ble_events.c +++ b/ports/espressif/common-hal/_bleio/ble_events.c @@ -126,3 +126,5 @@ int ble_event_run_handlers(struct ble_gap_event *event) { #endif return 0; } + +MP_REGISTER_ROOT_POINTER(struct ble_event_handler_entry *ble_event_handler_entries); diff --git a/ports/espressif/common-hal/analogio/AnalogIn.c b/ports/espressif/common-hal/analogio/AnalogIn.c index f3950e7f19..51ee5a9cb2 100644 --- a/ports/espressif/common-hal/analogio/AnalogIn.c +++ b/ports/espressif/common-hal/analogio/AnalogIn.c @@ -30,7 +30,6 @@ #include "shared-bindings/analogio/AnalogIn.h" #include "py/mperrno.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "adc_cali_schemes.h" #include "esp_adc/adc_oneshot.h" diff --git a/ports/espressif/common-hal/analogio/AnalogOut.c b/ports/espressif/common-hal/analogio/AnalogOut.c index b2bf7294f1..d6154392bd 100644 --- a/ports/espressif/common-hal/analogio/AnalogOut.c +++ b/ports/espressif/common-hal/analogio/AnalogOut.c @@ -33,7 +33,6 @@ #include "shared-bindings/analogio/AnalogOut.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #ifdef SOC_DAC_SUPPORTED #include "driver/dac_oneshot.h" diff --git a/ports/espressif/common-hal/audiobusio/I2SOut.c b/ports/espressif/common-hal/audiobusio/I2SOut.c index 33e5dd6ac0..7020f7cf59 100644 --- a/ports/espressif/common-hal/audiobusio/I2SOut.c +++ b/ports/espressif/common-hal/audiobusio/I2SOut.c @@ -42,7 +42,6 @@ #include "shared-bindings/audiobusio/I2SOut.h" #include "shared-bindings/audiocore/RawSample.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "driver/i2s_std.h" diff --git a/ports/espressif/common-hal/busio/I2C.c b/ports/espressif/common-hal/busio/I2C.c index ea752c986d..d3017e9587 100644 --- a/ports/espressif/common-hal/busio/I2C.c +++ b/ports/espressif/common-hal/busio/I2C.c @@ -32,7 +32,6 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { diff --git a/ports/espressif/common-hal/busio/UART.c b/ports/espressif/common-hal/busio/UART.c index e96861191f..386fe1f1b3 100644 --- a/ports/espressif/common-hal/busio/UART.c +++ b/ports/espressif/common-hal/busio/UART.c @@ -38,7 +38,6 @@ #include "py/runtime.h" #include "py/stream.h" #include "supervisor/port.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/tick.h" static uint8_t never_reset_uart_mask = 0; diff --git a/ports/espressif/common-hal/countio/Counter.c b/ports/espressif/common-hal/countio/Counter.c index 1cf6d8e707..4bea059b17 100644 --- a/ports/espressif/common-hal/countio/Counter.c +++ b/ports/espressif/common-hal/countio/Counter.c @@ -29,7 +29,6 @@ #include "common-hal/microcontroller/Pin.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "driver/gpio.h" diff --git a/ports/espressif/common-hal/digitalio/DigitalInOut.c b/ports/espressif/common-hal/digitalio/DigitalInOut.c index 4b6c966da3..6ff3aa41f6 100644 --- a/ports/espressif/common-hal/digitalio/DigitalInOut.c +++ b/ports/espressif/common-hal/digitalio/DigitalInOut.c @@ -26,7 +26,6 @@ #include "shared-bindings/digitalio/DigitalInOut.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "components/driver/gpio/include/driver/gpio.h" diff --git a/ports/espressif/common-hal/espidf/__init__.c b/ports/espressif/common-hal/espidf/__init__.c index e5f866b906..bd5cd51884 100644 --- a/ports/espressif/common-hal/espidf/__init__.c +++ b/ports/espressif/common-hal/espidf/__init__.c @@ -25,7 +25,6 @@ */ #include "bindings/espidf/__init__.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/memory.h" #include "py/runtime.h" diff --git a/ports/espressif/common-hal/microcontroller/Processor.c b/ports/espressif/common-hal/microcontroller/Processor.c index 4248a972f4..7c25608f89 100644 --- a/ports/espressif/common-hal/microcontroller/Processor.c +++ b/ports/espressif/common-hal/microcontroller/Processor.c @@ -33,7 +33,6 @@ #include "common-hal/microcontroller/Processor.h" #include "shared-bindings/microcontroller/Processor.h" #include "shared-bindings/microcontroller/ResetReason.h" -#include "supervisor/shared/translate/translate.h" #include "esp_sleep.h" #include "esp_system.h" diff --git a/ports/espressif/mpconfigport.h b/ports/espressif/mpconfigport.h index bb333ae4ac..96b4d4af14 100644 --- a/ports/espressif/mpconfigport.h +++ b/ports/espressif/mpconfigport.h @@ -37,23 +37,6 @@ #include "py/circuitpy_mpconfig.h" -#if CIRCUITPY_BLEIO -#define BLEIO_ROOT_POINTERS struct ble_event_handler_entry *ble_event_handler_entries; -#else -#define BLEIO_ROOT_POINTERS -#endif - -#if CIRCUITPY_ESPNOW -#define ESPNOW_ROOT_POINTERS struct _espnow_obj_t *espnow_singleton; -#else -#define ESPNOW_ROOT_POINTERS -#endif - -#define MICROPY_PORT_ROOT_POINTERS \ - CIRCUITPY_COMMON_ROOT_POINTERS \ - BLEIO_ROOT_POINTERS \ - ESPNOW_ROOT_POINTERS - #define MICROPY_NLR_SETJMP (1) #define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000 diff --git a/ports/espressif/supervisor/internal_flash_root_pointers.h b/ports/espressif/supervisor/internal_flash_root_pointers.h deleted file mode 100644 index b4908f8e4b..0000000000 --- a/ports/espressif/supervisor/internal_flash_root_pointers.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_ESPRESSIF_INTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_ESPRESSIF_INTERNAL_FLASH_ROOT_POINTERS_H - -#define FLASH_ROOT_POINTERS - -#endif // MICROPY_INCLUDED_ESPRESSIF_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/espressif/supervisor/usb_serial_jtag.c b/ports/espressif/supervisor/usb_serial_jtag.c index 9350d1bf97..957ae60c91 100644 --- a/ports/espressif/supervisor/usb_serial_jtag.c +++ b/ports/espressif/supervisor/usb_serial_jtag.c @@ -89,7 +89,7 @@ static void usb_serial_jtag_isr_handler(void *arg) { } void usb_serial_jtag_init(void) { - ringbuf_init(&ringbuf, buf, sizeof(buf) - 1); + ringbuf_init(&ringbuf, buf, sizeof(buf)); usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SOF | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_TOKEN_REC_IN_EP1); usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SOF | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_TOKEN_REC_IN_EP1); ESP_ERROR_CHECK(esp_intr_alloc(ETS_USB_SERIAL_JTAG_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1, diff --git a/ports/litex/Makefile b/ports/litex/Makefile index ce7805d067..7fd118de36 100644 --- a/ports/litex/Makefile +++ b/ports/litex/Makefile @@ -126,7 +126,7 @@ $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += diff --git a/ports/litex/common-hal/digitalio/DigitalInOut.c b/ports/litex/common-hal/digitalio/DigitalInOut.c index 7545722967..3a14d8e625 100644 --- a/ports/litex/common-hal/digitalio/DigitalInOut.c +++ b/ports/litex/common-hal/digitalio/DigitalInOut.c @@ -27,7 +27,6 @@ #include "shared-bindings/digitalio/DigitalInOut.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "csr.h" diff --git a/ports/litex/common-hal/microcontroller/Processor.c b/ports/litex/common-hal/microcontroller/Processor.c index 12c3787c79..5e4a57dfeb 100644 --- a/ports/litex/common-hal/microcontroller/Processor.c +++ b/ports/litex/common-hal/microcontroller/Processor.c @@ -31,7 +31,6 @@ #include "common-hal/microcontroller/Processor.h" #include "shared-bindings/microcontroller/Processor.h" #include "shared-bindings/microcontroller/ResetReason.h" -#include "supervisor/shared/translate/translate.h" #include "csr.h" #include "generated/soc.h" diff --git a/ports/litex/mpconfigport.h b/ports/litex/mpconfigport.h index cedc3badc3..9b214c5799 100644 --- a/ports/litex/mpconfigport.h +++ b/ports/litex/mpconfigport.h @@ -34,8 +34,6 @@ #include "py/circuitpy_mpconfig.h" -#define MICROPY_PORT_ROOT_POINTERS \ - CIRCUITPY_COMMON_ROOT_POINTERS #define MICROPY_NLR_SETJMP (1) #define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000 diff --git a/ports/mimxrt10xx/Makefile b/ports/mimxrt10xx/Makefile index c02cd79a07..0187bf5240 100644 --- a/ports/mimxrt10xx/Makefile +++ b/ports/mimxrt10xx/Makefile @@ -196,7 +196,7 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_CIRCUITPY_COMMON:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.S=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 $(BUILD)/firmware.hex diff --git a/ports/mimxrt10xx/common-hal/analogio/AnalogOut.c b/ports/mimxrt10xx/common-hal/analogio/AnalogOut.c index 14e1faab09..28c134f2b2 100644 --- a/ports/mimxrt10xx/common-hal/analogio/AnalogOut.c +++ b/ports/mimxrt10xx/common-hal/analogio/AnalogOut.c @@ -29,7 +29,6 @@ #include "shared-bindings/analogio/AnalogOut.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" void common_hal_analogio_analogout_construct(analogio_analogout_obj_t *self, const mcu_pin_obj_t *pin) { mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_AnalogOut); diff --git a/ports/mimxrt10xx/common-hal/audiobusio/I2SOut.c b/ports/mimxrt10xx/common-hal/audiobusio/I2SOut.c index 43074acc09..8c59922cc9 100644 --- a/ports/mimxrt10xx/common-hal/audiobusio/I2SOut.c +++ b/ports/mimxrt10xx/common-hal/audiobusio/I2SOut.c @@ -39,7 +39,6 @@ #include "shared-bindings/audiobusio/I2SOut.h" #include "shared-bindings/audiocore/RawSample.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/tick.h" // Where required we use identifier names that are required by NXP's diff --git a/ports/mimxrt10xx/common-hal/audiopwmio/PWMAudioOut.c b/ports/mimxrt10xx/common-hal/audiopwmio/PWMAudioOut.c index 8650522b41..11c2b8e87e 100644 --- a/ports/mimxrt10xx/common-hal/audiopwmio/PWMAudioOut.c +++ b/ports/mimxrt10xx/common-hal/audiopwmio/PWMAudioOut.c @@ -36,7 +36,6 @@ #include "common-hal/audiopwmio/PWMAudioOut.h" #include "shared-bindings/audiopwmio/PWMAudioOut.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/tick.h" // Where required we use identifier names that are required by NXP's diff --git a/ports/mimxrt10xx/common-hal/digitalio/DigitalInOut.c b/ports/mimxrt10xx/common-hal/digitalio/DigitalInOut.c index 31dac38bdc..c37646b098 100644 --- a/ports/mimxrt10xx/common-hal/digitalio/DigitalInOut.c +++ b/ports/mimxrt10xx/common-hal/digitalio/DigitalInOut.c @@ -36,7 +36,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/digitalio/DigitalInOut.h" -#include "supervisor/shared/translate/translate.h" #define IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_ALT5 5U diff --git a/ports/mimxrt10xx/common-hal/microcontroller/__init__.c b/ports/mimxrt10xx/common-hal/microcontroller/__init__.c index de970fa26a..ef7e481330 100644 --- a/ports/mimxrt10xx/common-hal/microcontroller/__init__.c +++ b/ports/mimxrt10xx/common-hal/microcontroller/__init__.c @@ -36,9 +36,7 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Processor.h" -#include "supervisor/linker.h" #include "supervisor/shared/safe_mode.h" -#include "supervisor/shared/translate/translate.h" #include "pins.h" diff --git a/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c b/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c index 0bf11403d2..cb1e7b0529 100644 --- a/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c +++ b/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c @@ -35,7 +35,6 @@ #include "sdk/drivers/pwm/fsl_pwm.h" -#include "supervisor/shared/translate/translate.h" #include "periph.h" static PWM_Type *const _flexpwms[] = PWM_BASE_PTRS; diff --git a/ports/mimxrt10xx/common-hal/rtc/RTC.c b/ports/mimxrt10xx/common-hal/rtc/RTC.c index 386b6a3ac5..3cbaac9ccf 100644 --- a/ports/mimxrt10xx/common-hal/rtc/RTC.c +++ b/ports/mimxrt10xx/common-hal/rtc/RTC.c @@ -33,7 +33,6 @@ #include "shared-bindings/rtc/__init__.h" #include "shared-bindings/rtc/RTC.h" #include "common-hal/rtc/RTC.h" -#include "supervisor/shared/translate/translate.h" #include "sdk/drivers/snvs_hp/fsl_snvs_hp.h" #include "sdk/drivers/snvs_lp/fsl_snvs_lp.h" diff --git a/ports/mimxrt10xx/mpconfigport.h b/ports/mimxrt10xx/mpconfigport.h index 7cc17494bf..eedfaaec15 100644 --- a/ports/mimxrt10xx/mpconfigport.h +++ b/ports/mimxrt10xx/mpconfigport.h @@ -52,10 +52,7 @@ extern uint8_t _ld_default_stack_size; #include "py/circuitpy_mpconfig.h" -#define MICROPY_PORT_ROOT_POINTERS \ - CIRCUITPY_COMMON_ROOT_POINTERS \ - // TODO: -// mp_obj_t playing_audio[AUDIO_DMA_CHANNEL_COUNT]; +// mp_obj_t playing_audio[AUDIO_DMA_CHANNEL_COUNT] as an MP_REGISTER_ROOT_POINTER. #endif // __INCLUDED_MPCONFIGPORT_H diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1042/clocks.c b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1042/clocks.c index 95db72df45..97d3d04f8f 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1042/clocks.c +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1042/clocks.c @@ -379,4 +379,5 @@ void clocks_init(void) { IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK; /* Set SystemCoreClock variable. */ SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; + CLOCK_SetMode(kCLOCK_ModeRun); } diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1052/clocks.c b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1052/clocks.c index de12bea6a0..aafd0fde33 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1052/clocks.c +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1052/clocks.c @@ -399,4 +399,5 @@ void clocks_init(void) { IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK; /* Set SystemCoreClock variable. */ SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; + CLOCK_SetMode(kCLOCK_ModeRun); } diff --git a/ports/mimxrt10xx/supervisor/internal_flash_root_pointers.h b/ports/mimxrt10xx/supervisor/internal_flash_root_pointers.h deleted file mode 100644 index c8173175eb..0000000000 --- a/ports/mimxrt10xx/supervisor/internal_flash_root_pointers.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_MIMXRT10XX_INTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_MIMXRT10XX_INTERNAL_FLASH_ROOT_POINTERS_H - -#define FLASH_ROOT_POINTERS - -#endif // MICROPY_INCLUDED_MIMXRT10XX_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 5829b465a6..bd2da35eea 100755 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -198,7 +198,7 @@ $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += diff --git a/ports/nrf/bluetooth/ble_drv.c b/ports/nrf/bluetooth/ble_drv.c index e3914e6a18..f362f28e97 100644 --- a/ports/nrf/bluetooth/ble_drv.c +++ b/ports/nrf/bluetooth/ble_drv.c @@ -196,3 +196,5 @@ void SD_EVT_IRQHandler(void) { ble_serial_enable(); #endif } + +MP_REGISTER_ROOT_POINTER(ble_drv_evt_handler_entry_t * ble_drv_evt_handler_entries); diff --git a/ports/nrf/common-hal/analogio/AnalogIn.c b/ports/nrf/common-hal/analogio/AnalogIn.c index b9d4b6a199..69b9eb984c 100644 --- a/ports/nrf/common-hal/analogio/AnalogIn.c +++ b/ports/nrf/common-hal/analogio/AnalogIn.c @@ -29,7 +29,6 @@ #include "shared-bindings/analogio/AnalogIn.h" #include "shared-bindings/microcontroller/Pin.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "nrf_saadc.h" #include "nrf_gpio.h" diff --git a/ports/nrf/common-hal/analogio/AnalogOut.c b/ports/nrf/common-hal/analogio/AnalogOut.c index 38ff935674..03e0515f49 100644 --- a/ports/nrf/common-hal/analogio/AnalogOut.c +++ b/ports/nrf/common-hal/analogio/AnalogOut.c @@ -31,7 +31,6 @@ #include "py/mperrno.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" void common_hal_analogio_analogout_construct(analogio_analogout_obj_t *self, const mcu_pin_obj_t *pin) { mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_AnalogOut); diff --git a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c index 2334db851a..88843e81b1 100644 --- a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +++ b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c @@ -37,7 +37,6 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "supervisor/shared/tick.h" -#include "supervisor/shared/translate/translate.h" // TODO: This should be the same size as PWMOut.c:pwms[], but there's no trivial way to accomplish that STATIC audiopwmio_pwmaudioout_obj_t *active_audio[4]; diff --git a/ports/nrf/common-hal/busio/I2C.c b/ports/nrf/common-hal/busio/I2C.c index 2bd1416f5a..03c8931e7e 100644 --- a/ports/nrf/common-hal/busio/I2C.c +++ b/ports/nrf/common-hal/busio/I2C.c @@ -32,7 +32,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "py/mperrno.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "nrfx_twim.h" #include "nrfx_spim.h" diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c index 5bc0854fe7..7fe936209f 100644 --- a/ports/nrf/common-hal/busio/UART.c +++ b/ports/nrf/common-hal/busio/UART.c @@ -33,7 +33,6 @@ #include "py/mperrno.h" #include "py/runtime.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" #include "nrfx_uarte.h" #include "nrf_gpio.h" diff --git a/ports/nrf/common-hal/digitalio/DigitalInOut.c b/ports/nrf/common-hal/digitalio/DigitalInOut.c index a6440228f1..e1e9e24e34 100644 --- a/ports/nrf/common-hal/digitalio/DigitalInOut.c +++ b/ports/nrf/common-hal/digitalio/DigitalInOut.c @@ -26,7 +26,6 @@ #include "shared-bindings/digitalio/DigitalInOut.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "nrf_gpio.h" diff --git a/ports/nrf/common-hal/neopixel_write/__init__.c b/ports/nrf/common-hal/neopixel_write/__init__.c index ce8ee8c7cf..6e38dca8c1 100644 --- a/ports/nrf/common-hal/neopixel_write/__init__.c +++ b/ports/nrf/common-hal/neopixel_write/__init__.c @@ -333,3 +333,5 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout, // Update the next start. next_start_raw_ticks = port_get_raw_ticks(NULL) + 4; } + +MP_REGISTER_ROOT_POINTER(uint16_t * pixels_pattern_heap); diff --git a/ports/nrf/common-hal/pulseio/PulseOut.c b/ports/nrf/common-hal/pulseio/PulseOut.c index c2d59ffdba..e3ee9dbeb9 100644 --- a/ports/nrf/common-hal/pulseio/PulseOut.c +++ b/ports/nrf/common-hal/pulseio/PulseOut.c @@ -35,7 +35,6 @@ #include "py/runtime.h" #include "shared-bindings/pulseio/PulseOut.h" #include "shared-bindings/pwmio/PWMOut.h" -#include "supervisor/shared/translate/translate.h" // A single timer is shared amongst all PulseOut objects under the assumption that // the code is single threaded. diff --git a/ports/nrf/common-hal/pwmio/PWMOut.c b/ports/nrf/common-hal/pwmio/PWMOut.c index 6171f5eb76..8edaa77f66 100644 --- a/ports/nrf/common-hal/pwmio/PWMOut.c +++ b/ports/nrf/common-hal/pwmio/PWMOut.c @@ -30,7 +30,6 @@ #include "py/runtime.h" #include "common-hal/pwmio/PWMOut.h" #include "shared-bindings/pwmio/PWMOut.h" -#include "supervisor/shared/translate/translate.h" #include "nrf_gpio.h" diff --git a/ports/nrf/common-hal/rtc/RTC.c b/ports/nrf/common-hal/rtc/RTC.c index 29d308eccc..a7bc89afb0 100644 --- a/ports/nrf/common-hal/rtc/RTC.c +++ b/ports/nrf/common-hal/rtc/RTC.c @@ -33,7 +33,6 @@ #include "common-hal/rtc/RTC.h" #include "shared-bindings/rtc/RTC.h" #include "supervisor/port.h" -#include "supervisor/shared/translate/translate.h" // This is the time in seconds since 2000 that the RTC was started. __attribute__((section(".uninitialized"))) static uint32_t rtc_offset[3]; diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 4726d51c55..d97d9277d0 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -204,11 +204,4 @@ #error RAM size regions do not use all of RAM #endif - -#define MICROPY_PORT_ROOT_POINTERS \ - CIRCUITPY_COMMON_ROOT_POINTERS \ - uint16_t *pixels_pattern_heap; \ - ble_drv_evt_handler_entry_t *ble_drv_evt_handler_entries; \ - - #endif // NRF5_MPCONFIGPORT_H__ diff --git a/ports/nrf/supervisor/internal_flash_root_pointers.h b/ports/nrf/supervisor/internal_flash_root_pointers.h deleted file mode 100644 index cc6074585e..0000000000 --- a/ports/nrf/supervisor/internal_flash_root_pointers.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_NRF_INTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_NRF_INTERNAL_FLASH_ROOT_POINTERS_H - -#define FLASH_ROOT_POINTERS - -#endif // MICROPY_INCLUDED_NRF_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile index 5a021494f6..9d35243dee 100644 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -39,7 +39,7 @@ INC_CYW43 := \ -isystem sdk/src/rp2_common/pico_lwip/include/ \ -isystem sdk/src/rp2_common/pico_rand/include/ \ -CFLAGS_CYW43 := -DCYW43_LWIP=1 -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_USE_SPI -DIGNORE_GPIO25 -DIGNORE_GPIO23 -DIGNORE_GPIO24 -DCYW43_LOGIC_DEBUG=0 -DCYW43_NETUTILS=1 -DPICO_BUILD +CFLAGS_CYW43 := -DCYW43_LWIP=1 -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_USE_SPI -DIGNORE_GPIO25 -DIGNORE_GPIO23 -DIGNORE_GPIO24 -DCYW43_LOGIC_DEBUG=0 -DCYW43_USE_STATS=0 -DPICO_BUILD -DCYW43_ENABLE_BLUETOOTH=0 -DPICO_CYW43_ARCH_POLL=0 SRC_SDK_CYW43 := \ src/common/pico_sync/sem.c \ src/rp2_common/pico_async_context/async_context_base.c \ @@ -436,7 +436,7 @@ $(BUILD)/boot2.elf: $(BUILD)/stage2.c $(Q)$(CC) $(CFLAGS) $(BOOT2_S_CFLAGS) -Os -ggdb3 -I. -fPIC --specs=nosys.specs -nostartfiles -Wl,-T,boot_stage2.ld -Wl,-Map=$@.map -o $@ $< $(Q)$(SIZE) $@ -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) all: $(BUILD)/firmware.uf2 diff --git a/ports/raspberrypi/audio_dma.c b/ports/raspberrypi/audio_dma.c index 940a383cbe..1095a88308 100644 --- a/ports/raspberrypi/audio_dma.c +++ b/ports/raspberrypi/audio_dma.c @@ -493,4 +493,5 @@ void isr_dma_0(void) { } } +MP_REGISTER_ROOT_POINTER(mp_obj_t playing_audio[enum_NUM_DMA_CHANNELS]); #endif diff --git a/ports/raspberrypi/bindings/cyw43/__init__.c b/ports/raspberrypi/bindings/cyw43/__init__.c index d00612518e..7704c08790 100644 --- a/ports/raspberrypi/bindings/cyw43/__init__.c +++ b/ports/raspberrypi/bindings/cyw43/__init__.c @@ -32,6 +32,9 @@ #include "shared-bindings/microcontroller/Pin.h" #include "bindings/cyw43/__init__.h" +#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" + +#include "lib/cyw43-driver/src/cyw43.h" static int power_management_value = PM_DISABLED; @@ -41,7 +44,7 @@ void cyw43_enter_deep_sleep(void) { gpio_put(WL_REG_ON, false); } -void bindings_cyw43_wifi_enforce_pm() { +void bindings_cyw43_wifi_enforce_pm(void) { cyw43_wifi_pm(&cyw43_state, power_management_value); } @@ -52,15 +55,13 @@ void bindings_cyw43_wifi_enforce_pm() { //| in :py:mod:`board`. A `CywPin` can be used as a DigitalInOut, but not with other //| peripherals such as `PWMOut`.""" //| -const mp_obj_type_t cyw43_pin_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_CywPin, - .print = shared_bindings_microcontroller_pin_print, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_generic_unary_op, - ) -}; +MP_DEFINE_CONST_OBJ_TYPE( + cyw43_pin_type, + MP_QSTR_CywPin, + MP_TYPE_FLAG_NONE, + print, shared_bindings_microcontroller_pin_print, + unary_op, mp_generic_unary_op + ); //| PM_STANDARD: int //| """The standard power management mode""" diff --git a/ports/raspberrypi/bindings/cyw43/__init__.h b/ports/raspberrypi/bindings/cyw43/__init__.h index 26c1aa008f..995c8f1345 100644 --- a/ports/raspberrypi/bindings/cyw43/__init__.h +++ b/ports/raspberrypi/bindings/cyw43/__init__.h @@ -29,6 +29,7 @@ #include "py/obj.h" #include "common-hal/microcontroller/Pin.h" +#include "lib/cyw43-driver/src/cyw43_ll.h" extern const mp_obj_type_t cyw43_pin_type; const mcu_pin_obj_t *validate_obj_is_free_pin_including_cyw43(mp_obj_t obj, qstr arg_name); diff --git a/ports/raspberrypi/bindings/picodvi/Framebuffer.c b/ports/raspberrypi/bindings/picodvi/Framebuffer.c index f6fa7f986a..c327ce284d 100644 --- a/ports/raspberrypi/bindings/picodvi/Framebuffer.c +++ b/ports/raspberrypi/bindings/picodvi/Framebuffer.c @@ -248,14 +248,12 @@ STATIC const framebuffer_p_t picodvi_framebuffer_proto = { .deinit = picodvi_framebuffer_deinit_proto, }; -const mp_obj_type_t picodvi_framebuffer_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Framebuffer, - .locals_dict = (mp_obj_dict_t *)&picodvi_framebuffer_locals_dict, - .make_new = picodvi_framebuffer_make_new, - MP_TYPE_EXTENDED_FIELDS( - .buffer_p = { .get_buffer = common_hal_picodvi_framebuffer_get_buffer, }, - .protocol = &picodvi_framebuffer_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + picodvi_framebuffer_type, + MP_QSTR_Framebuffer, + MP_TYPE_FLAG_NONE, + locals_dict, &picodvi_framebuffer_locals_dict, + make_new, picodvi_framebuffer_make_new, + buffer, common_hal_picodvi_framebuffer_get_buffer, + protocol, &picodvi_framebuffer_proto + ); diff --git a/ports/raspberrypi/bindings/rp2pio/StateMachine.c b/ports/raspberrypi/bindings/rp2pio/StateMachine.c index d5924277c8..120145f5ea 100644 --- a/ports/raspberrypi/bindings/rp2pio/StateMachine.c +++ b/ports/raspberrypi/bindings/rp2pio/StateMachine.c @@ -40,7 +40,6 @@ #include "py/mperrno.h" #include "py/objproperty.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class StateMachine: @@ -860,9 +859,10 @@ STATIC const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(rp2pio_statemachine_locals_dict, rp2pio_statemachine_locals_dict_table); -const mp_obj_type_t rp2pio_statemachine_type = { - { &mp_type_type }, - .name = MP_QSTR_StateMachine, - .make_new = rp2pio_statemachine_make_new, - .locals_dict = (mp_obj_dict_t *)&rp2pio_statemachine_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + rp2pio_statemachine_type, + MP_QSTR_StateMachine, + MP_TYPE_FLAG_NONE, + make_new, rp2pio_statemachine_make_new, + locals_dict, &rp2pio_statemachine_locals_dict + ); diff --git a/ports/raspberrypi/common-hal/analogbufio/BufferedIn.c b/ports/raspberrypi/common-hal/analogbufio/BufferedIn.c index bc5f9028b7..7dfc0fa11a 100644 --- a/ports/raspberrypi/common-hal/analogbufio/BufferedIn.c +++ b/ports/raspberrypi/common-hal/analogbufio/BufferedIn.c @@ -35,7 +35,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared/runtime/interrupt_char.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "src/rp2_common/hardware_adc/include/hardware/adc.h" #include "src/rp2_common/hardware_dma/include/hardware/dma.h" #include "src/common/pico_stdlib/include/pico/stdlib.h" diff --git a/ports/raspberrypi/common-hal/analogio/AnalogIn.c b/ports/raspberrypi/common-hal/analogio/AnalogIn.c index afa31e3c83..37f1000d0e 100644 --- a/ports/raspberrypi/common-hal/analogio/AnalogIn.c +++ b/ports/raspberrypi/common-hal/analogio/AnalogIn.c @@ -29,7 +29,6 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "src/rp2_common/hardware_adc/include/hardware/adc.h" diff --git a/ports/raspberrypi/common-hal/analogio/AnalogOut.c b/ports/raspberrypi/common-hal/analogio/AnalogOut.c index 38ff935674..03e0515f49 100644 --- a/ports/raspberrypi/common-hal/analogio/AnalogOut.c +++ b/ports/raspberrypi/common-hal/analogio/AnalogOut.c @@ -31,7 +31,6 @@ #include "py/mperrno.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" void common_hal_analogio_analogout_construct(analogio_analogout_obj_t *self, const mcu_pin_obj_t *pin) { mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_AnalogOut); diff --git a/ports/raspberrypi/common-hal/audiobusio/I2SOut.c b/ports/raspberrypi/common-hal/audiobusio/I2SOut.c index d9c5027cbd..c7d4b7c635 100644 --- a/ports/raspberrypi/common-hal/audiobusio/I2SOut.c +++ b/ports/raspberrypi/common-hal/audiobusio/I2SOut.c @@ -37,7 +37,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-module/audiocore/__init__.h" #include "bindings/rp2pio/StateMachine.h" -#include "supervisor/shared/translate/translate.h" const uint16_t i2s_program[] = { // ; Load the next set of samples @@ -108,7 +107,7 @@ void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self, mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_main_clock); } if (bit_clock->number != word_select->number - 1) { - mp_raise_ValueError(translate("Bit clock and word select must be sequential pins")); + mp_raise_ValueError(translate("Bit clock and word select must be sequential GPIO pins")); } const uint16_t *program = i2s_program; diff --git a/ports/raspberrypi/common-hal/audiobusio/PDMIn.c b/ports/raspberrypi/common-hal/audiobusio/PDMIn.c index 5d94afcecc..1e7e882277 100644 --- a/ports/raspberrypi/common-hal/audiobusio/PDMIn.c +++ b/ports/raspberrypi/common-hal/audiobusio/PDMIn.c @@ -32,7 +32,6 @@ #include "py/runtime.h" #include "shared-bindings/audiobusio/PDMIn.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "audio_dma.h" diff --git a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c index 8b5c3accec..67141c2a18 100644 --- a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +++ b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c @@ -39,7 +39,6 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Processor.h" -#include "supervisor/shared/translate/translate.h" #include "src/rp2040/hardware_structs/include/hardware/structs/dma.h" #include "src/rp2_common/hardware_pwm/include/hardware/pwm.h" diff --git a/ports/raspberrypi/common-hal/countio/Counter.c b/ports/raspberrypi/common-hal/countio/Counter.c index b51d182c3a..c68bc62945 100644 --- a/ports/raspberrypi/common-hal/countio/Counter.c +++ b/ports/raspberrypi/common-hal/countio/Counter.c @@ -2,7 +2,6 @@ #include "py/runtime.h" #include "py/mpstate.h" -#include "supervisor/shared/translate/translate.h" #include "shared-bindings/countio/Edge.h" #include "shared-bindings/digitalio/Pull.h" @@ -112,3 +111,5 @@ void counter_interrupt_handler(void) { self->count += 65536; } } + +MP_REGISTER_ROOT_POINTER(mp_obj_t counting[enum_NUM_PWM_SLICES]); diff --git a/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c b/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c index d90c0db81b..4eb2a6de9c 100644 --- a/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c +++ b/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c @@ -33,7 +33,6 @@ #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/digitalio/DigitalInOut.h" -#include "supervisor/shared/translate/translate.h" #include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" diff --git a/ports/raspberrypi/common-hal/microcontroller/__init__.c b/ports/raspberrypi/common-hal/microcontroller/__init__.c index 6d9b3d7fa0..45d46f4519 100644 --- a/ports/raspberrypi/common-hal/microcontroller/__init__.c +++ b/ports/raspberrypi/common-hal/microcontroller/__init__.c @@ -38,7 +38,6 @@ #include "supervisor/filesystem.h" #include "supervisor/port.h" #include "supervisor/shared/safe_mode.h" -#include "supervisor/shared/translate/translate.h" #include "src/rp2040/hardware_structs/include/hardware/structs/sio.h" #include "src/rp2_common/hardware_sync/include/hardware/sync.h" diff --git a/ports/raspberrypi/common-hal/pulseio/PulseIn.c b/ports/raspberrypi/common-hal/pulseio/PulseIn.c index a074ee3604..cd81e61e92 100644 --- a/ports/raspberrypi/common-hal/pulseio/PulseIn.c +++ b/ports/raspberrypi/common-hal/pulseio/PulseIn.c @@ -32,7 +32,6 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/pulseio/PulseIn.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "bindings/rp2pio/StateMachine.h" #include "common-hal/pulseio/PulseIn.h" diff --git a/ports/raspberrypi/common-hal/pulseio/PulseOut.c b/ports/raspberrypi/common-hal/pulseio/PulseOut.c index 881e003579..f0f3d36886 100644 --- a/ports/raspberrypi/common-hal/pulseio/PulseOut.c +++ b/ports/raspberrypi/common-hal/pulseio/PulseOut.c @@ -33,7 +33,6 @@ #include "shared-bindings/pwmio/PWMOut.h" #include "shared-bindings/microcontroller/__init__.h" #include "common-hal/pwmio/PWMOut.h" -#include "supervisor/shared/translate/translate.h" #include "src/rp2040/hardware_structs/include/hardware/structs/pwm.h" #include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" #include "src/rp2_common/hardware_pwm/include/hardware/pwm.h" diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.c b/ports/raspberrypi/common-hal/pwmio/PWMOut.c index 7925a734fb..512b88df1c 100644 --- a/ports/raspberrypi/common-hal/pwmio/PWMOut.c +++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.c @@ -32,8 +32,6 @@ #include "shared-bindings/pwmio/PWMOut.h" #include "shared-bindings/microcontroller/Processor.h" -#include "supervisor/shared/translate/translate.h" - #include "src/rp2040/hardware_regs/include/hardware/platform_defs.h" #include "src/rp2_common/hardware_clocks/include/hardware/clocks.h" #include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" diff --git a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c index 629811ab9f..7e3be9d3e3 100644 --- a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c +++ b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c @@ -1098,3 +1098,7 @@ bool common_hal_rp2pio_statemachine_get_writing(rp2pio_statemachine_obj_t *self) int common_hal_rp2pio_statemachine_get_pending(rp2pio_statemachine_obj_t *self) { return self->pending_buffers; } + +// Use a compile-time constant for MP_REGISTER_POINTER so the preprocessor will +// not split the expansion across multiple lines. +MP_REGISTER_ROOT_POINTER(mp_obj_t background_pio[enum_NUM_DMA_CHANNELS]); diff --git a/ports/raspberrypi/common-hal/socketpool/Socket.c b/ports/raspberrypi/common-hal/socketpool/Socket.c index f2b84f9ccb..b2a4ea63c6 100644 --- a/ports/raspberrypi/common-hal/socketpool/Socket.c +++ b/ports/raspberrypi/common-hal/socketpool/Socket.c @@ -54,6 +54,8 @@ #include "lwip/timeouts.h" #include "lwip/udp.h" +#include "sdk/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch.h" + #define MICROPY_PY_LWIP_SOCK_RAW (1) #if 0 // print debugging info diff --git a/ports/raspberrypi/common-hal/socketpool/SocketPool.h b/ports/raspberrypi/common-hal/socketpool/SocketPool.h index a7ad36b92f..e2f12c4717 100644 --- a/ports/raspberrypi/common-hal/socketpool/SocketPool.h +++ b/ports/raspberrypi/common-hal/socketpool/SocketPool.h @@ -28,6 +28,8 @@ #include "py/obj.h" +#include "lwip/ip_addr.h" + typedef struct { mp_obj_base_t base; } socketpool_socketpool_obj_t; diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index ffccd4faf8..0d196415fc 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -144,7 +144,7 @@ mp_obj_t common_hal_wifi_radio_start_scanning_networks(wifi_radio_obj_t *self, u } wifi_scannednetworks_obj_t *scan = mp_obj_malloc(wifi_scannednetworks_obj_t, &wifi_scannednetworks_type); mp_obj_t args[] = { mp_const_empty_tuple, MP_OBJ_NEW_SMALL_INT(16) }; - scan->results = mp_type_deque.make_new(&mp_type_deque, 2, 0, args); + scan->results = MP_OBJ_TYPE_GET_SLOT(&mp_type_deque, make_new)(&mp_type_deque, 2, 0, args); self->current_scan = scan; wifi_scannednetworks_start_scan(scan); return scan; diff --git a/ports/raspberrypi/cyw43_configport.h b/ports/raspberrypi/cyw43_configport.h new file mode 100644 index 0000000000..b764804821 --- /dev/null +++ b/ports/raspberrypi/cyw43_configport.h @@ -0,0 +1,58 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H +#define MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H + +// The board-level config will be included here, so it can set some CYW43 values. +#include "py/mpconfig.h" +#include "py/mperrno.h" +#include "py/mphal.h" + +#include "supervisor/port.h" + +#include "sdk/src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h" + +#define CYW43_NETUTILS (1) + +#if CIRCUITPY_USB +#include "supervisor/usb.h" +#define CYW43_EVENT_POLL_HOOK usb_background(); +#else +#define CYW43_EVENT_POLL_HOOK +#endif + +void cyw43_post_poll_hook(void); +extern volatile int cyw43_has_pending; + +static inline void cyw43_yield(void) { + uint32_t my_interrupts = save_and_disable_interrupts(); + if (!cyw43_has_pending) { + port_idle_until_interrupt(); + } + restore_interrupts(my_interrupts); +} + +#endif // MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H diff --git a/ports/raspberrypi/mbedtls/crt_bundle.c b/ports/raspberrypi/mbedtls/crt_bundle.c index 7fce35872b..09bd462762 100644 --- a/ports/raspberrypi/mbedtls/crt_bundle.c +++ b/ports/raspberrypi/mbedtls/crt_bundle.c @@ -166,7 +166,7 @@ static int crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int depth, uint /* Initialize the bundle into an array so we can do binary search for certs, the bundle generated by the python utility is already presorted by subject name */ -static err_t crt_bundle_init(const uint8_t *x509_bundle, size_t bundle_size) { +static int crt_bundle_init(const uint8_t *x509_bundle, size_t bundle_size) { if (bundle_size < BUNDLE_HEADER_OFFSET + CRT_HEADER_OFFSET) { LOGE(TAG, "Invalid certificate bundle"); return -MP_EINVAL; diff --git a/ports/raspberrypi/mbedtls/mbedtls_port.c b/ports/raspberrypi/mbedtls/mbedtls_port.c index 596d08ccd9..73929c85e8 100644 --- a/ports/raspberrypi/mbedtls/mbedtls_port.c +++ b/ports/raspberrypi/mbedtls/mbedtls_port.c @@ -34,6 +34,9 @@ #include "shared/timeutils/timeutils.h" #include "shared-bindings/os/__init__.h" +#include "hardware/rtc.h" +#include "shared/timeutils/timeutils.h" + extern uint8_t rosc_random_u8(size_t cycles); int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) { diff --git a/ports/raspberrypi/mpconfigport.h b/ports/raspberrypi/mpconfigport.h index 4458107974..bc61d2deda 100644 --- a/ports/raspberrypi/mpconfigport.h +++ b/ports/raspberrypi/mpconfigport.h @@ -55,14 +55,7 @@ // This also includes mpconfigboard.h. #include "py/circuitpy_mpconfig.h" -#define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t counting[NUM_PWM_SLICES]; \ - mp_obj_t playing_audio[NUM_DMA_CHANNELS]; \ - mp_obj_t background_pio[NUM_DMA_CHANNELS]; \ - CIRCUITPY_COMMON_ROOT_POINTERS; - #if CIRCUITPY_CYW43 -#include "pico/cyw43_arch.h" #define MICROPY_PY_LWIP_ENTER cyw43_arch_lwip_begin(); #define MICROPY_PY_LWIP_REENTER MICROPY_PY_LWIP_ENTER #define MICROPY_PY_LWIP_EXIT cyw43_arch_lwip_end(); @@ -74,5 +67,12 @@ extern critical_section_t background_queue_lock; #define CALLBACK_CRITICAL_BEGIN (critical_section_enter_blocking(&background_queue_lock)) #define CALLBACK_CRITICAL_END (critical_section_exit(&background_queue_lock)) +// Turn some macros into compile-time constants, using enum. +// Some nested macros expand across multiple lines, which is not +// handled by the MP_REGISTER_ROOT_POINTER processing in makeqstrdefs.py. +enum { + enum_NUM_DMA_CHANNELS = NUM_DMA_CHANNELS, + enum_NUM_PWM_SLICES = NUM_PWM_SLICES, +}; #endif // __INCLUDED_MPCONFIGPORT_H diff --git a/ports/raspberrypi/peripherals/pins.c b/ports/raspberrypi/peripherals/pins.c index 3b21d3f08c..647f571cb5 100644 --- a/ports/raspberrypi/peripherals/pins.c +++ b/ports/raspberrypi/peripherals/pins.c @@ -27,19 +27,23 @@ #include "pins.h" #include "shared-bindings/microcontroller/Pin.h" + +#if CIRCUITPY_CYW43 #include "bindings/cyw43/__init__.h" +#define CYW_PIN(p_number) \ + const mcu_pin_obj_t pin_CYW##p_number = { \ + { &cyw43_pin_type }, \ + .number = p_number \ + } +#endif + // This macro is used to simplify pin definition in boards//pins.c #define PIN(p_number) \ const mcu_pin_obj_t pin_GPIO##p_number = { \ { &mcu_pin_type }, \ .number = p_number \ } -#define CYW_PIN(p_number) \ - const mcu_pin_obj_t pin_CYW##p_number = { \ - { &cyw43_pin_type }, \ - .number = p_number \ - } PIN(0); PIN(1); diff --git a/ports/raspberrypi/supervisor/internal_flash_root_pointers.h b/ports/raspberrypi/supervisor/internal_flash_root_pointers.h deleted file mode 100644 index 419a4c9435..0000000000 --- a/ports/raspberrypi/supervisor/internal_flash_root_pointers.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_RASPBERRYPI_INTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_RASPBERRYPI_INTERNAL_FLASH_ROOT_POINTERS_H - -#define FLASH_ROOT_POINTERS - -#endif // MICROPY_INCLUDED_RASPBERRYPI_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/silabs/Makefile b/ports/silabs/Makefile index 71092afcbf..ab30e5d756 100644 --- a/ports/silabs/Makefile +++ b/ports/silabs/Makefile @@ -24,7 +24,7 @@ # .SUFFIXES: # ignore builtin rules -.PHONY: all clean slc-clean slc-generate dependents +.PHONY: all clean slc-clean slc-generate dependents flash # Values set by the initial generation PROJECTNAME = circuitpython_efr32 # If the build directory is not given, make it reflect the board name. @@ -118,7 +118,7 @@ $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += @@ -142,10 +142,13 @@ $(SILABS_BUILD)/$(PROJECTNAME).Makefile: | $(HEADER_BUILD)/mpversion.h +@$(MAKE) --no-print-directory slc-generate $(OUTPUT_DIR)/firmware.out: $(SILABS_BUILD)/pin_functions.h $(SILABS_BUILD)/pins.c $(OBJ) $(OBJS) $(LIB_FILES) - @echo 'Linking $(OUTPUT_DIR)/firmware.out' - @echo "$(OBJS) $(OBJ)" > $(OUTPUT_DIR)/linker_objs - $(CC) $(LD_FLAGS) @$(OUTPUT_DIR)/linker_objs $(LIBS) -o $(OUTPUT_DIR)/firmware.out - $(OBJCOPY) $(OUTPUT_DIR)/firmware.out -O binary $(OUTPUT_DIR)/firmware.bin + $(STEPECHO) 'Linking $(OUTPUT_DIR)/firmware.out' + $(Q)echo "$(OBJS) $(OBJ)" > $(OUTPUT_DIR)/linker_objs + $(Q)$(CC) $(LD_FLAGS) @$(OUTPUT_DIR)/linker_objs $(LIBS) -o $(OUTPUT_DIR)/firmware.out + $(Q)$(OBJCOPY) $(OUTPUT_DIR)/firmware.out -O binary $(OUTPUT_DIR)/firmware.bin + +flash: $(OUTPUT_DIR)/firmware.bin + $(Q)commander flash -d EFR32MG24 --address 08000000 $(OUTPUT_DIR)/firmware.bin $(OUTPUT_DIR)/firmware.hex: @@ -174,37 +177,11 @@ endif @sed -i 's/ autogen\// $(SILABS_BUILD)\/autogen\//g' $(SILABS_BUILD)/circuitpython_efr32.project.mak @sed -i 's/-T"autogen\//-T"$(SILABS_BUILD)\/autogen\//g' $(SILABS_BUILD)/circuitpython_efr32.project.mak -# tools/slc_cli_linux/bin/slc-cli/developer/exporter_templates/arm_gcc/arm_gcc.Makefile defines -# ECHO = @ -# which is not compatible with py/mkenv.mk: +# tools/slc_cli_linux/bin/slc-cli/developer/exporter_templates/arm_gcc/arm_gcc.Makefile includes +# build rules and defines ECHO = @ when VERBOSE = 1 which is not compatible with py/mkenv.mk: # ECHO = @echo # so override ECHO -$(OBJS): ECHO = +$(OBJS): ECHO = $(Q) #$(OBJS): -$(OUTPUT_DIR)/%.o: %.c - #@echo 'Building $<' - @$(MKDIR_P) $(@D) - @$(CC) $(CFLAGS) -c -o $@ $< - -$(OUTPUT_DIR)/%.o: %.cpp - #@echo 'Building $<' - @$(MKDIR_P) $(@D) - @$(CXX) $(CXXFLAGS) -c -o $@ $< - -$(OUTPUT_DIR)/%.o: %.cc - #@echo 'Building $<' - @$(MKDIR_P) $(@D) - @$(CXX) $(CXXFLAGS) -c -o $@ $< - -$(OUTPUT_DIR)/%.o: %.s - #@echo 'Building $<' - @$(MKDIR_P) $(@D) - @$(CC) $(ASMFLAGS) -c -o $@ $< - -$(OUTPUT_DIR)/%.o: %.S - #@echo 'Building $<' - @$(MKDIR_P) $(@D) - @$(CC) $(ASMFLAGS) -c -o $@ $< - include $(TOP)/py/mkrules.mk diff --git a/ports/silabs/README.md b/ports/silabs/README.md index 17423f57a3..3813104727 100644 --- a/ports/silabs/README.md +++ b/ports/silabs/README.md @@ -34,6 +34,8 @@ Install necessary packages sudo apt install default-jre gcc-arm-none-eabi wget python3 python3-pip git git-lfs gettext uncrustify sudo python -m pip install --upgrade pip +**Note** that this uses git lfs and will not link without it. The error is something like "Unknown file format" because git lfs has a text placeholder file. + ## Supported boards ## | Board | Code | Build CMD | @@ -71,6 +73,13 @@ Clean the project by using: make BOARD=explorerkit_xg24_brd2703a clean +## Flashing CircuitPython + +Flash the project by using [Simplicity Commander](https://community.silabs.com/s/article/simplicity-commander?language=en_US): + + make BOARD=explorerkit_xg24_brd2703a flash + + ## Running CircuitPython ## ### Connecting to the Serial Console ### diff --git a/ports/silabs/boards/devkit_xg24_brd2601b/mpconfigboard.h b/ports/silabs/boards/devkit_xg24_brd2601b/mpconfigboard.h index 5456e1ecd5..2504c12c63 100644 --- a/ports/silabs/boards/devkit_xg24_brd2601b/mpconfigboard.h +++ b/ports/silabs/boards/devkit_xg24_brd2601b/mpconfigboard.h @@ -34,6 +34,10 @@ #define BOARD_HSE_SOURCE (RCC_HSE_BYPASS) #define BOARD_HAS_LOW_SPEED_CRYSTAL (0) +#define CIRCUITPY_RGB_STATUS_R (&pin_PD2) +#define CIRCUITPY_RGB_STATUS_G (&pin_PA4) +#define CIRCUITPY_RGB_STATUS_B (&pin_PB0) + // On-board flash #define SPI_FLASH_MOSI_PIN (&pin_PC3) #define SPI_FLASH_MISO_PIN (&pin_PC2) diff --git a/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c b/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c index d981f416ab..a3b0b68993 100644 --- a/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c +++ b/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c @@ -27,7 +27,6 @@ #include "py/runtime.h" #include "common-hal/busio/I2C.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "em_i2c.h" #include "sl_i2cspm.h" #include "sl_i2cspm_sensor_config.h" diff --git a/ports/silabs/boards/explorerkit_xg24_brd2703a/mpconfigboard.h b/ports/silabs/boards/explorerkit_xg24_brd2703a/mpconfigboard.h index eb1efca12d..db3257e689 100644 --- a/ports/silabs/boards/explorerkit_xg24_brd2703a/mpconfigboard.h +++ b/ports/silabs/boards/explorerkit_xg24_brd2703a/mpconfigboard.h @@ -37,6 +37,8 @@ #define BOARD_HSE_SOURCE (RCC_HSE_BYPASS) #define BOARD_HAS_LOW_SPEED_CRYSTAL (0) +#define MICROPY_HW_LED_STATUS (&pin_PA4) + #define DEFAULT_I2C_BUS_SDA (&pin_PC5) #define DEFAULT_I2C_BUS_SCL (&pin_PC4) #define DEFAULT_I2C_PERIPHERAL I2C0 diff --git a/ports/silabs/boards/sparkfun_thingplus_matter_mgm240p_brd2704a/mpconfigboard.h b/ports/silabs/boards/sparkfun_thingplus_matter_mgm240p_brd2704a/mpconfigboard.h index ea43ef27cd..463a2e5b1f 100644 --- a/ports/silabs/boards/sparkfun_thingplus_matter_mgm240p_brd2704a/mpconfigboard.h +++ b/ports/silabs/boards/sparkfun_thingplus_matter_mgm240p_brd2704a/mpconfigboard.h @@ -34,6 +34,8 @@ #define BOARD_HSE_SOURCE (RCC_HSE_BYPASS) #define BOARD_HAS_LOW_SPEED_CRYSTAL (0) +#define MICROPY_HW_LED_STATUS (&pin_PA8) + #define DEFAULT_I2C_BUS_SDA (&pin_PB4) #define DEFAULT_I2C_BUS_SCL (&pin_PB3) #define DEFAULT_I2C_PERIPHERAL I2C0 diff --git a/ports/silabs/common-hal/analogio/AnalogIn.c b/ports/silabs/common-hal/analogio/AnalogIn.c index e22c5b3493..bfdce02415 100644 --- a/ports/silabs/common-hal/analogio/AnalogIn.c +++ b/ports/silabs/common-hal/analogio/AnalogIn.c @@ -28,7 +28,6 @@ #include "common-hal/analogio/AnalogIn.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared/runtime/interrupt_char.h" -#include "supervisor/shared/translate/translate.h" #include "em_cmu.h" #include "em_iadc.h" diff --git a/ports/silabs/common-hal/analogio/AnalogOut.c b/ports/silabs/common-hal/analogio/AnalogOut.c index 88b2f53f9e..ae5a8a6903 100644 --- a/ports/silabs/common-hal/analogio/AnalogOut.c +++ b/ports/silabs/common-hal/analogio/AnalogOut.c @@ -28,7 +28,6 @@ #include "py/runtime.h" #include "shared-bindings/analogio/AnalogOut.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "common-hal/microcontroller/Pin.h" #include "em_vdac.h" diff --git a/ports/silabs/common-hal/busio/I2C.c b/ports/silabs/common-hal/busio/I2C.c index 62ac14f4e9..cedd7371c1 100644 --- a/ports/silabs/common-hal/busio/I2C.c +++ b/ports/silabs/common-hal/busio/I2C.c @@ -28,7 +28,6 @@ #include "py/mperrno.h" #include "py/runtime.h" #include "shared-bindings/microcontroller/__init__.h" -#include "supervisor/shared/translate/translate.h" #include "shared-bindings/microcontroller/Pin.h" STATIC I2CSPM_Init_TypeDef i2cspm_init; diff --git a/ports/silabs/common-hal/busio/SPI.c b/ports/silabs/common-hal/busio/SPI.c index 89c8012477..e3b743309e 100644 --- a/ports/silabs/common-hal/busio/SPI.c +++ b/ports/silabs/common-hal/busio/SPI.c @@ -29,7 +29,6 @@ #include "py/runtime.h" #include "shared-bindings/microcontroller/__init__.h" #include "supervisor/board.h" -#include "supervisor/shared/translate/translate.h" #include "shared-bindings/microcontroller/Pin.h" // Note that any bugs introduced in this file can cause crashes diff --git a/ports/silabs/common-hal/busio/UART.c b/ports/silabs/common-hal/busio/UART.c index 813432e9aa..37273769ba 100644 --- a/ports/silabs/common-hal/busio/UART.c +++ b/ports/silabs/common-hal/busio/UART.c @@ -35,7 +35,6 @@ #include "py/mperrno.h" #include "py/runtime.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" #define UARTDRV_USART_BUFFER_SIZE 6 diff --git a/ports/silabs/common-hal/digitalio/DigitalInOut.c b/ports/silabs/common-hal/digitalio/DigitalInOut.c index b673d392f2..e9f2767308 100644 --- a/ports/silabs/common-hal/digitalio/DigitalInOut.c +++ b/ports/silabs/common-hal/digitalio/DigitalInOut.c @@ -27,7 +27,6 @@ #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/microcontroller/Pin.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" // Never reset pin when reload void common_hal_digitalio_digitalinout_never_reset( diff --git a/ports/silabs/common-hal/microcontroller/Processor.c b/ports/silabs/common-hal/microcontroller/Processor.c index 12cf5ca809..226fe4529f 100644 --- a/ports/silabs/common-hal/microcontroller/Processor.c +++ b/ports/silabs/common-hal/microcontroller/Processor.c @@ -33,7 +33,6 @@ #endif #include "common-hal/microcontroller/Processor.h" #include "shared-bindings/microcontroller/ResetReason.h" -#include "supervisor/shared/translate/translate.h" #include "tempdrv.h" #include "em_system.h" #include "em_cmu.h" diff --git a/ports/silabs/common-hal/nvm/ByteArray.c b/ports/silabs/common-hal/nvm/ByteArray.c index e94ed9198d..acdc7f131b 100644 --- a/ports/silabs/common-hal/nvm/ByteArray.c +++ b/ports/silabs/common-hal/nvm/ByteArray.c @@ -28,7 +28,6 @@ #include "supervisor/shared/stack.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "nvm3_default.h" #include "nvm3_default_config.h" diff --git a/ports/silabs/common-hal/pwmio/PWMOut.c b/ports/silabs/common-hal/pwmio/PWMOut.c index b55c821462..7382fade97 100644 --- a/ports/silabs/common-hal/pwmio/PWMOut.c +++ b/ports/silabs/common-hal/pwmio/PWMOut.c @@ -26,7 +26,6 @@ #include "py/runtime.h" #include "common-hal/pwmio/PWMOut.h" #include "shared-bindings/pwmio/PWMOut.h" -#include "supervisor/shared/translate/translate.h" #include "shared-bindings/microcontroller/Pin.h" STATIC sl_pwm_instance_t pwm_handle[TIM_BANK_ARRAY_LEN]; diff --git a/ports/silabs/common-hal/rtc/RTC.c b/ports/silabs/common-hal/rtc/RTC.c index f3de48894c..956412c7b6 100644 --- a/ports/silabs/common-hal/rtc/RTC.c +++ b/ports/silabs/common-hal/rtc/RTC.c @@ -33,7 +33,6 @@ #include "common-hal/rtc/RTC.h" #include "shared-bindings/rtc/RTC.h" #include "supervisor/port.h" -#include "supervisor/shared/translate/translate.h" #include "peripherals/rtc.h" #include "sl_sleeptimer.h" diff --git a/ports/silabs/common-hal/watchdog/WatchDogTimer.c b/ports/silabs/common-hal/watchdog/WatchDogTimer.c index d65c794833..21b6cc6126 100644 --- a/ports/silabs/common-hal/watchdog/WatchDogTimer.c +++ b/ports/silabs/common-hal/watchdog/WatchDogTimer.c @@ -33,11 +33,16 @@ #include "em_wdog.h" #include "em_cmu.h" +static bool _wdt_init = false; + void common_hal_watchdog_feed(watchdog_watchdogtimer_obj_t *self) { WDOGn_Feed(DEFAULT_WDOG); } void common_hal_watchdog_deinit(watchdog_watchdogtimer_obj_t *self) { + if (!_wdt_init) { + return; + } WDOG_Enable(false); } @@ -105,6 +110,8 @@ void common_hal_watchdog_set_timeout(watchdog_watchdogtimer_obj_t *self, // Initializing watchdog with chosen settings WDOGn_Init(DEFAULT_WDOG, &wdogInit); + + _wdt_init = true; } } diff --git a/ports/silabs/mpconfigport.h b/ports/silabs/mpconfigport.h index ba498dd763..ce7739ccca 100644 --- a/ports/silabs/mpconfigport.h +++ b/ports/silabs/mpconfigport.h @@ -65,9 +65,4 @@ #include "py/circuitpy_mpconfig.h" -#define MICROPY_PORT_ROOT_POINTERS \ - void *cpy_uart_obj_all[MAX_UART]; \ - void *cpy_i2c_obj_all[MAX_I2C]; \ - CIRCUITPY_COMMON_ROOT_POINTERS - #endif // EFR32_MPCONFIGPORT_H__ diff --git a/ports/silabs/supervisor/internal_flash_root_pointers.h b/ports/silabs/supervisor/internal_flash_root_pointers.h deleted file mode 100644 index 16694d5dac..0000000000 --- a/ports/silabs/supervisor/internal_flash_root_pointers.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of Adafruit for EFR32 project - * - * The MIT License (MIT) - * - * Copyright 2023 Silicon Laboratories Inc. www.silabs.com - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_EFR32_INTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_EFR32_INTERNAL_FLASH_ROOT_POINTERS_H - -#define FLASH_ROOT_POINTERS - -#endif // MICROPY_INCLUDED_EFR32_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/stm/Makefile b/ports/stm/Makefile index f8ac985ab9..03a41f526e 100755 --- a/ports/stm/Makefile +++ b/ports/stm/Makefile @@ -251,7 +251,7 @@ $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += diff --git a/ports/stm/boards/swan_r5/pins.c b/ports/stm/boards/swan_r5/pins.c index dc273cb6d4..28fda5e653 100644 --- a/ports/stm/boards/swan_r5/pins.c +++ b/ports/stm/boards/swan_r5/pins.c @@ -74,11 +74,12 @@ STATIC const mp_rom_map_elem_t board_module_carrier_table[] = { MP_DEFINE_CONST_DICT(board_module_carrier, board_module_carrier_table); -const mp_obj_type_t carrier_type = { - { &mp_type_type }, - .name = MP_QSTR_Ext, - .locals_dict = (mp_obj_dict_t *)&board_module_carrier, -}; +MP_DEFINE_CONST_OBJ_TYPE( + carrier_type, + MP_QSTR_Ext, + MP_TYPE_FLAG_NONE, + locals_dict, &board_module_carrier + ); // Core Feather Pins diff --git a/ports/stm/common-hal/analogio/AnalogIn.c b/ports/stm/common-hal/analogio/AnalogIn.c index 6a67720970..ccf11f96bf 100644 --- a/ports/stm/common-hal/analogio/AnalogIn.c +++ b/ports/stm/common-hal/analogio/AnalogIn.c @@ -27,7 +27,6 @@ #include "common-hal/analogio/AnalogIn.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "shared-bindings/microcontroller/Pin.h" diff --git a/ports/stm/common-hal/analogio/AnalogOut.c b/ports/stm/common-hal/analogio/AnalogOut.c index 129bb37266..23b8631c94 100644 --- a/ports/stm/common-hal/analogio/AnalogOut.c +++ b/ports/stm/common-hal/analogio/AnalogOut.c @@ -36,7 +36,6 @@ #include "shared-bindings/analogio/AnalogOut.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/translate/translate.h" #include "common-hal/microcontroller/Pin.h" diff --git a/ports/stm/common-hal/busio/I2C.c b/ports/stm/common-hal/busio/I2C.c index d565bd1633..7c3a0d59ad 100644 --- a/ports/stm/common-hal/busio/I2C.c +++ b/ports/stm/common-hal/busio/I2C.c @@ -30,7 +30,6 @@ #include "py/mperrno.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "shared-bindings/microcontroller/Pin.h" // I2C timing specs for the H7 and F7 @@ -401,3 +400,5 @@ void I2C3_EV_IRQHandler(void) { void I2C4_EV_IRQHandler(void) { call_hal_irq(4); } + +MP_REGISTER_ROOT_POINTER(void *cpy_i2c_obj_all[MAX_I2C]); diff --git a/ports/stm/common-hal/busio/SPI.c b/ports/stm/common-hal/busio/SPI.c index 54905d9d1e..d4975e9fc5 100644 --- a/ports/stm/common-hal/busio/SPI.c +++ b/ports/stm/common-hal/busio/SPI.c @@ -30,7 +30,6 @@ #include "shared-bindings/busio/SPI.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "shared-bindings/microcontroller/Pin.h" // Note that any bugs introduced in this file can cause crashes at startup diff --git a/ports/stm/common-hal/busio/UART.c b/ports/stm/common-hal/busio/UART.c index 5c9e05250a..7635c4aaf3 100644 --- a/ports/stm/common-hal/busio/UART.c +++ b/ports/stm/common-hal/busio/UART.c @@ -35,7 +35,6 @@ #include "py/mperrno.h" #include "py/runtime.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" #define ALL_UARTS 0xFFFF @@ -675,3 +674,5 @@ STATIC void uart_assign_irq(busio_uart_obj_t *self, USART_TypeDef *USARTx) { } #endif } + +MP_REGISTER_ROOT_POINTER(void *cpy_uart_obj_all[MAX_UART]); diff --git a/ports/stm/common-hal/microcontroller/Processor.c b/ports/stm/common-hal/microcontroller/Processor.c index 7b3e6a7232..e4952d8fbd 100644 --- a/ports/stm/common-hal/microcontroller/Processor.c +++ b/ports/stm/common-hal/microcontroller/Processor.c @@ -32,7 +32,6 @@ #endif #include "common-hal/microcontroller/Processor.h" #include "shared-bindings/microcontroller/ResetReason.h" -#include "supervisor/shared/translate/translate.h" #include STM32_HAL_H diff --git a/ports/stm/common-hal/pwmio/PWMOut.c b/ports/stm/common-hal/pwmio/PWMOut.c index a983718ff2..2bb3f1f7ab 100644 --- a/ports/stm/common-hal/pwmio/PWMOut.c +++ b/ports/stm/common-hal/pwmio/PWMOut.c @@ -29,7 +29,6 @@ #include "py/runtime.h" #include "common-hal/pwmio/PWMOut.h" #include "shared-bindings/pwmio/PWMOut.h" -#include "supervisor/shared/translate/translate.h" #include STM32_HAL_H #include "shared-bindings/microcontroller/Pin.h" diff --git a/ports/stm/common-hal/rtc/RTC.c b/ports/stm/common-hal/rtc/RTC.c index c9dc50d769..2c34ab5ad6 100644 --- a/ports/stm/common-hal/rtc/RTC.c +++ b/ports/stm/common-hal/rtc/RTC.c @@ -29,7 +29,6 @@ #include "py/runtime.h" #include "shared/timeutils/timeutils.h" #include "shared-bindings/rtc/RTC.h" -#include "supervisor/shared/translate/translate.h" #include "peripherals/rtc.h" diff --git a/ports/stm/common-hal/sdioio/SDCard.c b/ports/stm/common-hal/sdioio/SDCard.c index 5297c47748..a1b22a2047 100644 --- a/ports/stm/common-hal/sdioio/SDCard.c +++ b/ports/stm/common-hal/sdioio/SDCard.c @@ -32,7 +32,6 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/util.h" #include "supervisor/board.h" -#include "supervisor/shared/translate/translate.h" #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h" diff --git a/ports/stm/mpconfigport.h b/ports/stm/mpconfigport.h index 94fccd53e9..fc1f4ae336 100644 --- a/ports/stm/mpconfigport.h +++ b/ports/stm/mpconfigport.h @@ -60,9 +60,4 @@ extern uint8_t _ld_default_stack_size; #define MAX_I2C 4 #define MAX_SPI 6 -#define MICROPY_PORT_ROOT_POINTERS \ - void *cpy_uart_obj_all[MAX_UART]; \ - void *cpy_i2c_obj_all[MAX_I2C]; \ - CIRCUITPY_COMMON_ROOT_POINTERS - #endif // __INCLUDED_MPCONFIGPORT_H diff --git a/ports/stm/peripherals/timers.c b/ports/stm/peripherals/timers.c index 20b6bcc759..47fb33c59e 100644 --- a/ports/stm/peripherals/timers.c +++ b/ports/stm/peripherals/timers.c @@ -28,7 +28,6 @@ #include "py/mpconfig.h" #include "py/obj.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" diff --git a/ports/stm/supervisor/internal_flash_root_pointers.h b/ports/stm/supervisor/internal_flash_root_pointers.h deleted file mode 100644 index 7a8681bd95..0000000000 --- a/ports/stm/supervisor/internal_flash_root_pointers.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_STM32F4_INTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_STM32F4_INTERNAL_FLASH_ROOT_POINTERS_H - -#define FLASH_ROOT_POINTERS - -#endif // MICROPY_INCLUDED_STM32F4_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/unix/.gitignore b/ports/unix/.gitignore deleted file mode 100644 index 3ca8f6cb27..0000000000 --- a/ports/unix/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -micropython -micropython-* -*.gcov diff --git a/ports/unix/Makefile b/ports/unix/Makefile index a17e46b25e..f5b111a5fe 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -1,14 +1,21 @@ -# Select the variant to build for. +# Select the variant to build for: +ifdef VARIANT_DIR +# Custom variant path - remove trailing slash and get the final component of +# the path as the variant name. +VARIANT ?= $(notdir $(VARIANT_DIR:/=)) +else +# If not given on the command line, then default to standard. VARIANT ?= standard - -# If the build directory is not given, make it reflect the variant name. -BUILD ?= build-$(VARIANT) - VARIANT_DIR ?= variants/$(VARIANT) +endif + ifeq ($(wildcard $(VARIANT_DIR)/.),) $(error Invalid VARIANT specified: $(VARIANT_DIR)) endif +# If the build directory is not given, make it reflect the variant name. +BUILD ?= build-$(VARIANT) + include ../../py/mkenv.mk -include mpconfigport.mk include $(VARIANT_DIR)/mpconfigvariant.mk @@ -30,7 +37,7 @@ UNAME_S := $(shell uname -s) include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk -GIT_SUBMODULES += lib/axtls lib/berkeley-db-1.xx lib/libffi +GIT_SUBMODULES += lib/berkeley-db-1.xx INC += -I. INC += -I$(TOP) @@ -38,8 +45,8 @@ INC += -I$(BUILD) # compiler settings CWARN = -Wall -Werror -CWARN += -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -CFLAGS += $(INC) $(CWARN) -std=gnu11 -DUNIX $(CFLAGS_MOD) $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA) +CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith -Wdouble-promotion -Wfloat-conversion +CFLAGS += $(INC) $(CWARN) -std=gnu99 -DUNIX $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA) # Debugging/Optimization ifdef DEBUG @@ -110,60 +117,39 @@ ifeq ($(MICROPY_FORCE_32BIT),1) # starting with linux-libc-dev:i386 ifeq ($(MICROPY_PY_FFI),1) ifeq ($(UNAME_S),Linux) -CFLAGS_MOD += -I/usr/include/i686-linux-gnu +CFLAGS += -I/usr/include/i686-linux-gnu endif endif endif ifeq ($(MICROPY_USE_READLINE),1) INC += -I$(TOP)/shared/readline -CFLAGS_MOD += -DMICROPY_USE_READLINE=1 +CFLAGS += -DMICROPY_USE_READLINE=1 SHARED_SRC_C_EXTRA += readline/readline.c endif ifeq ($(MICROPY_PY_TERMIOS),1) -CFLAGS_MOD += -DMICROPY_PY_TERMIOS=1 -SRC_MOD += modtermios.c +CFLAGS += -DMICROPY_PY_TERMIOS=1 endif ifeq ($(MICROPY_PY_SOCKET),1) -CFLAGS_MOD += -DMICROPY_PY_SOCKET=1 -SRC_MOD += modusocket.c +CFLAGS += -DMICROPY_PY_SOCKET=1 endif ifeq ($(MICROPY_PY_THREAD),1) -CFLAGS_MOD += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0 -LDFLAGS_MOD += $(LIBPTHREAD) +CFLAGS += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0 +LDFLAGS += $(LIBPTHREAD) +endif + +ifeq ($(MICROPY_PY_USSL),1) +ifeq ($(MICROPY_SSL_AXTLS),1) + +endif endif # If the variant enables it, enable modbluetooth. ifeq ($(MICROPY_PY_BLUETOOTH),1) - +ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) HAVE_LIBUSB := $(shell (which pkg-config > /dev/null && pkg-config --exists libusb-1.0) 2>/dev/null && echo '1') -# Only one stack can be enabled. -ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) -ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) -$(error Cannot enable both NimBLE and BTstack at the same time) -endif -endif - -# Default to btstack, but a variant (or make command line) can set NimBLE -# explicitly (which is always via H4 UART). -ifneq ($(MICROPY_BLUETOOTH_NIMBLE),1) -ifneq ($(MICROPY_BLUETOOTH_BTSTACK),1) -MICROPY_BLUETOOTH_BTSTACK ?= 1 -endif -endif - -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 - -ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) - # Figure out which BTstack transport to use. -ifeq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1) -ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1) -$(error Cannot enable BTstack support for USB and H4 UART at the same time) -endif -else ifeq ($(HAVE_LIBUSB),1) # Default to btstack-over-usb. MICROPY_BLUETOOTH_BTSTACK_USB ?= 1 @@ -171,51 +157,40 @@ else # Fallback to HCI controller via a H4 UART (e.g. Zephyr on nRF) over a /dev/tty serial port. MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1 endif + +SRC_BTSTACK_C += lib/btstack/platform/embedded/btstack_run_loop_embedded.c endif - -# BTstack is enabled. -GIT_SUBMODULES += lib/btstack -include $(TOP)/extmod/btstack/btstack.mk -SRC_BTSTACK += lib/btstack/platform/embedded/btstack_run_loop_embedded.c - -else - -# NimBLE is enabled. -GIT_SUBMODULES += lib/mynewt-nimble -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS=1 -include $(TOP)/extmod/nimble/nimble.mk - -endif - endif ifeq ($(MICROPY_PY_FFI),1) ifeq ($(MICROPY_STANDALONE),1) -LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(BUILD)/lib/libffi/out/lib/libffi-*/include) +# Build libffi from source. +GIT_SUBMODULES += lib/libffi +DEPLIBS += libffi +LIBFFI_CFLAGS := -I$(shell ls -1d $(BUILD)/lib/libffi/out/lib/libffi-*/include) ifeq ($(MICROPY_FORCE_32BIT),1) - LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib32/libffi.a + LIBFFI_LDFLAGS = $(BUILD)/lib/libffi/out/lib32/libffi.a else - LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib/libffi.a + LIBFFI_LDFLAGS = $(BUILD)/lib/libffi/out/lib/libffi.a endif else -LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi) -LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi) +# Use system version of libffi. +LIBFFI_CFLAGS := $(shell pkg-config --cflags libffi) +LIBFFI_LDFLAGS := $(shell pkg-config --libs libffi) endif ifeq ($(UNAME_S),Linux) -LIBFFI_LDFLAGS_MOD += -ldl +LIBFFI_LDFLAGS += -ldl endif -CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1 -LDFLAGS_MOD += $(LIBFFI_LDFLAGS_MOD) -SRC_MOD += modffi.c +CFLAGS += $(LIBFFI_CFLAGS) -DMICROPY_PY_FFI=1 +LDFLAGS += $(LIBFFI_LDFLAGS) endif ifeq ($(MICROPY_PY_JNI),1) # Path for 64-bit OpenJDK, should be adjusted for other JDKs -CFLAGS_MOD += -I/usr/lib/jvm/java-7-openjdk-amd64/include -DMICROPY_PY_JNI=1 -SRC_MOD += modjni.c +CFLAGS += -I/usr/lib/jvm/java-7-openjdk-amd64/include -DMICROPY_PY_JNI=1 endif # source files @@ -236,6 +211,8 @@ SRC_C += \ $(SRC_MOD) \ $(wildcard $(VARIANT_DIR)/*.c) +$(BUILD)/supervisor/shared/translate/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/compressed_translations.generated.h + SHARED_SRC_C += $(addprefix shared/,\ runtime/gchelper_generic.c \ timeutils/timeutils.c \ @@ -243,17 +220,14 @@ SHARED_SRC_C += $(addprefix shared/,\ ) SRC_CXX += \ - $(SRC_MOD_CXX) OBJ = $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) $(EXTMOD_SRC_C) +SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += @@ -267,13 +241,7 @@ CFLAGS += -DMPZ_DIG_SIZE=16 # force 16 bits to work on both 32 and 64 bit archs CFLAGS += -DMICROPY_MODULE_FROZEN_STR endif -HASCPP17 = $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 7) -ifeq ($(HASCPP17), 1) - CXXFLAGS += -std=c++17 -else - CXXFLAGS += -std=c++11 -endif -CXXFLAGS += $(filter-out -Wmissing-prototypes -Wold-style-definition -std=gnu99 -std=gnu11,$(CFLAGS) $(CXXFLAGS_MOD)) +CXXFLAGS += $(filter-out -Wmissing-prototypes -Wold-style-definition -std=gnu99,$(CFLAGS) $(CXXFLAGS_MOD)) ifeq ($(MICROPY_FORCE_32BIT),1) RUN_TESTS_MPY_CROSS_FLAGS = --mpy-cross-flags='-march=x86' @@ -294,40 +262,31 @@ include $(TOP)/py/mkrules.mk .PHONY: test test_full -TEST_EXTRA ?= -test: $(PROG) $(TOP)/tests/run-tests.py - $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py $(TEST_EXTRA) - -test_full: $(PROG) $(TOP)/tests/run-tests.py - $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py -d thread - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py --emit native - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) -d basics float micropython - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) --emit native -d basics float micropython - cat $(TOP)/tests/basics/0prelim.py | ./$(PROG) | grep -q 'abc' - +# CIRCUITPY: these two targets are ours .PHONY: print-failures clean-failures print-failures clean-failures: ../../tests/run-tests.py --$@ + +# CIRCUITPY: support for passing args to run-tests, like `make test TEST_ARGS="basics/*.py"` +TEST_ARGS ?= +test: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py + $(eval DIRNAME=ports/$(notdir $(CURDIR))) + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py $(TEST_ARGS) + +test_full: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py + $(eval DIRNAME=ports/$(notdir $(CURDIR))) + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py -d thread + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py --emit native + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) -d basics float micropython + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) --emit native -d basics float micropython + cat $(TOP)/tests/basics/0prelim.py | ./$(BUILD)/$(PROG) | grep -q 'abc' + test_gcov: test_full gcov -o $(BUILD)/py $(TOP)/py/*.c gcov -o $(BUILD)/extmod $(TOP)/extmod/*.c -# build an interpreter for fuzzing -fuzz: - $(MAKE) \ - CC=afl-clang-fast DEBUG=1 \ - CFLAGS_EXTRA='$(CFLAGS_EXTRA) -ffunction-sections' \ - LDFLAGS_EXTRA='$(LDFLAGS_EXTRA)' \ - BUILD=build-fuzz PROG=micropython_fuzz - -fuzz_clean: - $(MAKE) V=2 BUILD=build-fuzz PROG=micropython_fuzz clean - - # Value of configure's --host= option (required for cross-compilation). # Deduce it from CROSS_COMPILE by default, but can be overridden. ifneq ($(CROSS_COMPILE),) @@ -336,7 +295,7 @@ else CROSS_COMPILE_HOST = endif -deplibs: libffi axtls +deplibs: $(DEPLIBS) libffi: $(BUILD)/lib/libffi/include/ffi.h @@ -347,23 +306,15 @@ $(TOP)/lib/libffi/configure: $(TOP)/lib/libffi/autogen.sh # docs and depending on makeinfo $(BUILD)/lib/libffi/include/ffi.h: $(TOP)/lib/libffi/configure mkdir -p $(BUILD)/lib/libffi; cd $(BUILD)/lib/libffi; \ - $(abspath $(TOP))/lib/libffi/configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out --disable-structs CC="$(CC)" CXX="$(CXX)" LD="$(LD)" CFLAGS="-Os -fomit-frame-pointer -fstrict-aliasing -ffast-math -fno-exceptions"; \ + $(abspath $(TOP))/lib/libffi/configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out --disable-shared --disable-structs CC="$(CC)" CXX="$(CXX)" LD="$(LD)" CFLAGS="-Os -fomit-frame-pointer -fstrict-aliasing -ffast-math -fno-exceptions"; \ $(MAKE) install-exec-recursive; $(MAKE) -C include install-data-am -axtls: $(TOP)/lib/axtls/README - -$(TOP)/lib/axtls/README: - @echo "You cloned without --recursive, fetching submodules for you." - (cd $(TOP); git submodule update --init --recursive) - PREFIX = /usr/local BINDIR = $(DESTDIR)$(PREFIX)/bin -install: $(PROG) +install: $(BUILD)/$(PROG) install -d $(BINDIR) - install $(PROG) $(BINDIR)/$(PROG) + install $(BUILD)/$(PROG) $(BINDIR)/$(PROG) uninstall: -rm $(BINDIR)/$(PROG) - -$(BUILD)/supervisor/shared/translate/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/compressed_translations.generated.h diff --git a/ports/unix/README.md b/ports/unix/README.md new file mode 100644 index 0000000000..a3a0dba75a --- /dev/null +++ b/ports/unix/README.md @@ -0,0 +1,74 @@ +The Unix version +---------------- + +The "unix" port requires a standard Unix-like environment with gcc and GNU +make. This includes Linux, BSD, macOS, and Windows Subsystem for Linux. The +x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well as +ARM and MIPS. Making a full-featured port to another architecture requires +writing some assembly code for the exception handling and garbage collection. +Alternatively, a fallback implementation based on setjmp/longjmp can be used. + +To build (see section below for required dependencies): + + $ cd ports/unix + $ make submodules + $ make + +Then to give it a try: + + $ ./build-standard/micropython + >>> list(5 * x + y for x in range(10) for y in [4, 2, 1]) + +Use `CTRL-D` (i.e. EOF) to exit the shell. + +Learn about command-line options (in particular, how to increase heap size +which may be needed for larger applications): + + $ ./build-standard/micropython -h + +To run the complete testsuite, use: + + $ make test + +The Unix port comes with a built-in package manager called `mip`, e.g.: + + $ ./build-standard/micropython -m mip install hmac + +or + + $ ./build-standard/micropython + >>> import mip + >>> mip.install("hmac") + +Browse available modules at [micropython-lib] +(https://github.com/micropython/micropython-lib). See +[Package management](https://docs.micropython.org/en/latest/reference/packages.html) +for more information about `mip`. + +External dependencies +--------------------- + +The `libffi` library and `pkg-config` tool are required. On Debian/Ubuntu/Mint +derivative Linux distros, install `build-essential`(includes toolchain and +make), `libffi-dev`, and `pkg-config` packages. + +Other dependencies can be built together with MicroPython. This may +be required to enable extra features or capabilities, and in recent +versions of MicroPython, these may be enabled by default. To build +these additional dependencies, in the unix port directory first execute: + + $ make submodules + +This will fetch all the relevant git submodules (sub repositories) that +the port needs. Use the same command to get the latest versions of +submodules as they are updated from time to time. After that execute: + + $ make deplibs + +This will build all available dependencies (regardless whether they are used +or not). If you intend to build MicroPython with additional options +(like cross-compiling), the same set of options should be passed to `make +deplibs`. To actually enable/disable use of dependencies, edit the +`ports/unix/mpconfigport.mk` file, which has inline descriptions of the +options. For example, to build the SSL module, `MICROPY_PY_USSL` should be +set to 1. diff --git a/ports/unix/alloc.c b/ports/unix/alloc.c index 7fe7b4dba4..e9cf521583 100644 --- a/ports/unix/alloc.c +++ b/ports/unix/alloc.c @@ -104,4 +104,6 @@ void ffi_closure_free(void *ptr) { } #endif +MP_REGISTER_ROOT_POINTER(void *mmap_region_head); + #endif // MICROPY_EMIT_NATIVE || (MICROPY_PY_FFI && MICROPY_FORCE_PLAT_ALLOC_EXEC) diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 058abab5ce..8ac1d3d298 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -1,4 +1,5 @@ #include +#include #include #include "py/obj.h" @@ -101,20 +102,18 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); STATIC const mp_stream_p_t fileio_stream_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stest_read, .write = stest_write, .ioctl = stest_ioctl, }; -STATIC const mp_obj_type_t mp_type_stest_fileio = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &fileio_stream_p, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_stest_fileio, + MP_QSTR_stest_fileio, + MP_TYPE_FLAG_NONE, + protocol, &fileio_stream_p, + locals_dict, &rawfile_locals_dict + ); // stream read returns non-blocking error STATIC mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { @@ -132,20 +131,18 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table2[] = { STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2); STATIC const mp_stream_p_t textio_stream_p2 = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stest_read2, .write = NULL, .is_text = true, }; -STATIC const mp_obj_type_t mp_type_stest_textio2 = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict2, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &textio_stream_p2, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_stest_textio2, + MP_QSTR_stest_textio2, + MP_TYPE_FLAG_NONE, + protocol, &textio_stream_p2, + locals_dict, &rawfile_locals_dict2 + ); // str/bytes objects without a valid hash STATIC const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte *)"0123456789"}; @@ -228,6 +225,42 @@ STATIC mp_obj_t extra_coverage(void) { mp_printf(&mp_plat_print, "%p\n", gc_nbytes(NULL)); } + // GC initialisation and allocation stress test, to check the logic behind ALLOC_TABLE_GAP_BYTE + // (the following test should fail when ALLOC_TABLE_GAP_BYTE=0) + { + mp_printf(&mp_plat_print, "# GC part 2\n"); + + // check the GC is unlocked and save its state + assert(MP_STATE_THREAD(gc_lock_depth) == 0); + mp_state_mem_t mp_state_mem_orig = mp_state_ctx.mem; + + // perform the test + unsigned heap_size = 64 * MICROPY_BYTES_PER_GC_BLOCK; + for (unsigned j = 0; j < 256 * MP_BYTES_PER_OBJ_WORD; ++j) { + char *heap = calloc(heap_size, 1); + gc_init(heap, heap + heap_size); + + m_malloc(MICROPY_BYTES_PER_GC_BLOCK); + void *o = gc_alloc(MICROPY_BYTES_PER_GC_BLOCK, GC_ALLOC_FLAG_HAS_FINALISER); + ((mp_obj_base_t *)o)->type = NULL; // ensure type is cleared so GC doesn't look for finaliser + for (unsigned i = 0; i < heap_size / MICROPY_BYTES_PER_GC_BLOCK; ++i) { + void *p = m_malloc_maybe(MICROPY_BYTES_PER_GC_BLOCK); + if (!p) { + break; + } + *(void **)p = o; + o = p; + } + gc_collect(); + free(heap); + heap_size += MICROPY_BYTES_PER_GC_BLOCK / 16; + } + mp_printf(&mp_plat_print, "pass\n"); + + // restore the GC state (the original heap) + mp_state_ctx.mem = mp_state_mem_orig; + } + // tracked allocation { #define NUM_PTRS (8) @@ -583,7 +616,7 @@ STATIC mp_obj_t extra_coverage(void) { byte buf[RINGBUF_SIZE]; ringbuf_t ringbuf; - ringbuf_init(&ringbuf, &buf[0], sizeof(buf)); + ringbuf_init(&ringbuf, buf, sizeof(buf)); mp_printf(&mp_plat_print, "# ringbuf\n"); diff --git a/ports/unix/gccollect.c b/ports/unix/gccollect.c index 79b17663c3..94c9c61ea4 100644 --- a/ports/unix/gccollect.c +++ b/ports/unix/gccollect.c @@ -34,8 +34,6 @@ #if MICROPY_ENABLE_GC void gc_collect(void) { - // gc_dump_info(); - gc_collect_start(); gc_helper_collect_regs_and_stack(); #if MICROPY_PY_THREAD @@ -45,9 +43,6 @@ void gc_collect(void) { mp_unix_mark_exec(); #endif gc_collect_end(); - - // printf("-----\n"); - // gc_dump_info(); } #endif // MICROPY_ENABLE_GC diff --git a/ports/unix/main.c b/ports/unix/main.c index e2ea429439..87f58014ec 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -43,6 +43,7 @@ #include "py/builtin.h" #include "py/repl.h" #include "py/gc.h" +#include "py/objstr.h" #include "py/stackctrl.h" #include "py/mphal.h" #include "py/mpthread.h" @@ -63,6 +64,11 @@ STATIC uint emit_opt = MP_EMIT_OPT_NONE; long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4); #endif +// Number of heaps to assign by default if MICROPY_GC_SPLIT_HEAP=1 +#ifndef MICROPY_GC_SPLIT_HEAP_N_HEAPS +#define MICROPY_GC_SPLIT_HEAP_N_HEAPS (1) +#endif + STATIC void stderr_print_strn(void *env, const char *str, size_t len) { (void)env; ssize_t ret; @@ -432,6 +438,17 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { } } +#if MICROPY_PY_SYS_EXECUTABLE +extern mp_obj_str_t mp_sys_executable_obj; +STATIC char executable_path[MICROPY_ALLOC_PATH_MAX]; + +STATIC void sys_set_excecutable(char *argv0) { + if (realpath(argv0, executable_path)) { + mp_obj_str_set_data(&mp_sys_executable_obj, (byte *)executable_path, strlen(executable_path)); + } +} +#endif + #ifdef _WIN32 #define PATHLIST_SEP_CHAR ';' #else @@ -479,8 +496,22 @@ MP_NOINLINE int main_(int argc, char **argv) { pre_process_options(argc, argv); #if MICROPY_ENABLE_GC + #if !MICROPY_GC_SPLIT_HEAP char *heap = malloc(heap_size); gc_init(heap, heap + heap_size); + #else + assert(MICROPY_GC_SPLIT_HEAP_N_HEAPS > 0); + char *heaps[MICROPY_GC_SPLIT_HEAP_N_HEAPS]; + long multi_heap_size = heap_size / MICROPY_GC_SPLIT_HEAP_N_HEAPS; + for (size_t i = 0; i < MICROPY_GC_SPLIT_HEAP_N_HEAPS; i++) { + heaps[i] = malloc(multi_heap_size); + if (i == 0) { + gc_init(heaps[i], heaps[i] + multi_heap_size); + } else { + gc_add(heaps[i], heaps[i] + multi_heap_size); + } + } + #endif #endif #if MICROPY_ENABLE_PYSTACK @@ -501,7 +532,7 @@ MP_NOINLINE int main_(int argc, char **argv) { { // Mount the host FS at the root of our internal VFS mp_obj_t args[2] = { - mp_type_vfs_posix.make_new(&mp_type_vfs_posix, 0, 0, NULL), + MP_OBJ_TYPE_GET_SLOT(&mp_type_vfs_posix, make_new)(&mp_type_vfs_posix, 0, 0, NULL), MP_OBJ_NEW_QSTR(MP_QSTR__slash_), }; mp_vfs_mount(2, args, (mp_map_t *)&mp_const_empty_map); @@ -542,7 +573,7 @@ MP_NOINLINE int main_(int argc, char **argv) { vstr_init(&vstr, home_l + (p1 - p - 1) + 1); vstr_add_strn(&vstr, home, home_l); vstr_add_strn(&vstr, p + 1, p1 - p - 1); - path_items[i] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + path_items[i] = mp_obj_new_str_from_vstr(&vstr); } else { path_items[i] = mp_obj_new_str_via_qstr(p, p1 - p); } @@ -581,6 +612,10 @@ MP_NOINLINE int main_(int argc, char **argv) { printf(" peak %d\n", m_get_peak_bytes_allocated()); */ + #if MICROPY_PY_SYS_EXECUTABLE + sys_set_excecutable(argv[0]); + #endif + const int NOTHING_EXECUTED = -2; int ret = NOTHING_EXECUTED; bool inspect = false; @@ -638,7 +673,7 @@ MP_NOINLINE int main_(int argc, char **argv) { vstr_init(&vstr, len + sizeof(".__main__")); vstr_add_strn(&vstr, argv[a + 1], len); vstr_add_strn(&vstr, ".__main__", sizeof(".__main__") - 1); - import_args[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + import_args[0] = mp_obj_new_str_from_vstr(&vstr); goto reimport; } @@ -666,6 +701,7 @@ MP_NOINLINE int main_(int argc, char **argv) { char *basedir = realpath(argv[a], pathbuf); if (basedir == NULL) { mp_printf(&mp_stderr_print, "%s: can't open file '%s': [Errno %d] %s\n", argv[0], argv[a], errno, strerror(errno)); + free(pathbuf); // CPython exits with 2 in such case ret = 2; break; @@ -731,7 +767,13 @@ MP_NOINLINE int main_(int argc, char **argv) { #if MICROPY_ENABLE_GC && !defined(NDEBUG) // We don't really need to free memory since we are about to exit the // process, but doing so helps to find memory leaks. + #if !MICROPY_GC_SPLIT_HEAP free(heap); + #else + for (size_t i = 0; i < MICROPY_GC_SPLIT_HEAP_N_HEAPS; i++) { + free(heaps[i]); + } + #endif #endif // printf("total bytes = %d\n", m_get_total_bytes_allocated()); @@ -739,6 +781,9 @@ MP_NOINLINE int main_(int argc, char **argv) { } void nlr_jump_fail(void *val) { + #if MICROPY_USE_READLINE == 1 + mp_hal_stdio_mode_orig(); + #endif fprintf(stderr, "FATAL: uncaught NLR %p\n", val); exit(1); } diff --git a/ports/unix/variants/freedos/mpconfigvariant.h b/ports/unix/mbedtls/mbedtls_config.h similarity index 72% rename from ports/unix/variants/freedos/mpconfigvariant.h rename to ports/unix/mbedtls/mbedtls_config.h index 562c783ca3..c8ffab0832 100644 --- a/ports/unix/variants/freedos/mpconfigvariant.h +++ b/ports/unix/mbedtls/mbedtls_config.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2015 Damien P. George + * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,16 +23,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H +#define MICROPY_INCLUDED_MBEDTLS_CONFIG_H -// options to control how MicroPython is built +// Set mbedtls configuration +#define MBEDTLS_CIPHER_MODE_CTR // needed for MICROPY_PY_UCRYPTOLIB_CTR -#define MICROPY_PY_USELECT_POSIX (0) +// Enable mbedtls modules +#define MBEDTLS_HAVEGE_C +#define MBEDTLS_TIMING_C -#define MICROPY_STREAMS_NON_BLOCK (0) +// Include common mbedtls configuration. +#include "extmod/mbedtls/mbedtls_config_common.h" -#define MICROPY_PY_SYS_PLATFORM "freedos" - -// djgpp dirent struct does not have d_ino field -#undef _DIRENT_HAVE_D_INO - -#define MICROPY_USE_INTERNAL_ERRNO (1) +#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c index 468006ba5d..bc585f8647 100644 --- a/ports/unix/modffi.c +++ b/ports/unix/modffi.c @@ -25,20 +25,19 @@ * THE SOFTWARE. */ -#include -#include -#include -#include -#include -#include - #include "py/runtime.h" #include "py/binary.h" #include "py/mperrno.h" #include "py/objint.h" #include "py/gc.h" -#include "supervisor/shared/translate/translate.h" +#if MICROPY_PY_FFI + +#include +#include +#include +#include +#include /* * modffi uses character codes to encode a value type, based on "struct" @@ -352,7 +351,7 @@ STATIC mp_obj_t mod_ffi_callback(size_t n_args, const mp_obj_t *pos_args, mp_map int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params); if (res != FFI_OK) { - mp_raise_ValueError(MP_ERROR_TEXT("Error in ffi_prep_cif")); + mp_raise_ValueError(MP_ERROR_TEXT("error in ffi_prep_cif")); } res = ffi_prep_closure_loc(o->clo, &o->cif, @@ -421,13 +420,14 @@ STATIC const mp_rom_map_elem_t ffimod_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ffimod_locals_dict, ffimod_locals_dict_table); -STATIC const mp_obj_type_t ffimod_type = { - { &mp_type_type }, - .name = MP_QSTR_ffimod, - .print = ffimod_print, - .make_new = ffimod_make_new, - .locals_dict = (mp_obj_dict_t *)&ffimod_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + ffimod_type, + MP_QSTR_ffimod, + MP_TYPE_FLAG_NONE, + make_new, ffimod_make_new, + print, ffimod_print, + locals_dict, &ffimod_locals_dict + ); // FFI function @@ -505,22 +505,19 @@ STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const } else if (mp_obj_is_str(a)) { const char *s = mp_obj_str_get_str(a); values[i].ffi = (ffi_arg)(intptr_t)s; - } else { - mp_getbuffer_fun_t get_buffer = mp_type_get_getbuffer_slot(((mp_obj_base_t *)MP_OBJ_TO_PTR(a))->type); - if (get_buffer != NULL) { - mp_obj_base_t *o = (mp_obj_base_t *)MP_OBJ_TO_PTR(a); - mp_buffer_info_t bufinfo; - int ret = get_buffer(MP_OBJ_FROM_PTR(o), &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ? - if (ret != 0) { - goto error; - } - values[i].ffi = (ffi_arg)(intptr_t)bufinfo.buf; - } else if (mp_obj_is_type(a, &fficallback_type)) { - mp_obj_fficallback_t *p = MP_OBJ_TO_PTR(a); - values[i].ffi = (ffi_arg)(intptr_t)p->func; - } else { + } else if (MP_OBJ_TYPE_HAS_SLOT(((mp_obj_base_t *)MP_OBJ_TO_PTR(a))->type, buffer)) { + mp_obj_base_t *o = (mp_obj_base_t *)MP_OBJ_TO_PTR(a); + mp_buffer_info_t bufinfo; + int ret = MP_OBJ_TYPE_GET_SLOT(o->type, buffer)(MP_OBJ_FROM_PTR(o), &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ? + if (ret != 0) { goto error; } + values[i].ffi = (ffi_arg)(intptr_t)bufinfo.buf; + } else if (mp_obj_is_type(a, &fficallback_type)) { + mp_obj_fficallback_t *p = MP_OBJ_TO_PTR(a); + values[i].ffi = (ffi_arg)(intptr_t)p->func; + } else { + goto error; } valueptrs[i] = &values[i]; } @@ -530,18 +527,16 @@ STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const return return_ffi_value(&retval, self->rettype); error: - mp_raise_TypeError(MP_ERROR_TEXT("Don't know how to pass object to native function")); + mp_raise_TypeError(MP_ERROR_TEXT("don't know how to pass object to native function")); } -STATIC const mp_obj_type_t ffifunc_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_ffifunc, - .print = ffifunc_print, - MP_TYPE_EXTENDED_FIELDS( - .call = ffifunc_call, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + ffifunc_type, + MP_QSTR_ffifunc, + MP_TYPE_FLAG_NONE, + print, ffifunc_print, + call, ffifunc_call + ); // FFI callback for Python function @@ -562,12 +557,13 @@ STATIC const mp_rom_map_elem_t fficallback_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(fficallback_locals_dict, fficallback_locals_dict_table); -STATIC const mp_obj_type_t fficallback_type = { - { &mp_type_type }, - .name = MP_QSTR_fficallback, - .print = fficallback_print, - .locals_dict = (mp_obj_dict_t *)&fficallback_locals_dict -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + fficallback_type, + MP_QSTR_fficallback, + MP_TYPE_FLAG_NONE, + print, fficallback_print, + locals_dict, &fficallback_locals_dict + ); // FFI variable @@ -598,21 +594,23 @@ STATIC const mp_rom_map_elem_t ffivar_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ffivar_locals_dict, ffivar_locals_dict_table); -STATIC const mp_obj_type_t ffivar_type = { - { &mp_type_type }, - .name = MP_QSTR_ffivar, - .print = ffivar_print, - .locals_dict = (mp_obj_dict_t *)&ffivar_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + ffivar_type, + MP_QSTR_ffivar, + MP_TYPE_FLAG_NONE, + print, ffivar_print, + locals_dict, &ffivar_locals_dict + ); // Generic opaque storage object (unused) /* -STATIC const mp_obj_type_t opaque_type = { - { &mp_type_type }, - .name = MP_QSTR_opaqueval, -// .print = opaque_print, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + opaque_type, + MP_QSTR_opaqueval, + MP_TYPE_FLAG_NONE, + make_new, // .print = opaque_print, + ); */ STATIC mp_obj_t mod_ffi_open(size_t n_args, const mp_obj_t *args) { @@ -639,3 +637,7 @@ const mp_obj_module_t mp_module_ffi = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t *)&mp_module_ffi_globals, }; + +MP_REGISTER_MODULE(MP_QSTR_ffi, mp_module_ffi); + +#endif // MICROPY_PY_FFI diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index c86f30653c..10622f588f 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -24,19 +24,19 @@ * THE SOFTWARE. */ +#include "py/runtime.h" +#include "py/binary.h" + +#if MICROPY_PY_JNI + #include #include #include #include #include -#include "py/runtime.h" -#include "py/binary.h" - #include -#if MICROPY_PY_JNI - #define JJ(call, ...) (*env)->call(env, __VA_ARGS__) #define JJ1(call) (*env)->call(env) #define MATCH(s, static) (!strncmp(s, static, sizeof(static) - 1)) @@ -174,14 +174,15 @@ STATIC const mp_rom_map_elem_t jclass_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(jclass_locals_dict, jclass_locals_dict_table); -STATIC const mp_obj_type_t jclass_type = { - { &mp_type_type }, - .name = MP_QSTR_jclass, - .print = jclass_print, - .attr = jclass_attr, - .call = jclass_call, - .locals_dict = (mp_obj_dict_t *)&jclass_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + jclass_type, + MP_QSTR_jclass, + MP_TYPE_FLAG_NONE, + print, jclass_print, + attr, jclass_attr, + call, jclass_call, + locals_dict, &jclass_locals_dict + ); STATIC mp_obj_t new_jclass(jclass jc) { mp_obj_jclass_t *o = mp_obj_malloc(mp_obj_jclass_t, &jclass_type); @@ -320,16 +321,17 @@ STATIC mp_obj_t subscr_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { return mp_obj_new_getitem_iter(dest, iter_buf); } -STATIC const mp_obj_type_t jobject_type = { - { &mp_type_type }, - .name = MP_QSTR_jobject, - .print = jobject_print, - .unary_op = jobject_unary_op, - .attr = jobject_attr, - .subscr = jobject_subscr, - .getiter = subscr_getiter, -// .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + jobject_type, + MP_QSTR_jobject, + MP_TYPE_FLAG_ITER_IS_GETITER, + print, jobject_print, + unary_op, jobject_unary_op, + attr, jobject_attr, + subscr, jobject_subscr, + iter, subscr_getiter, + // .locals_dict = &jobject_locals_dict, + ); STATIC mp_obj_t new_jobject(jobject jo) { if (jo == NULL) { @@ -376,7 +378,7 @@ STATIC const char *strprev(const char *s, char c) { STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out) { const char *arg_type = *jtypesig; - mp_obj_type_t *type = mp_obj_get_type(arg); + const mp_obj_type_t *type = mp_obj_get_type(arg); if (type == &mp_type_str) { if (IMATCH(arg_type, "java.lang.String") || IMATCH(arg_type, "java.lang.Object")) { @@ -567,14 +569,15 @@ STATIC mp_obj_t jmethod_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const return call_method(self->obj, name, methods, false, n_args, args); } -STATIC const mp_obj_type_t jmethod_type = { - { &mp_type_type }, - .name = MP_QSTR_jmethod, - .print = jmethod_print, - .call = jmethod_call, -// .attr = jobject_attr, -// .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + jmethod_type, + MP_QSTR_jmethod, + MP_TYPE_FLAG_NONE, + print, jmethod_print, + call, jmethod_call, + // .attr = jobject_attr, + // .locals_dict = &jobject_locals_dict, + ); #ifdef __ANDROID__ #define LIBJVM_SO "libdvm.so" diff --git a/ports/unix/modmachine.c b/ports/unix/modmachine.c index bcbf39406f..542ff50025 100644 --- a/ports/unix/modmachine.c +++ b/ports/unix/modmachine.c @@ -36,8 +36,6 @@ #include "extmod/machine_signal.h" #include "extmod/machine_pulse.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PLAT_DEV_MEM #include #include diff --git a/ports/unix/moduos.c b/ports/unix/moduos.c index e352b9f27b..e99c53ff62 100644 --- a/ports/unix/moduos.c +++ b/ports/unix/moduos.c @@ -25,6 +25,7 @@ * THE SOFTWARE. */ +#include #include #include @@ -39,7 +40,8 @@ os_getenv_err_t common_hal_os_getenv_str(const char *key, char *value, size_t va os_getenv_err_t common_hal_os_getenv_int(const char *key, mp_int_t *value); #endif -STATIC mp_obj_t mp_uos_getenv(mp_obj_t var_in) { +STATIC mp_obj_t mp_uos_getenv(size_t n_args, const mp_obj_t *args) { + mp_obj_t var_in = args[0]; #if defined(MICROPY_UNIX_COVERAGE) mp_obj_t result = common_hal_os_getenv(mp_obj_str_get_str(var_in), mp_const_none); if (result != mp_const_none) { @@ -48,11 +50,11 @@ STATIC mp_obj_t mp_uos_getenv(mp_obj_t var_in) { #endif const char *s = getenv(mp_obj_str_get_str(var_in)); if (s == NULL) { - return mp_const_none; + return n_args > 1 ? args[1] : mp_const_none; } return mp_obj_new_str(s, strlen(s)); } -MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_getenv_obj, mp_uos_getenv); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_getenv_obj, 1, 2, mp_uos_getenv); #if defined(MICROPY_UNIX_COVERAGE) STATIC mp_obj_t mp_uos_getenv_int(mp_obj_t var_in) { @@ -129,7 +131,7 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) { vstr_t vstr; vstr_init_len(&vstr, n); mp_hal_get_random(n, vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom); diff --git a/ports/unix/moduselect.c b/ports/unix/moduselect.c index 8295f3d8b5..dbbc86a053 100644 --- a/ports/unix/moduselect.c +++ b/ports/unix/moduselect.c @@ -311,16 +311,13 @@ STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); -STATIC const mp_obj_type_t mp_type_poll = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_poll, - .locals_dict = (void *)&poll_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = poll_iternext, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_poll, + MP_QSTR_poll, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + iter, poll_iternext, + locals_dict, &poll_locals_dict + ); STATIC mp_obj_t select_poll(size_t n_args, const mp_obj_t *args) { int alloc = 4; diff --git a/ports/unix/mpbthciport.c b/ports/unix/mpbthciport.c index 14afbebcd7..8813ce147c 100644 --- a/ports/unix/mpbthciport.c +++ b/ports/unix/mpbthciport.c @@ -46,7 +46,11 @@ #include #define DEBUG_printf(...) // printf(__VA_ARGS__) -#define DEBUG_HCI_DUMP (0) + +#define HCI_TRACE (0) +#define COL_OFF "\033[0m" +#define COL_GREEN "\033[0;32m" +#define COL_BLUE "\033[0;34m" uint8_t mp_bluetooth_hci_cmd_buf[4 + 256]; @@ -234,8 +238,8 @@ int mp_bluetooth_hci_uart_readchar(void) { ssize_t bytes_read = read(uart_fd, &c, 1); if (bytes_read == 1) { - #if DEBUG_HCI_DUMP - printf("[% 8ld] RX: %02x\n", mp_hal_ticks_ms(), c); + #if HCI_TRACE + printf(COL_BLUE "> [% 8ld] RX: %02x" COL_OFF "\n", mp_hal_ticks_ms(), c); #endif return c; } else { @@ -250,12 +254,12 @@ int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len) { return 0; } - #if DEBUG_HCI_DUMP - printf("[% 8ld] TX: %02x", mp_hal_ticks_ms(), buf[0]); + #if HCI_TRACE + printf(COL_GREEN "< [% 8ld] TX: %02x", mp_hal_ticks_ms(), buf[0]); for (size_t i = 1; i < len; ++i) { printf(":%02x", buf[i]); } - printf("\n"); + printf(COL_OFF "\n"); #endif return write(uart_fd, buf, len); diff --git a/ports/unix/mpbtstackport_common.c b/ports/unix/mpbtstackport_common.c index ec40db65bc..36412e96f4 100644 --- a/ports/unix/mpbtstackport_common.c +++ b/ports/unix/mpbtstackport_common.c @@ -35,6 +35,7 @@ #include "lib/btstack/platform/embedded/btstack_run_loop_embedded.h" #include "lib/btstack/platform/embedded/hal_cpu.h" #include "lib/btstack/platform/embedded/hal_time_ms.h" +#include "lib/btstack/platform/embedded/hci_dump_embedded_stdout.h" #include "extmod/btstack/modbluetooth_btstack.h" @@ -79,15 +80,9 @@ uint32_t hal_time_ms(void) { } void mp_bluetooth_btstack_port_init(void) { - static bool run_loop_init = false; - if (!run_loop_init) { - run_loop_init = true; - btstack_run_loop_init(btstack_run_loop_embedded_get_instance()); - } else { - btstack_run_loop_embedded_get_instance()->init(); - } + btstack_run_loop_init(btstack_run_loop_embedded_get_instance()); - // hci_dump_open(NULL, HCI_DUMP_STDOUT); + // hci_dump_init(hci_dump_embedded_stdout_get_instance()); #if MICROPY_BLUETOOTH_BTSTACK_H4 mp_bluetooth_btstack_port_init_h4(); diff --git a/ports/unix/mpbtstackport_h4.c b/ports/unix/mpbtstackport_h4.c index 4fdc20c22b..dacfff9a49 100644 --- a/ports/unix/mpbtstackport_h4.c +++ b/ports/unix/mpbtstackport_h4.c @@ -32,6 +32,7 @@ #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK && MICROPY_BLUETOOTH_BTSTACK_H4 +#include "lib/btstack/src/hci_transport_h4.h" #include "lib/btstack/chipset/zephyr/btstack_chipset_zephyr.h" #include "extmod/btstack/btstack_hci_uart.h" @@ -42,11 +43,12 @@ #define DEBUG_printf(...) // printf(__VA_ARGS__) STATIC hci_transport_config_uart_t hci_transport_config_uart = { - HCI_TRANSPORT_CONFIG_UART, - 1000000, // initial baudrate - 0, // main baudrate - 1, // flow control - NULL, // device name + .type = HCI_TRANSPORT_CONFIG_UART, + .baudrate_init = 1000000, + .baudrate_main = 0, + .flowcontrol = 1, + .device_name = NULL, + .parity = BTSTACK_UART_PARITY_OFF, }; void mp_bluetooth_hci_poll_h4(void) { @@ -58,7 +60,7 @@ void mp_bluetooth_hci_poll_h4(void) { void mp_bluetooth_btstack_port_init_h4(void) { DEBUG_printf("mp_bluetooth_btstack_port_init_h4\n"); - const hci_transport_t *transport = hci_transport_h4_instance(&mp_bluetooth_btstack_hci_uart_block); + const hci_transport_t *transport = hci_transport_h4_instance_for_uart(&mp_bluetooth_btstack_hci_uart_block); hci_init(transport, &hci_transport_config_uart); hci_set_chipset(btstack_chipset_zephyr_instance()); diff --git a/ports/unix/mpbtstackport_usb.c b/ports/unix/mpbtstackport_usb.c index 28d2c8c543..b8c7b758d9 100644 --- a/ports/unix/mpbtstackport_usb.c +++ b/ports/unix/mpbtstackport_usb.c @@ -34,6 +34,7 @@ #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK && MICROPY_BLUETOOTH_BTSTACK_USB #include "lib/btstack/src/btstack.h" +#include "lib/btstack/src/hci_transport_usb.h" #include "lib/btstack/platform/embedded/btstack_run_loop_embedded.h" #include "lib/btstack/platform/embedded/hal_cpu.h" #include "lib/btstack/platform/embedded/hal_time_ms.h" diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index a9e6cf9885..86ec15b822 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -24,91 +24,42 @@ * THE SOFTWARE. */ -// Options to control how MicroPython is built for this port, -// overriding defaults in py/mpconfig.h. +#pragma once + +// Options to control how MicroPython is built for this port, overriding +// defaults in py/mpconfig.h. This file is mostly about configuring the +// features to work on Unix-like systems, see mpconfigvariant.h (and +// mpconfigvariant_common.h) for feature enabling. + +// For size_t and ssize_t +#include // Variant-specific definitions. #include "mpconfigvariant.h" -// The minimal variant's config covers everything. -// If we're building the minimal variant, ignore the rest of this file. -#ifndef MICROPY_UNIX_MINIMAL - // CIRCUITPY #define CIRCUITPY_MICROPYTHON_ADVANCED (1) #define MICROPY_PY_ASYNC_AWAIT (1) -// If the variant did not set a feature level then configure a set of features. #ifndef MICROPY_CONFIG_ROM_LEVEL -#define MICROPY_COMP_MODULE_CONST (1) -#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) -#define MICROPY_COMP_RETURN_IF_EXPR (1) -#ifndef MICROPY_OPT_LOAD_ATTR_FAST_PATH -#define MICROPY_OPT_LOAD_ATTR_FAST_PATH (1) -#endif -#ifndef MICROPY_OPT_MAP_LOOKUP_CACHE -#define MICROPY_OPT_MAP_LOOKUP_CACHE (1) -#endif -#define MICROPY_ENABLE_FINALISER (1) -#define MICROPY_STACK_CHECK (1) -#define MICROPY_KBD_EXCEPTION (1) -#define MICROPY_HELPER_REPL (1) -#define MICROPY_REPL_EMACS_KEYS (1) -#define MICROPY_REPL_AUTO_INDENT (1) -#define MICROPY_ENABLE_SOURCE_LINE (1) -#ifndef MICROPY_STREAMS_NON_BLOCK -#define MICROPY_STREAMS_NON_BLOCK (1) -#endif -#define MICROPY_MODULE_WEAK_LINKS (1) -#define MICROPY_CAN_OVERRIDE_BUILTINS (1) -#define MICROPY_PY_FUNCTION_ATTRS (1) -#define MICROPY_PY_DESCRIPTORS (1) -#define MICROPY_PY_DELATTR_SETATTR (1) -#define MICROPY_PY_FSTRINGS (1) -#define MICROPY_PY_BUILTINS_STR_UNICODE (1) -#define MICROPY_PY_BUILTINS_STR_CENTER (1) -#define MICROPY_PY_BUILTINS_STR_PARTITION (1) -#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) -#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) -#define MICROPY_PY_BUILTINS_SLICE_INDICES (1) -#define MICROPY_PY_BUILTINS_FROZENSET (1) -#define MICROPY_PY_BUILTINS_ROUND_INT (1) -#define MICROPY_PY_ALL_SPECIAL_METHODS (1) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) -#define MICROPY_PY_BUILTINS_COMPILE (1) -#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) -#define MICROPY_PY_BUILTINS_INPUT (1) -#define MICROPY_PY_BUILTINS_POW3 (1) -#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) -#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) -#define MICROPY_PY_COLLECTIONS_DEQUE (1) -#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) -#ifndef MICROPY_PY_MATH_SPECIAL_FUNCTIONS -#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) -#endif -#define MICROPY_PY_MATH_ISCLOSE (MICROPY_PY_MATH_SPECIAL_FUNCTIONS) -#define MICROPY_PY_CMATH (1) -#define MICROPY_PY_IO_IOBASE (1) -#define MICROPY_PY_IO_FILEIO (1) -#define MICROPY_PY_SYS_MAXSIZE (1) -#define MICROPY_PY_SYS_STDFILES (1) -#define MICROPY_PY_UERRNO (1) -#define MICROPY_PY_UCTYPES (1) -#define MICROPY_PY_UZLIB (1) -#define MICROPY_PY_UJSON (1) -#define MICROPY_PY_UOS (1) -#define MICROPY_PY_URE (1) -#define MICROPY_PY_UHEAPQ (1) -#define MICROPY_PY_UHASHLIB (1) -#define MICROPY_PY_UBINASCII (1) -#define MICROPY_PY_UBINASCII_CRC32 (1) -#define MICROPY_PY_URANDOM (1) +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES) #endif -#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) -#define MICROPY_PERSISTENT_CODE_LOAD (1) +#ifndef MICROPY_PY_SYS_PLATFORM +#if defined(__APPLE__) && defined(__MACH__) + #define MICROPY_PY_SYS_PLATFORM "darwin" +#else + #define MICROPY_PY_SYS_PLATFORM "linux" +#endif +#endif +#ifndef MICROPY_PY_SYS_PATH_DEFAULT +#define MICROPY_PY_SYS_PATH_DEFAULT ".frozen:~/.micropython/lib:/usr/lib/micropython" +#endif + +#define MP_STATE_PORT MP_STATE_VM + +// Configure which emitter to use for this target. #if !defined(MICROPY_EMIT_X64) && defined(__x86_64__) #define MICROPY_EMIT_X64 (1) #endif @@ -124,115 +75,8 @@ #if !defined(MICROPY_EMIT_ARM) && defined(__arm__) && !defined(__thumb2__) #define MICROPY_EMIT_ARM (1) #endif -#define MICROPY_ENABLE_GC (1) -#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) -#define MICROPY_MEM_STATS (1) -#define MICROPY_DEBUG_PRINTERS (1) -// Printing debug to stderr may give tests which -// check stdout a chance to pass, etc. -#define MICROPY_DEBUG_PRINTER (&mp_stderr_print) -#define MICROPY_READER_POSIX (1) -#define MICROPY_READER_VFS (1) -#define MICROPY_USE_READLINE_HISTORY (1) -#define MICROPY_HELPER_LEXER_UNIX (1) -#ifndef MICROPY_FLOAT_IMPL -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) -#endif -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) -#define MICROPY_STREAMS_POSIX_API (1) -#define MICROPY_OPT_COMPUTED_GOTO (1) -#define MICROPY_MODULE_OVERRIDE_MAIN_IMPORT (1) -#define MICROPY_VFS (1) -#define MICROPY_VFS_POSIX (1) -#define MICROPY_PY_SYS_PATH_ARGV_DEFAULTS (0) -#define MICROPY_PY_SYS_EXIT (1) -#define MICROPY_PY_SYS_ATEXIT (1) -#if MICROPY_PY_SYS_SETTRACE -#define MICROPY_PERSISTENT_CODE_SAVE (1) -#define MICROPY_COMP_CONST (0) -#endif -#ifndef MICROPY_PY_SYS_PLATFORM -#if defined(__APPLE__) && defined(__MACH__) - #define MICROPY_PY_SYS_PLATFORM "darwin" -#else - #define MICROPY_PY_SYS_PLATFORM "linux" -#endif -#endif -#ifndef MICROPY_PY_SYS_PATH_DEFAULT -#define MICROPY_PY_SYS_PATH_DEFAULT ".frozen:~/.micropython/lib:/usr/lib/micropython" -#endif -#define MICROPY_PY_SYS_EXC_INFO (1) -#define MICROPY_PY_GC_COLLECT_RETVAL (1) -#ifndef MICROPY_STACKLESS -#define MICROPY_STACKLESS (0) -#define MICROPY_STACKLESS_STRICT (0) -#endif - -#define MICROPY_PY_UOS_INCLUDEFILE "ports/unix/moduos.c" -#define MICROPY_PY_UOS_ERRNO (1) -#define MICROPY_PY_UOS_GETENV_PUTENV_UNSETENV (1) -#define MICROPY_PY_UOS_SEP (1) -#define MICROPY_PY_UOS_SYSTEM (1) -#define MICROPY_PY_UOS_URANDOM (1) -#define MICROPY_PY_UTIME (1) -#define MICROPY_PY_UTIME_MP_HAL (1) -#define MICROPY_PY_UTIMEQ (1) -#define MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT (SOMAXCONN < 128 ? SOMAXCONN : 128) -#if MICROPY_PY_USSL -#define MICROPY_PY_UHASHLIB_MD5 (1) -#define MICROPY_PY_UHASHLIB_SHA1 (1) -#define MICROPY_PY_UCRYPTOLIB (1) -#endif -#ifndef MICROPY_PY_USELECT_POSIX -#define MICROPY_PY_USELECT_POSIX (1) -#endif -#define MICROPY_PY_UWEBSOCKET (0) -#define MICROPY_PY_MACHINE (0) -#define MICROPY_PY_MACHINE_PULSE (0) -#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr -#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr - -#define MICROPY_FATFS_ENABLE_LFN (1) -#define MICROPY_FATFS_RPATH (2) -#define MICROPY_FATFS_MAX_SS (4096) -#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ -#define MICROPY_FATFS_LFN_UNICODE (2) - -#define FF_FS_CASE_INSENSITIVE_COMPARISON_ASCII_ONLY (1) - -// Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc. -// names in exception messages (may require more RAM). -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) -#define MICROPY_WARNINGS (1) -#define MICROPY_ERROR_PRINTER (&mp_stderr_print) -#define MICROPY_PY_STR_BYTES_CMP_WARN (1) - -// VFS stat functions should return time values relative to 1970/1/1 -#define MICROPY_EPOCH_IS_1970 (1) - -extern const struct _mp_print_t mp_stderr_print; - -#define RUN_BACKGROUND_TASKS - -#if !(defined(MICROPY_GCREGS_SETJMP) || defined(__x86_64__) || defined(__i386__) || defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) -// Fall back to setjmp() implementation for discovery of GC pointers in registers. -#define MICROPY_GCREGS_SETJMP (1) -#endif - -#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) -#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) -#define MICROPY_ASYNC_KBD_INTR (1) - -#define mp_type_fileio mp_type_vfs_posix_fileio -#define mp_type_textio mp_type_vfs_posix_textio - -// type definitions for the specific machine - -// For size_t and ssize_t -#include - -// assume that if we already defined the obj repr then we also defined types +// Type definitions for the specific machine based on the word size. #ifndef MICROPY_OBJ_REPR #ifdef __LP64__ typedef long mp_int_t; // must be pointer size @@ -243,6 +87,8 @@ typedef unsigned long mp_uint_t; // must be pointer size typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size #endif +#else +// Assume that if we already defined the obj repr then we also defined types. #endif // Cannot include , as it may lead to symbol name clashes @@ -252,6 +98,85 @@ typedef long long mp_off_t; typedef long mp_off_t; #endif +// We need to provide a declaration/definition of alloca() +// unless support for it is disabled. +#if !defined(MICROPY_NO_ALLOCA) || MICROPY_NO_ALLOCA == 0 +#if defined(__FreeBSD__) || defined(__NetBSD__) +#include +#else +#include +#endif +#endif + +// Always enable GC. +#define MICROPY_ENABLE_GC (1) + +#if !(defined(MICROPY_GCREGS_SETJMP) || defined(__x86_64__) || defined(__i386__) || defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) +// Fall back to setjmp() implementation for discovery of GC pointers in registers. +#define MICROPY_GCREGS_SETJMP (1) +#endif + +// Enable the VFS, and enable the posix "filesystem". +#define MICROPY_ENABLE_FINALISER (1) +#define MICROPY_VFS (1) +#define MICROPY_READER_VFS (1) +#define MICROPY_HELPER_LEXER_UNIX (1) +#define MICROPY_VFS_POSIX (1) +#define MICROPY_READER_POSIX (1) +#ifndef MICROPY_TRACKED_ALLOC +#define MICROPY_TRACKED_ALLOC (MICROPY_BLUETOOTH_BTSTACK) +#endif + +// VFS stat functions should return time values relative to 1970/1/1 +#define MICROPY_EPOCH_IS_1970 (1) + +// Assume that select() call, interrupted with a signal, and erroring +// with EINTR, updates remaining timeout value. +#define MICROPY_SELECT_REMAINING_TIME (1) + +// Disable stackless by default. +#ifndef MICROPY_STACKLESS +#define MICROPY_STACKLESS (0) +#define MICROPY_STACKLESS_STRICT (0) +#endif + +// If settrace is enabled then we need code saving. +#if MICROPY_PY_SYS_SETTRACE +#define MICROPY_PERSISTENT_CODE_SAVE (1) +#define MICROPY_COMP_CONST (0) +#endif + +// Unix-specific configuration of machine.mem*. +#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr +#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr + +#define MICROPY_FATFS_ENABLE_LFN (1) +#define MICROPY_FATFS_RPATH (2) +#define MICROPY_FATFS_MAX_SS (4096) +#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ +#define MICROPY_FATFS_MKFS_FAT32 (1) +#define MICROPY_FATFS_USE_LABEL (1) + +#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) + +// Ensure builtinimport.c works with -m. +#define MICROPY_MODULE_OVERRIDE_MAIN_IMPORT (1) + +// Don't default sys.argv because we do that in main. +#define MICROPY_PY_SYS_PATH_ARGV_DEFAULTS (0) + +// Enable sys.executable. +#define MICROPY_PY_SYS_EXECUTABLE (1) + +#define MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT (SOMAXCONN < 128 ? SOMAXCONN : 128) + +// Bare-metal ports don't have stderr. Printing debug to stderr may give tests +// which check stdout a chance to pass, etc. +extern const struct _mp_print_t mp_stderr_print; +#define MICROPY_DEBUG_PRINTER (&mp_stderr_print) +#define MICROPY_ERROR_PRINTER (&mp_stderr_print) + +// For the native emitter configure how to mark a region as executable. void mp_unix_alloc_exec(size_t min_size, void **ptr, size_t *size); void mp_unix_free_exec(void *ptr, size_t size); void mp_unix_mark_exec(void); @@ -263,8 +188,8 @@ void mp_unix_mark_exec(void); #define MICROPY_FORCE_PLAT_ALLOC_EXEC (1) #endif +// If enabled, configure how to seed random on init. #ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC -// Support for seeding the random module on import. #include void mp_hal_get_random(size_t n, void *buf); static inline unsigned long mp_urandom_seed_init(void) { @@ -279,10 +204,6 @@ static inline unsigned long mp_urandom_seed_init(void) { #define MICROPY_PLAT_DEV_MEM (1) #endif -// Assume that select() call, interrupted with a signal, and erroring -// with EINTR, updates remaining timeout value. -#define MICROPY_SELECT_REMAINING_TIME (1) - #ifdef __ANDROID__ #include #if __ANDROID_API__ < 4 @@ -292,37 +213,6 @@ static inline unsigned long mp_urandom_seed_init(void) { #endif #endif -#define MP_STATE_PORT MP_STATE_VM - -#if MICROPY_PY_BLUETOOTH -#if MICROPY_BLUETOOTH_BTSTACK -struct _mp_bluetooth_btstack_root_pointers_t; -#define MICROPY_BLUETOOTH_ROOT_POINTERS struct _mp_bluetooth_btstack_root_pointers_t *bluetooth_btstack_root_pointers; -#endif -#if MICROPY_BLUETOOTH_NIMBLE -struct _mp_bluetooth_nimble_root_pointers_t; -struct _mp_bluetooth_nimble_malloc_t; -#define MICROPY_BLUETOOTH_ROOT_POINTERS struct _mp_bluetooth_nimble_malloc_t *bluetooth_nimble_memory; struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; -#endif -#else -#define MICROPY_BLUETOOTH_ROOT_POINTERS -#endif - -#define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[50]; \ - void *mmap_region_head; \ - MICROPY_BLUETOOTH_ROOT_POINTERS \ - -// We need to provide a declaration/definition of alloca() -// unless support for it is disabled. -#if !defined(MICROPY_NO_ALLOCA) || MICROPY_NO_ALLOCA == 0 -#ifdef __FreeBSD__ -#include -#else -#include -#endif -#endif - // From "man readdir": "Under glibc, programs can check for the availability // of the fields [in struct dirent] not defined in POSIX.1 by testing whether // the macros [...], _DIRENT_HAVE_D_TYPE are defined." @@ -342,19 +232,32 @@ struct _mp_bluetooth_nimble_malloc_t; #include #endif +// If threading is enabled, configure the atomic section. #if MICROPY_PY_THREAD #define MICROPY_BEGIN_ATOMIC_SECTION() (mp_thread_unix_begin_atomic_section(), 0xffffffff) #define MICROPY_END_ATOMIC_SECTION(x) (void)x; mp_thread_unix_end_atomic_section() #endif +// In lieu of a WFI(), slow down polling from being a tight loop. +#ifndef MICROPY_EVENT_POLL_HOOK #define MICROPY_EVENT_POLL_HOOK \ do { \ extern void mp_handle_pending(bool); \ mp_handle_pending(true); \ - mp_hal_delay_us(500); \ + usleep(500); /* equivalent to mp_hal_delay_us(500) */ \ } while (0); +#endif +// Configure the implementation of machine.idle(). #include #define MICROPY_UNIX_MACHINE_IDLE sched_yield(); -#endif // MICROPY_UNIX_MINIMAL +#ifndef MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +#define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (1) +#endif + +#ifndef MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS +#define MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS (MICROPY_BLUETOOTH_NIMBLE) +#endif + +#define RUN_BACKGROUND_TASKS ((void)0) // CIRCUITPY diff --git a/ports/unix/mpconfigport.mk b/ports/unix/mpconfigport.mk index a0f654597b..2bdd87534e 100644 --- a/ports/unix/mpconfigport.mk +++ b/ports/unix/mpconfigport.mk @@ -40,6 +40,14 @@ MICROPY_PY_JNI = 0 # as submodules (currently affects only libffi). MICROPY_STANDALONE = 0 +# CIRCUITPY: not used +MICROPY_ROM_TEXT_COMPRESSION = 0 + +MICROPY_VFS_FAT = 1 +# CIRCUITPY: not used +MICROPY_VFS_LFS1 = 0 +MICROPY_VFS_LFS2 = 0 + # CIRCUITPY CIRCUITPY_ULAB = 1 MICROPY_EMIT_NATIVE = 0 diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index 665d038c0d..a385121775 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -206,6 +206,7 @@ void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } +#ifndef mp_hal_ticks_ms mp_uint_t mp_hal_ticks_ms(void) { #if (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(_POSIX_MONOTONIC_CLOCK) struct timespec tv; @@ -217,7 +218,9 @@ mp_uint_t mp_hal_ticks_ms(void) { return tv.tv_sec * 1000 + tv.tv_usec / 1000; #endif } +#endif +#ifndef mp_hal_ticks_us mp_uint_t mp_hal_ticks_us(void) { #if (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(_POSIX_MONOTONIC_CLOCK) struct timespec tv; @@ -229,18 +232,22 @@ mp_uint_t mp_hal_ticks_us(void) { return tv.tv_sec * 1000000 + tv.tv_usec; #endif } +#endif +#ifndef mp_hal_time_ns uint64_t mp_hal_time_ns(void) { struct timeval tv; gettimeofday(&tv, NULL); return (uint64_t)tv.tv_sec * 1000000000ULL + (uint64_t)tv.tv_usec * 1000ULL; } +#endif +#ifndef mp_hal_delay_ms void mp_hal_delay_ms(mp_uint_t ms) { #ifdef MICROPY_EVENT_POLL_HOOK mp_uint_t start = mp_hal_ticks_ms(); while (mp_hal_ticks_ms() - start < ms) { - // MICROPY_EVENT_POLL_HOOK does mp_hal_delay_us(500) (i.e. usleep(500)). + // MICROPY_EVENT_POLL_HOOK does usleep(500). MICROPY_EVENT_POLL_HOOK } #else @@ -249,6 +256,7 @@ void mp_hal_delay_ms(mp_uint_t ms) { usleep(ms * 1000); #endif } +#endif void mp_hal_get_random(size_t n, void *buf) { #ifdef _HAVE_GETRANDOM diff --git a/ports/unix/variants/coverage/manifest.py b/ports/unix/variants/coverage/manifest.py index 6111050884..7c3d9a6b64 100644 --- a/ports/unix/variants/coverage/manifest.py +++ b/ports/unix/variants/coverage/manifest.py @@ -1,2 +1,3 @@ freeze_as_str("frzstr") freeze_as_mpy("frzmpy") +freeze_mpy("$(MPY_DIR)/tests/frozen") diff --git a/ports/unix/variants/coverage/mpconfigvariant.h b/ports/unix/variants/coverage/mpconfigvariant.h index 5828cb5616..72c25263b2 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.h +++ b/ports/unix/variants/coverage/mpconfigvariant.h @@ -28,52 +28,18 @@ // for coverage testing. // Set base feature level. -#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EVERYTHING) -#define MICROPY_VFS (1) -#define MICROPY_PY_UOS_VFS (1) - -// Disable some features that come enabled by default with the feature level. -#define MICROPY_PY_BUILTINS_EXECFILE (0) -#define MICROPY_PY_SYS_STDIO_BUFFER (0) -#define MICROPY_PY_USELECT (0) +// Enable extra Unix features. +#include "../mpconfigvariant_common.h" // Enable additional features. #define MICROPY_DEBUG_PARSE_RULE_NAME (1) -#define MICROPY_TRACKED_ALLOC (1) -#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) -#define MICROPY_ENABLE_SCHEDULER (1) -#define MICROPY_READER_VFS (1) -#define MICROPY_REPL_EMACS_WORDS_MOVE (1) -#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (1) +#define MICROPY_TRACKED_ALLOC (1) #define MICROPY_WARNINGS_CATEGORY (1) -#define MICROPY_MODULE_GETATTR (1) -#define MICROPY_PY_DELATTR_SETATTR (1) -#define MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS (1) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) -#define MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE (1) -#define MICROPY_PY_BUILTINS_NEXT2 (1) -#define MICROPY_PY_BUILTINS_RANGE_BINOP (1) -#define MICROPY_PY_BUILTINS_HELP (1) -#define MICROPY_PY_BUILTINS_HELP_MODULES (1) -#define MICROPY_PY_SYS_GETSIZEOF (1) -#define MICROPY_PY_SYS_TRACEBACKLIMIT (1) -#define MICROPY_PY_MATH_FACTORIAL (1) -#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) -#define MICROPY_PY_IO_BUFFEREDWRITER (1) -#define MICROPY_PY_UASYNCIO (1) -#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (mp_urandom_seed_init()) -#define MICROPY_PY_URE_DEBUG (1) -#define MICROPY_PY_URE_MATCH_GROUPS (1) -#define MICROPY_PY_URE_MATCH_SPAN_START_END (1) -#define MICROPY_PY_URE_SUB (1) -#define MICROPY_VFS_POSIX (1) -#define MICROPY_FATFS_USE_LABEL (1) -#define MICROPY_FF_MKFS_FAT32 (1) -#define MICROPY_PY_FRAMEBUF (1) -#define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (1) -#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) + +// Disable things never used in circuitpython +#define MICROPY_PY_UCRYPTOLIB (0) +#define MICROPY_PY_UCRYPTOLIB_CTR (0) #define MICROPY_PY_STRUCT (0) // uses shared-bindings struct -#define MICROPY_PY_UCRYPTOLIB (1) -#define MICROPY_PY_UCRYPTOLIB_CTR (1) -#define MICROPY_PY_MICROPYTHON_HEAP_LOCKED (1) +#define MICROPY_GC_SPLIT_HEAP (0) diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk index 656fd77289..37b7cb46b6 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.mk +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -1,5 +1,3 @@ -PROG ?= micropython-coverage - # Disable optimisations and enable assert() on coverage builds. DEBUG ?= 1 @@ -8,18 +6,13 @@ CFLAGS += \ -Wformat -Wmissing-declarations -Wmissing-prototypes \ -Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \ -DMICROPY_UNIX_COVERAGE \ - -DMICROPY_CPYTHON_EXCEPTION_CHAIN=1 \ - -DMODULE_CEXAMPLE_ENABLED=1 -DMODULE_CPPEXAMPLE_ENABLED=1 + -DMICROPY_CPYTHON_EXCEPTION_CHAIN=1 LDFLAGS += -fprofile-arcs -ftest-coverage FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py USER_C_MODULES = $(TOP)/examples/usercmodule -MICROPY_VFS_FAT = 1 -MICROPY_VFS_LFS1 = 1 -MICROPY_VFS_LFS2 = 1 - SRC_QRIO := $(patsubst ../../%,%,$(wildcard ../../shared-bindings/qrio/*.c ../../shared-module/qrio/*.c ../../lib/quirc/lib/*.c)) SRC_C += $(SRC_QRIO) diff --git a/ports/unix/variants/dev/manifest.py b/ports/unix/variants/dev/manifest.py deleted file mode 100644 index 92a681116a..0000000000 --- a/ports/unix/variants/dev/manifest.py +++ /dev/null @@ -1,3 +0,0 @@ -include("$(PORT_DIR)/variants/manifest.py") - -include("$(MPY_DIR)/extmod/uasyncio/manifest.py") diff --git a/ports/unix/variants/dev/mpconfigvariant.h b/ports/unix/variants/dev/mpconfigvariant.h deleted file mode 100644 index 61092394cd..0000000000 --- a/ports/unix/variants/dev/mpconfigvariant.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// Set base feature level. -#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) - -// Disable some features that come enabled by default with the feature level. -#define MICROPY_PY_BUILTINS_EXECFILE (0) -#define MICROPY_PY_SYS_STDIO_BUFFER (0) -#define MICROPY_PY_USELECT (0) - -// Enable some additional features. -#define MICROPY_REPL_EMACS_WORDS_MOVE (1) -#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (1) -#define MICROPY_PY_SYS_SETTRACE (1) -#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (mp_urandom_seed_init()) diff --git a/ports/unix/variants/dev/mpconfigvariant.mk b/ports/unix/variants/dev/mpconfigvariant.mk deleted file mode 100644 index 91bd28da9b..0000000000 --- a/ports/unix/variants/dev/mpconfigvariant.mk +++ /dev/null @@ -1,10 +0,0 @@ -PROG ?= micropython-dev - -FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py - -MICROPY_ROM_TEXT_COMPRESSION = 1 -MICROPY_VFS_FAT = 1 -MICROPY_VFS_LFS1 = 1 -MICROPY_VFS_LFS2 = 1 - -MICROPY_PY_BLUETOOTH ?= 1 diff --git a/ports/unix/variants/fast/mpconfigvariant.h b/ports/unix/variants/fast/mpconfigvariant.h deleted file mode 100644 index 8a531b056a..0000000000 --- a/ports/unix/variants/fast/mpconfigvariant.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// This config file is intended to configure artificially fast uPy build for -// synthetic benchmarking, at the expense of features supported and memory -// usage. This config is not intended to be used in production. - -#define MICROPY_PY___FILE__ (0) -// 91 is a magic number proposed by @dpgeorge, which make pystone run ~ at tie -// with CPython 3.4. -#define MICROPY_MODULE_DICT_SIZE (91) diff --git a/ports/unix/variants/fast/mpconfigvariant.mk b/ports/unix/variants/fast/mpconfigvariant.mk deleted file mode 100644 index 595e575645..0000000000 --- a/ports/unix/variants/fast/mpconfigvariant.mk +++ /dev/null @@ -1,7 +0,0 @@ -# build synthetically fast interpreter for benchmarking - -COPT += -fno-crossjumping -O2 - -PROG = micropython-fast - -FROZEN_MANIFEST = diff --git a/ports/unix/variants/freedos/mpconfigvariant.mk b/ports/unix/variants/freedos/mpconfigvariant.mk deleted file mode 100644 index a30db3e0c1..0000000000 --- a/ports/unix/variants/freedos/mpconfigvariant.mk +++ /dev/null @@ -1,20 +0,0 @@ -CC = i586-pc-msdosdjgpp-gcc - -STRIP = i586-pc-msdosdjgpp-strip - -SIZE = i586-pc-msdosdjgpp-size - -CFLAGS += \ - -DMICROPY_NLR_SETJMP \ - -Dtgamma=gamma \ - -DMICROPY_EMIT_X86=0 \ - -DMICROPY_NO_ALLOCA=1 \ - -PROG = micropython-freedos - -MICROPY_PY_SOCKET = 0 -MICROPY_PY_FFI = 0 -MICROPY_PY_JNI = 0 -MICROPY_PY_BTREE = 0 -MICROPY_PY_THREAD = 0 -MICROPY_PY_USSL = 0 diff --git a/ports/unix/variants/manifest.py b/ports/unix/variants/manifest.py index 7708e598db..f8e8f250ac 100644 --- a/ports/unix/variants/manifest.py +++ b/ports/unix/variants/manifest.py @@ -1,2 +1 @@ -freeze_as_mpy("$(MPY_DIR)/tools", "upip.py") -freeze_as_mpy("$(MPY_DIR)/tools", "upip_utarfile.py", opt=3) +require("mip-cmdline") diff --git a/ports/unix/variants/minimal/mpconfigvariant.h b/ports/unix/variants/minimal/mpconfigvariant.h index 60d194b6a1..6b107e7790 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.h +++ b/ports/unix/variants/minimal/mpconfigvariant.h @@ -26,123 +26,44 @@ // options to control how MicroPython is built -// Prevent the rest of the default mpconfigport.h being used. -#define MICROPY_UNIX_MINIMAL (1) +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_MINIMUM) +// Disable native emitters. +#define MICROPY_EMIT_X86 (0) +#define MICROPY_EMIT_X64 (0) +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_ARM (0) + +// Tune the parser to use less RAM by default. #define MICROPY_ALLOC_QSTR_CHUNK_INIT (64) #define MICROPY_ALLOC_PARSE_RULE_INIT (8) #define MICROPY_ALLOC_PARSE_RULE_INC (8) #define MICROPY_ALLOC_PARSE_RESULT_INIT (8) #define MICROPY_ALLOC_PARSE_RESULT_INC (8) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (64) -#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) -#define MICROPY_ENABLE_GC (1) -#define MICROPY_GC_ALLOC_THRESHOLD (0) -#define MICROPY_ENABLE_FINALISER (0) -#define MICROPY_STACK_CHECK (0) -#define MICROPY_COMP_CONST (0) -#define MICROPY_MEM_STATS (0) -#define MICROPY_DEBUG_PRINTERS (0) -#define MICROPY_READER_POSIX (1) -#define MICROPY_READER_VFS (1) -#define MICROPY_HELPER_REPL (1) -#define MICROPY_HELPER_LEXER_UNIX (1) -#define MICROPY_ENABLE_SOURCE_LINE (0) -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) -#define MICROPY_WARNINGS (0) -#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) -#define MICROPY_KBD_EXCEPTION (1) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) -#define MICROPY_STREAMS_NON_BLOCK (0) -#define MICROPY_OPT_COMPUTED_GOTO (0) -#define MICROPY_OPT_LOAD_ATTR_FAST_PATH (0) -#define MICROPY_OPT_MAP_LOOKUP_CACHE (0) -#define MICROPY_CAN_OVERRIDE_BUILTINS (0) -#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) -#define MICROPY_VFS (1) -#define MICROPY_VFS_POSIX (1) -#define MICROPY_CPYTHON_COMPAT (0) -#define MICROPY_PY_BUILTINS_BYTEARRAY (0) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (0) -#define MICROPY_PY_BUILTINS_COMPILE (0) -#define MICROPY_PY_BUILTINS_ENUMERATE (0) -#define MICROPY_PY_BUILTINS_FILTER (0) -#define MICROPY_PY_BUILTINS_FROZENSET (0) -#define MICROPY_PY_BUILTINS_REVERSED (0) -#define MICROPY_PY_BUILTINS_SET (0) -#define MICROPY_PY_BUILTINS_SLICE (0) -#define MICROPY_PY_BUILTINS_STR_COUNT (0) -#define MICROPY_PY_BUILTINS_STR_OP_MODULO (0) -#define MICROPY_PY_BUILTINS_STR_UNICODE (0) -#define MICROPY_PY_BUILTINS_PROPERTY (0) -#define MICROPY_PY_BUILTINS_MIN_MAX (0) -#define MICROPY_PY___FILE__ (0) -#define MICROPY_PY_MICROPYTHON_MEM_INFO (0) -#define MICROPY_PY_GC (0) -#define MICROPY_PY_GC_COLLECT_RETVAL (0) -#define MICROPY_PY_ARRAY (0) -#define MICROPY_PY_COLLECTIONS (0) -#define MICROPY_PY_MATH (0) -#define MICROPY_PY_CMATH (0) -#define MICROPY_PY_IO (0) -#define MICROPY_PY_IO_FILEIO (0) -#define MICROPY_PY_STRUCT (0) -#define MICROPY_PY_SYS (1) -#define MICROPY_PY_SYS_EXIT (0) -#define MICROPY_PY_SYS_PLATFORM "linux" -#ifndef MICROPY_PY_SYS_PATH_DEFAULT -#define MICROPY_PY_SYS_PATH_DEFAULT ".frozen:~/.micropython/lib:/usr/lib/micropython" -#endif -#define MICROPY_PY_SYS_MAXSIZE (0) -#define MICROPY_PY_SYS_STDFILES (0) -#define MICROPY_PY_CMATH (0) -#define MICROPY_PY_UCTYPES (0) -#define MICROPY_PY_UTIME (0) -#define MICROPY_PY_UZLIB (0) -#define MICROPY_PY_UJSON (0) -#define MICROPY_PY_UOS (1) -#define MICROPY_PY_URE (0) -#define MICROPY_PY_UHEAPQ (0) -#define MICROPY_PY_UHASHLIB (0) -#define MICROPY_PY_UBINASCII (0) -#define MICROPY_PORT_ROOT_POINTERS \ +// Enable features that are not enabled by default with the minimum config. +#define MICROPY_COMP_CONST_FOLDING (1) +#define MICROPY_COMP_CONST_LITERAL (1) +#define MICROPY_COMP_CONST_TUPLE (1) +#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) +#define MICROPY_ENABLE_COMPILER (1) +#define MICROPY_ENABLE_EXTERNAL_IMPORT (1) +#define MICROPY_FULL_CHECKS (1) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_KBD_EXCEPTION (1) +#define MICROPY_MODULE_GETATTR (1) +#define MICROPY_MULTIPLE_INHERITANCE (1) +#define MICROPY_PY_ASSIGN_EXPR (1) +#define MICROPY_PY_ASYNC_AWAIT (1) +#define MICROPY_PY_ATTRTUPLE (1) +#define MICROPY_PY_BUILTINS_DICT_FROMKEYS (1) +#define MICROPY_PY_BUILTINS_RANGE_ATTRS (1) +#define MICROPY_PY_GENERATOR_PEND_THROW (1) -#define mp_type_fileio mp_type_vfs_posix_fileio -#define mp_type_textio mp_type_vfs_posix_textio +// Enable just the sys and os built-in modules. +#define MICROPY_PY_SYS (1) +#define MICROPY_PY_UOS (1) -////////////////////////////////////////// -// Do not change anything beyond this line -////////////////////////////////////////// - -#if !(defined(MICROPY_GCREGS_SETJMP) || defined(__x86_64__) || defined(__i386__) || defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) -// Fall back to setjmp() implementation for discovery of GC pointers in registers. -#define MICROPY_GCREGS_SETJMP (1) -#endif - -// type definitions for the specific machine - -#ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size -#else -// These are definitions for machines where sizeof(int) == sizeof(void*), -// regardless for actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -#endif - -// Cannot include , as it may lead to symbol name clashes -#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) -typedef long long mp_off_t; -#else -typedef long mp_off_t; -#endif - -// We need to provide a declaration/definition of alloca() -#ifdef __FreeBSD__ -#include -#else -#include -#endif +// The minimum sets this to 1 to save flash. +#define MICROPY_QSTR_BYTES_IN_HASH (2) diff --git a/ports/unix/variants/minimal/mpconfigvariant.mk b/ports/unix/variants/minimal/mpconfigvariant.mk index ec3b21c0b9..d5c2a52e9a 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.mk +++ b/ports/unix/variants/minimal/mpconfigvariant.mk @@ -1,9 +1,7 @@ # build a minimal interpreter -PROG = micropython-minimal FROZEN_MANIFEST = -MICROPY_ROM_TEXT_COMPRESSION = 1 MICROPY_PY_BTREE = 0 MICROPY_PY_FFI = 0 MICROPY_PY_SOCKET = 0 @@ -11,3 +9,7 @@ MICROPY_PY_THREAD = 0 MICROPY_PY_TERMIOS = 0 MICROPY_PY_USSL = 0 MICROPY_USE_READLINE = 0 + +MICROPY_VFS_FAT = 0 +MICROPY_VFS_LFS1 = 0 +MICROPY_VFS_LFS2 = 0 diff --git a/ports/unix/variants/mpconfigvariant_common.h b/ports/unix/variants/mpconfigvariant_common.h new file mode 100644 index 0000000000..de3411087c --- /dev/null +++ b/ports/unix/variants/mpconfigvariant_common.h @@ -0,0 +1,124 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Jim Mussared + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// This file enables and configures features common to all variants +// other than "minimal". + +// Send raise KeyboardInterrupt directly from the signal handler rather than +// scheduling it into the VM. +#define MICROPY_ASYNC_KBD_INTR (1) + +// Enable helpers for printing debugging information. +#ifndef MICROPY_DEBUG_PRINTERS +#define MICROPY_DEBUG_PRINTERS (1) +#endif + +// Enable floating point by default. +#ifndef MICROPY_FLOAT_IMPL +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) +#endif + +// Enable arbitrary precision long-int by default. +#ifndef MICROPY_LONGINT_IMPL +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#endif + +// Enable use of C libraries that need read/write/lseek/fsync, e.g. axtls. +#define MICROPY_STREAMS_POSIX_API (1) + +// REPL conveniences. +#define MICROPY_REPL_EMACS_WORDS_MOVE (1) +#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (1) +#define MICROPY_USE_READLINE_HISTORY (1) +#ifndef MICROPY_READLINE_HISTORY_SIZE +#define MICROPY_READLINE_HISTORY_SIZE (50) +#endif + +// Seed random on import. +#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (mp_urandom_seed_init()) + +// Allow exception details in low-memory conditions. +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) +#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) + +// Allow loading of .mpy files. +#define MICROPY_PERSISTENT_CODE_LOAD (1) + +// Extra memory debugging. +#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) +#define MICROPY_MEM_STATS (1) + +// Enable a small performance boost for the VM. +#define MICROPY_OPT_COMPUTED_GOTO (1) + +// Return number of collected objects from gc.collect(). +#define MICROPY_PY_GC_COLLECT_RETVAL (1) + +// Enable detailed error messages and warnings. +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) +#define MICROPY_WARNINGS (1) +#define MICROPY_PY_STR_BYTES_CMP_WARN (1) + +// Configure the "sys" module with features not usually enabled on bare-metal. +#define MICROPY_PY_SYS_ATEXIT (1) +#define MICROPY_PY_SYS_EXC_INFO (1) + +// Configure the "os" module with extra unix features. +#define MICROPY_PY_UOS_INCLUDEFILE "ports/unix/moduos.c" +#define MICROPY_PY_UOS_ERRNO (1) +#define MICROPY_PY_UOS_GETENV_PUTENV_UNSETENV (1) +#define MICROPY_PY_UOS_SEP (1) +#define MICROPY_PY_UOS_SYSTEM (1) +#define MICROPY_PY_UOS_URANDOM (1) + +// Enable the unix-specific "time" module. +#define MICROPY_PY_UTIME (1) +#define MICROPY_PY_UTIME_MP_HAL (1) + +// Enable the utimeq module used by the previous (v2) version of uasyncio. +#define MICROPY_PY_UTIMEQ (1) + +#if MICROPY_PY_USSL +#define MICROPY_PY_UHASHLIB_MD5 (1) +#define MICROPY_PY_UHASHLIB_SHA1 (1) +#define MICROPY_PY_UCRYPTOLIB (1) +#endif + +// Use the posix implementation of the "select" module (unless the variant +// specifically asks for the MicroPython version). +#ifndef MICROPY_PY_USELECT +#define MICROPY_PY_USELECT (0) +#endif +#ifndef MICROPY_PY_USELECT_POSIX +#define MICROPY_PY_USELECT_POSIX (!MICROPY_PY_USELECT) +#endif + +// Enable the "websocket" module. +#define MICROPY_PY_UWEBSOCKET (1) + +// Enable the "machine" module, mostly for machine.mem*. +#define MICROPY_PY_MACHINE (1) +#define MICROPY_PY_MACHINE_PULSE (1) diff --git a/ports/unix/variants/nanbox/mpconfigvariant.h b/ports/unix/variants/nanbox/mpconfigvariant.h index f827158fb7..7b13b7dc6c 100644 --- a/ports/unix/variants/nanbox/mpconfigvariant.h +++ b/ports/unix/variants/nanbox/mpconfigvariant.h @@ -28,6 +28,11 @@ // continues to build (i.e. catches usage of mp_obj_t that don't work with // this representation). +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) + +// Enable extra Unix features. +#include "../mpconfigvariant_common.h" + // select nan-boxing object model #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_D) diff --git a/ports/unix/variants/nanbox/mpconfigvariant.mk b/ports/unix/variants/nanbox/mpconfigvariant.mk index 9752b922c1..e588e657ef 100644 --- a/ports/unix/variants/nanbox/mpconfigvariant.mk +++ b/ports/unix/variants/nanbox/mpconfigvariant.mk @@ -1,4 +1,3 @@ # build interpreter with nan-boxing as object model (object repr D) -PROG = micropython-nanbox MICROPY_FORCE_32BIT = 1 diff --git a/ports/unix/variants/standard/manifest.py b/ports/unix/variants/standard/manifest.py new file mode 100644 index 0000000000..08295fc678 --- /dev/null +++ b/ports/unix/variants/standard/manifest.py @@ -0,0 +1 @@ +include("$(PORT_DIR)/variants/manifest.py") diff --git a/ports/unix/variants/standard/mpconfigvariant.h b/ports/unix/variants/standard/mpconfigvariant.h index 1ec46ef92d..75201e9abc 100644 --- a/ports/unix/variants/standard/mpconfigvariant.h +++ b/ports/unix/variants/standard/mpconfigvariant.h @@ -27,19 +27,5 @@ // Set base feature level. #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) -// Disable some features that come enabled by default with the feature level. -#define MICROPY_OPT_MPZ_BITWISE (0) -#define MICROPY_OPT_MATH_FACTORIAL (0) -#define MICROPY_MODULE_ATTR_DELEGATION (0) -#define MICROPY_MODULE_BUILTIN_INIT (0) -#define MICROPY_ENABLE_SCHEDULER (0) -#define MICROPY_PY_BUILTINS_EXECFILE (0) -#define MICROPY_PY_MATH_CONSTANTS (0) -#define MICROPY_PY_MATH_FACTORIAL (0) -#define MICROPY_PY_SYS_PS1_PS2 (0) -#define MICROPY_PY_SYS_STDIO_BUFFER (0) -#define MICROPY_PY_USELECT (0) -#define MICROPY_PY_UASYNCIO (0) -#define MICROPY_PY_URE_SUB (0) -#define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) -#define MICROPY_PY_FRAMEBUF (0) +// Enable extra Unix features. +#include "../mpconfigvariant_common.h" diff --git a/ports/unix/variants/standard/mpconfigvariant.mk b/ports/unix/variants/standard/mpconfigvariant.mk index cf3efab8ae..c91db1aa10 100644 --- a/ports/unix/variants/standard/mpconfigvariant.mk +++ b/ports/unix/variants/standard/mpconfigvariant.mk @@ -1,3 +1,3 @@ # This is the default variant when you `make` the Unix port. -PROG ?= micropython +FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py diff --git a/py/argcheck.c b/py/argcheck.c index 76c84e83b0..8c34a681fe 100644 --- a/py/argcheck.c +++ b/py/argcheck.c @@ -29,8 +29,6 @@ #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - void PLACE_IN_ITCM(mp_arg_check_num_sig)(size_t n_args, size_t n_kw, uint32_t sig) { // TODO maybe take the function name as an argument so we can print nicer error messages @@ -174,7 +172,7 @@ NORETURN void mp_arg_error_terse_mismatch(void) { #if MICROPY_CPYTHON_COMPAT NORETURN void mp_arg_error_unimpl_kw(void) { - mp_raise_NotImplementedError(MP_ERROR_TEXT("keyword argument(s) not yet implemented - use normal args instead")); + mp_raise_NotImplementedError(MP_ERROR_TEXT("keyword argument(s) not implemented - use normal args instead")); } #endif diff --git a/py/asmbase.c b/py/asmbase.c index 4a3fd089cb..cf64e3f3d0 100644 --- a/py/asmbase.c +++ b/py/asmbase.c @@ -55,15 +55,20 @@ void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) { assert(as->code_base != NULL); } as->pass = pass; + as->suppress = false; as->code_offset = 0; } // all functions must go through this one to emit bytes // if as->pass < MP_ASM_PASS_EMIT, then this function just counts the number // of bytes needed and returns NULL, and callers should not store any data +// It also returns NULL if generated code should be suppressed at this point. uint8_t *mp_asm_base_get_cur_to_write_bytes(void *as_in, size_t num_bytes_to_write) { mp_asm_base_t *as = as_in; uint8_t *c = NULL; + if (as->suppress) { + return c; + } if (as->pass == MP_ASM_PASS_EMIT) { assert(as->code_offset + num_bytes_to_write <= as->code_size); c = as->code_base + as->code_offset; @@ -74,6 +79,11 @@ uint8_t *mp_asm_base_get_cur_to_write_bytes(void *as_in, size_t num_bytes_to_wri void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) { assert(label < as->max_num_labels); + + // Assigning a label ends any dead-code region, and all following machine + // code should be emitted (until another mp_asm_base_suppress_code() call). + as->suppress = false; + if (as->pass < MP_ASM_PASS_EMIT) { // assign label offset assert(as->label_offsets[label] == (size_t)-1); diff --git a/py/asmbase.h b/py/asmbase.h index 960be7685f..352d2f54cc 100644 --- a/py/asmbase.h +++ b/py/asmbase.h @@ -33,7 +33,12 @@ #define MP_ASM_PASS_EMIT (2) typedef struct _mp_asm_base_t { - int pass; + uint8_t pass; + + // Set to true using mp_asm_base_suppress_code() if the code generator + // should suppress emitted code due to it being dead code. + bool suppress; + size_t code_offset; size_t code_size; uint8_t *code_base; @@ -50,6 +55,10 @@ void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label); void mp_asm_base_align(mp_asm_base_t *as, unsigned int align); void mp_asm_base_data(mp_asm_base_t *as, unsigned int bytesize, uintptr_t val); +static inline void mp_asm_base_suppress_code(mp_asm_base_t *as) { + as->suppress = true; +} + static inline size_t mp_asm_base_get_code_pos(mp_asm_base_t *as) { return as->code_offset; } diff --git a/py/bc.c b/py/bc.c index ecd2f60879..0dc7229a2c 100644 --- a/py/bc.c +++ b/py/bc.c @@ -213,6 +213,7 @@ STATIC void mp_setup_code_state_helper(mp_code_state_t *code_state, size_t n_arg #endif if (wanted_arg_name == MP_OBJ_NEW_QSTR(arg_qstr)) { if (code_state_state[n_state - 1 - j] != MP_OBJ_NULL) { + error_multiple: mp_raise_msg_varg(&mp_type_TypeError, MP_ERROR_TEXT("function got multiple values for argument '%q'"), MP_OBJ_QSTR_VALUE(wanted_arg_name)); } @@ -229,7 +230,12 @@ STATIC void mp_setup_code_state_helper(mp_code_state_t *code_state, size_t n_arg MP_ERROR_TEXT("unexpected keyword argument '%q'"), MP_OBJ_QSTR_VALUE(wanted_arg_name)); #endif } - mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]); + mp_map_elem_t *elem = mp_map_lookup(mp_obj_dict_get_map(dict), wanted_arg_name, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); + if (elem->value == MP_OBJ_NULL) { + elem->value = kwargs[2 * i + 1]; + } else { + goto error_multiple; + } continue2:; } diff --git a/py/bc.h b/py/bc.h index d620be8e82..b732028dbf 100644 --- a/py/bc.h +++ b/py/bc.h @@ -219,7 +219,7 @@ typedef struct _mp_module_context_t { // Outer level struct defining a compiled module. typedef struct _mp_compiled_module_t { - const mp_module_context_t *context; + mp_module_context_t *context; const struct _mp_raw_code_t *rc; #if MICROPY_PERSISTENT_CODE_SAVE bool has_native; diff --git a/py/binary.c b/py/binary.c index 60a74d6162..6d2075f3b4 100644 --- a/py/binary.c +++ b/py/binary.c @@ -36,8 +36,6 @@ #include "py/objint.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - // Helpers to work with binary-encoded data #ifndef alignof @@ -217,7 +215,7 @@ long long mp_binary_get_int(size_t size, bool is_signed, bool big_endian, const val = -1; } for (uint i = 0; i < size; i++) { - // CIRCUITPY fix + // CIRCUITPY fix for undefined behavior on left shift val *= 256; val |= *src; src += delta; @@ -254,13 +252,15 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte * #endif #if MICROPY_PY_BUILTINS_FLOAT } else if (val_type == 'f') { - union { uint32_t i; - float f; + union { + uint32_t i; + float f; } fpu = {val}; return mp_obj_new_float_from_f(fpu.f); } else if (val_type == 'd') { - union { uint64_t i; - double f; + union { + uint64_t i; + double f; } fpu = {val}; return mp_obj_new_float_from_d(fpu.f); #endif @@ -323,17 +323,19 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p #endif #if MICROPY_PY_BUILTINS_FLOAT case 'f': { - union { uint32_t i; - float f; + union { + uint32_t i; + float f; } fp_sp; fp_sp.f = mp_obj_get_float_to_f(val_in); val = fp_sp.i; break; } case 'd': { - union { uint64_t i64; - uint32_t i32[2]; - double f; + union { + uint64_t i64; + uint32_t i32[2]; + double f; } fp_dp; fp_dp.f = mp_obj_get_float_to_d(val_in); if (MP_BYTES_PER_OBJ_WORD == 8) { @@ -350,7 +352,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p default: { bool signed_type = is_signed(val_type); #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE - if (mp_obj_is_type(val_in, &mp_type_int)) { + if (mp_obj_is_exact_type(val_in, &mp_type_int)) { // It's a longint. mp_obj_int_buffer_overflow_check(val_in, size, signed_type); mp_obj_int_to_bytes_impl(val_in, struct_type == '>', size, p); @@ -398,7 +400,7 @@ void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_ bool signed_type = is_signed(typecode); #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE - if (mp_obj_is_type(val_in, &mp_type_int)) { + if (mp_obj_is_exact_type(val_in, &mp_type_int)) { // It's a long int. mp_obj_int_buffer_overflow_check(val_in, size, signed_type); mp_obj_int_to_bytes_impl(val_in, MP_ENDIANNESS_BIG, diff --git a/py/builtin.h b/py/builtin.h index ab228278a7..7232142b77 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -64,7 +64,13 @@ MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj); #endif +// A port can provide its own import handler by defining mp_builtin___import__. +#ifndef mp_builtin___import__ +#define mp_builtin___import__ mp_builtin___import___default +#endif mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args); +mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args); + mp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj); @@ -120,40 +126,16 @@ MP_DECLARE_CONST_FUN_OBJ_2(mp_op_getitem_obj); MP_DECLARE_CONST_FUN_OBJ_3(mp_op_setitem_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_op_delitem_obj); +// Modules needed by the runtime. +extern const mp_obj_dict_t mp_module_builtins_globals; extern const mp_obj_module_t mp_module___main__; extern const mp_obj_module_t mp_module_builtins; -extern const mp_obj_module_t mp_module_array; -extern const mp_obj_module_t mp_module_collections; -extern const mp_obj_module_t mp_module_io; -extern const mp_obj_module_t mp_module_math; -extern const mp_obj_module_t mp_module_cmath; -extern const mp_obj_module_t mp_module_micropython; -extern const mp_obj_module_t mp_module_ustruct; extern const mp_obj_module_t mp_module_sys; -extern const mp_obj_module_t mp_module_gc; -extern const mp_obj_module_t mp_module_thread; -extern const mp_obj_dict_t mp_module_builtins_globals; - -// extmod modules -extern const mp_obj_module_t mp_module_uasyncio; +// Modules needed by the parser when MICROPY_COMP_MODULE_CONST is enabled. extern const mp_obj_module_t mp_module_uerrno; extern const mp_obj_module_t mp_module_uctypes; -extern const mp_obj_module_t mp_module_uzlib; -extern const mp_obj_module_t mp_module_ujson; -extern const mp_obj_module_t mp_module_ure; -extern const mp_obj_module_t mp_module_uheapq; -extern const mp_obj_module_t mp_module_uhashlib; -extern const mp_obj_module_t mp_module_ucryptolib; -extern const mp_obj_module_t mp_module_ubinascii; -extern const mp_obj_module_t mp_module_urandom; -extern const mp_obj_module_t mp_module_uselect; -extern const mp_obj_module_t mp_module_utimeq; extern const mp_obj_module_t mp_module_machine; -extern const mp_obj_module_t mp_module_framebuf; -extern const mp_obj_module_t mp_module_btree; -extern const mp_obj_module_t mp_module_ubluetooth; -extern const mp_obj_module_t mp_module_uplatform; extern const char MICROPY_PY_BUILTINS_HELP_TEXT[]; diff --git a/py/builtinevex.c b/py/builtinevex.c index b6b27c2a67..173978ef52 100644 --- a/py/builtinevex.c +++ b/py/builtinevex.c @@ -31,8 +31,6 @@ #include "py/runtime.h" #include "py/builtin.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_COMPILE typedef struct _mp_obj_code_t { @@ -40,10 +38,11 @@ typedef struct _mp_obj_code_t { mp_obj_t module_fun; } mp_obj_code_t; -STATIC const mp_obj_type_t mp_type_code = { - { &mp_type_type }, - .name = MP_QSTR_code, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_code, + MP_QSTR_code, + MP_TYPE_FLAG_NONE + ); STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj_dict_t *locals) { // save context and set new context diff --git a/py/builtinhelp.c b/py/builtinhelp.c index c26a1a5490..fc922935ed 100644 --- a/py/builtinhelp.c +++ b/py/builtinhelp.c @@ -32,8 +32,6 @@ #include "py/mpconfig.h" #include "py/objmodule.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_HELP const char mp_help_default_text[] = @@ -153,14 +151,20 @@ STATIC void mp_help_print_obj(const mp_obj_t obj) { if (type == &mp_type_type) { type = MP_OBJ_TO_PTR(obj); } - if (type->locals_dict != NULL) { - map = &type->locals_dict->map; + if (MP_OBJ_TYPE_HAS_SLOT(type, locals_dict)) { + map = &MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->map; } } if (map != NULL) { for (uint i = 0; i < map->alloc; i++) { - if (map->table[i].key != MP_OBJ_NULL) { - mp_help_print_info_about_object(map->table[i].key, map->table[i].value); + mp_obj_t key = map->table[i].key; + if (key != MP_OBJ_NULL + #if MICROPY_MODULE_ATTR_DELEGATION + // MP_MODULE_ATTR_DELEGATION_ENTRY entries have MP_QSTRnull as qstr key. + && key != MP_OBJ_NEW_QSTR(MP_QSTRnull) + #endif + ) { + mp_help_print_info_about_object(key, map->table[i].value); } } } diff --git a/py/builtinimport.c b/py/builtinimport.c index bf47b2567e..a57841cd8c 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -38,8 +38,6 @@ #include "py/builtin.h" #include "py/frozenmod.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf @@ -48,6 +46,15 @@ #define DEBUG_printf(...) (void)0 #endif +#if MICROPY_MODULE_WEAK_LINKS +STATIC qstr make_weak_link_name(vstr_t *buffer, qstr name) { + vstr_reset(buffer); + vstr_add_char(buffer, 'u'); + vstr_add_str(buffer, qstr_str(name)); + return qstr_from_strn(buffer->buf, buffer->len); +} +#endif + #if MICROPY_ENABLE_EXTERNAL_IMPORT // Must be a string of one byte. @@ -162,7 +169,7 @@ STATIC void do_load_from_lexer(mp_module_context_t *context, mp_lexer_t *lex) { #endif #if (MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD) || MICROPY_MODULE_FROZEN_MPY -STATIC void do_execute_raw_code(mp_module_context_t *context, const mp_raw_code_t *rc, const mp_module_context_t *mc, const char *source_name) { +STATIC void do_execute_raw_code(const mp_module_context_t *context, const mp_raw_code_t *rc, const char *source_name) { (void)source_name; #if MICROPY_PY___FILE__ @@ -182,7 +189,7 @@ STATIC void do_execute_raw_code(mp_module_context_t *context, const mp_raw_code_ nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - mp_obj_t module_fun = mp_make_function_from_raw_code(rc, mc, NULL); + mp_obj_t module_fun = mp_make_function_from_raw_code(rc, context, NULL); mp_call_function_0(module_fun); // finish nlr block, restore context @@ -227,7 +234,7 @@ STATIC void do_load(mp_module_context_t *module_obj, vstr_t *file) { if (frozen_type == MP_FROZEN_MPY) { const mp_frozen_module_t *frozen = modref; module_obj->constants = frozen->constants; - do_execute_raw_code(module_obj, frozen->rc, module_obj, file_str + frozen_path_prefix_len); + do_execute_raw_code(module_obj, frozen->rc, file_str + frozen_path_prefix_len); return; } #endif @@ -239,8 +246,10 @@ STATIC void do_load(mp_module_context_t *module_obj, vstr_t *file) { // the correct format and, if so, load and execute the file. #if MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD if (file_str[file->len - 3] == 'm') { - mp_compiled_module_t cm = mp_raw_code_load_file(file_str, module_obj); - do_execute_raw_code(module_obj, cm.rc, cm.context, file_str); + mp_compiled_module_t cm; + cm.context = module_obj; + mp_raw_code_load_file(file_str, &cm); + do_execute_raw_code(cm.context, cm.rc, file_str); return; } #endif @@ -370,10 +379,7 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, // formerly known as "weak links"). #if MICROPY_MODULE_WEAK_LINKS if (stat == MP_IMPORT_STAT_NO_EXIST && module_obj == MP_OBJ_NULL) { - char *umodule_buf = vstr_str(path); - umodule_buf[0] = 'u'; - strcpy(umodule_buf + 1, qstr_str(level_mod_name)); - qstr umodule_name = qstr_from_str(umodule_buf); + qstr umodule_name = make_weak_link_name(path, level_mod_name); module_obj = mp_module_get_builtin(umodule_name); } #elif MICROPY_PY_SYS @@ -475,7 +481,7 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, return module_obj; } -mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { +mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) { #if DEBUG_PRINT DEBUG_printf("__import__:\n"); for (size_t i = 0; i < n_args; i++) { @@ -574,7 +580,11 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { #else // MICROPY_ENABLE_EXTERNAL_IMPORT -mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { +bool mp_obj_is_package(mp_obj_t module) { + return false; +} + +mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) { // Check that it's not a relative import if (n_args >= 5 && MP_OBJ_SMALL_INT_VALUE(args[4]) != 0) { mp_raise_NotImplementedError(MP_ERROR_TEXT("relative import")); @@ -589,10 +599,8 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { #if MICROPY_MODULE_WEAK_LINKS // Check if there is a weak link to this module - char umodule_buf[MICROPY_ALLOC_PATH_MAX]; - umodule_buf[0] = 'u'; - strcpy(umodule_buf + 1, args[0]); - qstr umodule_name_qstr = qstr_from_str(umodule_buf); + VSTR_FIXED(umodule_path, MICROPY_ALLOC_PATH_MAX); + qstr umodule_name_qstr = make_weak_link_name(&umodule_path, module_name_qstr); module_obj = mp_module_get_loaded_or_builtin(umodule_name_qstr); if (module_obj != MP_OBJ_NULL) { return module_obj; diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 3974e27df4..5b87291485 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -794,6 +794,7 @@ endif $(patsubst %.c,$(BUILD)/%.o,$(SRC_LIBM)): CFLAGS += -Wno-missing-prototypes endif +# Sources used in all ports except unix. SRC_CIRCUITPY_COMMON = \ shared/libc/string0.c \ shared/readline/readline.c \ @@ -843,3 +844,8 @@ invalid-board: echo "Valid boards:" && \ printf '%s\n' $(ALL_BOARDS_IN_PORT) | column -xc $$(tput cols || echo 80) 1>&2 && \ false + +# Print out the value of a make variable. +# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile +print-%: + @echo $* = $($*) diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index ab72eddd40..e066a1cabe 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -108,6 +108,7 @@ extern void common_hal_mcu_enable_interrupts(void); #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_ATTRTUPLE (1) #define MICROPY_PY_BUILTINS_BYTEARRAY (1) +#define MICROPY_PY_BUILTINS_BYTES_HEX (1) #define MICROPY_PY_BUILTINS_ENUMERATE (1) #define MICROPY_PY_BUILTINS_FILTER (1) #define MICROPY_PY_BUILTINS_HELP (1) @@ -127,7 +128,6 @@ extern void common_hal_mcu_enable_interrupts(void); #define MICROPY_PY_CMATH (0) #define MICROPY_PY_COLLECTIONS (CIRCUITPY_COLLECTIONS) #define MICROPY_PY_DESCRIPTORS (1) -#define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_GC (1) // Supplanted by shared-bindings/math #define MICROPY_PY_IO (CIRCUITPY_IO) @@ -263,8 +263,8 @@ typedef long mp_off_t; #define MICROPY_FATFS_EXFAT (CIRCUITPY_FULL_BUILD) #endif -#ifndef MICROPY_FF_MKFS_FAT32 -#define MICROPY_FF_MKFS_FAT32 (CIRCUITPY_FULL_BUILD) +#ifndef MICROPY_FATFS_MKFS_FAT32 +#define MICROPY_FATFS_MKFS_FAT32 (CIRCUITPY_FULL_BUILD) #endif // LONGINT_IMPL_xxx are defined in the Makefile. @@ -315,15 +315,12 @@ typedef long mp_off_t; #if defined(DEFAULT_UART_BUS_TX) && defined(DEFAULT_UART_BUS_RX) #define CIRCUITPY_BOARD_UART (1) #define CIRCUITPY_BOARD_UART_PIN {{.tx = DEFAULT_UART_BUS_TX, .rx = DEFAULT_UART_BUS_RX}} -#define BOARD_UART_ROOT_POINTER mp_obj_t board_uart_bus; #else #define CIRCUITPY_BOARD_UART (0) -#define BOARD_UART_ROOT_POINTER #endif -#else -#define BOARD_UART_ROOT_POINTER mp_obj_t board_uart_bus; #endif + #if MICROPY_PY_ASYNC_AWAIT && !CIRCUITPY_TRACEBACK #error CIRCUITPY_ASYNCIO requires CIRCUITPY_TRACEBACK #endif @@ -358,19 +355,6 @@ typedef long mp_off_t; #define CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE (0) #endif -#if CIRCUITPY_KEYPAD -#define KEYPAD_ROOT_POINTERS mp_obj_t keypad_scanners_linked_list; -#else -#define KEYPAD_ROOT_POINTERS -#endif - -#if CIRCUITPY_MEMORYMONITOR -#define MEMORYMONITOR_ROOT_POINTERS mp_obj_t active_allocationsizes; \ - mp_obj_t active_allocationalarms; -#else -#define MEMORYMONITOR_ROOT_POINTERS -#endif - // This is not a top-level module; it's microcontroller.nvm. #if CIRCUITPY_NVM extern const struct _mp_obj_module_t nvm_module; @@ -387,12 +371,6 @@ extern const struct _mp_obj_module_t nvm_module; #endif #endif -#if CIRCUITPY_WIFI -#define WIFI_MONITOR_ROOT_POINTERS mp_obj_t wifi_monitor_singleton; -#else -#define WIFI_MONITOR_ROOT_POINTERS -#endif - // Define certain native modules with weak links so they can be replaced with Python // implementations. This list may grow over time. @@ -430,23 +408,9 @@ extern const struct _mp_obj_module_t nvm_module; #define MP_STATE_PORT MP_STATE_VM -#include "supervisor/flash_root_pointers.h" - // From supervisor/memory.c struct _supervisor_allocation_node; -#define CIRCUITPY_COMMON_ROOT_POINTERS \ - FLASH_ROOT_POINTERS \ - KEYPAD_ROOT_POINTERS \ - BOARD_UART_ROOT_POINTER \ - WIFI_MONITOR_ROOT_POINTERS \ - MEMORYMONITOR_ROOT_POINTERS \ - vstr_t *repl_line; \ - mp_obj_t pew_singleton; \ - mp_obj_t rtc_time_source; \ - const char *readline_hist[8]; \ - struct _supervisor_allocation_node *first_embedded_allocation; \ - void background_callback_run_all(void); #define RUN_BACKGROUND_TASKS (background_callback_run_all()) diff --git a/py/compile.c b/py/compile.c index 82ab354eb4..b1addc76fc 100644 --- a/py/compile.c +++ b/py/compile.c @@ -39,8 +39,6 @@ #include "py/persistentcode.h" #include "py/smallint.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_ENABLE_COMPILER // TODO need to mangle __attr names @@ -1288,6 +1286,14 @@ STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_in } } +STATIC void compile_declare_global_or_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info, bool is_global) { + if (is_global) { + compile_declare_global(comp, pn, id_info); + } else { + compile_declare_nonlocal(comp, pn, id_info); + } +} + STATIC void compile_global_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->pass == MP_PASS_SCOPE) { bool is_global = MP_PARSE_NODE_STRUCT_KIND(pns) == PN_global_stmt; @@ -1302,11 +1308,7 @@ STATIC void compile_global_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_ for (size_t i = 0; i < n; i++) { qstr qst = MP_PARSE_NODE_LEAF_ARG(nodes[i]); id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, ID_INFO_KIND_UNDECIDED); - if (is_global) { - compile_declare_global(comp, (mp_parse_node_t)pns, id_info); - } else { - compile_declare_nonlocal(comp, (mp_parse_node_t)pns, id_info); - } + compile_declare_global_or_nonlocal(comp, (mp_parse_node_t)pns, id_info, is_global); } } } @@ -1344,12 +1346,8 @@ STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { goto done; } - if ( - // optimisation: don't jump over non-existent elif/else blocks - !(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3])) - // optimisation: don't jump if last instruction was return - && !EMIT(last_emit_was_return_value) - ) { + // optimisation: don't jump over non-existent elif/else blocks + if (!(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3]))) { // jump over elif/else blocks EMIT_ARG(jump, l_end); } @@ -1376,10 +1374,7 @@ STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { goto done; } - // optimisation: don't jump if last instruction was return - if (!EMIT(last_emit_was_return_value)) { - EMIT_ARG(jump, l_end); - } + EMIT_ARG(jump, l_end); EMIT_ARG(label_assign, l_fail); } } @@ -1594,9 +1589,7 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT_ARG(for_iter, pop_label); c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable compile_node(comp, pns->nodes[2]); // body - if (!EMIT(last_emit_was_return_value)) { - EMIT_ARG(jump, continue_label); - } + EMIT_ARG(jump, continue_label); EMIT_ARG(label_assign, pop_label); EMIT(for_iter_end); @@ -2155,13 +2148,30 @@ STATIC void compile_namedexpr_helper(compiler_t *comp, mp_parse_node_t pn_name, } compile_node(comp, pn_expr); EMIT(dup_top); - scope_t *old_scope = comp->scope_cur; - if (SCOPE_IS_COMP_LIKE(comp->scope_cur->kind)) { - // Use parent's scope for assigned value so it can "escape" - comp->scope_cur = comp->scope_cur->parent; + + qstr target = MP_PARSE_NODE_LEAF_ARG(pn_name); + + // When a variable is assigned via := in a comprehension then that variable is bound to + // the parent scope. Any global or nonlocal declarations in the parent scope are honoured. + // For details see: https://peps.python.org/pep-0572/#scope-of-the-target + if (comp->pass == MP_PASS_SCOPE && SCOPE_IS_COMP_LIKE(comp->scope_cur->kind)) { + id_info_t *id_info_parent = mp_emit_common_get_id_for_modification(comp->scope_cur->parent, target); + if (id_info_parent->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) { + scope_find_or_add_id(comp->scope_cur, target, ID_INFO_KIND_GLOBAL_EXPLICIT); + } else { + id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, target, ID_INFO_KIND_UNDECIDED); + bool is_global = comp->scope_cur->parent->parent == NULL; // comprehension is defined in outer scope + if (!is_global && id_info->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { + // Variable was already referenced but now needs to be closed over, so reset the kind + // such that scope_check_to_close_over() is called in compile_declare_nonlocal(). + id_info->kind = ID_INFO_KIND_UNDECIDED; + } + compile_declare_global_or_nonlocal(comp, pn_name, id_info, is_global); + } } - compile_store_id(comp, MP_PARSE_NODE_LEAF_ARG(pn_name)); - comp->scope_cur = old_scope; + + // Do the store to the target variable. + compile_store_id(comp, target); } STATIC void compile_namedexpr(compiler_t *comp, mp_parse_node_struct_t *pns) { @@ -3075,11 +3085,8 @@ STATIC bool compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { } compile_node(comp, pns->nodes[3]); // 3 is function body - // emit return if it wasn't the last opcode - if (!EMIT(last_emit_was_return_value)) { - EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); - EMIT(return_value); - } + EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); + EMIT(return_value); } else if (scope->kind == SCOPE_LAMBDA) { assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn; @@ -3325,12 +3332,13 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind if (pass > MP_PASS_SCOPE) { mp_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]); for (uint j = 1; j < n_args; j++) { - if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[j])) { + mp_obj_t int_obj; + if (!mp_parse_node_get_int_maybe(pn_arg[j], &int_obj)) { compile_syntax_error(comp, nodes[i], MP_ERROR_TEXT("'data' requires integer arguments")); return; } mp_asm_base_data((mp_asm_base_t *)comp->emit_inline_asm, - bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[j])); + bytesize, mp_obj_int_get_truncated(int_obj)); } } } else { @@ -3465,7 +3473,7 @@ STATIC void scope_compute_things(scope_t *scope) { #if !MICROPY_PERSISTENT_CODE_SAVE STATIC #endif -mp_compiled_module_t mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl, mp_module_context_t *context) { +void mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl, mp_compiled_module_t *cm) { // put compiler state on the stack, it's relatively small compiler_t comp_state = {0}; compiler_t *comp = &comp_state; @@ -3606,26 +3614,24 @@ mp_compiled_module_t mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr so } // construct the global qstr/const table for this module - mp_compiled_module_t cm; - cm.rc = module_scope->raw_code; - cm.context = context; + cm->rc = module_scope->raw_code; #if MICROPY_PERSISTENT_CODE_SAVE - cm.has_native = false; + cm->has_native = false; #if MICROPY_EMIT_NATIVE if (emit_native != NULL) { - cm.has_native = true; + cm->has_native = true; } #endif #if MICROPY_EMIT_INLINE_ASM if (comp->emit_inline_asm != NULL) { - cm.has_native = true; + cm->has_native = true; } #endif - cm.n_qstr = comp->emit_common.qstr_map.used; - cm.n_obj = comp->emit_common.const_obj_list.len; + cm->n_qstr = comp->emit_common.qstr_map.used; + cm->n_obj = comp->emit_common.const_obj_list.len; #endif if (comp->compile_error == MP_OBJ_NULL) { - mp_emit_common_populate_module_context(&comp->emit_common, source_file, context); + mp_emit_common_populate_module_context(&comp->emit_common, source_file, cm->context); #if MICROPY_DEBUG_PRINTERS // now that the module context is valid, the raw codes can be printed @@ -3633,7 +3639,7 @@ mp_compiled_module_t mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr so for (scope_t *s = comp->scope_head; s != NULL; s = s->next) { mp_raw_code_t *rc = s->raw_code; if (rc->kind == MP_CODE_BYTECODE) { - mp_bytecode_print(&mp_plat_print, rc, &cm.context->constants); + mp_bytecode_print(&mp_plat_print, rc, &cm->context->constants); } } } @@ -3667,14 +3673,13 @@ mp_compiled_module_t mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr so if (comp->compile_error != MP_OBJ_NULL) { nlr_raise(comp->compile_error); } - - return cm; } mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) { - mp_module_context_t *context = m_new_obj(mp_module_context_t); - context->module.globals = mp_globals_get(); - mp_compiled_module_t cm = mp_compile_to_raw_code(parse_tree, source_file, is_repl, context); + mp_compiled_module_t cm; + cm.context = m_new_obj(mp_module_context_t); + cm.context->module.globals = mp_globals_get(); + mp_compile_to_raw_code(parse_tree, source_file, is_repl, &cm); // return function that executes the outer module return mp_make_function_from_raw_code(cm.rc, cm.context, NULL); } diff --git a/py/compile.h b/py/compile.h index ae87bf2a04..5e0fd8b31c 100644 --- a/py/compile.h +++ b/py/compile.h @@ -37,7 +37,7 @@ mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) #if MICROPY_PERSISTENT_CODE_SAVE // this has the same semantics as mp_compile -mp_compiled_module_t mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl, mp_module_context_t *globals); +void mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl, mp_compiled_module_t *cm); #endif // this is implemented in runtime.c diff --git a/py/dynruntime.h b/py/dynruntime.h index b7a9a89156..9303638055 100644 --- a/py/dynruntime.h +++ b/py/dynruntime.h @@ -105,7 +105,7 @@ static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { #define mp_const_none ((mp_obj_t)mp_fun_table.const_none) #define mp_const_false ((mp_obj_t)mp_fun_table.const_false) #define mp_const_true ((mp_obj_t)mp_fun_table.const_true) -#define mp_const_empty_bytes (mp_type_bytes.make_new(NULL, 0, 0, NULL)) +#define mp_const_empty_bytes (MP_OBJ_TYPE_GET_SLOT(&mp_type_bytes, make_new)(NULL, 0, 0, NULL)) #define mp_const_empty_tuple (mp_fun_table.new_tuple(0, NULL)) #define mp_obj_new_bool(b) ((b) ? (mp_obj_t)mp_fun_table.const_true : (mp_obj_t)mp_fun_table.const_false) @@ -127,6 +127,7 @@ static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { #define mp_obj_str_get_data(o, len) (mp_obj_str_get_data_dyn((o), (len))) #define mp_get_buffer_raise(o, bufinfo, fl) (mp_fun_table.get_buffer_raise((o), (bufinfo), (fl))) #define mp_get_stream_raise(s, flags) (mp_fun_table.get_stream_raise((s), (flags))) +#define mp_obj_is_true(o) (mp_fun_table.native_from_obj(o, MP_NATIVE_TYPE_BOOL)) #define mp_obj_len(o) (mp_obj_len_dyn(o)) #define mp_obj_subscr(base, index, val) (mp_fun_table.obj_subscr((base), (index), (val))) @@ -151,7 +152,7 @@ static inline mp_obj_t mp_obj_cast_to_native_base_dyn(mp_obj_t self_in, mp_const if (MP_OBJ_FROM_PTR(self_type) == native_type) { return self_in; - } else if (self_type->parent != native_type) { + } else if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(self_type, parent) != native_type) { // The self_in object is not a direct descendant of native_type, so fail the cast. // This is a very simple version of mp_obj_is_subclass_fast that could be improved. return MP_OBJ_NULL; diff --git a/py/dynruntime.mk b/py/dynruntime.mk index 09cbb2dd37..62db43ad14 100644 --- a/py/dynruntime.mk +++ b/py/dynruntime.mk @@ -7,7 +7,7 @@ ECHO = @echo RM = /bin/rm MKDIR = /bin/mkdir PYTHON = python3 -MPY_CROSS = $(MPY_DIR)/mpy-cross/mpy-cross +MPY_CROSS = $(MPY_DIR)/mpy-cross/build/mpy-cross MPY_TOOL = $(PYTHON) $(MPY_DIR)/tools/mpy-tool.py MPY_LD = $(PYTHON) $(MPY_DIR)/tools/mpy_ld.py @@ -35,7 +35,7 @@ CFLAGS += -U _FORTIFY_SOURCE # prevent use of __*_chk libc functions MPY_CROSS_FLAGS += -march=$(ARCH) -SRC_O += $(addprefix $(BUILD)/, $(patsubst %.c,%.o,$(filter %.c,$(SRC)))) +SRC_O += $(addprefix $(BUILD)/, $(patsubst %.c,%.o,$(filter %.c,$(SRC))) $(patsubst %.S,%.o,$(filter %.S,$(SRC)))) SRC_MPY += $(addprefix $(BUILD)/, $(patsubst %.py,%.mpy,$(filter %.py,$(SRC)))) ################################################################################ @@ -134,6 +134,11 @@ $(BUILD)/%.o: %.c $(CONFIG_H) Makefile $(ECHO) "CC $<" $(Q)$(CROSS)gcc $(CFLAGS) -o $@ -c $< +# Build .o from .S source files +$(BUILD)/%.o: %.S $(CONFIG_H) Makefile + $(ECHO) "AS $<" + $(Q)$(CROSS)gcc $(CFLAGS) -o $@ -c $< + # Build .mpy from .py source files $(BUILD)/%.mpy: %.py $(ECHO) "MPY $<" diff --git a/py/emit.h b/py/emit.h index 608734552a..26f978ba59 100644 --- a/py/emit.h +++ b/py/emit.h @@ -115,7 +115,6 @@ typedef struct _emit_method_table_t { void (*start_pass)(emit_t *emit, pass_kind_t pass, scope_t *scope); bool (*end_pass)(emit_t *emit); - bool (*last_emit_was_return_value)(emit_t *emit); void (*adjust_stack_size)(emit_t *emit, mp_int_t delta); void (*set_source_line)(emit_t *emit, mp_uint_t line); @@ -192,7 +191,7 @@ static inline void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst) { scope_find_or_add_id(scope, qst, ID_INFO_KIND_GLOBAL_IMPLICIT); } -void mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst); +id_info_t *mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst); void mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emit_method_table, scope_t *scope, qstr qst); extern const emit_method_table_t emit_bc_method_table; @@ -227,7 +226,6 @@ void emit_native_xtensawin_free(emit_t *emit); void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope); bool mp_emit_bc_end_pass(emit_t *emit); -bool mp_emit_bc_last_emit_was_return_value(emit_t *emit); void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta); void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t line); diff --git a/py/emitbc.c b/py/emitbc.c index 2007975c5e..a07657408f 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -47,7 +47,11 @@ struct _emit_t { byte dummy_data[DUMMY_DATA_SIZE]; pass_kind_t pass : 8; - mp_uint_t last_emit_was_return_value : 8; + + // Set to true if the code generator should suppress emitted code due to it + // being dead code. This can happen when opcodes immediately follow an + // unconditional flow control (eg jump or raise). + bool suppress; int stack_size; @@ -141,6 +145,9 @@ STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_sk // all functions must go through this one to emit byte code STATIC uint8_t *emit_get_cur_to_write_bytecode(void *emit_in, size_t num_bytes_to_write) { emit_t *emit = emit_in; + if (emit->suppress) { + return emit->dummy_data; + } if (emit->pass < MP_PASS_EMIT) { emit->bytecode_offset += num_bytes_to_write; return emit->dummy_data; @@ -223,6 +230,10 @@ STATIC void emit_write_bytecode_byte_child(emit_t *emit, int stack_adj, byte b, STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) { mp_emit_bc_adjust_stack_size(emit, stack_adj); + if (emit->suppress) { + return; + } + // Determine if the jump offset is signed or unsigned, based on the opcode. const bool is_signed = b1 <= MP_BC_POP_JUMP_IF_FALSE; @@ -272,7 +283,7 @@ STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit->pass = pass; emit->stack_size = 0; - emit->last_emit_was_return_value = false; + emit->suppress = false; emit->scope = scope; emit->last_source_line_offset = 0; emit->last_source_line = 1; @@ -397,10 +408,6 @@ bool mp_emit_bc_end_pass(emit_t *emit) { return true; } -bool mp_emit_bc_last_emit_was_return_value(emit_t *emit) { - return emit->last_emit_was_return_value; -} - void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) { if (emit->pass == MP_PASS_SCOPE) { return; @@ -410,7 +417,6 @@ void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) { if (emit->stack_size > emit->scope->stack_size) { emit->scope->stack_size = emit->stack_size; } - emit->last_emit_was_return_value = false; } void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) { @@ -433,6 +439,10 @@ void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) { } void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) { + // Assigning a label ends any dead-code region, and all following opcodes + // should be emitted (until another unconditional flow control). + emit->suppress = false; + mp_emit_bc_adjust_stack_size(emit, 0); if (emit->pass == MP_PASS_SCOPE) { return; @@ -596,6 +606,7 @@ void mp_emit_bc_rot_three(emit_t *emit) { void mp_emit_bc_jump(emit_t *emit, mp_uint_t label) { emit_write_bytecode_byte_label(emit, 0, MP_BC_JUMP, label); + emit->suppress = true; } void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) { @@ -629,6 +640,7 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept emit_write_bytecode_byte_label(emit, 0, MP_BC_UNWIND_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR); emit_write_bytecode_raw_byte(emit, ((label & MP_EMIT_BREAK_FROM_FOR) ? 0x80 : 0) | except_depth); } + emit->suppress = true; } void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind) { @@ -670,6 +682,7 @@ void mp_emit_bc_for_iter_end(emit_t *emit) { void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) { (void)within_exc_handler; emit_write_bytecode_byte_label(emit, 0, MP_BC_POP_EXCEPT_JUMP, label); + emit->suppress = true; } void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) { @@ -773,7 +786,7 @@ void mp_emit_bc_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_ke void mp_emit_bc_return_value(emit_t *emit) { emit_write_bytecode_byte(emit, -1, MP_BC_RETURN_VALUE); - emit->last_emit_was_return_value = true; + emit->suppress = true; } void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) { @@ -781,6 +794,7 @@ void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) { MP_STATIC_ASSERT(MP_BC_RAISE_LAST + 2 == MP_BC_RAISE_FROM); assert(n_args <= 2); emit_write_bytecode_byte(emit, -n_args, MP_BC_RAISE_LAST + n_args); + emit->suppress = true; } void mp_emit_bc_yield(emit_t *emit, int kind) { @@ -806,7 +820,6 @@ const emit_method_table_t emit_bc_method_table = { mp_emit_bc_start_pass, mp_emit_bc_end_pass, - mp_emit_bc_last_emit_was_return_value, mp_emit_bc_adjust_stack_size, mp_emit_bc_set_source_line, diff --git a/py/emitcommon.c b/py/emitcommon.c index 679ef1d973..a9eb6e2021 100644 --- a/py/emitcommon.c +++ b/py/emitcommon.c @@ -86,7 +86,7 @@ size_t mp_emit_common_use_const_obj(mp_emit_common_t *emit, mp_obj_t const_obj) return emit->const_obj_list.len - 1; } -void mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst) { +id_info_t *mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst) { // name adding/lookup id_info_t *id = scope_find_or_add_id(scope, qst, ID_INFO_KIND_GLOBAL_IMPLICIT); if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { @@ -98,6 +98,7 @@ void mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst) { id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT_ASSIGNED; } } + return id; } void mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emit_method_table, scope_t *scope, qstr qst) { diff --git a/py/emitnative.c b/py/emitnative.c index 9fafa1104a..619f75bdbb 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -305,8 +305,6 @@ struct _emit_t { uint16_t n_info; uint16_t n_cell; - bool last_emit_was_return_value; - scope_t *scope; ASM_T *as; @@ -399,7 +397,6 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop emit->pass = pass; emit->do_viper_types = scope->emit_options == MP_EMIT_OPT_VIPER; emit->stack_size = 0; - emit->last_emit_was_return_value = false; emit->scope = scope; // allocate memory for keeping track of the types of locals @@ -433,7 +430,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop // local variables begin unbound, and have unknown type for (mp_uint_t i = num_args; i < emit->local_vtype_alloc; i++) { - emit->local_vtype[i] = VTYPE_UNBOUND; + emit->local_vtype[i] = emit->do_viper_types ? VTYPE_UNBOUND : VTYPE_PYOBJ; } // values on stack begin unbound @@ -762,10 +759,6 @@ STATIC bool emit_native_end_pass(emit_t *emit) { return true; } -STATIC bool emit_native_last_emit_was_return_value(emit_t *emit) { - return emit->last_emit_was_return_value; -} - STATIC void ensure_extra_stack(emit_t *emit, size_t delta) { if (emit->stack_size + delta > emit->stack_info_alloc) { size_t new_alloc = (emit->stack_size + delta + 8) & ~3; @@ -822,7 +815,7 @@ STATIC void emit_native_set_source_line(emit_t *emit, mp_uint_t source_line) { // this must be called at start of emit functions STATIC void emit_native_pre(emit_t *emit) { - emit->last_emit_was_return_value = false; + (void)emit; } // depth==0 is top, depth==1 is before top, etc @@ -946,7 +939,6 @@ STATIC void emit_fold_stack_top(emit_t *emit, int reg_dest) { // If stacked value is in a register and the register is not r1 or r2, then // *reg_dest is set to that register. Otherwise the value is put in *reg_dest. STATIC void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *reg_dest, int not_r1, int not_r2) { - emit->last_emit_was_return_value = false; stack_info_t *si = peek_stack(emit, 0); if (si->kind == STACK_REG && si->data.u_reg != not_r1 && si->data.u_reg != not_r2) { *vtype = si->vtype; @@ -959,12 +951,10 @@ STATIC void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *re } STATIC void emit_pre_pop_discard(emit_t *emit) { - emit->last_emit_was_return_value = false; adjust_stack(emit, -1); } STATIC void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest) { - emit->last_emit_was_return_value = false; emit_access_stack(emit, 1, vtype, reg_dest); adjust_stack(emit, -1); } @@ -1566,6 +1556,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) { break; } #endif + need_reg_single(emit, reg_index, 0); ASM_MOV_REG_IMM(emit->as, reg_index, index_value); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base reg_base = reg_index; @@ -1583,6 +1574,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) { break; } #endif + need_reg_single(emit, reg_index, 0); ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 1); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base reg_base = reg_index; @@ -1600,6 +1592,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) { break; } #endif + need_reg_single(emit, reg_index, 0); ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 2); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base reg_base = reg_index; @@ -1722,10 +1715,18 @@ STATIC void emit_native_store_global(emit_t *emit, qstr qst, int kind) { } STATIC void emit_native_store_attr(emit_t *emit, qstr qst) { - vtype_kind_t vtype_base, vtype_val; - emit_pre_pop_reg_reg(emit, &vtype_base, REG_ARG_1, &vtype_val, REG_ARG_3); // arg1 = base, arg3 = value + vtype_kind_t vtype_base; + vtype_kind_t vtype_val = peek_vtype(emit, 1); + if (vtype_val == VTYPE_PYOBJ) { + emit_pre_pop_reg_reg(emit, &vtype_base, REG_ARG_1, &vtype_val, REG_ARG_3); // arg1 = base, arg3 = value + } else { + emit_access_stack(emit, 2, &vtype_val, REG_ARG_1); // arg1 = value + emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, vtype_val, REG_ARG_2); // arg2 = type + ASM_MOV_REG_REG(emit->as, REG_ARG_3, REG_RET); // arg3 = value (converted) + emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base + adjust_stack(emit, -1); // pop value + } assert(vtype_base == VTYPE_PYOBJ); - assert(vtype_val == VTYPE_PYOBJ); emit_call_with_qstr_arg(emit, MP_F_STORE_ATTR, qst, REG_ARG_2); // arg2 = attribute name emit_post(emit); } @@ -2005,6 +2006,7 @@ STATIC void emit_native_jump(emit_t *emit, mp_uint_t label) { need_stack_settled(emit); ASM_JUMP(emit->as, label); emit_post(emit); + mp_asm_base_suppress_code(&emit->as->base); } STATIC void emit_native_jump_helper(emit_t *emit, bool cond, mp_uint_t label, bool pop) { @@ -2392,14 +2394,13 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { } else if (op == MP_BINARY_OP_MULTIPLY) { ASM_MUL_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, vtype_lhs, REG_ARG_2); - } else if (MP_BINARY_OP_LESS <= op && op <= MP_BINARY_OP_NOT_EQUAL) { - // comparison ops are (in enum order): - // MP_BINARY_OP_LESS - // MP_BINARY_OP_MORE - // MP_BINARY_OP_EQUAL - // MP_BINARY_OP_LESS_EQUAL - // MP_BINARY_OP_MORE_EQUAL - // MP_BINARY_OP_NOT_EQUAL + } else if (op == MP_BINARY_OP_LESS + || op == MP_BINARY_OP_MORE + || op == MP_BINARY_OP_EQUAL + || op == MP_BINARY_OP_LESS_EQUAL + || op == MP_BINARY_OP_MORE_EQUAL + || op == MP_BINARY_OP_NOT_EQUAL) { + // comparison ops if (vtype_lhs != vtype_rhs) { EMIT_NATIVE_VIPER_TYPE_ERROR(emit, MP_ERROR_TEXT("comparison of int and uint")); @@ -2800,7 +2801,6 @@ STATIC void emit_native_return_value(emit_t *emit) { // Do the unwinding jump to get to the return handler emit_native_unwind_jump(emit, emit->exit_label, emit->exc_stack_size); - emit->last_emit_was_return_value = true; return; } @@ -2838,7 +2838,6 @@ STATIC void emit_native_return_value(emit_t *emit) { ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_RET_VAL(emit), REG_PARENT_RET); } emit_native_unwind_jump(emit, emit->exit_label, emit->exc_stack_size); - emit->last_emit_was_return_value = true; } STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) { @@ -2851,6 +2850,7 @@ STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) { } // TODO probably make this 1 call to the runtime (which could even call convert, native_raise(obj, type)) emit_call(emit, MP_F_NATIVE_RAISE); + mp_asm_base_suppress_code(&emit->as->base); } STATIC void emit_native_yield(emit_t *emit, int kind) { @@ -2957,7 +2957,6 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_start_pass, emit_native_end_pass, - emit_native_last_emit_was_return_value, emit_native_adjust_stack_size, emit_native_set_source_line, diff --git a/py/enum.c b/py/enum.c index 22b9090196..5a50a93ff3 100644 --- a/py/enum.c +++ b/py/enum.c @@ -27,10 +27,8 @@ #include "py/enum.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - mp_obj_t cp_enum_find(const mp_obj_type_t *type, int value) { - const mp_obj_dict_t *dict = type->locals_dict; + const mp_obj_dict_t *dict = MP_OBJ_TYPE_GET_SLOT(type, locals_dict); for (size_t i = 0; i < dict->map.used; i++) { const cp_enum_obj_t *v = MP_OBJ_TO_PTR(dict->map.table[i].value); if (v->value == value) { diff --git a/py/enum.h b/py/enum.h index b83257e00f..689c52a3d8 100644 --- a/py/enum.h +++ b/py/enum.h @@ -51,15 +51,13 @@ typedef struct { } #define MAKE_ENUM_TYPE(module, type, typename, ...) \ - const mp_obj_type_t typename##_type = { \ - { &mp_type_type }, \ - .name = MP_QSTR_##type, \ - .print = typename##_print, \ - .locals_dict = (mp_obj_dict_t *)&typename##_locals_dict, \ - ##__VA_ARGS__ \ - } - - + MP_DEFINE_CONST_OBJ_TYPE(typename##_type, \ + MP_QSTR_##type, \ + 0, \ + print, typename##_print, \ + locals_dict, &typename##_locals_dict, \ + ##__VA_ARGS__ \ + ) mp_obj_t cp_enum_find(const mp_obj_type_t *type, int value); int cp_enum_value(const mp_obj_type_t *type, mp_obj_t obj, qstr arg_name); diff --git a/py/formatfloat.c b/py/formatfloat.c index 854944976f..050d3a9dfb 100644 --- a/py/formatfloat.c +++ b/py/formatfloat.c @@ -1,5 +1,3 @@ -// CIRCUITPY: https://github.com/adafruit/circuitpython/pull/6722 -// post v1.19.1. Remove this comment during v1.20 merge. /* * This file is part of the MicroPython project, http://micropython.org/ * @@ -64,26 +62,20 @@ #define FPMIN_BUF_SIZE 6 // +9e+99 #define FLT_SIGN_MASK 0x80000000 -#define FLT_EXP_MASK 0x7F800000 -#define FLT_MAN_MASK 0x007FFFFF -union floatbits { - float f; - uint32_t u; -}; static inline int fp_signbit(float x) { - union floatbits fb = {x}; - return fb.u & FLT_SIGN_MASK; + mp_float_union_t fb = {x}; + return fb.i & FLT_SIGN_MASK; } #define fp_isnan(x) isnan(x) #define fp_isinf(x) isinf(x) static inline int fp_iszero(float x) { - union floatbits fb = {x}; - return fb.u == 0; + mp_float_union_t fb = {x}; + return fb.i == 0; } static inline int fp_isless1(float x) { - union floatbits fb = {x}; - return fb.u < 0x3f800000; + mp_float_union_t fb = {x}; + return fb.i < 0x3f800000; } #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE @@ -101,28 +93,11 @@ static inline int fp_isless1(float x) { #endif // MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT/DOUBLE -static inline int fp_ge_eps(FPTYPE x, FPTYPE y) { - mp_float_union_t fb_y = {y}; - // Back off 2 eps. - // This is valid for almost all values, but in practice - // it's only used when y = 1eX for X>=0. - fb_y.i -= 2; - return x >= fb_y.f; +static inline int fp_expval(FPTYPE x) { + mp_float_union_t fb = {x}; + return (int)((fb.i >> MP_FLOAT_FRAC_BITS) & (~(0xFFFFFFFF << MP_FLOAT_EXP_BITS))) - MP_FLOAT_EXP_OFFSET; } -static const FPTYPE g_pos_pow[] = { - #if FPDECEXP > 32 - MICROPY_FLOAT_CONST(1e256), MICROPY_FLOAT_CONST(1e128), MICROPY_FLOAT_CONST(1e64), - #endif - MICROPY_FLOAT_CONST(1e32), MICROPY_FLOAT_CONST(1e16), MICROPY_FLOAT_CONST(1e8), MICROPY_FLOAT_CONST(1e4), MICROPY_FLOAT_CONST(1e2), MICROPY_FLOAT_CONST(1e1) -}; -static const FPTYPE g_neg_pow[] = { - #if FPDECEXP > 32 - MICROPY_FLOAT_CONST(1e-256), MICROPY_FLOAT_CONST(1e-128), MICROPY_FLOAT_CONST(1e-64), - #endif - MICROPY_FLOAT_CONST(1e-32), MICROPY_FLOAT_CONST(1e-16), MICROPY_FLOAT_CONST(1e-8), MICROPY_FLOAT_CONST(1e-4), MICROPY_FLOAT_CONST(1e-2), MICROPY_FLOAT_CONST(1e-1) -}; - int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) { char *s = buf; @@ -179,14 +154,15 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch if (fmt == 'g' && prec == 0) { prec = 1; } - int e, e1; + int e; int dec = 0; char e_sign = '\0'; int num_digits = 0; - const FPTYPE *pos_pow = g_pos_pow; - const FPTYPE *neg_pow = g_neg_pow; int signed_e = 0; + // Approximate power of 10 exponent from binary exponent. + // abs(e_guess) is lower bound on abs(power of 10 exponent). + int e_guess = (int)(fp_expval(f) * FPCONST(0.3010299956639812)); // 1/log2(10). if (fp_iszero(f)) { e = 0; if (fmt == 'f') { @@ -205,25 +181,18 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } } } else if (fp_isless1(f)) { - FPTYPE f_mod = f; + FPTYPE f_entry = f; // Save f in case we go to 'f' format. // Build negative exponent - for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) { - if (*neg_pow > f_mod) { - e += e1; - f_mod *= *pos_pow; - } - } - - char e_sign_char = '-'; - if (fp_isless1(f_mod) && f_mod >= FPROUND_TO_ONE) { - f_mod = FPCONST(1.0); - if (e == 0) { - e_sign_char = '+'; - } - } else if (fp_isless1(f_mod)) { - e++; - f_mod *= FPCONST(10.0); + e = -e_guess; + FPTYPE u_base = MICROPY_FLOAT_C_FUN(pow)(10, -e); + while (u_base > f) { + ++e; + u_base = MICROPY_FLOAT_C_FUN(pow)(10, -e); } + // Normalize out the inferred unit. Use divide because + // pow(10, e) * pow(10, -e) is slightly < 1 for some e in float32 + // (e.g. print("%.12f" % ((1e13) * (1e-13)))) + f /= u_base; // If the user specified 'g' format, and e is <= 4, then we'll switch // to the fixed format ('f') @@ -243,11 +212,12 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch num_digits = prec; signed_e = 0; + f = f_entry; ++num_digits; } else { // For e & g formats, we'll be printing the exponent, so set the // sign. - e_sign = e_sign_char; + e_sign = '-'; dec = 0; if (prec > (buf_remaining - FPMIN_BUF_SIZE)) { @@ -264,19 +234,11 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch // scaling it. Instead, we find the product of powers of 10 // that is not greater than it, and use that to start the // mantissa. - FPTYPE u_base = FPCONST(1.0); - for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++) { - FPTYPE next_u = u_base * *pos_pow; - // fp_ge_eps performs "f >= (next_u - 2eps)" so that if, for - // numerical reasons, f is very close to a power of ten but - // not strictly equal, we still treat it as that power of 10. - // The comparison was failing for maybe 10% of 1eX values, but - // although rounding fixed many of them, there were still some - // rendering as 9.99999998e(X-1). - if (fp_ge_eps(f, next_u)) { - u_base = next_u; - e += e1; - } + e = e_guess; + FPTYPE next_u = MICROPY_FLOAT_C_FUN(pow)(10, e + 1); + while (f >= next_u) { + ++e; + next_u = MICROPY_FLOAT_C_FUN(pow)(10, e + 1); } // If the user specified fixed format (fmt == 'f') and e makes the @@ -343,46 +305,22 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch num_digits = prec; } - if (signed_e < 0) { - // The algorithm below treats numbers smaller than 1 by scaling them - // repeatedly by 10 to bring the new digit to the top. Our input number - // was smaller than 1, so scale it up to be 1 <= f < 10. - FPTYPE u_base = FPCONST(1.0); - const FPTYPE *pow_u = g_pos_pow; - for (int m = FPDECEXP; m; m >>= 1, pow_u++) { - if (m & e) { - u_base *= *pow_u; - } - } - f *= u_base; - } - int d = 0; - int num_digits_left = num_digits; - for (int digit_index = signed_e; num_digits_left >= 0; --digit_index) { + for (int digit_index = signed_e; num_digits >= 0; --digit_index) { FPTYPE u_base = FPCONST(1.0); if (digit_index > 0) { // Generate 10^digit_index for positive digit_index. - const FPTYPE *pow_u = g_pos_pow; - int target_index = digit_index; - for (int m = FPDECEXP; m; m >>= 1, pow_u++) { - if (m & target_index) { - u_base *= *pow_u; - } - } + u_base = MICROPY_FLOAT_C_FUN(pow)(10, digit_index); } for (d = 0; d < 9; ++d) { - // This is essentially "if (f < u_base)", but with 2eps margin - // so that if f is just a tiny bit smaller, we treat it as - // equal (and accept the additional digit value). - if (!fp_ge_eps(f, u_base)) { + if (f < u_base) { break; } f -= u_base; } // We calculate one more digit than we display, to use in rounding // below. So only emit the digit if it's one that we display. - if (num_digits_left > 0) { + if (num_digits > 0) { // Emit this number (the leading digit). *s++ = '0' + d; if (dec == 0 && prec > 0) { @@ -390,7 +328,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } } --dec; - --num_digits_left; + --num_digits; if (digit_index <= 0) { // Once we get below 1.0, we scale up f instead of calculating // negative powers of 10 in u_base. This provides better diff --git a/py/gc.c b/py/gc.c index d83fe2dfa8..cccc096e57 100644 --- a/py/gc.c +++ b/py/gc.c @@ -36,6 +36,7 @@ #include #endif +// CIRCUITPY #include "supervisor/shared/safe_mode.h" #if CIRCUITPY_MEMORYMONITOR @@ -52,6 +53,7 @@ #define DEBUG_printf(...) (void)0 #endif +// CIRCUITPY // Uncomment this if you want to use a debugger to capture state at every allocation and free. // #define LOG_HEAP_ACTIVITY 1 @@ -87,17 +89,28 @@ #define ATB_2_IS_FREE(a) (((a) & ATB_MASK_2) == 0) #define ATB_3_IS_FREE(a) (((a) & ATB_MASK_3) == 0) -#define BLOCK_SHIFT(block) (2 * ((block) & (BLOCKS_PER_ATB - 1))) -#define ATB_GET_KIND(block) ((MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] >> BLOCK_SHIFT(block)) & 3) -#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) -#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) -#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) -#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) -#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) +#if MICROPY_GC_SPLIT_HEAP +#define NEXT_AREA(area) (area->next) +#else +#define NEXT_AREA(area) (NULL) +#endif -#define BLOCK_FROM_PTR(ptr) (((byte *)(ptr) - MP_STATE_MEM(gc_pool_start)) / BYTES_PER_BLOCK) -#define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (uintptr_t)MP_STATE_MEM(gc_pool_start))) -#define ATB_FROM_BLOCK(bl) ((bl) / BLOCKS_PER_ATB) +#define BLOCK_SHIFT(block) (2 * ((block) & (BLOCKS_PER_ATB - 1))) +#define ATB_GET_KIND(area, block) (((area)->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] >> BLOCK_SHIFT(block)) & 3) +#define ATB_ANY_TO_FREE(area, block) do { area->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] &= (~(AT_MARK << BLOCK_SHIFT(block))); } while (0) +#define ATB_FREE_TO_HEAD(area, block) do { area->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] |= (AT_HEAD << BLOCK_SHIFT(block)); } while (0) +#define ATB_FREE_TO_TAIL(area, block) do { area->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] |= (AT_TAIL << BLOCK_SHIFT(block)); } while (0) +#define ATB_HEAD_TO_MARK(area, block) do { area->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0) +#define ATB_MARK_TO_HEAD(area, block) do { area->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0) + +#define BLOCK_FROM_PTR(area, ptr) (((byte *)(ptr) - area->gc_pool_start) / BYTES_PER_BLOCK) +#define PTR_FROM_BLOCK(area, block) (((block) * BYTES_PER_BLOCK + (uintptr_t)area->gc_pool_start)) + +// After the ATB, there must be a byte filled with AT_FREE so that gc_mark_tree +// cannot erroneously conclude that a block extends past the end of the GC heap +// due to bit patterns in the FTB (or first block, if finalizers are disabled) +// being interpreted as AT_TAIL. +#define ALLOC_TABLE_GAP_BYTE (1) #if MICROPY_ENABLE_FINALISER // FTB = finaliser table byte @@ -105,9 +118,9 @@ #define BLOCKS_PER_FTB (8) -#define FTB_GET(block) ((MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] >> ((block) & 7)) & 1) -#define FTB_SET(block) do { MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] |= (1 << ((block) & 7)); } while (0) -#define FTB_CLEAR(block) do { MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] &= (~(1 << ((block) & 7))); } while (0) +#define FTB_GET(area, block) ((area->gc_finaliser_table_start[(block) / BLOCKS_PER_FTB] >> ((block) & 7)) & 1) +#define FTB_SET(area, block) do { area->gc_finaliser_table_start[(block) / BLOCKS_PER_FTB] |= (1 << ((block) & 7)); } while (0) +#define FTB_CLEAR(area, block) do { area->gc_finaliser_table_start[(block) / BLOCKS_PER_FTB] &= (~(1 << ((block) & 7))); } while (0) #endif #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL @@ -130,11 +143,7 @@ void __attribute__ ((noinline)) gc_log_change(uint32_t start_block, uint32_t len #endif // TODO waste less memory; currently requires that all entries in alloc_table have a corresponding block in pool -void gc_init(void *start, void *end) { - // align end pointer on block boundary - end = (void *)((uintptr_t)end & (~(BYTES_PER_BLOCK - 1))); - DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte *)end - (byte *)start); - +STATIC void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) { // calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes): // T = A + F + P // F = A * BLOCKS_PER_ATB / BLOCKS_PER_FTB @@ -142,39 +151,59 @@ void gc_init(void *start, void *end) { // => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK) size_t total_byte_len = (byte *)end - (byte *)start; #if MICROPY_ENABLE_FINALISER - // CIRCUITPY: https://github.com/adafruit/circuitpython/pull/5245 (bug fix) - MP_STATE_MEM(gc_alloc_table_byte_len) = (total_byte_len - 1) * MP_BITS_PER_BYTE / (MP_BITS_PER_BYTE + MP_BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + MP_BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK); + area->gc_alloc_table_byte_len = (total_byte_len - ALLOC_TABLE_GAP_BYTE) * MP_BITS_PER_BYTE / (MP_BITS_PER_BYTE + MP_BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + MP_BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK); #else - MP_STATE_MEM(gc_alloc_table_byte_len) = total_byte_len / (1 + MP_BITS_PER_BYTE / 2 * BYTES_PER_BLOCK); + area->gc_alloc_table_byte_len = (total_byte_len - ALLOC_TABLE_GAP_BYTE) / (1 + MP_BITS_PER_BYTE / 2 * BYTES_PER_BLOCK); #endif - MP_STATE_MEM(gc_alloc_table_start) = (byte *)start; + area->gc_alloc_table_start = (byte *)start; #if MICROPY_ENABLE_FINALISER - 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; - MP_STATE_MEM(gc_finaliser_table_start) = MP_STATE_MEM(gc_alloc_table_start) + MP_STATE_MEM(gc_alloc_table_byte_len); + size_t gc_finaliser_table_byte_len = (area->gc_alloc_table_byte_len * BLOCKS_PER_ATB + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; + area->gc_finaliser_table_start = area->gc_alloc_table_start + area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE; #endif - size_t gc_pool_block_len = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; - MP_STATE_MEM(gc_pool_start) = (byte *)end - gc_pool_block_len * BYTES_PER_BLOCK; - MP_STATE_MEM(gc_pool_end) = end; + size_t gc_pool_block_len = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; + area->gc_pool_start = (byte *)end - gc_pool_block_len * BYTES_PER_BLOCK; + area->gc_pool_end = end; #if MICROPY_ENABLE_FINALISER - // CIRCUITPY: https://github.com/adafruit/circuitpython/pull/6397 (compiler diagnostic) - (void)gc_finaliser_table_byte_len; // avoid unused variable diagnostic if asserts are disabled - assert(MP_STATE_MEM(gc_pool_start) >= MP_STATE_MEM(gc_finaliser_table_start) + gc_finaliser_table_byte_len); + assert(area->gc_pool_start >= area->gc_finaliser_table_start + gc_finaliser_table_byte_len); #endif - // clear ATB's - memset(MP_STATE_MEM(gc_alloc_table_start), 0, MP_STATE_MEM(gc_alloc_table_byte_len)); - #if MICROPY_ENABLE_FINALISER - // clear FTB's - memset(MP_STATE_MEM(gc_finaliser_table_start), 0, gc_finaliser_table_byte_len); + // clear ATBs and FTBs + memset(area->gc_alloc_table_start, 0, gc_finaliser_table_byte_len + area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE); + #else + // clear ATBs + memset(area->gc_alloc_table_start, 0, area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE); #endif + area->gc_last_free_atb_index = 0; + + #if MICROPY_GC_SPLIT_HEAP + area->next = NULL; + #endif + + DEBUG_printf("GC layout:\n"); + DEBUG_printf(" alloc table at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(area).gc_alloc_table_start, MP_STATE_MEM(area).gc_alloc_table_byte_len, MP_STATE_MEM(area).gc_alloc_table_byte_len * BLOCKS_PER_ATB); + #if MICROPY_ENABLE_FINALISER + DEBUG_printf(" finaliser table at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(area).gc_finaliser_table_start, gc_finaliser_table_byte_len, gc_finaliser_table_byte_len * BLOCKS_PER_FTB); + #endif + DEBUG_printf(" pool at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(area).gc_pool_start, gc_pool_block_len * BYTES_PER_BLOCK, gc_pool_block_len); +} + +void gc_init(void *start, void *end) { + // align end pointer on block boundary + end = (void *)((uintptr_t)end & (~(BYTES_PER_BLOCK - 1))); + DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte *)end - (byte *)start); + + gc_setup_area(&MP_STATE_MEM(area), start, end); + // set last free ATB index to start of heap - MP_STATE_MEM(gc_last_free_atb_index) = 0; + #if MICROPY_GC_SPLIT_HEAP + MP_STATE_MEM(gc_last_free_area) = &MP_STATE_MEM(area); + #endif // unlock the GC MP_STATE_THREAD(gc_lock_depth) = 0; @@ -191,22 +220,38 @@ void gc_init(void *start, void *end) { #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL mp_thread_mutex_init(&MP_STATE_MEM(gc_mutex)); #endif - - MP_STATE_MEM(permanent_pointers) = NULL; - - DEBUG_printf("GC layout:\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); - #if MICROPY_ENABLE_FINALISER - 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); - #endif - 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); } +#if MICROPY_GC_SPLIT_HEAP +void gc_add(void *start, void *end) { + // Place the area struct at the start of the area. + mp_state_mem_area_t *area = (mp_state_mem_area_t *)start; + start = (void *)((uintptr_t)start + sizeof(mp_state_mem_area_t)); + + end = (void *)((uintptr_t)end & (~(BYTES_PER_BLOCK - 1))); + DEBUG_printf("Adding GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte *)end - (byte *)start); + + // Init this area + gc_setup_area(area, start, end); + + // Find the last registered area in the linked list + mp_state_mem_area_t *prev_area = &MP_STATE_MEM(area); + while (prev_area->next != NULL) { + prev_area = prev_area->next; + } + + // Add this area to the linked list + prev_area->next = area; +} +#endif + +// CIRCUITPY +// TODO FOR MERGE: fix this for multiple areas?? void gc_deinit(void) { // Run any finalisers before we stop using the heap. gc_sweep_all(); - - MP_STATE_MEM(gc_pool_start) = 0; + MP_STATIC_ASSERT(!MICROPY_GC_SPLIT_HEAP); + memset(&MP_STATE_MEM(area), 0, sizeof(MP_STATE_MEM(area))); } void gc_lock(void) { @@ -226,6 +271,23 @@ bool gc_is_locked(void) { return MP_STATE_THREAD(gc_lock_depth) != 0; } +#if MICROPY_GC_SPLIT_HEAP +// Returns the area to which this pointer belongs, or NULL if it isn't +// allocated on the GC-managed heap. +STATIC inline mp_state_mem_area_t *gc_get_ptr_area(const void *ptr) { + if (((uintptr_t)(ptr) & (BYTES_PER_BLOCK - 1)) != 0) { // must be aligned on a block + return NULL; + } + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + if (ptr >= (void *)area->gc_pool_start // must be above start of pool + && ptr < (void *)area->gc_pool_end) { // must be below end of pool + return area; + } + } + return NULL; +} +#endif + // CIRCUITPY: VERIFY_PTR moved to gc.h to make it available elsewhere. #ifndef TRACE_MARK @@ -241,36 +303,65 @@ bool gc_is_locked(void) { // blocks on the stack. When all children have been checked, pop off the // topmost block on the stack and repeat with that one. // CIRCUITPY: We don't instrument these functions because they occur a lot during GC and -// fill up the output buffer quickly. -STATIC void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark_subtree)(size_t block) { +#if MICROPY_GC_SPLIT_HEAP +STATIC void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark_subtree)(mp_state_mem_area_t * area, size_t block) +#else +STATIC void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark_subtree)(size_t block) +#endif +{ // Start with the block passed in the argument. size_t sp = 0; for (;;) { MICROPY_GC_HOOK_LOOP + + #if !MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t * area = &MP_STATE_MEM(area); + #endif + // work out number of consecutive blocks in the chain starting with this one size_t n_blocks = 0; do { n_blocks += 1; - } while (ATB_GET_KIND(block + n_blocks) == AT_TAIL); + } while (ATB_GET_KIND(area, block + n_blocks) == AT_TAIL); + + // check that the consecutive blocks didn't overflow past the end of the area + assert(area->gc_pool_start + (block + n_blocks) * BYTES_PER_BLOCK <= area->gc_pool_end); // check this block's children - void **ptrs = (void **)PTR_FROM_BLOCK(block); + void **ptrs = (void **)PTR_FROM_BLOCK(area, block); for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void *); i > 0; i--, ptrs++) { MICROPY_GC_HOOK_LOOP void *ptr = *ptrs; - if (VERIFY_PTR(ptr)) { - // Mark and push this pointer - size_t childblock = BLOCK_FROM_PTR(ptr); - if (ATB_GET_KIND(childblock) == AT_HEAD) { - // an unmarked head, mark it, and push it on gc stack - TRACE_MARK(childblock, ptr); - ATB_HEAD_TO_MARK(childblock); - if (sp < MICROPY_ALLOC_GC_STACK_SIZE) { - MP_STATE_MEM(gc_stack)[sp++] = childblock; - } else { - MP_STATE_MEM(gc_stack_overflow) = 1; - } - } + // If this is a heap pointer that hasn't been marked, mark it and push + // it's children to the stack. + #if MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t *ptr_area = gc_get_ptr_area(ptr); + if (!ptr_area) { + // Not a heap-allocated pointer (might even be random data). + continue; + } + #else + if (!VERIFY_PTR(ptr)) { + continue; + } + mp_state_mem_area_t *ptr_area = area; + #endif + size_t ptr_block = BLOCK_FROM_PTR(ptr_area, ptr); + if (ATB_GET_KIND(ptr_area, ptr_block) != AT_HEAD) { + // This block is already marked. + continue; + } + // An unmarked head. Mark it, and push it on gc stack. + TRACE_MARK(ptr_block, ptr); + ATB_HEAD_TO_MARK(ptr_area, ptr_block); + if (sp < MICROPY_ALLOC_GC_STACK_SIZE) { + MP_STATE_MEM(gc_block_stack)[sp] = ptr_block; + #if MICROPY_GC_SPLIT_HEAP + MP_STATE_MEM(gc_area_stack)[sp] = ptr_area; + #endif + sp += 1; + } else { + MP_STATE_MEM(gc_stack_overflow) = 1; } } @@ -280,7 +371,11 @@ STATIC void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark_subtree)(size_t block) { } // pop the next block off the stack - block = MP_STATE_MEM(gc_stack)[--sp]; + sp -= 1; + block = MP_STATE_MEM(gc_block_stack)[sp]; + #if MICROPY_GC_SPLIT_HEAP + area = MP_STATE_MEM(gc_area_stack)[sp]; + #endif } } @@ -289,11 +384,17 @@ STATIC void gc_deal_with_stack_overflow(void) { MP_STATE_MEM(gc_stack_overflow) = 0; // scan entire memory looking for blocks which have been marked but not their children - for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) { - MICROPY_GC_HOOK_LOOP - // trace (again) if mark bit set - if (ATB_GET_KIND(block) == AT_MARK) { - gc_mark_subtree(block); + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + for (size_t block = 0; block < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) { + MICROPY_GC_HOOK_LOOP + // trace (again) if mark bit set + if (ATB_GET_KIND(area, block) == AT_MARK) { + #if MICROPY_GC_SPLIT_HEAP + gc_mark_subtree(area, block); + #else + gc_mark_subtree(block); + #endif + } } } } @@ -305,70 +406,55 @@ STATIC void gc_sweep(void) { #endif // free unmarked heads and their tails int free_tail = 0; - for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) { - MICROPY_GC_HOOK_LOOP - switch (ATB_GET_KIND(block)) { - case AT_HEAD: - #if MICROPY_ENABLE_FINALISER - if (FTB_GET(block)) { - mp_obj_base_t *obj = (mp_obj_base_t *)PTR_FROM_BLOCK(block); - if (obj->type != NULL) { - // if the object has a type then see if it has a __del__ method - mp_obj_t dest[2]; - mp_load_method_maybe(MP_OBJ_FROM_PTR(obj), MP_QSTR___del__, dest); - if (dest[0] != MP_OBJ_NULL) { - // load_method returned a method, execute it in a protected environment - #if MICROPY_ENABLE_SCHEDULER - mp_sched_lock(); - #endif - mp_call_function_1_protected(dest[0], dest[1]); - #if MICROPY_ENABLE_SCHEDULER - mp_sched_unlock(); - #endif + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + for (size_t block = 0; block < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) { + MICROPY_GC_HOOK_LOOP + switch (ATB_GET_KIND(area, block)) { + case AT_HEAD: + #if MICROPY_ENABLE_FINALISER + if (FTB_GET(area, block)) { + mp_obj_base_t *obj = (mp_obj_base_t *)PTR_FROM_BLOCK(area, block); + if (obj->type != NULL) { + // if the object has a type then see if it has a __del__ method + mp_obj_t dest[2]; + mp_load_method_maybe(MP_OBJ_FROM_PTR(obj), MP_QSTR___del__, dest); + if (dest[0] != MP_OBJ_NULL) { + // load_method returned a method, execute it in a protected environment + #if MICROPY_ENABLE_SCHEDULER + mp_sched_lock(); + #endif + mp_call_function_1_protected(dest[0], dest[1]); + #if MICROPY_ENABLE_SCHEDULER + mp_sched_unlock(); + #endif + } } + // clear finaliser flag + FTB_CLEAR(area, block); } - // clear finaliser flag - FTB_CLEAR(block); - } - #endif - free_tail = 1; - DEBUG_printf("gc_sweep(%p)\n", (void *)PTR_FROM_BLOCK(block)); - - #ifdef LOG_HEAP_ACTIVITY - gc_log_change(block, 0); - #endif - #if MICROPY_PY_GC_COLLECT_RETVAL - MP_STATE_MEM(gc_collected)++; - #endif - // fall through to free the head - MP_FALLTHROUGH - - case AT_TAIL: - if (free_tail) { - ATB_ANY_TO_FREE(block); - #if CLEAR_ON_SWEEP - memset((void *)PTR_FROM_BLOCK(block), 0, BYTES_PER_BLOCK); #endif - } - break; + free_tail = 1; + DEBUG_printf("gc_sweep(%p)\n", (void *)PTR_FROM_BLOCK(area, block)); + #if MICROPY_PY_GC_COLLECT_RETVAL + MP_STATE_MEM(gc_collected)++; + #endif + // fall through to free the head + MP_FALLTHROUGH - case AT_MARK: - ATB_MARK_TO_HEAD(block); - free_tail = 0; - break; - } - } -} + case AT_TAIL: + if (free_tail) { + ATB_ANY_TO_FREE(area, block); + #if CLEAR_ON_SWEEP + memset((void *)PTR_FROM_BLOCK(area, block), 0, BYTES_PER_BLOCK); + #endif + } + break; -// Mark can handle NULL pointers because it verifies the pointer is within the heap bounds. -STATIC void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark)(void *ptr) { - if (VERIFY_PTR(ptr)) { - size_t block = BLOCK_FROM_PTR(ptr); - if (ATB_GET_KIND(block) == AT_HEAD) { - // An unmarked head: mark it, and mark all its children - TRACE_MARK(block, ptr); - ATB_HEAD_TO_MARK(block); - gc_mark_subtree(block); + case AT_MARK: + ATB_MARK_TO_HEAD(area, block); + free_tail = 0; + break; + } } } } @@ -389,8 +475,6 @@ void gc_collect_start(void) { size_t root_end = offsetof(mp_state_ctx_t, vm.qstr_last_chunk); gc_collect_root(ptrs + root_start / sizeof(void *), (root_end - root_start) / sizeof(void *)); - gc_mark(MP_STATE_MEM(permanent_pointers)); - #if MICROPY_ENABLE_PYSTACK // Trace root pointers from the Python stack. ptrs = (void **)(void *)MP_STATE_THREAD(pystack_start); @@ -398,8 +482,10 @@ void gc_collect_start(void) { #endif } +// CIRCUITPY void gc_collect_ptr(void *ptr) { - gc_mark(ptr); + void *ptrs[1] = { ptr }; + gc_collect_root(ptrs, 1); } // Address sanitizer needs to know that the access to ptrs[i] must always be @@ -418,18 +504,44 @@ static void *MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_get_ptr)(void **ptrs, int i) { } void gc_collect_root(void **ptrs, size_t len) { + #if !MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t *area = &MP_STATE_MEM(area); + #endif for (size_t i = 0; i < len; i++) { MICROPY_GC_HOOK_LOOP void *ptr = gc_get_ptr(ptrs, i); - // CIRCUITPY changed in PR #1816 - gc_mark(ptr); + #if MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t *area = gc_get_ptr_area(ptr); + if (!area) { + continue; + } + #else + if (!VERIFY_PTR(ptr)) { + continue; + } + #endif + size_t block = BLOCK_FROM_PTR(area, ptr); + if (ATB_GET_KIND(area, block) == AT_HEAD) { + // An unmarked head: mark it, and mark all its children + ATB_HEAD_TO_MARK(area, block); + #if MICROPY_GC_SPLIT_HEAP + gc_mark_subtree(area, block); + #else + gc_mark_subtree(block); + #endif + } } } void gc_collect_end(void) { gc_deal_with_stack_overflow(); gc_sweep(); - MP_STATE_MEM(gc_last_free_atb_index) = 0; + #if MICROPY_GC_SPLIT_HEAP + MP_STATE_MEM(gc_last_free_area) = &MP_STATE_MEM(area); + #endif + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + area->gc_last_free_atb_index = 0; + } MP_STATE_THREAD(gc_lock_depth)--; GC_EXIT(); } @@ -443,59 +555,62 @@ void gc_sweep_all(void) { void gc_info(gc_info_t *info) { GC_ENTER(); - info->total = MP_STATE_MEM(gc_pool_end) - MP_STATE_MEM(gc_pool_start); + info->total = 0; info->used = 0; info->free = 0; info->max_free = 0; info->num_1block = 0; info->num_2block = 0; info->max_block = 0; - bool finish = false; - for (size_t block = 0, len = 0, len_free = 0; !finish;) { - size_t kind = ATB_GET_KIND(block); - switch (kind) { - case AT_FREE: - info->free += 1; - len_free += 1; - len = 0; - break; + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + bool finish = false; + info->total += area->gc_pool_end - area->gc_pool_start; + for (size_t block = 0, len = 0, len_free = 0; !finish;) { + size_t kind = ATB_GET_KIND(area, block); + switch (kind) { + case AT_FREE: + info->free += 1; + len_free += 1; + len = 0; + break; - case AT_HEAD: - info->used += 1; - len = 1; - break; + case AT_HEAD: + info->used += 1; + len = 1; + break; - case AT_TAIL: - info->used += 1; - len += 1; - break; + case AT_TAIL: + info->used += 1; + len += 1; + break; - case AT_MARK: - // shouldn't happen - break; - } - - block++; - finish = (block == MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB); - // Get next block type if possible - if (!finish) { - kind = ATB_GET_KIND(block); - } - - if (finish || kind == AT_FREE || kind == AT_HEAD) { - if (len == 1) { - info->num_1block += 1; - } else if (len == 2) { - info->num_2block += 1; + case AT_MARK: + // shouldn't happen + break; } - if (len > info->max_block) { - info->max_block = len; + + block++; + finish = (block == area->gc_alloc_table_byte_len * BLOCKS_PER_ATB); + // Get next block type if possible + if (!finish) { + kind = ATB_GET_KIND(area, block); } - if (finish || kind == AT_HEAD) { - if (len_free > info->max_free) { - info->max_free = len_free; + + if (finish || kind == AT_FREE || kind == AT_HEAD) { + if (len == 1) { + info->num_1block += 1; + } else if (len == 2) { + info->num_2block += 1; + } + if (len > info->max_block) { + info->max_block = len; + } + if (finish || kind == AT_HEAD) { + if (len_free > info->max_free) { + info->max_free = len_free; + } + len_free = 0; } - len_free = 0; } } } @@ -506,7 +621,11 @@ void gc_info(gc_info_t *info) { } bool gc_alloc_possible(void) { - return MP_STATE_MEM(gc_pool_start) != 0; + #if MICROPY_GC_SPLIT_HEAP + return MP_STATE_MEM(gc_last_free_area) != 0; + #else + return MP_STATE_MEM(area).gc_pool_start != 0; + #endif } void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { @@ -524,12 +643,9 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { return NULL; } - if (MP_STATE_MEM(gc_pool_start) == 0) { - reset_into_safe_mode(SAFE_MODE_GC_ALLOC_OUTSIDE_VM); - } - GC_ENTER(); + mp_state_mem_area_t *area; size_t i; size_t end_block; size_t start_block; @@ -547,16 +663,37 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { for (;;) { + #if MICROPY_GC_SPLIT_HEAP + area = MP_STATE_MEM(gc_last_free_area); + #else + area = &MP_STATE_MEM(area); + #endif + + if (area == 0) { + reset_into_safe_mode(SAFE_MODE_GC_ALLOC_OUTSIDE_VM); + } + // look for a run of n_blocks available blocks - n_free = 0; - for (i = MP_STATE_MEM(gc_last_free_atb_index); i < MP_STATE_MEM(gc_alloc_table_byte_len); i++) { - byte a = MP_STATE_MEM(gc_alloc_table_start)[i]; - // *FORMAT-OFF* - if (ATB_0_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 0; goto found; } } else { n_free = 0; } - if (ATB_1_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 1; goto found; } } else { n_free = 0; } - if (ATB_2_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 2; goto found; } } else { n_free = 0; } - if (ATB_3_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 3; goto found; } } else { n_free = 0; } - // *FORMAT-ON* + for (; area != NULL; area = NEXT_AREA(area), i = 0) { + n_free = 0; + for (i = area->gc_last_free_atb_index; i < area->gc_alloc_table_byte_len; i++) { + byte a = area->gc_alloc_table_start[i]; + // *FORMAT-OFF* + if (ATB_0_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 0; goto found; } } else { n_free = 0; } + if (ATB_1_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 1; goto found; } } else { n_free = 0; } + if (ATB_2_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 2; goto found; } } else { n_free = 0; } + if (ATB_3_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 3; goto found; } } else { n_free = 0; } + // *FORMAT-ON* + } + + // No free blocks found on this heap. Mark this heap as + // filled, so we won't try to find free space here again until + // space is freed. + #if MICROPY_GC_SPLIT_HEAP + if (n_blocks == 1) { + area->gc_last_free_atb_index = (i + 1) / BLOCKS_PER_ATB; // or (size_t)-1 + } + #endif } GC_EXIT(); @@ -582,26 +719,29 @@ found: // before this one. Also, whenever we free or shink a block we must check // if this index needs adjusting (see gc_realloc and gc_free). if (n_free == 1) { - MP_STATE_MEM(gc_last_free_atb_index) = (i + 1) / BLOCKS_PER_ATB; + #if MICROPY_GC_SPLIT_HEAP + MP_STATE_MEM(gc_last_free_area) = area; + #endif + area->gc_last_free_atb_index = (i + 1) / BLOCKS_PER_ATB; } - + // CIRCUITPY #ifdef LOG_HEAP_ACTIVITY gc_log_change(start_block, end_block - start_block + 1); #endif // mark first block as used head - ATB_FREE_TO_HEAD(start_block); + ATB_FREE_TO_HEAD(area, start_block); // mark rest of blocks as used tail // TODO for a run of many blocks can make this more efficient for (size_t bl = start_block + 1; bl <= end_block; bl++) { - ATB_FREE_TO_TAIL(bl); + ATB_FREE_TO_TAIL(area, bl); } // get pointer to first block // we must create this pointer before unlocking the GC so a collection can find it - void *ret_ptr = (void *)(MP_STATE_MEM(gc_pool_start) + start_block * BYTES_PER_BLOCK); + void *ret_ptr = (void *)(area->gc_pool_start + start_block * BYTES_PER_BLOCK); DEBUG_printf("gc_alloc(%p)\n", ret_ptr); #if MICROPY_GC_ALLOC_THRESHOLD @@ -628,7 +768,7 @@ found: ((mp_obj_base_t *)ret_ptr)->type = NULL; // set mp_obj flag only if it has a finaliser GC_ENTER(); - FTB_SET(start_block); + FTB_SET(area, start_block); GC_EXIT(); } #else @@ -636,7 +776,7 @@ found: #endif #if EXTENSIVE_HEAP_PROFILING - gc_dump_alloc_table(); + gc_dump_alloc_table(&mp_plat_print); #endif #if CIRCUITPY_MEMORYMONITOR @@ -660,7 +800,9 @@ void *gc_alloc_with_finaliser(mp_uint_t n_bytes) { // TODO: freeing here does not call finaliser void gc_free(void *ptr) { if (MP_STATE_THREAD(gc_lock_depth) > 0) { - // TODO how to deal with this error? + // Cannot free while the GC is locked. However free is an optimisation + // to reclaim the memory immediately, this means it will now be left + // until the next collection. return; } @@ -669,54 +811,91 @@ void gc_free(void *ptr) { DEBUG_printf("gc_free(%p)\n", ptr); if (ptr == NULL) { + // free(NULL) is a no-op GC_EXIT(); - } else { - // CIRCUITPY extra checking - if (MP_STATE_MEM(gc_pool_start) == 0) { - reset_into_safe_mode(SAFE_MODE_GC_ALLOC_OUTSIDE_VM); - } - // get the GC block number corresponding to this pointer - assert(VERIFY_PTR(ptr)); - size_t block = BLOCK_FROM_PTR(ptr); - assert(ATB_GET_KIND(block) == AT_HEAD); - - #if MICROPY_ENABLE_FINALISER - FTB_CLEAR(block); - #endif - - // set the last_free pointer to this block if it's earlier in the heap - if (block / BLOCKS_PER_ATB < MP_STATE_MEM(gc_last_free_atb_index)) { - MP_STATE_MEM(gc_last_free_atb_index) = block / BLOCKS_PER_ATB; - } - - #ifdef LOG_HEAP_ACTIVITY - gc_log_change(start_block, 0); - #endif - - // free head and all of its tail blocks - do { - ATB_ANY_TO_FREE(block); - block += 1; - } while (ATB_GET_KIND(block) == AT_TAIL); - - GC_EXIT(); - - #if EXTENSIVE_HEAP_PROFILING - gc_dump_alloc_table(); - #endif + return; } + + // get the GC block number corresponding to this pointer + mp_state_mem_area_t *area; + #if MICROPY_GC_SPLIT_HEAP + area = gc_get_ptr_area(ptr); + // CIRCUITPY extra checking + if (MP_STATE_MEM(gc_pool_start) == 0) { + reset_into_safe_mode(SAFE_MODE_GC_ALLOC_OUTSIDE_VM); + } + // assert(area); + #else + assert(VERIFY_PTR(ptr)); + area = &MP_STATE_MEM(area); + #endif + + size_t block = BLOCK_FROM_PTR(area, ptr); + assert(ATB_GET_KIND(area, block) == AT_HEAD); + + #if MICROPY_ENABLE_FINALISER + FTB_CLEAR(area, block); + #endif + + #if MICROPY_GC_SPLIT_HEAP + if (MP_STATE_MEM(gc_last_free_area) != area) { + // We freed something but it isn't the current area. Reset the + // last free area to the start for a rescan. Note that this won't + // give much of a performance hit, since areas that are completely + // filled will likely be skipped (the gc_last_free_atb_index + // points to the last block). + // The reason why this is necessary is because it is not possible + // to see which area came first (like it is possible to adjust + // gc_last_free_atb_index based on whether the freed block is + // before the last free block). + MP_STATE_MEM(gc_last_free_area) = &MP_STATE_MEM(area); + } + #endif + + // set the last_free pointer to this block if it's earlier in the heap + if (block / BLOCKS_PER_ATB < area->gc_last_free_atb_index) { + area->gc_last_free_atb_index = block / BLOCKS_PER_ATB; + } + + #ifdef LOG_HEAP_ACTIVITY + gc_log_change(start_block, 0); + #endif + + // free head and all of its tail blocks + do { + ATB_ANY_TO_FREE(area, block); + block += 1; + } while (ATB_GET_KIND(area, block) == AT_TAIL); + + GC_EXIT(); + + #if EXTENSIVE_HEAP_PROFILING + gc_dump_alloc_table(&mp_plat_print); + #endif } size_t gc_nbytes(const void *ptr) { GC_ENTER(); + + mp_state_mem_area_t *area; + #if MICROPY_GC_SPLIT_HEAP + area = gc_get_ptr_area(ptr); + #else if (VERIFY_PTR(ptr)) { - size_t block = BLOCK_FROM_PTR(ptr); - if (ATB_GET_KIND(block) == AT_HEAD) { + area = &MP_STATE_MEM(area); + } else { + area = NULL; + } + #endif + + if (area) { + size_t block = BLOCK_FROM_PTR(area, ptr); + if (ATB_GET_KIND(area, block) == AT_HEAD) { // work out number of consecutive blocks in the chain starting with this on size_t n_blocks = 0; do { n_blocks += 1; - } while (ATB_GET_KIND(block + n_blocks) == AT_TAIL); + } while (ATB_GET_KIND(area, block + n_blocks) == AT_TAIL); GC_EXIT(); return n_blocks * BYTES_PER_BLOCK; } @@ -727,23 +906,6 @@ size_t gc_nbytes(const void *ptr) { return 0; } -bool gc_has_finaliser(const void *ptr) { - #if MICROPY_ENABLE_FINALISER - GC_ENTER(); - if (VERIFY_PTR(ptr)) { - bool has_finaliser = FTB_GET(BLOCK_FROM_PTR(ptr)); - GC_EXIT(); - return has_finaliser; - } - - // invalid pointer - GC_EXIT(); - #else - (void)ptr; - #endif - return false; -} - #if 0 // old, simple realloc that didn't expand memory in place void *gc_realloc(void *ptr, mp_uint_t n_bytes) { @@ -794,9 +956,16 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { GC_ENTER(); // get the GC block number corresponding to this pointer + mp_state_mem_area_t *area; + #if MICROPY_GC_SPLIT_HEAP + area = gc_get_ptr_area(ptr); + assert(area); + #else assert(VERIFY_PTR(ptr)); - size_t block = BLOCK_FROM_PTR(ptr); - assert(ATB_GET_KIND(block) == AT_HEAD); + area = &MP_STATE_MEM(area); + #endif + size_t block = BLOCK_FROM_PTR(area, ptr); + assert(ATB_GET_KIND(area, block) == AT_HEAD); // compute number of new blocks that are requested size_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK; @@ -809,9 +978,9 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { // efficiently shrink it (see below for shrinking code). size_t n_free = 0; size_t n_blocks = 1; // counting HEAD block - size_t max_block = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; + size_t max_block = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; for (size_t bl = block + n_blocks; bl < max_block; bl++) { - byte block_type = ATB_GET_KIND(bl); + byte block_type = ATB_GET_KIND(area, bl); if (block_type == AT_TAIL) { n_blocks++; continue; @@ -837,18 +1006,25 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { if (new_blocks < n_blocks) { // free unneeded tail blocks for (size_t bl = block + new_blocks, count = n_blocks - new_blocks; count > 0; bl++, count--) { - ATB_ANY_TO_FREE(bl); + ATB_ANY_TO_FREE(area, bl); } + #if MICROPY_GC_SPLIT_HEAP + if (MP_STATE_MEM(gc_last_free_area) != area) { + // See comment in gc_free. + MP_STATE_MEM(gc_last_free_area) = &MP_STATE_MEM(area); + } + #endif + // set the last_free pointer to end of this block if it's earlier in the heap - if ((block + new_blocks) / BLOCKS_PER_ATB < MP_STATE_MEM(gc_last_free_atb_index)) { - MP_STATE_MEM(gc_last_free_atb_index) = (block + new_blocks) / BLOCKS_PER_ATB; + if ((block + new_blocks) / BLOCKS_PER_ATB < area->gc_last_free_atb_index) { + area->gc_last_free_atb_index = (block + new_blocks) / BLOCKS_PER_ATB; } GC_EXIT(); #if EXTENSIVE_HEAP_PROFILING - gc_dump_alloc_table(); + gc_dump_alloc_table(&mp_plat_print); #endif #ifdef LOG_HEAP_ACTIVITY @@ -866,8 +1042,8 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { if (new_blocks <= n_blocks + n_free) { // mark few more blocks as used tail for (size_t bl = block + n_blocks; bl < block + new_blocks; bl++) { - assert(ATB_GET_KIND(bl) == AT_FREE); - ATB_FREE_TO_TAIL(bl); + assert(ATB_GET_KIND(area, bl) == AT_FREE); + ATB_FREE_TO_TAIL(area, bl); } GC_EXIT(); @@ -881,7 +1057,7 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { #endif #if EXTENSIVE_HEAP_PROFILING - gc_dump_alloc_table(); + gc_dump_alloc_table(&mp_plat_print); #endif #ifdef LOG_HEAP_ACTIVITY @@ -896,7 +1072,7 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { } #if MICROPY_ENABLE_FINALISER - bool ftb_state = FTB_GET(block); + bool ftb_state = FTB_GET(area, block); #else bool ftb_state = false; #endif @@ -955,142 +1131,144 @@ bool gc_never_free(void *ptr) { return true; } -void gc_dump_info(void) { +void gc_dump_info(const mp_print_t *print) { gc_info_t info; gc_info(&info); - mp_printf(&mp_plat_print, "GC: total: %u, used: %u, free: %u\n", + mp_printf(print, "GC: total: %u, used: %u, free: %u\n", (uint)info.total, (uint)info.used, (uint)info.free); - mp_printf(&mp_plat_print, " No. of 1-blocks: %u, 2-blocks: %u, max blk sz: %u, max free sz: %u\n", + mp_printf(print, " No. of 1-blocks: %u, 2-blocks: %u, max blk sz: %u, max free sz: %u\n", (uint)info.num_1block, (uint)info.num_2block, (uint)info.max_block, (uint)info.max_free); } -void gc_dump_alloc_table(void) { +void gc_dump_alloc_table(const mp_print_t *print) { GC_ENTER(); static const size_t DUMP_BYTES_PER_LINE = 64; - #if !EXTENSIVE_HEAP_PROFILING - // When comparing heap output we don't want to print the starting - // pointer of the heap because it changes from run to run. - mp_printf(&mp_plat_print, "GC memory layout; from %p:", MP_STATE_MEM(gc_pool_start)); - #endif - for (size_t bl = 0; bl < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; bl++) { - if (bl % DUMP_BYTES_PER_LINE == 0) { - // a new line of blocks - { - // check if this line contains only free blocks - size_t bl2 = bl; - while (bl2 < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB && ATB_GET_KIND(bl2) == AT_FREE) { - bl2++; - } - if (bl2 - bl >= 2 * DUMP_BYTES_PER_LINE) { - // there are at least 2 lines containing only free blocks, so abbreviate their printing - mp_printf(&mp_plat_print, "\n (%u lines all free)", (uint)(bl2 - bl) / DUMP_BYTES_PER_LINE); - bl = bl2 & (~(DUMP_BYTES_PER_LINE - 1)); - if (bl >= MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB) { - // got to end of heap - break; + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + #if !EXTENSIVE_HEAP_PROFILING + // When comparing heap output we don't want to print the starting + // pointer of the heap because it changes from run to run. + mp_printf(print, "GC memory layout; from %p:", area->gc_pool_start); + #endif + for (size_t bl = 0; bl < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; bl++) { + if (bl % DUMP_BYTES_PER_LINE == 0) { + // a new line of blocks + { + // check if this line contains only free blocks + size_t bl2 = bl; + while (bl2 < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB && ATB_GET_KIND(area, bl2) == AT_FREE) { + bl2++; + } + if (bl2 - bl >= 2 * DUMP_BYTES_PER_LINE) { + // there are at least 2 lines containing only free blocks, so abbreviate their printing + mp_printf(print, "\n (%u lines all free)", (uint)(bl2 - bl) / DUMP_BYTES_PER_LINE); + bl = bl2 & (~(DUMP_BYTES_PER_LINE - 1)); + if (bl >= area->gc_alloc_table_byte_len * BLOCKS_PER_ATB) { + // got to end of heap + break; + } } } + // print header for new line of blocks + // (the cast to uint32_t is for 16-bit ports) + mp_printf(print, "\n%08x: ", (uint)(bl * BYTES_PER_BLOCK)); } - // print header for new line of blocks - // (the cast to uint32_t is for 16-bit ports) - // mp_printf(&mp_plat_print, "\n%05x: ", (uint)(PTR_FROM_BLOCK(bl) & (uint32_t)0xfffff)); - mp_printf(&mp_plat_print, "\n%05x: ", (uint)((bl * BYTES_PER_BLOCK) & (uint32_t)0xfffff)); - } - int c = ' '; - switch (ATB_GET_KIND(bl)) { - case AT_FREE: - c = '.'; - break; - /* this prints out if the object is reachable from BSS or STACK (for unix only) - case AT_HEAD: { - c = 'h'; - void **ptrs = (void**)(void*)&mp_state_ctx; - mp_uint_t len = offsetof(mp_state_ctx_t, vm.stack_top) / sizeof(mp_uint_t); - for (mp_uint_t i = 0; i < len; i++) { - mp_uint_t ptr = (mp_uint_t)ptrs[i]; - if (VERIFY_PTR(ptr) && BLOCK_FROM_PTR(ptr) == bl) { - c = 'B'; - break; - } - } - if (c == 'h') { - ptrs = (void**)&c; - len = ((mp_uint_t)MP_STATE_THREAD(stack_top) - (mp_uint_t)&c) / sizeof(mp_uint_t); + int c = ' '; + switch (ATB_GET_KIND(area, bl)) { + case AT_FREE: + c = '.'; + break; + /* this prints out if the object is reachable from BSS or STACK (for unix only) + case AT_HEAD: { + c = 'h'; + void **ptrs = (void**)(void*)&mp_state_ctx; + mp_uint_t len = offsetof(mp_state_ctx_t, vm.stack_top) / sizeof(mp_uint_t); for (mp_uint_t i = 0; i < len; i++) { mp_uint_t ptr = (mp_uint_t)ptrs[i]; - if (VERIFY_PTR(ptr) && BLOCK_FROM_PTR(ptr) == bl) { - c = 'S'; + if (gc_get_ptr_area(ptr) && BLOCK_FROM_PTR(ptr) == bl) { + c = 'B'; break; } } - } - break; - } - */ - /* this prints the uPy object type of the head block */ - case AT_HEAD: { - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wcast-align" - void **ptr = (void **)(MP_STATE_MEM(gc_pool_start) + bl * BYTES_PER_BLOCK); - #pragma GCC diagnostic pop - if (*ptr == &mp_type_tuple) { - c = 'T'; - } else if (*ptr == &mp_type_list) { - c = 'L'; - } else if (*ptr == &mp_type_dict) { - c = 'D'; - } else if (*ptr == &mp_type_str || *ptr == &mp_type_bytes) { - c = 'S'; - } - #if MICROPY_PY_BUILTINS_BYTEARRAY - else if (*ptr == &mp_type_bytearray) { - c = 'A'; - } - #endif - #if MICROPY_PY_ARRAY - else if (*ptr == &mp_type_array) { - c = 'A'; - } - #endif - #if MICROPY_PY_BUILTINS_FLOAT - else if (*ptr == &mp_type_float) { - c = 'F'; - } - #endif - else if (*ptr == &mp_type_fun_bc) { - c = 'B'; - } else if (*ptr == &mp_type_module) { - c = 'M'; - } else { - c = 'h'; - #if 0 - // This code prints "Q" for qstr-pool data, and "q" for qstr-str - // data. It can be useful to see how qstrs are being allocated, - // but is disabled by default because it is very slow. - for (const qstr_pool_t *pool = MP_STATE_VM(last_pool); c == 'h' && pool != NULL; pool = pool->prev) { - if ((const qstr_pool_t *)ptr == pool) { - c = 'Q'; - break; - } - for (const char *const *q = pool->qstrs, *const *q_top = pool->qstrs + pool->len; q < q_top; q++) { - if ((const char *)ptr == *q) { - c = 'q'; + if (c == 'h') { + ptrs = (void**)&c; + len = ((mp_uint_t)MP_STATE_THREAD(stack_top) - (mp_uint_t)&c) / sizeof(mp_uint_t); + for (mp_uint_t i = 0; i < len; i++) { + mp_uint_t ptr = (mp_uint_t)ptrs[i]; + if (gc_get_ptr_area(ptr) && BLOCK_FROM_PTR(ptr) == bl) { + c = 'S'; break; } } } - #endif + break; } - break; + */ + /* this prints the uPy object type of the head block */ + case AT_HEAD: { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + void **ptr = (void **)(area->gc_pool_start + bl * BYTES_PER_BLOCK); + #pragma GCC diagnostic pop + if (*ptr == &mp_type_tuple) { + c = 'T'; + } else if (*ptr == &mp_type_list) { + c = 'L'; + } else if (*ptr == &mp_type_dict) { + c = 'D'; + } else if (*ptr == &mp_type_str || *ptr == &mp_type_bytes) { + c = 'S'; + } + #if MICROPY_PY_BUILTINS_BYTEARRAY + else if (*ptr == &mp_type_bytearray) { + c = 'A'; + } + #endif + #if MICROPY_PY_ARRAY + else if (*ptr == &mp_type_array) { + c = 'A'; + } + #endif + #if MICROPY_PY_BUILTINS_FLOAT + else if (*ptr == &mp_type_float) { + c = 'F'; + } + #endif + else if (*ptr == &mp_type_fun_bc) { + c = 'B'; + } else if (*ptr == &mp_type_module) { + c = 'M'; + } else { + c = 'h'; + #if 0 + // This code prints "Q" for qstr-pool data, and "q" for qstr-str + // data. It can be useful to see how qstrs are being allocated, + // but is disabled by default because it is very slow. + for (qstr_pool_t *pool = MP_STATE_VM(last_pool); c == 'h' && pool != NULL; pool = pool->prev) { + if ((qstr_pool_t *)ptr == pool) { + c = 'Q'; + break; + } + for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) { + if ((const byte *)ptr == *q) { + c = 'q'; + break; + } + } + } + #endif + } + break; + } + case AT_TAIL: + c = '='; + break; + case AT_MARK: + c = 'm'; + break; } - case AT_TAIL: - c = '='; - break; - case AT_MARK: - c = 'm'; - break; + mp_printf(print, "%c", c); } - mp_printf(&mp_plat_print, "%c", c); + mp_print_str(print, "\n"); } mp_print_str(&mp_plat_print, "\n"); GC_EXIT(); @@ -1123,13 +1301,13 @@ void gc_test(void) { } printf("Before GC:\n"); - gc_dump_alloc_table(); + gc_dump_alloc_table(&mp_plat_print); printf("Starting GC...\n"); gc_collect_start(); gc_collect_root(ptrs, sizeof(ptrs) / sizeof(void *)); gc_collect_end(); printf("After GC:\n"); - gc_dump_alloc_table(); + gc_dump_alloc_table(&mp_plat_print); } #endif diff --git a/py/gc.h b/py/gc.h index c88ac78006..8d0a4a8607 100644 --- a/py/gc.h +++ b/py/gc.h @@ -28,15 +28,17 @@ #include #include +#include "py/mpprint.h" #include "py/mpconfig.h" #include "py/mpstate.h" #include "py/misc.h" +#if !MICROPY_GC_SPLIT_HEAP #define HEAP_PTR(ptr) ( \ - MP_STATE_MEM(gc_pool_start) != 0 /* Not on the heap if it isn't inited */ \ - && ptr >= (void *)MP_STATE_MEM(gc_pool_start) /* must be above start of pool */ \ - && ptr < (void *)MP_STATE_MEM(gc_pool_end) /* must be below end of pool */ \ + MP_STATE_MEM(area).gc_pool_start != 0 /* Not on the heap if it isn't inited */ \ + && ptr >= (void *)MP_STATE_MEM(area).gc_pool_start /* must be above start of pool */ \ + && ptr < (void *)MP_STATE_MEM(area).gc_pool_end /* must be below end of pool */ \ ) // ptr should be of type void* @@ -44,10 +46,16 @@ ((uintptr_t)(ptr) & (MICROPY_BYTES_PER_GC_BLOCK - 1)) == 0 /* must be aligned on a block */ \ && HEAP_PTR(ptr) \ ) +#endif void gc_init(void *start, void *end); void gc_deinit(void); +#if MICROPY_GC_SPLIT_HEAP +// Used to add additional memory areas to the heap. +void gc_add(void *start, void *end); +#endif + // These lock/unlock functions can be nested. // They can be used to prevent the GC from allocating/freeing. void gc_lock(void); @@ -92,7 +100,7 @@ typedef struct _gc_info_t { } gc_info_t; void gc_info(gc_info_t *info); -void gc_dump_info(void); -void gc_dump_alloc_table(void); +void gc_dump_info(const mp_print_t *print); +void gc_dump_alloc_table(const mp_print_t *print); #endif // MICROPY_INCLUDED_PY_GC_H diff --git a/py/genlast.py b/py/genlast.py deleted file mode 100644 index 1c5089fdfc..0000000000 --- a/py/genlast.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import re -import os -import itertools -from concurrent.futures import ProcessPoolExecutor -import multiprocessing -import threading -import subprocess - -from makeqstrdefs import qstr_unescape, QSTRING_BLOCK_LIST - -re_line = re.compile(r"#[line]*\s(\d+)\s\"([^\"]+)\"", re.DOTALL) -re_qstr = re.compile(r"\bMP_QSTR_[_a-zA-Z0-9]+", re.DOTALL) -re_translate = re.compile(r"translate\(\"((?:(?=(\\?))\2.)*?)\"\)", re.DOTALL) - - -def write_out(fname, output_dir, output): - if output: - for m, r in [("/", "__"), ("\\", "__"), (":", "@"), ("..", "@@")]: - fname = fname.replace(m, r) - with open(output_dir + "/" + fname + ".qstr", "w") as f: - f.write("\n".join(output) + "\n") - - -def process_file(fname, output_dir, content): - content = content.decode("utf-8", errors="ignore") - output = [] - for match in re_qstr.findall(content): - name = match.replace("MP_QSTR_", "") - if name not in QSTRING_BLOCK_LIST: - output.append("Q(" + qstr_unescape(name) + ")") - for match in re_translate.findall(content): - output.append('TRANSLATE("' + match[0] + '")') - - write_out(fname, output_dir, output) - - -def checkoutput1(args): - info = subprocess.run(args, check=True, stdout=subprocess.PIPE, input="") - return info.stdout - - -def preprocess(command, output_dir, fn): - try: - output = checkoutput1(command + [fn]) - process_file(fn, output_dir, output) - except Exception as e: - print(e, file=sys.stderr) - raise - - -def maybe_preprocess(command, output_dir, fn): - # Preprocess the source file if it contains "MP_QSTR", "translate", - # or if it uses enum.h (which generates "MP_QSTR" strings. - if subprocess.call(["grep", "-lqE", r"(MP_QSTR|translate|enum\.h)", fn]) == 0: - preprocess(command, output_dir, fn) - - -if __name__ == "__main__": - idx1 = sys.argv.index("--") - idx2 = sys.argv.index("--", idx1 + 1) - output_dir = sys.argv[1] - check = sys.argv[2:idx1] - always = sys.argv[idx1 + 1 : idx2] - command = sys.argv[idx2 + 1 :] - - if not os.path.isdir(output_dir): - os.makedirs(output_dir) - - # Mac and Windows use 'spawn'. Uncomment this during testing to catch spawn-specific problems on Linux. - # multiprocessing.set_start_method("spawn") - executor = ProcessPoolExecutor(max_workers=multiprocessing.cpu_count() + 1) - results = [] - try: - results.extend( - executor.map( - maybe_preprocess, itertools.repeat(command), itertools.repeat(output_dir), check - ) - ) - results.extend( - executor.map( - preprocess, itertools.repeat(command), itertools.repeat(output_dir), always - ) - ) - except subprocess.CalledProcessError: - raise SystemExit(1) - executor.shutdown() diff --git a/py/lexer.c b/py/lexer.c index 39e9662f63..e7d0e81440 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -356,6 +356,9 @@ STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw, bool is_fstring) vstr_add_byte(&lex->vstr, '{'); next_char(lex); } else { + // wrap each argument in (), e.g. + // f"{a,b,}, {c}" --> "{}".format((a,b), (c),) + vstr_add_byte(&lex->fstring_args, '('); // remember the start of this argument (if we need it for f'{a=}'). size_t i = lex->fstring_args.len; // extract characters inside the { until we reach the @@ -382,7 +385,9 @@ STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw, bool is_fstring) // remove the trailing '=' lex->fstring_args.len--; } - // comma-separate args + // close the paren-wrapped arg to .format(). + vstr_add_byte(&lex->fstring_args, ')'); + // comma-separate args to .format(). vstr_add_byte(&lex->fstring_args, ','); } vstr_add_byte(&lex->vstr, '{'); diff --git a/py/make_root_pointers.py b/py/make_root_pointers.py new file mode 100644 index 0000000000..efe398b822 --- /dev/null +++ b/py/make_root_pointers.py @@ -0,0 +1,55 @@ +""" +This pre-processor parses a single file containing a list of +MP_REGISTER_ROOT_POINTER(variable declaration) items. + +These are used to generate a header with the required entries for +"struct _mp_state_vm_t" in py/mpstate.h +""" + +from __future__ import print_function + +import argparse +import io +import re + + +PATTERN = re.compile(r"MP_REGISTER_ROOT_POINTER\((.*?)\);") + + +def find_root_pointer_registrations(filename): + """Find any MP_REGISTER_ROOT_POINTER definitions in the provided file. + + :param str filename: path to file to check + :return: List[variable_declaration] + """ + with io.open(filename, encoding="utf-8") as c_file_obj: + return set(re.findall(PATTERN, c_file_obj.read())) + + +def generate_root_pointer_header(root_pointers): + """Generate header with root pointer entries. + + :param List[variable_declaration] root_pointers: root pointer declarations + :return: None + """ + + # Print header file for all external modules. + print("// Automatically generated by make_root_pointers.py.") + print() + + for item in root_pointers: + print(item, end=";") + print() + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("file", nargs=1, help="file with MP_REGISTER_ROOT_POINTER definitions") + args = parser.parse_args() + + root_pointers = find_root_pointer_registrations(args.file[0]) + generate_root_pointer_header(sorted(root_pointers)) + + +if __name__ == "__main__": + main() diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 504fc31a15..d476f5988a 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -342,6 +342,10 @@ def parse_input_headers_with_translations(infiles): order = -190000 elif ident.startswith("__"): order -= 100000 + elif ident.startswith("_lt"): + order -= 100000 + elif ident.startswith("_gt"): + order -= 100000 qstrs[ident] = (order, ident, qstr) if not qcfgs and qstrs: diff --git a/py/makeqstrdefs.py b/py/makeqstrdefs.py index 178149c688..8990f2a034 100644 --- a/py/makeqstrdefs.py +++ b/py/makeqstrdefs.py @@ -2,7 +2,7 @@ This script processes the output from the C preprocessor and extracts all qstr. Each qstr is transformed into a qstr definition of the form 'Q(...)'. -This script works with Python 3.x +This script works with Python 3.x (CIRCUITPY: not 2.x) """ from __future__ import print_function @@ -17,10 +17,6 @@ import multiprocessing, multiprocessing.dummy from html.entities import name2codepoint -# Blocklist of qstrings that are specially handled in further -# processing and should be ignored -QSTRING_BLOCK_LIST = set(["NULL", "number_of"]) - # add some custom names to map characters that aren't in HTML name2codepoint["hyphen"] = ord("-") name2codepoint["space"] = ord(" ") @@ -64,6 +60,9 @@ _MODE_COMPRESS = "compress" # Extract MP_REGISTER_MODULE(...) macros. _MODE_MODULE = "module" +# Extract MP_REGISTER_ROOT_POINTER(...) macros. +_MODE_ROOT_POINTER = "root_pointer" + def is_c_source(fname): return os.path.splitext(fname)[1] in [".c"] @@ -135,25 +134,26 @@ def qstr_unescape(qstr): def process_file(f): - re_line = re.compile(r"#[line]*\s\d+\s\"([^\"]+)\"") + # match gcc-like output (# n "file") and msvc-like output (#line n "file") + re_line = re.compile(r"^#(?:line)?\s+\d+\s\"([^\"]+)\"") if args.mode == _MODE_QSTR: re_match = re.compile(r"MP_QSTR_[_a-zA-Z0-9]+") elif args.mode == _MODE_COMPRESS: re_match = re.compile(r'MP_COMPRESSED_ROM_TEXT\("([^"]*)"\)') elif args.mode == _MODE_MODULE: re_match = re.compile(r"MP_REGISTER_MODULE\(.*?,\s*.*?\);") + elif args.mode == _MODE_ROOT_POINTER: + re_match = re.compile(r"MP_REGISTER_ROOT_POINTER\(.*?\);") re_translate = re.compile(r"translate\(\"((?:(?=(\\?))\2.)*?)\"\)") output = [] last_fname = None for line in f: if line.isspace(): continue - # match gcc-like output (# n "file") and msvc-like output (#line n "file") - if line.startswith(("# ", "#line")): - m = re_line.match(line) - assert m is not None + m = re_line.match(line) + if m: fname = m.group(1) - if os.path.splitext(fname)[1] not in [".c", ".cpp"]: + if not is_c_source(fname) and not is_cxx_source(fname): continue if fname != last_fname: write_out(last_fname, output) @@ -163,9 +163,9 @@ def process_file(f): for match in re_match.findall(line): if args.mode == _MODE_QSTR: name = match.replace("MP_QSTR_", "") - if name not in QSTRING_BLOCK_LIST: - output.append("Q(" + qstr_unescape(name) + ")") - elif args.mode in (_MODE_COMPRESS, _MODE_MODULE): + # CIRCUITPY: undo character escapes in qstrs in C code + output.append("Q(" + qstr_unescape(name) + ")") + elif args.mode in (_MODE_COMPRESS, _MODE_MODULE, _MODE_ROOT_POINTER): output.append(match) for match in re_translate.findall(line): @@ -205,6 +205,8 @@ def cat_together(): mode_full = "Compressed data" elif args.mode == _MODE_MODULE: mode_full = "Module registrations" + elif args.mode == _MODE_ROOT_POINTER: + mode_full = "Root pointer registrations" if old_hash != new_hash: print(mode_full, "updated") try: @@ -265,7 +267,7 @@ if __name__ == "__main__": args.output_dir = sys.argv[4] args.output_file = None if len(sys.argv) == 5 else sys.argv[5] # Unused for command=split - if args.mode not in (_MODE_QSTR, _MODE_COMPRESS, _MODE_MODULE): + if args.mode not in (_MODE_QSTR, _MODE_COMPRESS, _MODE_MODULE, _MODE_ROOT_POINTER): print("error: mode %s unrecognised" % sys.argv[2]) sys.exit(2) diff --git a/py/makeversionhdr.py b/py/makeversionhdr.py index 11d162ecea..bc9dbdfb79 100644 --- a/py/makeversionhdr.py +++ b/py/makeversionhdr.py @@ -6,31 +6,46 @@ This script works with Python 3.7 and newer from __future__ import print_function +import argparse import sys import os import pathlib import datetime import subprocess -tools_describe = str(pathlib.Path(__file__).parent.parent / "tools/describe") +# CIRCUITPY: use external script that can override git describe output with an +# environment variable. +tools_describe = str(pathlib.Path(__file__).resolve().parent.parent / "tools/describe") -def get_version_info_from_git(): +def get_version_info_from_git(repo_path): + # Python 2.6 doesn't have check_output, so check for that + try: + subprocess.check_output + subprocess.check_call + except AttributeError: + return None + # Note: git describe doesn't work if no tag is available try: git_tag = subprocess.check_output( - [tools_describe], stderr=subprocess.STDOUT, universal_newlines=True, shell=True + [tools_describe], + cwd=repo_path, + shell=True, + stderr=subprocess.STDOUT, + universal_newlines=True, ).strip() except subprocess.CalledProcessError as er: if er.returncode == 128: # git exit code of 128 means no repository found return None git_tag = "" - except OSError as e: + except OSError: return None try: git_hash = subprocess.check_output( ["git", "rev-parse", "--short", "HEAD"], + cwd=repo_path, stderr=subprocess.STDOUT, universal_newlines=True, ).strip() @@ -42,17 +57,22 @@ def get_version_info_from_git(): try: # Check if there are any modified files. subprocess.check_call( - ["git", "diff", "--no-ext-diff", "--quiet", "--exit-code"], stderr=subprocess.STDOUT + ["git", "diff", "--no-ext-diff", "--quiet", "--exit-code"], + cwd=repo_path, + stderr=subprocess.STDOUT, ) # Check if there are any staged files. subprocess.check_call( - ["git", "diff-index", "--cached", "--quiet", "HEAD", "--"], stderr=subprocess.STDOUT + ["git", "diff-index", "--cached", "--quiet", "HEAD", "--"], + cwd=repo_path, + stderr=subprocess.STDOUT, ) except subprocess.CalledProcessError: git_hash += "-dirty" except OSError: return None + # CIRCUITPY # Try to extract MicroPython version from git tag ver = git_tag.split("-")[0].split(".") @@ -70,9 +90,9 @@ If you cloned from a fork, fetch the tags from adafruit/circuitpython as follows ) -def make_version_header(filename): +def make_version_header(repo_path, filename): # Get version info using git (required) - info = get_version_info_from_git() + info = get_version_info_from_git(repo_path) if info is None: cannot_determine_version() git_tag, git_hash, ver = info @@ -120,9 +140,26 @@ def make_version_header(filename): # Only write the file if we need to if write_file: + print("GEN %s" % filename) with open(filename, "w") as f: f.write(file_data) +def main(): + parser = argparse.ArgumentParser() + # makeversionheader.py lives in repo/py, so default repo_path to the + # parent of sys.argv[0]'s directory. + parser.add_argument( + "-r", + "--repo-path", + default=os.path.join(os.path.dirname(sys.argv[0]), ".."), + help="path to MicroPython Git repo to query for version", + ) + parser.add_argument("dest", nargs=1, help="output file path") + args = parser.parse_args() + + make_version_header(args.repo_path, args.dest[0]) + + if __name__ == "__main__": - make_version_header(sys.argv[1]) + main() diff --git a/py/map.c b/py/map.c index b194250cb4..c18df5a9f3 100644 --- a/py/map.c +++ b/py/map.c @@ -174,7 +174,7 @@ mp_map_elem_t *MICROPY_WRAP_MP_MAP_LOOKUP(mp_map_lookup)(mp_map_t * map, mp_obj_ if (compare_only_ptrs) { if (mp_obj_is_qstr(index)) { // Index is a qstr, so can just do ptr comparison. - } else if (mp_obj_is_type(index, &mp_type_str)) { + } else if (mp_obj_is_exact_type(index, &mp_type_str)) { // Index is a non-interned string. // We can either intern the string, or force a full equality comparison. // We chose the latter, since interning costs time and potentially RAM, @@ -221,6 +221,7 @@ mp_map_elem_t *MICROPY_WRAP_MP_MAP_LOOKUP(mp_map_lookup)(mp_map_t * map, mp_obj_ } mp_map_elem_t *elem = map->table + map->used++; elem->key = index; + elem->value = MP_OBJ_NULL; if (!mp_obj_is_qstr(index)) { map->all_keys_are_qstrs = 0; } diff --git a/py/misc.h b/py/misc.h index 816d6446b1..78cddc394a 100644 --- a/py/misc.h +++ b/py/misc.h @@ -54,6 +54,11 @@ typedef unsigned int uint; // Static assertion macro #define MP_STATIC_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)])) +#if defined(_MSC_VER) +#define MP_STATIC_ASSERT_NOT_MSC(cond) (1) +#else +#define MP_STATIC_ASSERT_NOT_MSC(cond) MP_STATIC_ASSERT(cond) +#endif // Round-up integer division #define MP_CEIL_DIVIDE(a, b) (((a) + (b) - 1) / (b)) @@ -70,6 +75,7 @@ typedef unsigned int uint; #define m_new_obj(type) (m_new(type, 1)) #define m_new_obj_maybe(type) (m_new_maybe(type, 1)) #define m_new_obj_var(obj_type, var_type, var_num) ((obj_type *)m_malloc(sizeof(obj_type) + sizeof(var_type) * (var_num))) +#define m_new_obj_var0(obj_type, var_type, var_num) ((obj_type *)m_malloc0(sizeof(obj_type) + sizeof(var_type) * (var_num))) #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))) #if MICROPY_ENABLE_FINALISER #define m_new_obj_with_finaliser(type) ((type *)(m_malloc_with_finaliser(sizeof(type)))) @@ -179,7 +185,7 @@ typedef struct _vstr_t { size_t alloc; size_t len; char *buf; - bool fixed_buf : 1; + bool fixed_buf; } vstr_t; // convenience macro to declare a vstr with a fixed size buffer on the stack @@ -244,10 +250,12 @@ extern mp_uint_t mp_verbose_flag; #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE #define MP_FLOAT_EXP_BITS (11) +#define MP_FLOAT_EXP_OFFSET (1023) #define MP_FLOAT_FRAC_BITS (52) typedef uint64_t mp_float_uint_t; #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #define MP_FLOAT_EXP_BITS (8) +#define MP_FLOAT_EXP_OFFSET (127) #define MP_FLOAT_FRAC_BITS (23) typedef uint32_t mp_float_uint_t; #endif @@ -294,15 +302,16 @@ typedef union _mp_float_union_t { // Force usage of the MP_ERROR_TEXT macro by requiring an opaque type. typedef struct { - #ifdef __clang__ - // Fix "error: empty struct has size 0 in C, size 1 in C++". + #if defined(__clang__) || defined(_MSC_VER) + // Fix "error: empty struct has size 0 in C, size 1 in C++", and the msvc counterpart + // "C requires that a struct or union have at least one member" char dummy; #endif } *mp_rom_error_text_t; #include -inline __attribute__((always_inline)) const char *MP_COMPRESSED_ROM_TEXT(const char *msg) { +inline MP_ALWAYSINLINE const char *MP_COMPRESSED_ROM_TEXT(const char *msg) { // "genhdr/compressed.data.h" contains an invocation of the MP_MATCH_COMPRESSED macro for each compressed string. // The giant if(strcmp) tree is optimized by the compiler, which turns this into a direct return of the compressed data. #define MP_MATCH_COMPRESSED(a, b) if (strcmp(msg, a) == 0) { return b; } else @@ -332,7 +341,9 @@ typedef const char *mp_rom_error_text_t; // Might add more types of compressed text in the future. // For now, forward directly to MP_COMPRESSED_ROM_TEXT. // CIRCUITPY: MP_ERROR_TEXT() -> translate() -#if !CIRCUITPY +#if CIRCUITPY +#include "supervisor/shared/translate/translate.h" +#else #define MP_ERROR_TEXT(x) (mp_rom_error_text_t)MP_COMPRESSED_ROM_TEXT(x) #endif diff --git a/py/mkenv.mk b/py/mkenv.mk index a53e030aed..ee2a96e258 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -67,6 +67,7 @@ NPROC = $(PYTHON) -c 'import multiprocessing as mp; print(mp.cpu_count())' AS = $(CROSS_COMPILE)as CC = $(CROSS_COMPILE)gcc +CPP = $(CC) -E CXX = $(CROSS_COMPILE)g++ GDB = $(CROSS_COMPILE)gdb LD = $(CROSS_COMPILE)ld @@ -80,10 +81,11 @@ MAKE_FROZEN = $(PYTHON) $(TOP)/tools/make-frozen.py MPY_TOOL = $(PYTHON) $(TOP)/tools/mpy-tool.py PREPROCESS_FROZEN_MODULES = PYTHONPATH=$(TOP)/tools/python-semver $(TOP)/tools/preprocess_frozen_modules.py -MPY_LIB_DIR = $(TOP)/../micropython-lib +MPY_LIB_SUBMODULE_DIR = $(TOP)/lib/micropython-lib +MPY_LIB_DIR = $(MPY_LIB_SUBMODULE_DIR) ifeq ($(MICROPY_MPYCROSS),) -MICROPY_MPYCROSS = $(TOP)/mpy-cross/mpy-cross +MICROPY_MPYCROSS = $(TOP)/mpy-cross/build/mpy-cross MICROPY_MPYCROSS_DEPENDENCY = $(MICROPY_MPYCROSS) endif diff --git a/py/mkrules.cmake b/py/mkrules.cmake index d0dc019625..7eb5fcf018 100644 --- a/py/mkrules.cmake +++ b/py/mkrules.cmake @@ -11,6 +11,9 @@ set(MICROPY_QSTRDEFS_GENERATED "${MICROPY_GENHDR_DIR}/qstrdefs.generated.h") set(MICROPY_MODULEDEFS_SPLIT "${MICROPY_GENHDR_DIR}/moduledefs.split") set(MICROPY_MODULEDEFS_COLLECTED "${MICROPY_GENHDR_DIR}/moduledefs.collected") set(MICROPY_MODULEDEFS "${MICROPY_GENHDR_DIR}/moduledefs.h") +set(MICROPY_ROOT_POINTERS_SPLIT "${MICROPY_GENHDR_DIR}/root_pointers.split") +set(MICROPY_ROOT_POINTERS_COLLECTED "${MICROPY_GENHDR_DIR}/root_pointers.collected") +set(MICROPY_ROOT_POINTERS "${MICROPY_GENHDR_DIR}/root_pointers.h") # Need to do this before extracting MICROPY_CPP_DEF below. Rest of frozen # manifest handling is at the end of this file. @@ -46,23 +49,18 @@ target_sources(${MICROPY_TARGET} PRIVATE ${MICROPY_MPVERSION} ${MICROPY_QSTRDEFS_GENERATED} ${MICROPY_MODULEDEFS} + ${MICROPY_ROOT_POINTERS} ) # Command to force the build of another command -add_custom_command( - OUTPUT MICROPY_FORCE_BUILD - COMMENT "" - COMMAND echo -n -) - # Generate mpversion.h -add_custom_command( - OUTPUT ${MICROPY_MPVERSION} +add_custom_target( + BUILD_VERSION_HEADER ALL + BYPRODUCTS ${MICROPY_MPVERSION} COMMAND ${CMAKE_COMMAND} -E make_directory ${MICROPY_GENHDR_DIR} COMMAND ${Python3_EXECUTABLE} ${MICROPY_DIR}/py/makeversionhdr.py ${MICROPY_MPVERSION} - DEPENDS MICROPY_FORCE_BUILD ) # Generate qstrs @@ -139,6 +137,31 @@ add_custom_command( DEPENDS ${MICROPY_MODULEDEFS_COLLECTED} ) +# Generate root_pointers.h + +add_custom_command( + OUTPUT ${MICROPY_ROOT_POINTERS_SPLIT} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makeqstrdefs.py split root_pointer ${MICROPY_GENHDR_DIR}/qstr.i.last ${MICROPY_GENHDR_DIR}/root_pointer _ + COMMAND touch ${MICROPY_ROOT_POINTERS_SPLIT} + DEPENDS ${MICROPY_QSTRDEFS_LAST} + VERBATIM + COMMAND_EXPAND_LISTS +) + +add_custom_command( + OUTPUT ${MICROPY_ROOT_POINTERS_COLLECTED} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makeqstrdefs.py cat root_pointer _ ${MICROPY_GENHDR_DIR}/root_pointer ${MICROPY_ROOT_POINTERS_COLLECTED} + DEPENDS ${MICROPY_ROOT_POINTERS_SPLIT} + VERBATIM + COMMAND_EXPAND_LISTS +) + +add_custom_command( + OUTPUT ${MICROPY_ROOT_POINTERS} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/make_root_pointers.py ${MICROPY_ROOT_POINTERS_COLLECTED} > ${MICROPY_ROOT_POINTERS} + DEPENDS ${MICROPY_ROOT_POINTERS_COLLECTED} ${MICROPY_PY_DIR}/make_root_pointers.py +) + # Build frozen code if enabled if(MICROPY_FROZEN_MANIFEST) @@ -151,7 +174,12 @@ if(MICROPY_FROZEN_MANIFEST) # Note: target_compile_definitions already added earlier. if(NOT MICROPY_LIB_DIR) - set(MICROPY_LIB_DIR ${MICROPY_DIR}/../micropython-lib) + string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/micropython-lib) + set(MICROPY_LIB_DIR ${MICROPY_DIR}/lib/micropython-lib) + endif() + + if(NOT (${ECHO_SUBMODULES}) AND NOT EXISTS ${MICROPY_LIB_DIR}/README.md) + message(FATAL_ERROR " micropython-lib not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'") endif() # If MICROPY_MPYCROSS is not explicitly defined in the environment (which @@ -159,7 +187,7 @@ if(MICROPY_FROZEN_MANIFEST) # to automatically build mpy-cross if needed. set(MICROPY_MPYCROSS $ENV{MICROPY_MPYCROSS}) if(NOT MICROPY_MPYCROSS) - set(MICROPY_MPYCROSS_DEPENDENCY ${MICROPY_DIR}/mpy-cross/mpy-cross) + set(MICROPY_MPYCROSS_DEPENDENCY ${MICROPY_DIR}/mpy-cross/build/mpy-cross) if(NOT MICROPY_MAKE_EXECUTABLE) set(MICROPY_MAKE_EXECUTABLE make) endif() @@ -169,11 +197,13 @@ if(MICROPY_FROZEN_MANIFEST) ) endif() - add_custom_command( - OUTPUT ${MICROPY_FROZEN_CONTENT} - COMMAND ${Python3_EXECUTABLE} ${MICROPY_DIR}/tools/makemanifest.py -o ${MICROPY_FROZEN_CONTENT} -v "MPY_DIR=${MICROPY_DIR}" -v "MPY_LIB_DIR=${MICROPY_LIB_DIR}" -v "PORT_DIR=${MICROPY_PORT_DIR}" -v "BOARD_DIR=${MICROPY_BOARD_DIR}" -b "${CMAKE_BINARY_DIR}" -f${MICROPY_CROSS_FLAGS} ${MICROPY_FROZEN_MANIFEST} - DEPENDS MICROPY_FORCE_BUILD + add_custom_target( + BUILD_FROZEN_CONTENT ALL + BYPRODUCTS ${MICROPY_FROZEN_CONTENT} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_DIR}/tools/makemanifest.py -o ${MICROPY_FROZEN_CONTENT} -v "MPY_DIR=${MICROPY_DIR}" -v "MPY_LIB_DIR=${MICROPY_LIB_DIR}" -v "PORT_DIR=${MICROPY_PORT_DIR}" -v "BOARD_DIR=${MICROPY_BOARD_DIR}" -b "${CMAKE_BINARY_DIR}" -f${MICROPY_CROSS_FLAGS} --mpy-tool-flags=${MICROPY_MPY_TOOL_FLAGS} ${MICROPY_FROZEN_MANIFEST} + DEPENDS ${MICROPY_QSTRDEFS_GENERATED} + ${MICROPY_ROOT_POINTERS} ${MICROPY_MPYCROSS_DEPENDENCY} VERBATIM ) @@ -182,6 +212,15 @@ endif() # Update submodules if(ECHO_SUBMODULES) # If cmake is run with GIT_SUBMODULES defined on command line, process the port / board - # settings then print the final GIT_SUBMODULES variable as a fatal error and exit. - message(FATAL_ERROR "GIT_SUBMODULES=${GIT_SUBMODULES}") + # settings then print the final GIT_SUBMODULES variable and exit. + # Note: the GIT_SUBMODULES is done via echo rather than message, as message splits + # the output onto multiple lines + execute_process(COMMAND ${CMAKE_COMMAND} -E echo "GIT_SUBMODULES=${GIT_SUBMODULES}") + message(FATAL_ERROR "Done") +endif() + +# Display BOARD_VARIANTS +if(ECHO_BOARD_VARIANTS) + execute_process(COMMAND ${CMAKE_COMMAND} -E echo "BOARD_VARIANTS=${BOARD_VARIANTS}") + message(FATAL_ERROR "Done") endif() diff --git a/py/mkrules.mk b/py/mkrules.mk index 5b871af62b..87db5f24e9 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -4,11 +4,14 @@ THIS_MAKEFILE = $(lastword $(MAKEFILE_LIST)) include $(dir $(THIS_MAKEFILE))mkenv.mk endif +HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m" +HELP_MPY_LIB_SUBMODULE ?= "\033[1;31mError: micropython-lib submodule is not initialized.\033[0m Run 'make submodules'" + # Extra deps that need to happen before object compilation. OBJ_EXTRA_ORDER_DEPS = -# Generate moduledefs.h. -OBJ_EXTRA_ORDER_DEPS += $(HEADER_BUILD)/moduledefs.h +# Generate header files. +OBJ_EXTRA_ORDER_DEPS += $(HEADER_BUILD)/moduledefs.h $(HEADER_BUILD)/root_pointers.h ifeq ($(MICROPY_ROM_TEXT_COMPRESSION),1) # If compression is enabled, trigger the build of compressed.data.h... @@ -65,7 +68,7 @@ endef define compile_cxx $(ECHO) "CXX $<" -$(Q)$(CXX) $(CXXFLAGS) -c -MD -o $@ $< +$(Q)$(CXX) $(CXXFLAGS) -c -MD -o $@ $< || (echo -e $(HELP_BUILD_ERROR); false) @# The following fixes the dependency file. @# See http://make.paulandlesley.org/autodep.html for details. @# Regex adjusted from the above to play better with Windows paths, etc. @@ -75,7 +78,7 @@ $(Q)$(CXX) $(CXXFLAGS) -c -MD -o $@ $< $(RM) -f $(@:.o=.d) endef -# frozen.c and frozen_mpy.c are created in $(BUILD), so add it to the vpath as well. +# CIRCUITPY: add $(DEVICES_MODULES) and $(BUILD) vpath %.c . $(TOP) $(USER_C_MODULES) $(DEVICES_MODULES) $(BUILD) $(BUILD)/%.o: %.c $(call compile_c) @@ -127,6 +130,16 @@ $(HEADER_BUILD)/moduledefs.collected: $(HEADER_BUILD)/moduledefs.split $(STEPECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py cat module _ $(HEADER_BUILD)/module $@ +# Module definitions via MP_REGISTER_ROOT_POINTER. +$(HEADER_BUILD)/root_pointers.split: $(HEADER_BUILD)/qstr.i.last + $(STEPECHO) "GEN $@" + $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py split root_pointer $< $(HEADER_BUILD)/root_pointer _ + $(Q)$(TOUCH) $@ + +$(HEADER_BUILD)/root_pointers.collected: $(HEADER_BUILD)/root_pointers.split + $(STEPECHO) "GEN $@" + $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py cat root_pointer _ $(HEADER_BUILD)/root_pointer $@ + # Compressed error strings. $(HEADER_BUILD)/compressed.split: $(HEADER_BUILD)/qstr.i.last $(STEPECHO) "GEN $@" @@ -153,7 +166,7 @@ $(HEADER_BUILD): ifneq ($(MICROPY_MPYCROSS_DEPENDENCY),) # to automatically build mpy-cross, if needed $(MICROPY_MPYCROSS_DEPENDENCY): - $(MAKE) -C $(dir $@) + $(MAKE) -C $(TOP)/mpy-cross endif ifneq ($(FROZEN_DIR),) @@ -165,8 +178,16 @@ $(error Support for FROZEN_MPY_DIR was removed. Please use manifest.py instead, endif ifneq ($(FROZEN_MANIFEST),) +# If we're using the default submodule path for micropython-lib, then make +# sure it's included in "make submodules". +ifeq ($(MPY_LIB_DIR),$(MPY_LIB_SUBMODULE_DIR)) +GIT_SUBMODULES += lib/micropython-lib +endif + # to build frozen_content.c from a manifest -$(BUILD)/frozen_content.c: $(BUILD)/genhdr/qstrdefs.generated.h $(FROZEN_MANIFEST) | $(MICROPY_MPYCROSS_DEPENDENCY) +# CIRCUITPY: FROZEN_MANIFEST is constructed at build time +$(BUILD)/frozen_content.c: FORCE $(BUILD)/genhdr/qstrdefs.generated.h $(BUILD)/genhdr/root_pointers.h $(FROZEN_MANIFEST) | $(MICROPY_MPYCROSS_DEPENDENCY) + $(Q)test -e "$(MPY_LIB_DIR)/README.md" || (echo -e $(HELP_MPY_LIB_SUBMODULE); false) $(Q)$(MAKE_MANIFEST) -o $@ -v "MPY_DIR=$(TOP)" -v "MPY_LIB_DIR=$(MPY_LIB_DIR)" -v "PORT_DIR=$(shell pwd)" -v "BOARD_DIR=$(BOARD_DIR)" -b "$(BUILD)" $(if $(MPY_CROSS_FLAGS),-f"$(MPY_CROSS_FLAGS)",) --mpy-tool-flags="$(MPY_TOOL_FLAGS)" $(FROZEN_MANIFEST) endif @@ -180,22 +201,22 @@ ifneq (,$(findstring mingw,$(COMPILER_TARGET))) PROG := $(PROG).exe endif -all: $(PROG) +all: $(BUILD)/$(PROG) -$(PROG): $(OBJ) - $(STEPECHO) "LINK $@" +$(BUILD)/$(PROG): $(OBJ) + $(ECHO) "LINK $@" # Do not pass COPT here - it's *C* compiler optimizations. For example, # we may want to compile using Thumb, but link with non-Thumb libc. $(Q)$(CC) -o $@ $^ $(LIB) $(LDFLAGS) -ifdef STRIP_CIRCUITPYTHON +ifndef DEBUG $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $@ endif $(Q)$(SIZE) $$(find $(BUILD) -path "$(BUILD)/build/frozen*.o") $@ clean: clean-prog clean-prog: - $(RM) -f $(PROG) - $(RM) -f $(PROG).map + $(RM) -f $(BUILD)/$(PROG) + $(RM) -f $(BUILD)/$(PROG).map .PHONY: clean-prog endif @@ -215,8 +236,8 @@ LIBMICROPYTHON = libmicropython.a # with 3rd-party projects which don't have proper dependency # tracking. Then LIBMICROPYTHON_EXTRA_CMD can e.g. touch some # other file to cause needed effect, e.g. relinking with new lib. -lib $(LIBMICROPYTHON): $(OBJ) - $(Q)$(AR) rcs $(LIBMICROPYTHON) $^ +lib $(BUILD)/$(LIBMICROPYTHON): $(OBJ) + $(Q)$(AR) rcs $(BUILD)/$(LIBMICROPYTHON) $^ $(LIBMICROPYTHON_EXTRA_CMD) clean: @@ -237,6 +258,7 @@ print-def: -include $(OBJ:.o=.P) +# CIRCUITPY addition # Print out the value of a make variable. # https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile print-%: diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 870b19d7b2..e5695bfb53 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -35,8 +35,6 @@ #include "py/builtin.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_FLOAT #include #endif @@ -253,7 +251,7 @@ STATIC mp_obj_t mp_builtin_input(size_t n_args, const mp_obj_t *args) { if (line.len == 0 && ret == CHAR_CTRL_D) { mp_raise_type(&mp_type_EOFError); } - return mp_obj_new_str_from_vstr(&mp_type_str, &line); + return mp_obj_new_str_from_vstr(&line); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj, 0, 1, mp_builtin_input); @@ -462,7 +460,7 @@ STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) { #if MICROPY_CAN_OVERRIDE_BUILTINS // Set "_" special variable mp_obj_t dest[2] = {MP_OBJ_SENTINEL, o}; - mp_type_module.attr(MP_OBJ_FROM_PTR(&mp_module_builtins), MP_QSTR__, dest); + MP_OBJ_TYPE_GET_SLOT(&mp_type_module, attr)(MP_OBJ_FROM_PTR(&mp_module_builtins), MP_QSTR__, dest); #endif } return mp_const_none; @@ -474,7 +472,7 @@ STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) { mp_print_t print; vstr_init_print(&vstr, 16, &print); mp_obj_print_helper(&print, o_in, PRINT_REPR); - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_utf8_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr); @@ -554,7 +552,7 @@ STATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t if (n_args > 1) { mp_raise_TypeError(MP_ERROR_TEXT("must use keyword argument for key function")); } - mp_obj_t self = mp_type_list.make_new(&mp_type_list, 1, 0, args); + mp_obj_t self = mp_obj_list_make_new(&mp_type_list, 1, 0, args); mp_obj_list_sort(1, &self, kwargs); return self; diff --git a/py/modio.c b/py/modio.c index 985903ffe7..0ccdd5c337 100644 --- a/py/modio.c +++ b/py/modio.c @@ -37,9 +37,6 @@ #if MICROPY_PY_IO -extern const mp_obj_type_t mp_type_fileio; -extern const mp_obj_type_t mp_type_textio; - #if MICROPY_PY_IO_IOBASE STATIC const mp_obj_type_t mp_type_iobase; @@ -95,21 +92,18 @@ STATIC mp_uint_t iobase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, in } STATIC const mp_stream_p_t iobase_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = iobase_read, .write = iobase_write, .ioctl = iobase_ioctl, }; -STATIC const mp_obj_type_t mp_type_iobase = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_IOBase, - .make_new = iobase_make_new, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &iobase_p, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_iobase, + MP_QSTR_IOBase, + MP_TYPE_FLAG_NONE, + make_new, iobase_make_new, + protocol, &iobase_p + ); #endif // MICROPY_PY_IO_IOBASE @@ -195,40 +189,27 @@ STATIC const mp_rom_map_elem_t bufwriter_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(bufwriter_locals_dict, bufwriter_locals_dict_table); STATIC const mp_stream_p_t bufwriter_stream_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .write = bufwriter_write, }; -STATIC const mp_obj_type_t mp_type_bufwriter = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_BufferedWriter, - .make_new = bufwriter_make_new, - .locals_dict = (mp_obj_dict_t *)&bufwriter_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &bufwriter_stream_p, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bufwriter, + MP_QSTR_BufferedWriter, + MP_TYPE_FLAG_NONE, + make_new, bufwriter_make_new, + protocol, &bufwriter_stream_p, + locals_dict, &bufwriter_locals_dict + ); #endif // MICROPY_PY_IO_BUFFEREDWRITER STATIC const mp_rom_map_elem_t mp_module_io_globals_table[] = { - #if CIRCUITPY - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_io) }, - #else { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uio) }, - #endif // Note: mp_builtin_open_obj should be defined by port, it's not // part of the core. { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, #if MICROPY_PY_IO_IOBASE { MP_ROM_QSTR(MP_QSTR_IOBase), MP_ROM_PTR(&mp_type_iobase) }, #endif - #if MICROPY_PY_IO_FILEIO - { MP_ROM_QSTR(MP_QSTR_FileIO), MP_ROM_PTR(&mp_type_fileio) }, - #if MICROPY_CPYTHON_COMPAT - { MP_ROM_QSTR(MP_QSTR_TextIOWrapper), MP_ROM_PTR(&mp_type_textio) }, - #endif - #endif { MP_ROM_QSTR(MP_QSTR_StringIO), MP_ROM_PTR(&mp_type_stringio) }, #if MICROPY_PY_IO_BYTESIO { MP_ROM_QSTR(MP_QSTR_BytesIO), MP_ROM_PTR(&mp_type_bytesio) }, diff --git a/py/modmath.c b/py/modmath.c index 0567e5dd94..81cf0cb8fa 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -27,8 +27,6 @@ #include "py/builtin.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_MATH #include @@ -56,7 +54,7 @@ STATIC mp_obj_t math_generic_2(mp_obj_t x_obj, mp_obj_t y_obj, mp_float_t (*f)(m mp_float_t x = mp_obj_get_float(x_obj); mp_float_t y = mp_obj_get_float(y_obj); mp_float_t ans = f(x, y); - if ((isnan(ans) && !isnan(x) && !isnan(y)) || (isinf(ans) && !isinf(x))) { + if ((isnan(ans) && !isnan(x) && !isnan(y)) || (isinf(ans) && !isinf(x) && !isinf(y))) { math_error(); } return mp_obj_new_float(ans); diff --git a/py/modmicropython.c b/py/modmicropython.c index ee4d57d94b..7c097ff487 100644 --- a/py/modmicropython.c +++ b/py/modmicropython.c @@ -32,7 +32,7 @@ #include "py/gc.h" #include "py/mphal.h" -#include "supervisor/shared/translate/translate.h" +#if MICROPY_PY_MICROPYTHON // Various builtins specific to MicroPython runtime, // living in micropython module @@ -81,10 +81,10 @@ mp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args) { mp_printf(&mp_plat_print, "stack: " UINT_FMT "\n", mp_stack_usage()); #endif #if MICROPY_ENABLE_GC - gc_dump_info(); + gc_dump_info(&mp_plat_print); if (n_args == 1) { // arg given means dump gc allocation table - gc_dump_alloc_table(); + gc_dump_alloc_table(&mp_plat_print); } #else (void)n_args; @@ -213,3 +213,5 @@ const mp_obj_module_t mp_module_micropython = { }; MP_REGISTER_MODULE(MP_QSTR_micropython, mp_module_micropython); + +#endif // MICROPY_PY_MICROPYTHON diff --git a/py/modstruct.c b/py/modstruct.c index a2dfa91655..c772977013 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -34,8 +34,6 @@ #include "py/binary.h" #include "py/parsenum.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_STRUCT /* @@ -237,7 +235,7 @@ STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) { byte *p = (byte *)vstr.buf; memset(p, 0, size); struct_pack_into_internal(args[0], p, n_args - 1, &args[1]); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, MP_OBJ_FUN_ARGS_MAX, struct_pack); diff --git a/py/modsys.c b/py/modsys.c index 68d254641a..226a422833 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -113,6 +113,12 @@ STATIC const mp_rom_obj_tuple_t mp_sys_implementation_obj = { STATIC const MP_DEFINE_STR_OBJ(mp_sys_platform_obj, MICROPY_PY_SYS_PLATFORM); #endif +#ifdef MICROPY_PY_SYS_EXECUTABLE +// executable - the path to the micropython binary +// This object is non-const and is populated at startup in main() +MP_DEFINE_STR_OBJ(mp_sys_executable_obj, ""); +#endif + // exit([retval]): raise SystemExit, with optional argument given to the exception STATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { @@ -260,6 +266,10 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_getsizeof), MP_ROM_PTR(&mp_sys_getsizeof_obj) }, #endif + #if MICROPY_PY_SYS_EXECUTABLE + { MP_ROM_QSTR(MP_QSTR_executable), MP_ROM_PTR(&mp_sys_executable_obj) }, + #endif + /* * Extensions to CPython */ @@ -284,4 +294,24 @@ const mp_obj_module_t mp_module_sys = { MP_REGISTER_MODULE(MP_QSTR_sys, mp_module_sys); +// If MICROPY_PY_SYS_PATH_ARGV_DEFAULTS is not enabled then these two lists +// must be initialised after the call to mp_init. +MP_REGISTER_ROOT_POINTER(mp_obj_list_t mp_sys_path_obj); +MP_REGISTER_ROOT_POINTER(mp_obj_list_t mp_sys_argv_obj); + +#if MICROPY_PY_SYS_EXC_INFO +// current exception being handled, for sys.exc_info() +MP_REGISTER_ROOT_POINTER(mp_obj_base_t * cur_exception); #endif + +#if MICROPY_PY_SYS_ATEXIT +// exposed through sys.atexit function +MP_REGISTER_ROOT_POINTER(mp_obj_t sys_exitfunc); +#endif + +#if MICROPY_PY_SYS_ATTR_DELEGATION +// Contains mutable sys attributes. +MP_REGISTER_ROOT_POINTER(mp_obj_t sys_mutable[MP_SYS_MUTABLE_NUM]); +#endif + +#endif // MICROPY_PY_SYS diff --git a/py/modthread.c b/py/modthread.c index bad94fbf2f..51d63e4703 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -116,11 +116,12 @@ STATIC const mp_rom_map_elem_t thread_lock_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(thread_lock_locals_dict, thread_lock_locals_dict_table); -STATIC const mp_obj_type_t mp_type_thread_lock = { - { &mp_type_type }, - .name = MP_QSTR_lock, - .locals_dict = (mp_obj_dict_t *)&thread_lock_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_thread_lock, + MP_QSTR_lock, + MP_TYPE_FLAG_NONE, + locals_dict, &thread_lock_locals_dict + ); /****************************************************************/ // _thread module diff --git a/py/moduerrno.c b/py/moduerrno.c index a132474e4c..2332b5df96 100644 --- a/py/moduerrno.c +++ b/py/moduerrno.c @@ -30,8 +30,6 @@ #include "py/obj.h" #include "py/mperrno.h" -#include "supervisor/shared/translate/translate.h" - // This list can be defined per port in mpconfigport.h to tailor it to a // specific port's needs. If it's not defined then we provide a default. #ifndef MICROPY_PY_UERRNO_LIST diff --git a/py/mpconfig.h b/py/mpconfig.h index 0c4b924ef9..d7fd785fdc 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -32,8 +32,8 @@ #else // Current version of MicroPython #define MICROPY_VERSION_MAJOR 1 -#define MICROPY_VERSION_MINOR 19 -#define MICROPY_VERSION_MICRO 1 +#define MICROPY_VERSION_MINOR 20 +#define MICROPY_VERSION_MICRO 0 // Combined version as a 32-bit number for convenience #define MICROPY_VERSION ( \ @@ -53,21 +53,6 @@ // You can override any of the options below using mpconfigport.h file // located in a directory of your port. -// mpconfigport.h is a file containing configuration settings for a -// particular port. mpconfigport.h is actually a default name for -// such config, and it can be overridden using MP_CONFIGFILE preprocessor -// define (you can do that by passing CFLAGS_EXTRA='-DMP_CONFIGFILE=""' -// argument to make when using standard MicroPython makefiles). -// This is useful to have more than one config per port, for example, -// release vs debug configs, etc. Note that if you switch from one config -// to another, you must rebuild from scratch using "-B" switch to make. - -#ifdef MP_CONFIGFILE -#include MP_CONFIGFILE -#else -#include -#endif - // Is this a CircuitPython build? #ifndef CIRCUITPY #define CIRCUITPY 0 @@ -86,6 +71,21 @@ // Enable everything (e.g. coverage) #define MICROPY_CONFIG_ROM_LEVEL_EVERYTHING (50) +// mpconfigport.h is a file containing configuration settings for a +// particular port. mpconfigport.h is actually a default name for +// such config, and it can be overridden using MP_CONFIGFILE preprocessor +// define (you can do that by passing CFLAGS_EXTRA='-DMP_CONFIGFILE=""' +// argument to make when using standard MicroPython makefiles). +// This is useful to have more than one config per port, for example, +// release vs debug configs, etc. Note that if you switch from one config +// to another, you must rebuild from scratch using "-B" switch to make. + +#ifdef MP_CONFIGFILE +#include MP_CONFIGFILE +#else +#include +#endif + // Ports/boards should set this, but default to level=core. #ifndef MICROPY_CONFIG_ROM_LEVEL #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES) @@ -521,7 +521,6 @@ #define MICROPY_DEBUG_VM_STACK_OVERFLOW (0) #endif -// CIRCUITPY // Whether to enable extra instrumentation for valgrind #ifndef MICROPY_DEBUG_VALGRIND #define MICROPY_DEBUG_VALGRIND (0) @@ -638,6 +637,11 @@ #define MICROPY_ENABLE_GC (0) #endif +// Whether the garbage-collected heap can be split over multiple memory areas. +#ifndef MICROPY_GC_SPLIT_HEAP +#define MICROPY_GC_SPLIT_HEAP (0) +#endif + // Hook to run code during time consuming garbage collector operations #ifndef MICROPY_GC_HOOK_LOOP #define MICROPY_GC_HOOK_LOOP @@ -710,7 +714,7 @@ // This adds Alt+F, Alt+B, Alt+D and Alt+Backspace for forward-word, backward-word, forward-kill-word // and backward-kill-word, respectively. #ifndef MICROPY_REPL_EMACS_WORDS_MOVE -#define MICROPY_REPL_EMACS_WORDS_MOVE (0) +#define MICROPY_REPL_EMACS_WORDS_MOVE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to include extra convenience keys for word movement/kill in readline REPL. @@ -718,7 +722,7 @@ // respectively. Ctrl+Delete is not implemented because it's a very different escape sequence. // Depends on MICROPY_REPL_EMACS_WORDS_MOVE. #ifndef MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE -#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (0) +#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to implement auto-indent in REPL @@ -731,6 +735,11 @@ #define MICROPY_REPL_EVENT_DRIVEN (0) #endif +// The number of items to keep in the readline history. +#ifndef MICROPY_READLINE_HISTORY_SIZE +#define MICROPY_READLINE_HISTORY_SIZE (8) +#endif + // Whether to include lexer helper function for unix #ifndef MICROPY_HELPER_LEXER_UNIX #define MICROPY_HELPER_LEXER_UNIX (0) @@ -784,6 +793,16 @@ typedef long long mp_longint_impl_t; #define MICROPY_WARNINGS (0) #endif +// Whether to support warning categories +#ifndef MICROPY_WARNINGS_CATEGORY +#define MICROPY_WARNINGS_CATEGORY (0) +#endif + +// This macro is used when printing runtime warnings and errors +#ifndef MICROPY_ERROR_PRINTER +#define MICROPY_ERROR_PRINTER (&mp_plat_print) +#endif + // CIRCUITPY // Whether to support chained exceptions #ifndef MICROPY_CPYTHON_EXCEPTION_CHAIN @@ -796,15 +815,6 @@ typedef long long mp_longint_impl_t; #define MICROPY_CONST_GENERATOREXIT_OBJ (!MICROPY_CPYTHON_EXCEPTION_CHAIN) #endif -// Whether to support warning categories -#ifndef MICROPY_WARNINGS_CATEGORY -#define MICROPY_WARNINGS_CATEGORY (0) -#endif - -// This macro is used when printing runtime warnings and errors -#ifndef MICROPY_ERROR_PRINTER -#define MICROPY_ERROR_PRINTER (&mp_plat_print) -#endif // Float and complex implementation #define MICROPY_FLOAT_IMPL_NONE (0) @@ -836,7 +846,7 @@ typedef double mp_float_t; // Whether to provide a high-quality hash for float and complex numbers. // Otherwise the default is a very simple but correct hashing function. #ifndef MICROPY_FLOAT_HIGH_QUALITY_HASH -#define MICROPY_FLOAT_HIGH_QUALITY_HASH (0) +#define MICROPY_FLOAT_HIGH_QUALITY_HASH (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Enable features which improve CPython compatibility @@ -933,6 +943,16 @@ typedef double mp_float_t; #define MICROPY_USE_INTERNAL_PRINTF (1) #endif +// The mp_print_t printer used for printf output when MICROPY_USE_INTERNAL_PRINTF is enabled +#ifndef MICROPY_INTERNAL_PRINTF_PRINTER +#define MICROPY_INTERNAL_PRINTF_PRINTER (&mp_plat_print) +#endif + +// Whether to support mp_sched_vm_abort to asynchronously abort to the top level. +#ifndef MICROPY_ENABLE_VM_ABORT +#define MICROPY_ENABLE_VM_ABORT (0) +#endif + // Support for internal scheduler #ifndef MICROPY_ENABLE_SCHEDULER #define MICROPY_ENABLE_SCHEDULER (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) @@ -954,15 +974,25 @@ typedef double mp_float_t; #endif // Support for VFS POSIX component, to mount a POSIX filesystem within VFS -#ifndef MICROPY_VFS +#ifndef MICROPY_VFS_POSIX #define MICROPY_VFS_POSIX (0) #endif // Support for VFS FAT component, to mount a FAT filesystem within VFS -#ifndef MICROPY_VFS +#ifndef MICROPY_VFS_FAT #define MICROPY_VFS_FAT (0) #endif +// Support for VFS LittleFS v1 component, to mount a LFSv1 filesystem within VFS +#ifndef MICROPY_VFS_LFS1 +#define MICROPY_VFS_LFS1 (0) +#endif + +// Support for VFS LittleFS v2 component, to mount a LFSv2 filesystem within VFS +#ifndef MICROPY_VFS_LFS2 +#define MICROPY_VFS_LFS2 (0) +#endif + /*****************************************************************************/ /* Fine control over Python builtins, classes, modules, etc */ @@ -1021,6 +1051,11 @@ typedef double mp_float_t; #define MICROPY_PY_STR_BYTES_CMP_WARN (0) #endif +// Add bytes.hex and bytes.fromhex +#ifndef MICROPY_PY_BUILTINS_BYTES_HEX +#define MICROPY_PY_BUILTINS_BYTES_HEX (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) +#endif + // Whether str object is proper unicode #ifndef MICROPY_PY_BUILTINS_STR_UNICODE #define MICROPY_PY_BUILTINS_STR_UNICODE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) @@ -1073,7 +1108,7 @@ typedef double mp_float_t; // Whether to support memoryview.itemsize attribute #ifndef MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE -#define MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE (0) +#define MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to support set object @@ -1107,11 +1142,6 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_PROPERTY (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif -// Whether to optimize property flash storage size (requires linker script support) -#ifndef MICROPY_PY_BUILTINS_PROPERTY -#define MICROPY_PY_BUILTINS_PROPERTY (0) -#endif - // Whether to implement the start/stop/step attributes (readback) on // the "range" builtin type. Rarely used, and costs ~60 bytes (x86). #ifndef MICROPY_PY_BUILTINS_RANGE_ATTRS @@ -1123,12 +1153,12 @@ typedef double mp_float_t; // the same object will compare as not-equal. With it enabled the semantics // match CPython and ranges are equal if they yield the same sequence of items. #ifndef MICROPY_PY_BUILTINS_RANGE_BINOP -#define MICROPY_PY_BUILTINS_RANGE_BINOP (0) +#define MICROPY_PY_BUILTINS_RANGE_BINOP (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Support for callling next() with second argument #ifndef MICROPY_PY_BUILTINS_NEXT2 -#define MICROPY_PY_BUILTINS_NEXT2 (0) +#define MICROPY_PY_BUILTINS_NEXT2 (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to support rounding of integers (incl bignum); eg round(123,-1)=120 @@ -1148,7 +1178,7 @@ typedef double mp_float_t; // Whether to support all inplace arithmetic operarion methods // (__imul__, etc.) #ifndef MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS -#define MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS (0) +#define MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to support reverse arithmetic operarion methods @@ -1243,7 +1273,7 @@ typedef double mp_float_t; // Whether to provide the "micropython.heap_locked" function #ifndef MICROPY_PY_MICROPYTHON_HEAP_LOCKED -#define MICROPY_PY_MICROPYTHON_HEAP_LOCKED (0) +#define MICROPY_PY_MICROPYTHON_HEAP_LOCKED (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to provide "array" module. Note that large chunk of the @@ -1259,12 +1289,6 @@ typedef double mp_float_t; #define MICROPY_PY_ARRAY_SLICE_ASSIGN (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif -// Whether to support nonstandard typecodes "O", "P" and "S" -// in array and struct modules. -#ifndef MICROPY_NONSTANDARD_TYPECODES -#define MICROPY_NONSTANDARD_TYPECODES (1) -#endif - // Whether to support attrtuple type (MicroPython extension) // It provides space-efficient tuples with attribute access #ifndef MICROPY_PY_ATTRTUPLE @@ -1288,7 +1312,7 @@ typedef double mp_float_t; // Whether to provide the _asdict function for namedtuple #ifndef MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT -#define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (0) +#define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to provide "math" module @@ -1341,6 +1365,11 @@ typedef double mp_float_t; #define MICROPY_PY_CMATH (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif +// Whether to provide "micropython" module +#ifndef MICROPY_PY_MICROPYTHON +#define MICROPY_PY_MICROPYTHON (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) +#endif + // Whether to provide "gc" module #ifndef MICROPY_PY_GC #define MICROPY_PY_GC (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) @@ -1361,11 +1390,6 @@ typedef double mp_float_t; #define MICROPY_PY_IO_IOBASE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif -// Whether to provide "io.FileIO" class -#ifndef MICROPY_PY_IO_FILEIO -#define MICROPY_PY_IO_FILEIO (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) -#endif - // Whether to provide "io.BytesIO" class #ifndef MICROPY_PY_IO_BYTESIO #define MICROPY_PY_IO_BYTESIO (1) @@ -1373,7 +1397,7 @@ typedef double mp_float_t; // Whether to provide "io.BufferedWriter" class #ifndef MICROPY_PY_IO_BUFFEREDWRITER -#define MICROPY_PY_IO_BUFFEREDWRITER (0) +#define MICROPY_PY_IO_BUFFEREDWRITER (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to provide "struct" module @@ -1381,6 +1405,11 @@ typedef double mp_float_t; #define MICROPY_PY_STRUCT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif +// Whether to provide non-standard typecodes in "struct" module +#ifndef MICROPY_NONSTANDARD_TYPECODES +#define MICROPY_NONSTANDARD_TYPECODES (1) +#endif + // Whether to provide "sys" module #ifndef MICROPY_PY_SYS #define MICROPY_PY_SYS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) @@ -1407,6 +1436,13 @@ typedef double mp_float_t; #define MICROPY_PY_SYS_EXC_INFO (0) #endif +// Whether to provide "sys.executable", which is the absolute path to the +// micropython binary +// Intended for use on the "OS" ports (e.g. Unix) +#ifndef MICROPY_PY_SYS_EXECUTABLE +#define MICROPY_PY_SYS_EXECUTABLE (0) +#endif + // Whether to provide "sys.exit" function #ifndef MICROPY_PY_SYS_EXIT #define MICROPY_PY_SYS_EXIT (1) @@ -1429,7 +1465,7 @@ typedef double mp_float_t; // Whether to provide "sys.getsizeof" function #ifndef MICROPY_PY_SYS_GETSIZEOF -#define MICROPY_PY_SYS_GETSIZEOF (0) +#define MICROPY_PY_SYS_GETSIZEOF (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to provide sys.{stdin,stdout,stderr} objects @@ -1555,15 +1591,15 @@ typedef double mp_float_t; #endif #ifndef MICROPY_PY_URE_DEBUG -#define MICROPY_PY_URE_DEBUG (0) +#define MICROPY_PY_URE_DEBUG (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif #ifndef MICROPY_PY_URE_MATCH_GROUPS -#define MICROPY_PY_URE_MATCH_GROUPS (0) +#define MICROPY_PY_URE_MATCH_GROUPS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif #ifndef MICROPY_PY_URE_MATCH_SPAN_START_END -#define MICROPY_PY_URE_MATCH_SPAN_START_END (0) +#define MICROPY_PY_URE_MATCH_SPAN_START_END (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif #ifndef MICROPY_PY_URE_SUB @@ -1663,6 +1699,11 @@ typedef double mp_float_t; #define MICROPY_PY_MACHINE_SOFTSPI (0) #endif +// Whether to provide the "machine.Timer" class +#ifndef MICROPY_PY_MACHINE_TIMER +#define MICROPY_PY_MACHINE_TIMER (0) +#endif + // The default backlog value for socket.listen(backlog) #ifndef MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT #define MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT (2) @@ -1698,6 +1739,11 @@ typedef double mp_float_t; #define MICROPY_PY_ONEWIRE (0) #endif +// Whether to provide the "platform" module +#ifndef MICROPY_PY_UPLATFORM +#define MICROPY_PY_UPLATFORM (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) +#endif + /*****************************************************************************/ /* Hooks for a port to add builtins */ @@ -1717,11 +1763,6 @@ typedef double mp_float_t; #define MICROPY_PORT_CONSTANTS #endif -// Any root pointers for GC scanning - see mpstate.c -#ifndef MICROPY_PORT_ROOT_POINTERS -#define MICROPY_PORT_ROOT_POINTERS -#endif - /*****************************************************************************/ /* Hooks for a port to wrap functions with attributes */ @@ -1761,6 +1802,10 @@ typedef double mp_float_t; #define MICROPY_WRAP_MP_SCHED_SCHEDULE(f) f #endif +#ifndef MICROPY_WRAP_MP_SCHED_VM_ABORT +#define MICROPY_WRAP_MP_SCHED_VM_ABORT(f) f +#endif + /*****************************************************************************/ /* Miscellaneous settings */ diff --git a/py/mpprint.h b/py/mpprint.h index fbfa3d9914..562afdad44 100644 --- a/py/mpprint.h +++ b/py/mpprint.h @@ -56,7 +56,7 @@ typedef struct _mp_print_ext_t { mp_print_t base; const char *item_separator; const char *key_separator; -}mp_print_ext_t; +} mp_print_ext_t; #define MP_PRINT_GET_EXT(print) ((mp_print_ext_t *)print) diff --git a/py/mpstate.h b/py/mpstate.h index 6871e2b40a..1519efb71d 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -77,12 +77,11 @@ typedef struct _mp_sched_item_t { mp_obj_t arg; } mp_sched_item_t; -// This structure hold information about the memory allocation system. -typedef struct _mp_state_mem_t { - #if MICROPY_MEM_STATS - size_t total_bytes_allocated; - size_t current_bytes_allocated; - size_t peak_bytes_allocated; +// This structure holds information about a single contiguous area of +// memory reserved for the memory manager. +typedef struct _mp_state_mem_area_t { + #if MICROPY_GC_SPLIT_HEAP + struct _mp_state_mem_area_t *next; #endif byte *gc_alloc_table_start; @@ -93,8 +92,25 @@ typedef struct _mp_state_mem_t { byte *gc_pool_start; byte *gc_pool_end; + size_t gc_last_free_atb_index; +} mp_state_mem_area_t; + +// This structure hold information about the memory allocation system. +typedef struct _mp_state_mem_t { + #if MICROPY_MEM_STATS + size_t total_bytes_allocated; + size_t current_bytes_allocated; + size_t peak_bytes_allocated; + #endif + + mp_state_mem_area_t area; + int gc_stack_overflow; - MICROPY_GC_STACK_ENTRY_TYPE gc_stack[MICROPY_ALLOC_GC_STACK_SIZE]; + MICROPY_GC_STACK_ENTRY_TYPE gc_block_stack[MICROPY_ALLOC_GC_STACK_SIZE]; + #if MICROPY_GC_SPLIT_HEAP + // Array that tracks the area for each block on gc_block_stack. + mp_state_mem_area_t *gc_area_stack[MICROPY_ALLOC_GC_STACK_SIZE]; + #endif // This variable controls auto garbage collection. If set to 0 then the // GC won't automatically run when gc_alloc can't find enough blocks. But @@ -106,7 +122,9 @@ typedef struct _mp_state_mem_t { size_t gc_alloc_threshold; #endif - size_t gc_last_free_atb_index; + #if MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t *gc_last_free_area; + #endif #if MICROPY_PY_GC_COLLECT_RETVAL size_t gc_collected; @@ -165,69 +183,19 @@ typedef struct _mp_state_vm_t { // dictionary with loaded modules (may be exposed as sys.modules) mp_obj_dict_t mp_loaded_modules_dict; - #if MICROPY_ENABLE_SCHEDULER - mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH]; - #endif - - // current exception being handled, for sys.exc_info() - #if MICROPY_PY_SYS_EXC_INFO - mp_obj_base_t *cur_exception; - #endif - - #if MICROPY_PY_SYS_ATEXIT - // exposed through sys.atexit function - mp_obj_t sys_exitfunc; - #endif - // dictionary for the __main__ module mp_obj_dict_t dict_main; - #if MICROPY_PY_SYS - // If MICROPY_PY_SYS_PATH_ARGV_DEFAULTS is not enabled then these two lists - // must be initialised after the call to mp_init. - mp_obj_list_t mp_sys_path_obj; - mp_obj_list_t mp_sys_argv_obj; - - #if MICROPY_PY_SYS_ATTR_DELEGATION - // Contains mutable sys attributes. - mp_obj_t sys_mutable[MP_SYS_MUTABLE_NUM]; - #endif - #endif - // dictionary for overridden builtins #if MICROPY_CAN_OVERRIDE_BUILTINS mp_obj_dict_t *mp_module_builtins_override_dict; #endif - #if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE - // An mp_obj_list_t that tracks relocated native code to prevent the GC from reclaiming them. - mp_obj_t track_reloc_code_list; - #endif - - // include any root pointers defined by a port - MICROPY_PORT_ROOT_POINTERS - - // root pointers for extmod - - #if MICROPY_REPL_EVENT_DRIVEN - vstr_t *repl_line; - #endif - - #if MICROPY_PY_OS_DUPTERM - mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM]; - #endif - - #if MICROPY_PY_LWIP_SLIP - mp_obj_t lwip_slip_stream; - #endif - - #if MICROPY_VFS - struct _mp_vfs_mount_t *vfs_cur; - struct _mp_vfs_mount_t *vfs_mount_table; - #endif - - #if MICROPY_PY_BLUETOOTH - mp_obj_t bluetooth; + // Include any root pointers registered with MP_REGISTER_ROOT_POINTER(). + #ifndef NO_QSTR + // Only include root pointer definitions when not doing qstr extraction, because + // the qstr extraction stage also generates the root pointers header file. + #include "genhdr/root_pointers.h" #endif // @@ -273,6 +241,11 @@ typedef struct _mp_state_vm_t { uint8_t sched_idx; #endif + #if MICROPY_ENABLE_VM_ABORT + bool vm_abort; + nlr_buf_t *nlr_abort; + #endif + #if MICROPY_PY_THREAD_GIL // This is a global mutex used to make the VM/runtime thread-safe. mp_thread_mutex_t gil_mutex; @@ -349,8 +322,10 @@ extern mp_state_ctx_t mp_state_ctx; #if MICROPY_PY_THREAD extern mp_state_thread_t *mp_thread_get_state(void); #define MP_STATE_THREAD(x) (mp_thread_get_state()->x) +#define mp_thread_is_main_thread() (mp_thread_get_state() == &mp_state_ctx.thread) #else #define MP_STATE_THREAD(x) MP_STATE_MAIN_THREAD(x) +#define mp_thread_is_main_thread() (true) #endif #endif // MICROPY_INCLUDED_PY_MPSTATE_H diff --git a/py/nativeglue.c b/py/nativeglue.c index 0e9bbf54eb..2afe466428 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -318,7 +318,7 @@ const mp_fun_table_t mp_fun_table = { gc_realloc, mp_printf, mp_vprintf, - mp_raise_msg_str, + mp_raise_msg_str, // CIRCUITPY mp_obj_get_type, mp_obj_new_str, mp_obj_new_bytes, diff --git a/py/nlr.c b/py/nlr.c index 32e2b42c30..6435df66fb 100644 --- a/py/nlr.c +++ b/py/nlr.c @@ -49,3 +49,10 @@ void nlr_pop(void) { nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); *top = (*top)->prev; } + +#if MICROPY_ENABLE_VM_ABORT +NORETURN void nlr_jump_abort(void) { + MP_STATE_THREAD(nlr_top) = MP_STATE_VM(nlr_abort); + nlr_jump(NULL); +} +#endif diff --git a/py/nlr.h b/py/nlr.h index b7b016b1e6..2b8ec4b64e 100644 --- a/py/nlr.h +++ b/py/nlr.h @@ -40,6 +40,7 @@ #define MICROPY_NLR_NUM_REGS_ARM_THUMB (10) #define MICROPY_NLR_NUM_REGS_ARM_THUMB_FP (10 + 6) #define MICROPY_NLR_NUM_REGS_AARCH64 (13) +#define MICROPY_NLR_NUM_REGS_MIPS (13) #define MICROPY_NLR_NUM_REGS_XTENSA (10) #define MICROPY_NLR_NUM_REGS_XTENSAWIN (17) @@ -88,6 +89,9 @@ #define MICROPY_NLR_POWERPC (1) // this could be less but using 128 for safety #define MICROPY_NLR_NUM_REGS (128) +#elif defined(__mips__) + #define MICROPY_NLR_MIPS (1) + #define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_MIPS) #else #define MICROPY_NLR_SETJMP (1) // #warning "No native NLR support for this arch, using setjmp implementation" @@ -107,9 +111,16 @@ typedef struct _nlr_buf_t nlr_buf_t; struct _nlr_buf_t { - // the entries here must all be machine word size + // The entries in this struct must all be machine word size. + + // Pointer to the previous nlr_buf_t in the chain. + // Or NULL if it's the top-level one. nlr_buf_t *prev; - void *ret_val; // always a concrete object (an exception instance) + + // The exception that is being raised: + // - NULL means the jump is because of a VM abort (only if MICROPY_ENABLE_VM_ABORT enabled) + // - otherwise it's always a concrete object (an exception instance) + void *ret_val; #if MICROPY_NLR_SETJMP jmp_buf jmpbuf; @@ -155,6 +166,12 @@ unsigned int nlr_push_tail(nlr_buf_t *top); void nlr_pop(void); NORETURN void nlr_jump(void *val); +#if MICROPY_ENABLE_VM_ABORT +#define nlr_set_abort(buf) MP_STATE_VM(nlr_abort) = buf +#define nlr_get_abort() MP_STATE_VM(nlr_abort) +NORETURN void nlr_jump_abort(void); +#endif + // This must be implemented by a port. It's called by nlr_jump // if no nlr buf has been pushed. It must not return, but rather // should bail out with a fatal error. diff --git a/py/nlrmips.c b/py/nlrmips.c new file mode 100644 index 0000000000..b75d06cda6 --- /dev/null +++ b/py/nlrmips.c @@ -0,0 +1,86 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2017 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mpstate.h" + +#if defined(MICROPY_NLR_MIPS) && MICROPY_NLR_MIPS + +__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr); + +__asm( + ".globl nlr_push \n" + "nlr_push: \n" + ".ent nlr_push \n" + ".frame $29, 0, $31 \n" + ".set noreorder \n" + ".cpload $25 \n" + ".set reorder \n" + "sw $31, 8($4) \n" /* is the offset of regs in nlr_buf_t */ + "sw $30, 12($4) \n" + "sw $29, 16($4) \n" + "sw $28, 20($4) \n" + "sw $23, 24($4) \n" + "sw $22, 28($4) \n" + "sw $21, 32($4) \n" + "sw $20, 36($4) \n" + "sw $19, 40($4) \n" + "sw $18, 44($4) \n" + "sw $17, 48($4) \n" + "sw $16, 52($4) \n" +#ifdef __pic__ + "la $25, nlr_push_tail \n" +#endif + "j nlr_push_tail \n" + ".end nlr_push \n" + ); + +NORETURN void nlr_jump(void *val) { + MP_NLR_JUMP_HEAD(val, top) + __asm( + "move $4, %0 \n" + "lw $31, 8($4) \n" + "lw $30, 12($4) \n" + "lw $29, 16($4) \n" + "lw $28, 20($4) \n" + "lw $23, 24($4) \n" + "lw $22, 28($4) \n" + "lw $21, 32($4) \n" + "lw $20, 36($4) \n" + "lw $19, 40($4) \n" + "lw $18, 44($4) \n" + "lw $17, 48($4) \n" + "lw $16, 52($4) \n" + "lui $2,1 \n" // set return value 1 + "j $31 \n" + "nop \n" + : + : "r" (top) + : + ); + MP_UNREACHABLE +} + +#endif // MICROPY_NLR_MIPS diff --git a/py/nlrpowerpc.c b/py/nlrpowerpc.c index 43eb34583d..a1b44efef1 100644 --- a/py/nlrpowerpc.c +++ b/py/nlrpowerpc.c @@ -32,6 +32,8 @@ // Saving all ABI non-vol registers here +#ifdef __LP64__ + unsigned int nlr_push(nlr_buf_t *nlr) { __asm__ volatile ( @@ -118,4 +120,95 @@ NORETURN void nlr_jump(void *val) { MP_UNREACHABLE; } +#else +// Saving all ABI non-vol registers here + +unsigned int nlr_push(nlr_buf_t *nlr) { + + __asm__ volatile ( + "li 4, 0x4eed ; " // Store canary + "stw 4, 0x00(%0) ;" + "stw 0, 0x04(%0) ;" + "stw 1, 0x08(%0) ;" + "stw 2, 0x0c(%0) ;" + "stw 14, 0x10(%0) ;" + "stw 15, 0x14(%0) ;" + "stw 16, 0x18(%0) ;" + "stw 17, 0x1c(%0) ;" + "stw 18, 0x20(%0) ;" + "stw 19, 0x24(%0) ;" + "stw 20, 0x28(%0) ;" + "stw 21, 0x2c(%0) ;" + "stw 22, 0x30(%0) ;" + "stw 23, 0x34(%0) ;" + "stw 24, 0x38(%0) ;" + "stw 25, 0x3c(%0) ;" + "stw 26, 0x40(%0) ;" + "stw 27, 0x44(%0) ;" + "stw 28, 0x48(%0) ;" + "stw 29, 0x4c(%0) ;" + "stw 30, 0x50(%0) ;" + "stw 31, 0x54(%0) ;" + + "mfcr 4 ; " + "stw 4, 0x58(%0) ;" + "mflr 4 ;" + "stw 4, 0x5c(%0) ;" + "li 4, nlr_push_tail@l ;" + "oris 4, 4, nlr_push_tail@h ;" + "mtctr 4 ;" + "mr 3, %1 ; " + "bctr ;" + : + : "r" (&nlr->regs), "r" (nlr) + : + ); + + return 0; +} + +NORETURN void nlr_jump(void *val) { + MP_NLR_JUMP_HEAD(val, top) + + __asm__ volatile ( + "l 3, 0x0(%0) ;" + "cmpdi 3, 0x4eed ; " // Check canary + "bne . ; " + "l 0, 0x04(%0) ;" + "l 1, 0x08(%0) ;" + "l 2, 0x0c(%0) ;" + "l 14, 0x10(%0) ;" + "l 15, 0x14(%0) ;" + "l 16, 0x18(%0) ;" + "l 17, 0x1c(%0) ;" + "l 18, 0x20(%0) ;" + "l 19, 0x24(%0) ;" + "l 20, 0x28(%0) ;" + "l 21, 0x2c(%0) ;" + "l 22, 0x30(%0) ;" + "l 23, 0x34(%0) ;" + "l 24, 0x38(%0) ;" + "l 25, 0x3c(%0) ;" + "l 26, 0x40(%0) ;" + "l 27, 0x44(%0) ;" + "l 28, 0x48(%0) ;" + "l 29, 0x4c(%0) ;" + "l 30, 0x50(%0) ;" + "l 31, 0x54(%0) ;" + "l 3, 0x58(%0) ;" + "mtcr 3 ;" + "l 3, 0x5c(%0) ;" + "mtlr 3 ; " + "li 3, 1;" + "blr ;" + : + : "r" (&top->regs) + : + ); + + MP_UNREACHABLE; +} + +#endif // __LP64__ + #endif // MICROPY_NLR_POWERPC diff --git a/py/obj.c b/py/obj.c index 31d469770c..f8316ce5b2 100644 --- a/py/obj.c +++ b/py/obj.c @@ -39,12 +39,10 @@ #include "py/stackctrl.h" #include "py/stream.h" // for mp_obj_print -#include "supervisor/linker.h" #include "supervisor/shared/stack.h" -#include "supervisor/shared/translate/translate.h" // Allocates an object and also sets type, for mp_obj_malloc{,_var} macros. -void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type) { +MP_NOINLINE void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type) { mp_obj_base_t *base = (mp_obj_base_t *)m_malloc(num_bytes); base->type = type; return base; @@ -108,12 +106,6 @@ const mp_obj_type_t *MICROPY_WRAP_MP_OBJ_GET_TYPE(mp_obj_get_type)(mp_const_obj_ #endif } -const mp_obj_full_type_t *mp_obj_get_full_type(mp_const_obj_t o_in) { - const mp_obj_type_t *type = mp_obj_get_type(o_in); - assert(type->flags & MP_TYPE_FLAG_EXTENDED); - return (mp_obj_full_type_t *)type; -} - const char *mp_obj_get_type_str(mp_const_obj_t o_in) { return qstr_str(mp_obj_get_type_qstr(o_in)); } @@ -138,8 +130,8 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t } #endif const mp_obj_type_t *type = mp_obj_get_type(o_in); - if (type->print != NULL) { - type->print((mp_print_t *)print, o_in, kind); + if (MP_OBJ_TYPE_HAS_SLOT(type, print)) { + MP_OBJ_TYPE_GET_SLOT(type, print)((mp_print_t *)print, o_in, kind); } else { mp_printf(print, "<%q>", type->name); } @@ -250,9 +242,8 @@ bool PLACE_IN_ITCM(mp_obj_is_true)(mp_obj_t arg) { } } else { const mp_obj_type_t *type = mp_obj_get_type(arg); - mp_unary_op_fun_t unary_op = mp_type_get_unary_op_slot(type); - if (unary_op) { - mp_obj_t result = unary_op(MP_UNARY_OP_BOOL, arg); + if (MP_OBJ_TYPE_HAS_SLOT(type, unary_op)) { + mp_obj_t result = MP_OBJ_TYPE_GET_SLOT(type, unary_op)(MP_UNARY_OP_BOOL, arg); if (result != MP_OBJ_NULL) { return result == mp_const_true; } @@ -270,7 +261,7 @@ bool PLACE_IN_ITCM(mp_obj_is_true)(mp_obj_t arg) { } bool mp_obj_is_callable(mp_obj_t o_in) { - const mp_call_fun_t call = mp_type_get_call_slot(mp_obj_get_type(o_in)); + const mp_call_fun_t call = MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o_in), call); if (call != mp_obj_instance_call) { return call != NULL; } @@ -337,20 +328,19 @@ mp_obj_t mp_obj_equal_not_equal(mp_binary_op_t op, mp_obj_t o1, mp_obj_t o2) { const mp_obj_type_t *type = mp_obj_get_type(o1); // If a full equality test is not needed and the other object is a different // type then we don't need to bother trying the comparison. - mp_binary_op_fun_t binary_op = mp_type_get_binary_op_slot(type); - if (binary_op != NULL && + if (MP_OBJ_TYPE_HAS_SLOT(type, binary_op) && ((type->flags & MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE) || mp_obj_get_type(o2) == type)) { // CPython is asymmetric: it will try __eq__ if there's no __ne__ but not the // other way around. If the class doesn't need a full test we can skip __ne__. if (op == MP_BINARY_OP_NOT_EQUAL && (type->flags & MP_TYPE_FLAG_EQ_HAS_NEQ_TEST)) { - mp_obj_t r = binary_op(MP_BINARY_OP_NOT_EQUAL, o1, o2); + mp_obj_t r = MP_OBJ_TYPE_GET_SLOT(type, binary_op)(MP_BINARY_OP_NOT_EQUAL, o1, o2); if (r != MP_OBJ_NULL) { return r; } } // Try calling __eq__. - mp_obj_t r = binary_op(MP_BINARY_OP_EQUAL, o1, o2); + mp_obj_t r = MP_OBJ_TYPE_GET_SLOT(type, binary_op)(MP_BINARY_OP_EQUAL, o1, o2); if (r != MP_OBJ_NULL) { if (op == MP_BINARY_OP_EQUAL) { return r; @@ -386,7 +376,7 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) { return 1; } else if (mp_obj_is_small_int(arg)) { return MP_OBJ_SMALL_INT_VALUE(arg); - } else if (mp_obj_is_type(arg, &mp_type_int)) { + } else if (mp_obj_is_exact_type(arg, &mp_type_int)) { return mp_obj_int_get_checked(arg); } else { mp_obj_t res = mp_unary_op(MP_UNARY_OP_INT, (mp_obj_t)arg); @@ -412,7 +402,7 @@ bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value) { *value = 1; } else if (mp_obj_is_small_int(arg)) { *value = MP_OBJ_SMALL_INT_VALUE(arg); - } else if (mp_obj_is_type(arg, &mp_type_int)) { + } else if (mp_obj_is_exact_type(arg, &mp_type_int)) { *value = mp_obj_int_get_checked(arg); } else { return false; @@ -431,15 +421,19 @@ bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value) { } else if (mp_obj_is_small_int(arg)) { val = (mp_float_t)MP_OBJ_SMALL_INT_VALUE(arg); #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE - } else if (mp_obj_is_type(arg, &mp_type_int)) { + } else if (mp_obj_is_exact_type(arg, &mp_type_int)) { val = mp_obj_int_as_float_impl(arg); #endif } else if (mp_obj_is_float(arg)) { val = mp_obj_float_get(arg); } else { - return false; + arg = mp_unary_op(MP_UNARY_OP_FLOAT_MAYBE, (mp_obj_t)arg); + if (arg != MP_OBJ_NULL && mp_obj_is_float(arg)) { + val = mp_obj_float_get(arg); + } else { + return false; + } } - *value = val; return true; } @@ -461,27 +455,17 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) { #if MICROPY_PY_BUILTINS_COMPLEX bool mp_obj_get_complex_maybe(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { - if (arg == mp_const_false) { - *real = 0; - *imag = 0; - } else if (arg == mp_const_true) { - *real = 1; - *imag = 0; - } else if (mp_obj_is_small_int(arg)) { - *real = (mp_float_t)MP_OBJ_SMALL_INT_VALUE(arg); - *imag = 0; - #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE - } else if (mp_obj_is_type(arg, &mp_type_int)) { - *real = mp_obj_int_as_float_impl(arg); - *imag = 0; - #endif - } else if (mp_obj_is_float(arg)) { - *real = mp_obj_float_get(arg); + if (mp_obj_get_float_maybe(arg, real)) { *imag = 0; } else if (mp_obj_is_type(arg, &mp_type_complex)) { mp_obj_complex_get(arg, real, imag); } else { - return false; + arg = mp_unary_op(MP_UNARY_OP_COMPLEX_MAYBE, (mp_obj_t)arg); + if (arg != MP_OBJ_NULL && mp_obj_is_type(arg, &mp_type_complex)) { + mp_obj_complex_get(arg, real, imag); + } else { + return false; + } } return true; } @@ -606,9 +590,8 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { return MP_OBJ_NEW_SMALL_INT(l); } else { const mp_obj_type_t *type = mp_obj_get_type(o_in); - mp_unary_op_fun_t unary_op = mp_type_get_unary_op_slot(type); - if (unary_op != NULL) { - return unary_op(MP_UNARY_OP_LEN, o_in); + if (MP_OBJ_TYPE_HAS_SLOT(type, unary_op)) { + return MP_OBJ_TYPE_GET_SLOT(type, unary_op)(MP_UNARY_OP_LEN, o_in); } else { return MP_OBJ_NULL; } @@ -617,14 +600,14 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { const mp_obj_type_t *type = mp_obj_get_type(base); - mp_subscr_fun_t subscr = mp_type_get_subscr_slot(type); - if (subscr != NULL) { - mp_obj_t ret = subscr(base, index, value); + if (MP_OBJ_TYPE_HAS_SLOT(type, subscr)) { + mp_obj_t ret = MP_OBJ_TYPE_GET_SLOT(type, subscr)(base, index, value); // May have called port specific C code. Make sure it didn't mess up the heap. assert_heap_ok(); if (ret != MP_OBJ_NULL) { return ret; } + // TODO: call base classes here? } if (value == MP_OBJ_NULL) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE @@ -657,24 +640,22 @@ mp_obj_t mp_identity(mp_obj_t self) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity); -mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) { - (void)iter_buf; - return self; -} - +// CIRCUITPY +// generic subscript iterator, which iterates through anything with a 0-based subscript. typedef struct { mp_obj_base_t base; mp_fun_1_t iternext; mp_obj_t obj; mp_int_t cur; -} mp_obj_generic_it_t; +} mp_obj_generic_subscript_it_t; -STATIC mp_obj_t generic_it_iternext(mp_obj_t self_in) { - mp_obj_generic_it_t *self = MP_OBJ_TO_PTR(self_in); - const mp_obj_full_type_t *type = mp_obj_get_full_type(self->obj); - mp_obj_t current_length = type->MP_TYPE_UNARY_OP(MP_UNARY_OP_LEN, self->obj); +STATIC mp_obj_t generic_subscript_it_iternext(mp_obj_t self_in) { + mp_obj_generic_subscript_it_t *self = MP_OBJ_TO_PTR(self_in); + const mp_obj_type_t *type = mp_obj_get_type(self->obj); + mp_obj_t current_length = MP_OBJ_TYPE_GET_SLOT(type, unary_op)(MP_UNARY_OP_LEN, self->obj); if (self->cur < MP_OBJ_SMALL_INT_VALUE(current_length)) { - mp_obj_t o_out = type->ext[0].subscr(self->obj, MP_OBJ_NEW_SMALL_INT(self->cur), MP_OBJ_SENTINEL); + mp_obj_t o_out = + MP_OBJ_TYPE_GET_SLOT(type, subscr)(self->obj, MP_OBJ_NEW_SMALL_INT(self->cur), MP_OBJ_SENTINEL); self->cur += 1; return o_out; } else { @@ -682,23 +663,27 @@ STATIC mp_obj_t generic_it_iternext(mp_obj_t self_in) { } } -mp_obj_t mp_obj_new_generic_iterator(mp_obj_t obj, mp_obj_iter_buf_t *iter_buf) { - assert(sizeof(mp_obj_generic_it_t) <= sizeof(mp_obj_iter_buf_t)); - mp_obj_generic_it_t *o = (mp_obj_generic_it_t *)iter_buf; +mp_obj_t mp_obj_generic_subscript_getiter(mp_obj_t obj, mp_obj_iter_buf_t *iter_buf) { + assert(sizeof(mp_obj_generic_subscript_it_t) <= sizeof(mp_obj_iter_buf_t)); + mp_obj_generic_subscript_it_t *o = (mp_obj_generic_subscript_it_t *)iter_buf; o->base.type = &mp_type_polymorph_iter; - o->iternext = generic_it_iternext; + o->iternext = &generic_subscript_it_iternext; o->obj = obj; o->cur = 0; return MP_OBJ_FROM_PTR(o); } +// mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) { +// (void)iter_buf; +// return self; +// } + bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { const mp_obj_type_t *type = mp_obj_get_type(obj); - const mp_getbuffer_fun_t get_buffer = mp_type_get_getbuffer_slot(type); - if (get_buffer == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(type, buffer)) { return false; } - int ret = get_buffer(obj, bufinfo, flags); + int ret = MP_OBJ_TYPE_GET_SLOT(type, buffer)(obj, bufinfo, flags); if (ret != 0) { return false; } @@ -719,82 +704,3 @@ mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in) { return MP_OBJ_NULL; // op not supported } } - -mp_call_fun_t mp_type_get_call_slot(const mp_obj_type_t *type) { - if (!(type->flags & MP_TYPE_FLAG_EXTENDED)) { - return NULL; - } - return type->ext[0].call; -} - -mp_unary_op_fun_t mp_type_get_unary_op_slot(const mp_obj_type_t *type) { - if (!(type->flags & MP_TYPE_FLAG_EXTENDED)) { - return NULL; - } - return type->ext[0].unary_op; -} - - -mp_binary_op_fun_t mp_type_get_binary_op_slot(const mp_obj_type_t *type) { - if (!(type->flags & MP_TYPE_FLAG_EXTENDED)) { - return NULL; - } - return type->ext[0].binary_op; -} - - -mp_attr_fun_t mp_type_get_attr_slot(const mp_obj_type_t *type) { - return type->attr; -} - - -mp_subscr_fun_t mp_type_get_subscr_slot(const mp_obj_type_t *type) { - if (!(type->flags & MP_TYPE_FLAG_EXTENDED)) { - return NULL; - } - return type->MP_TYPE_SUBSCR; -} - - -mp_getiter_fun_t mp_type_get_getiter_slot(const mp_obj_type_t *type) { - if (!(type->flags & MP_TYPE_FLAG_EXTENDED)) { - return NULL; - } - return type->MP_TYPE_GETITER; -} - - -mp_fun_1_t mp_type_get_iternext_slot(const mp_obj_type_t *type) { - if (!(type->flags & MP_TYPE_FLAG_EXTENDED)) { - return NULL; - } - return type->MP_TYPE_ITERNEXT; -} - - -mp_getbuffer_fun_t mp_type_get_getbuffer_slot(const mp_obj_type_t *type) { - if (!(type->flags & MP_TYPE_FLAG_EXTENDED)) { - return NULL; - } - return type->MP_TYPE_GET_BUFFER; -} - - -const void *mp_type_get_protocol_slot(const mp_obj_type_t *type) { - if (!(type->flags & MP_TYPE_FLAG_EXTENDED)) { - return NULL; - } - return type->MP_TYPE_PROTOCOL; -} - - -const void *mp_type_get_parent_slot(const mp_obj_type_t *type) { - return type->parent; -} - -size_t mp_type_size(const mp_obj_type_t *type) { - if (!(type->flags & MP_TYPE_FLAG_EXTENDED)) { - return sizeof(mp_obj_type_t); - } - return sizeof(mp_obj_full_type_t); -} diff --git a/py/obj.h b/py/obj.h index d1874a8cd2..789e05b884 100644 --- a/py/obj.h +++ b/py/obj.h @@ -50,7 +50,6 @@ typedef const void *mp_const_obj_t; // This mp_obj_type_t struct is a concrete MicroPython object which holds info // about a type. See below for actual definition of the struct. typedef struct _mp_obj_type_t mp_obj_type_t; -typedef struct _mp_obj_full_type_t mp_obj_full_type_t; // Anything that wants to be a concrete MicroPython object must have mp_obj_base_t // as its first member (small ints, qstr objs and inline floats are not concrete). @@ -86,19 +85,19 @@ typedef struct _mp_obj_base_t mp_obj_base_t; #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A -static MP_INLINE bool mp_obj_is_small_int(mp_const_obj_t o) { +static inline bool mp_obj_is_small_int(mp_const_obj_t o) { return (((mp_int_t)(o)) & 1) != 0; } #define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 1) #define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 1) | 1)) -static MP_INLINE bool mp_obj_is_qstr(mp_const_obj_t o) { +static inline bool mp_obj_is_qstr(mp_const_obj_t o) { return (((mp_int_t)(o)) & 7) == 2; } #define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 3) #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 3) | 2)) -static MP_INLINE bool mp_obj_is_immediate_obj(mp_const_obj_t o) { +static inline bool mp_obj_is_immediate_obj(mp_const_obj_t o) { return (((mp_int_t)(o)) & 7) == 6; } #define MP_OBJ_IMMEDIATE_OBJ_VALUE(o) (((mp_uint_t)(o)) >> 3) @@ -125,25 +124,25 @@ mp_float_t mp_obj_float_get(mp_obj_t self_in); mp_obj_t mp_obj_new_float(mp_float_t value); #endif -static MP_INLINE bool mp_obj_is_obj(mp_const_obj_t o) { +static inline bool mp_obj_is_obj(mp_const_obj_t o) { return (((mp_int_t)(o)) & 3) == 0; } #elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B -static MP_INLINE bool mp_obj_is_small_int(mp_const_obj_t o) { +static inline bool mp_obj_is_small_int(mp_const_obj_t o) { return (((mp_int_t)(o)) & 3) == 1; } #define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 2) #define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 2) | 1)) -static MP_INLINE bool mp_obj_is_qstr(mp_const_obj_t o) { +static inline bool mp_obj_is_qstr(mp_const_obj_t o) { return (((mp_int_t)(o)) & 7) == 3; } #define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 3) #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 3) | 3)) -static MP_INLINE bool mp_obj_is_immediate_obj(mp_const_obj_t o) { +static inline bool mp_obj_is_immediate_obj(mp_const_obj_t o) { return (((mp_int_t)(o)) & 7) == 7; } #define MP_OBJ_IMMEDIATE_OBJ_VALUE(o) (((mp_uint_t)(o)) >> 3) @@ -170,13 +169,17 @@ mp_float_t mp_obj_float_get(mp_obj_t self_in); mp_obj_t mp_obj_new_float(mp_float_t value); #endif -static MP_INLINE bool mp_obj_is_obj(mp_const_obj_t o) { +static inline bool mp_obj_is_obj(mp_const_obj_t o) { return (((mp_int_t)(o)) & 1) == 0; } #elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C -static MP_INLINE bool mp_obj_is_small_int(mp_const_obj_t o) { +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_NONE +#error "MICROPY_OBJ_REPR_C requires float to be enabled." +#endif + +static inline bool mp_obj_is_small_int(mp_const_obj_t o) { return (((mp_int_t)(o)) & 1) != 0; } #define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 1) @@ -191,17 +194,20 @@ static MP_INLINE bool mp_obj_is_small_int(mp_const_obj_t o) { #define mp_const_float_nan MP_ROM_PTR((mp_obj_t)(((0xffc00000 & ~3) | 2) + 0x80800000)) #endif -static MP_INLINE bool mp_obj_is_float(mp_const_obj_t o) { +static inline bool mp_obj_is_float(mp_const_obj_t o) { + // Ensure that 32-bit arch can only use single precision. + MP_STATIC_ASSERT(sizeof(mp_float_t) <= sizeof(mp_obj_t)); + return (((mp_uint_t)(o)) & 3) == 2 && (((mp_uint_t)(o)) & 0xff800007) != 0x00000006; } -static MP_INLINE mp_float_t mp_obj_float_get(mp_const_obj_t o) { +static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) { union { mp_float_t f; mp_uint_t u; } num = {.u = ((mp_uint_t)o - 0x80800000) & ~3}; return num.f; } -static MP_INLINE mp_obj_t mp_obj_new_float(mp_float_t f) { +static inline mp_obj_t mp_obj_new_float(mp_float_t f) { union { mp_float_t f; mp_uint_t u; @@ -210,37 +216,37 @@ static MP_INLINE mp_obj_t mp_obj_new_float(mp_float_t f) { } #endif -static MP_INLINE bool mp_obj_is_qstr(mp_const_obj_t o) { +static inline bool mp_obj_is_qstr(mp_const_obj_t o) { return (((mp_uint_t)(o)) & 0xff80000f) == 0x00000006; } #define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 4) #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 4) | 0x00000006)) -static MP_INLINE bool mp_obj_is_immediate_obj(mp_const_obj_t o) { +static inline bool mp_obj_is_immediate_obj(mp_const_obj_t o) { return (((mp_uint_t)(o)) & 0xff80000f) == 0x0000000e; } #define MP_OBJ_IMMEDIATE_OBJ_VALUE(o) (((mp_uint_t)(o)) >> 4) #define MP_OBJ_NEW_IMMEDIATE_OBJ(val) ((mp_obj_t)(((val) << 4) | 0xe)) -static MP_INLINE bool mp_obj_is_obj(mp_const_obj_t o) { +static inline bool mp_obj_is_obj(mp_const_obj_t o) { return (((mp_int_t)(o)) & 3) == 0; } #elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D -static MP_INLINE bool mp_obj_is_small_int(mp_const_obj_t o) { +static inline bool mp_obj_is_small_int(mp_const_obj_t o) { return (((uint64_t)(o)) & 0xffff000000000000) == 0x0001000000000000; } #define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)((o) << 16)) >> 17) #define MP_OBJ_NEW_SMALL_INT(small_int) (((((uint64_t)(small_int)) & 0x7fffffffffff) << 1) | 0x0001000000000001) -static MP_INLINE bool mp_obj_is_qstr(mp_const_obj_t o) { +static inline bool mp_obj_is_qstr(mp_const_obj_t o) { return (((uint64_t)(o)) & 0xffff000000000000) == 0x0002000000000000; } #define MP_OBJ_QSTR_VALUE(o) ((((uint32_t)(o)) >> 1) & 0xffffffff) #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)(((uint64_t)(((uint32_t)(qst)) << 1)) | 0x0002000000000001)) -static MP_INLINE bool mp_obj_is_immediate_obj(mp_const_obj_t o) { +static inline bool mp_obj_is_immediate_obj(mp_const_obj_t o) { return (((uint64_t)(o)) & 0xffff000000000000) == 0x0003000000000000; } #define MP_OBJ_IMMEDIATE_OBJ_VALUE(o) ((((uint32_t)(o)) >> 46) & 3) @@ -260,17 +266,17 @@ static MP_INLINE bool mp_obj_is_immediate_obj(mp_const_obj_t o) { #define mp_const_float_nan {((mp_obj_t)((uint64_t)0xfff8000000000000 + 0x8004000000000000))} #endif -static MP_INLINE bool mp_obj_is_float(mp_const_obj_t o) { +static inline bool mp_obj_is_float(mp_const_obj_t o) { return ((uint64_t)(o) & 0xfffc000000000000) != 0; } -static MP_INLINE mp_float_t mp_obj_float_get(mp_const_obj_t o) { +static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) { union { mp_float_t f; uint64_t r; } num = {.r = o - 0x8004000000000000}; return num.f; } -static MP_INLINE mp_obj_t mp_obj_new_float(mp_float_t f) { +static inline mp_obj_t mp_obj_new_float(mp_float_t f) { union { mp_float_t f; uint64_t r; @@ -279,16 +285,18 @@ static MP_INLINE mp_obj_t mp_obj_new_float(mp_float_t f) { } #endif -static MP_INLINE bool mp_obj_is_obj(mp_const_obj_t o) { +static inline bool mp_obj_is_obj(mp_const_obj_t o) { return (((uint64_t)(o)) & 0xffff000000000000) == 0x0000000000000000; } #define MP_OBJ_TO_PTR(o) ((void *)(uintptr_t)(o)) #define MP_OBJ_FROM_PTR(p) ((mp_obj_t)((uintptr_t)(p))) // rom object storage needs special handling to widen 32-bit pointer to 64-bits -typedef union _mp_rom_obj_t { uint64_t u64; - struct { const void *lo, *hi; - } u32; +typedef union _mp_rom_obj_t { + uint64_t u64; + struct { + const void *lo, *hi; + } u32; } mp_rom_obj_t; #define MP_ROM_INT(i) {MP_OBJ_NEW_SMALL_INT(i)} #define MP_ROM_QSTR(q) {MP_OBJ_NEW_QSTR(q)} @@ -307,12 +315,12 @@ typedef union _mp_rom_obj_t { uint64_t u64; // Cast mp_obj_t to object pointer #ifndef MP_OBJ_TO_PTR -#define MP_OBJ_TO_PTR(o) ((void *)o) +#define MP_OBJ_TO_PTR(o) ((void *)(o)) #endif // Cast object pointer to mp_obj_t #ifndef MP_OBJ_FROM_PTR -#define MP_OBJ_FROM_PTR(p) ((mp_obj_t)p) +#define MP_OBJ_FROM_PTR(p) ((mp_obj_t)(p)) #endif // Macros to create objects that are stored in ROM. @@ -389,6 +397,7 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; MP_PROPERTY_GETTER(obj_name, (mp_obj_t)&fun_name##_obj); // These macros are used to define constant or mutable map/dict objects +// These macros are used to define constant map/dict objects // You can put "static" in front of the definition to make it local #define MP_DEFINE_CONST_MAP(map_name, table_name) \ @@ -401,19 +410,21 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; .table = (mp_map_elem_t *)(mp_rom_map_elem_t *)table_name, \ } -#define MP_DEFINE_CONST_DICT(dict_name, table_name) \ +#define MP_DEFINE_CONST_DICT_WITH_SIZE(dict_name, table_name, n) \ const mp_obj_dict_t dict_name = { \ .base = {&mp_type_dict}, \ .map = { \ .all_keys_are_qstrs = 1, \ .is_fixed = 1, \ .is_ordered = 1, \ - .used = MP_ARRAY_SIZE(table_name), \ - .alloc = MP_ARRAY_SIZE(table_name), \ + .used = n, \ + .alloc = n, \ .table = (mp_map_elem_t *)(mp_rom_map_elem_t *)table_name, \ }, \ } +#define MP_DEFINE_CONST_DICT(dict_name, table_name) MP_DEFINE_CONST_DICT_WITH_SIZE(dict_name, table_name, MP_ARRAY_SIZE(table_name)) + #define MP_DEFINE_MUTABLE_MAP(map_name, table_name) \ mp_map_t map_name = { \ .all_keys_are_qstrs = 1, \ @@ -438,6 +449,7 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; } // These macros are used to declare and define constant staticmethond and classmethod objects +// These macros are used to declare and define constant staticmethod and classmethod objects // You can put "static" in front of the definitions to make them local #define MP_DECLARE_CONST_STATICMETHOD_OBJ(obj_name) extern const mp_rom_obj_static_class_method_t obj_name @@ -446,13 +458,18 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; #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} #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} +#ifndef NO_QSTR + // Declare a module as a builtin, processed by makemoduledefs.py // param module_name: MP_QSTR_ // param obj_module: mp_obj_module_t instance - -#ifndef NO_QSTR #define MP_REGISTER_MODULE(module_name, obj_module) -#endif + +// Declare a root pointer (to avoid garbage collection of a global static variable). +// param variable_declaration: a valid C variable declaration +#define MP_REGISTER_ROOT_POINTER(variable_declaration) + +#endif // NO_QSTR // Underlying map/hash table implementation (not dict object or map function) @@ -483,7 +500,7 @@ typedef enum _mp_map_lookup_kind_t { MP_MAP_LOOKUP_ADD_IF_NOT_FOUND_OR_REMOVE_IF_FOUND = 3, // only valid for mp_set_lookup } mp_map_lookup_kind_t; -static MP_INLINE bool mp_map_slot_is_filled(const mp_map_t *map, size_t pos) { +static inline bool mp_map_slot_is_filled(const mp_map_t *map, size_t pos) { assert(pos < map->alloc); return (map)->table[pos].key != MP_OBJ_NULL && (map)->table[pos].key != MP_OBJ_SENTINEL; } @@ -505,7 +522,7 @@ typedef struct _mp_set_t { mp_obj_t *table; } mp_set_t; -static MP_INLINE bool mp_set_slot_is_filled(const mp_set_t *set, size_t pos) { +static 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; } @@ -528,12 +545,22 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); // Flags for type behaviour (mp_obj_type_t.flags) // If MP_TYPE_FLAG_EQ_NOT_REFLEXIVE is clear then __eq__ is reflexive (A==A returns True). // If MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE is clear then the type can't be equal to an -// instance of any different class that also clears this flag. If this flag is set -// then the type may check for equality against a different type. +// instance of any different class that also clears this flag. If this flag is set +// then the type may check for equality against a different type. // If MP_TYPE_FLAG_EQ_HAS_NEQ_TEST is clear then the type only implements the __eq__ -// operator and not the __ne__ operator. If it's set then __ne__ may be implemented. +// operator and not the __ne__ operator. If it's set then __ne__ may be implemented. // If MP_TYPE_FLAG_BINDS_SELF is set then the type as a method binds self as the first arg. // If MP_TYPE_FLAG_BUILTIN_FUN is set then the type is a built-in function type. +// MP_TYPE_FLAG_ITER_IS_GETITER is a no-op flag that means the default behaviour for the +// iter slot and it's the getiter function. +// If MP_TYPE_FLAG_ITER_IS_ITERNEXT is set then the "iter" slot is the iternext +// function and getiter will be automatically implemented as "return self". +// If MP_TYPE_FLAG_ITER_IS_CUSTOM is set then the "iter" slot is a pointer to a +// mp_getiter_iternext_custom_t struct instance (with both .getiter and .iternext set). +// If MP_TYPE_FLAG_ITER_IS_STREAM is set then the type implicitly gets a "return self" +// getiter, and mp_stream_unbuffered_iter for iternext. +// If MP_TYPE_FLAG_INSTANCE_TYPE is set then this is an instance type (i.e. defined in Python). +#define MP_TYPE_FLAG_NONE (0x0000) #define MP_TYPE_FLAG_IS_SUBCLASSED (0x0001) #define MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002) #define MP_TYPE_FLAG_EQ_NOT_REFLEXIVE (0x0004) @@ -541,7 +568,11 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); #define MP_TYPE_FLAG_EQ_HAS_NEQ_TEST (0x0010) #define MP_TYPE_FLAG_BINDS_SELF (0x0020) #define MP_TYPE_FLAG_BUILTIN_FUN (0x0040) -#define MP_TYPE_FLAG_EXTENDED (0x0080) // contains the 'ext' fields +#define MP_TYPE_FLAG_ITER_IS_GETITER (0x0000) +#define MP_TYPE_FLAG_ITER_IS_ITERNEXT (0x0080) +#define MP_TYPE_FLAG_ITER_IS_CUSTOM (0x0100) +#define MP_TYPE_FLAG_ITER_IS_STREAM (MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_ITER_IS_CUSTOM) +#define MP_TYPE_FLAG_INSTANCE_TYPE (0x0200) typedef enum { PRINT_STR = 0, @@ -561,8 +592,6 @@ typedef struct _mp_obj_iter_buf_t { // It's rounded up in case mp_obj_base_t is smaller than mp_obj_t (eg for OBJ_REPR_D). #define MP_OBJ_ITER_BUF_NSLOTS ((sizeof(mp_obj_iter_buf_t) + sizeof(mp_obj_t) - 1) / sizeof(mp_obj_t)) -struct _mp_buffer_info_t; - typedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind); typedef 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); typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args); @@ -571,7 +600,13 @@ typedef mp_obj_t (*mp_binary_op_fun_t)(mp_binary_op_t op, mp_obj_t, mp_obj_t); typedef void (*mp_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); typedef mp_obj_t (*mp_subscr_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); typedef mp_obj_t (*mp_getiter_fun_t)(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); -typedef mp_int_t (*mp_getbuffer_fun_t)(mp_obj_t obj, struct _mp_buffer_info_t *bufinfo, mp_uint_t flags); +typedef mp_fun_1_t mp_iternext_fun_t; + +// For MP_TYPE_FLAG_ITER_IS_CUSTOM, the "getiter" slot points to an instance of this type. +typedef struct _mp_getiter_iternext_custom_t { + mp_getiter_fun_t getiter; + mp_iternext_fun_t iternext; +} mp_getiter_iternext_custom_t; // Buffer protocol typedef struct _mp_buffer_info_t { @@ -582,61 +617,42 @@ typedef struct _mp_buffer_info_t { #define MP_BUFFER_READ (1) #define MP_BUFFER_WRITE (2) #define MP_BUFFER_RW (MP_BUFFER_READ | MP_BUFFER_WRITE) -typedef struct _mp_buffer_p_t { - mp_getbuffer_fun_t get_buffer; -} mp_buffer_p_t; +typedef mp_int_t (*mp_buffer_fun_t)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); -struct _mp_obj_type_ext { - // Corresponds to __call__ special method, ie T(...). - mp_call_fun_t call; - - // Implements unary and binary operations. - // Can return MP_OBJ_NULL if the operation is not supported. - mp_unary_op_fun_t unary_op; - mp_binary_op_fun_t binary_op; - - // Implements load, store and delete subscripting: - // - value = MP_OBJ_SENTINEL means load - // - value = MP_OBJ_NULL means delete - // - all other values mean store the value - // Can return MP_OBJ_NULL if operation not supported. - mp_subscr_fun_t subscr; - - // Corresponds to __iter__ special method. - // Can use the given mp_obj_iter_buf_t to store iterator object, - // otherwise can return a pointer to an object on the heap. - mp_getiter_fun_t getiter; - - // Corresponds to __next__ special method. May return MP_OBJ_STOP_ITERATION - // as an optimisation instead of raising StopIteration() with no args. - mp_fun_1_t iternext; - - // Implements the buffer protocol if supported by this type. - mp_buffer_p_t buffer_p; - - // One of disjoint protocols (interfaces), like mp_stream_p_t, etc. - const void *protocol; -}; - +// This struct will be updated to become a variable sized struct. In order to +// use this as a member, or allocate dynamically, use the mp_obj_empty_type_t +// or mp_obj_full_type_t structs below (which must be kept in sync). struct _mp_obj_type_t { // A type is an object so must start with this entry, which points to mp_type_type. mp_obj_base_t base; // Flags associated with this type. uint16_t flags; + // The name of this type, a qstr. uint16_t name; - // A dict mapping qstrs to objects local methods/constants/etc. - struct _mp_obj_dict_t *locals_dict; + // Slots: For the rest of the fields, the slot index points to the + // relevant function in the variable-length "slots" field. Ideally these + // would be only 4 bits, but the extra overhead of accessing them adds + // more code, and we also need to be able to take the address of them for + // mp_obj_class_lookup. // Corresponds to __new__ and __init__ special methods, to make an instance of the type. - mp_make_new_fun_t make_new; + uint8_t slot_index_make_new; // Corresponds to __repr__ and __str__ special methods. - mp_print_fun_t print; + uint8_t slot_index_print; + + // Corresponds to __call__ special method, ie T(...). + uint8_t slot_index_call; + + // Implements unary and binary operations. + // Can return MP_OBJ_NULL if the operation is not supported. + uint8_t slot_index_unary_op; + uint8_t slot_index_binary_op; // Implements load, store and delete attribute. // @@ -650,62 +666,152 @@ struct _mp_obj_type_t { // dest[0,1] = {MP_OBJ_SENTINEL, object} means store // return: for fail, do nothing // for success set dest[0] = MP_OBJ_NULL - mp_attr_fun_t attr; + uint8_t slot_index_attr; + + // Implements load, store and delete subscripting: + // - value = MP_OBJ_SENTINEL means load + // - value = MP_OBJ_NULL means delete + // - all other values mean store the value + // Can return MP_OBJ_NULL if operation not supported. + uint8_t slot_index_subscr; + + // This slot's behaviour depends on the MP_TYPE_FLAG_ITER_IS_* flags above. + // - If MP_TYPE_FLAG_ITER_IS_GETITER flag is set, then this corresponds to the __iter__ + // special method (of type mp_getiter_fun_t). Can use the given mp_obj_iter_buf_t + // to store the iterator object, otherwise can return a pointer to an object on the heap. + // - If MP_TYPE_FLAG_ITER_IS_ITERNEXT is set, then this corresponds to __next__ special method. + // May return MP_OBJ_STOP_ITERATION as an optimisation instead of raising StopIteration() + // with no args. The type will implicitly implement getiter as "return self". + // - If MP_TYPE_FLAG_ITER_IS_CUSTOM is set, then this slot must point to an + // mp_getiter_iternext_custom_t instance with both the getiter and iternext fields set. + // - If MP_TYPE_FLAG_ITER_IS_STREAM is set, this this slot should be unset. + uint8_t slot_index_iter; + + // Implements the buffer protocol if supported by this type. + uint8_t slot_index_buffer; + + // One of disjoint protocols (interfaces), like mp_stream_p_t, etc. + uint8_t slot_index_protocol; // A pointer to the parents of this type: // - 0 parents: pointer is NULL (object is implicitly the single parent) // - 1 parent: a pointer to the type of that parent // - 2 or more parents: pointer to a tuple object containing the parent types - const void *parent; + uint8_t slot_index_parent; -#define MP_TYPE_EXTENDED_FIELDS(...) .ext = {{ __VA_ARGS__ }} - struct _mp_obj_type_ext ext[]; + // A dict mapping qstrs to objects local methods/constants/etc. + uint8_t slot_index_locals_dict; + + const void *slots[]; }; -// _mp_obj_full_type_t must match _mp_obj_type_t exactly, except that the `ext` field -// is a 1-element array rather than a flexible array member. -struct _mp_obj_full_type_t { +// Non-variable sized versions of mp_obj_type_t to be used as a member +// in other structs or for dynamic allocation. The fields are exactly +// as in mp_obj_type_t, but with a fixed size for the flexible array +// members. +typedef struct _mp_obj_empty_type_t { mp_obj_base_t base; uint16_t flags; uint16_t name; - // A dict mapping qstrs to objects local methods/constants/etc. - struct _mp_obj_dict_t *locals_dict; - mp_make_new_fun_t make_new; - mp_print_fun_t print; - mp_attr_fun_t attr; - const void *parent; - struct _mp_obj_type_ext ext[1]; -}; + uint8_t slot_index_make_new; + uint8_t slot_index_print; + uint8_t slot_index_call; + uint8_t slot_index_unary_op; + uint8_t slot_index_binary_op; + uint8_t slot_index_attr; + uint8_t slot_index_subscr; + uint8_t slot_index_iter; + uint8_t slot_index_buffer; + uint8_t slot_index_protocol; + uint8_t slot_index_parent; + uint8_t slot_index_locals_dict; -// If the type object in question is known to have the extended fields, you can -// refer to type->MP_TYPE_CALL. Otherwise, you have to use mp_type_get_call_slot(type) -// The same goes for other fields within the extended region. -#define MP_TYPE_CALL ext[0].call -#define MP_TYPE_UNARY_OP ext[0].unary_op -#define MP_TYPE_BINARY_OP ext[0].binary_op -#define MP_TYPE_SUBSCR ext[0].subscr -#define MP_TYPE_GETITER ext[0].getiter -#define MP_TYPE_ITERNEXT ext[0].iternext -#define MP_TYPE_GET_BUFFER ext[0].buffer_p.get_buffer -#define MP_TYPE_PROTOCOL ext[0].protocol -extern mp_call_fun_t mp_type_get_call_slot(const mp_obj_type_t *); -extern mp_unary_op_fun_t mp_type_get_unary_op_slot(const mp_obj_type_t *); -extern mp_binary_op_fun_t mp_type_get_binary_op_slot(const mp_obj_type_t *); -extern mp_subscr_fun_t mp_type_get_subscr_slot(const mp_obj_type_t *); -extern mp_getiter_fun_t mp_type_get_getiter_slot(const mp_obj_type_t *); -extern mp_fun_1_t mp_type_get_iternext_slot(const mp_obj_type_t *); -extern mp_getbuffer_fun_t mp_type_get_getbuffer_slot(const mp_obj_type_t *); -extern const void *mp_type_get_protocol_slot(const mp_obj_type_t *); + // No slots member. +} mp_obj_empty_type_t; -// These fields ended up not being placed in the extended area, but accessors -// were created for them anyway. -extern mp_attr_fun_t mp_type_get_attr_slot(const mp_obj_type_t *); -extern const void *mp_type_get_parent_slot(const mp_obj_type_t *); +typedef struct _mp_obj_full_type_t { + mp_obj_base_t base; + uint16_t flags; + uint16_t name; -// Return the size of a type object, which can be one of two lengths depending whether it has -// the extended fields or not. -extern size_t mp_type_size(const mp_obj_type_t *); + uint8_t slot_index_make_new; + uint8_t slot_index_print; + uint8_t slot_index_call; + uint8_t slot_index_unary_op; + uint8_t slot_index_binary_op; + uint8_t slot_index_attr; + uint8_t slot_index_subscr; + uint8_t slot_index_iter; + uint8_t slot_index_buffer; + uint8_t slot_index_protocol; + uint8_t slot_index_parent; + uint8_t slot_index_locals_dict; + + // Explicitly add 12 slots. + const void *slots[11]; +} mp_obj_full_type_t; + +#define _MP_OBJ_TYPE_SLOT_TYPE_make_new (mp_make_new_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_print (mp_print_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_call (mp_call_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_unary_op (mp_unary_op_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_binary_op (mp_binary_op_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_attr (mp_attr_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_subscr (mp_subscr_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_iter (const void *) +#define _MP_OBJ_TYPE_SLOT_TYPE_buffer (mp_buffer_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_protocol (const void *) +#define _MP_OBJ_TYPE_SLOT_TYPE_parent (const void *) +#define _MP_OBJ_TYPE_SLOT_TYPE_locals_dict (struct _mp_obj_dict_t *) + +// Implementation of MP_DEFINE_CONST_OBJ_TYPE for each number of arguments. +// Do not use these directly, instead use MP_DEFINE_CONST_OBJ_TYPE. +// Generated with: +// for i in range(13): +// print(f"#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_{i}(_struct_type, _typename, _name, _flags{''.join(f', f{j+1}, v{j+1}' for j in range(i))}) const _struct_type _typename = {{ .base = {{ &mp_type_type }}, .name = _name, .flags = _flags{''.join(f', .slot_index_##f{j+1} = {j+1}' for j in range(i))}{', .slots = { ' + ''.join(f'v{j+1}, ' for j in range(i)) + '}' if i else '' } }}") +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_0(_struct_type, _typename, _name, _flags) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_1(_struct_type, _typename, _name, _flags, f1, v1) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slots = { v1, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_2(_struct_type, _typename, _name, _flags, f1, v1, f2, v2) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slots = { v1, v2, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_3(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slots = { v1, v2, v3, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_4(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slots = { v1, v2, v3, v4, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_5(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slots = { v1, v2, v3, v4, v5, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_6(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slots = { v1, v2, v3, v4, v5, v6, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_7(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slots = { v1, v2, v3, v4, v5, v6, v7, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_8(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_9(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_10(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slot_index_##f12 = 12, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, } } + +// Because the mp_obj_type_t instances are in (zero-initialised) ROM, we take +// slot_index_foo=0 to mean that the slot is unset. This also simplifies checking +// if the slot is set. That means that we need to store index+1 in slot_index_foo +// though and then access it as slots[slot_index_foo - 1]. This is an implementation +// detail, the user of these macros doesn't need to be aware of it, and when using +// MP_OBJ_TYPE_OFFSETOF_SLOT you should use zero-based indexing. +#define MP_OBJ_TYPE_HAS_SLOT(t, f) ((t)->slot_index_##f) +#define MP_OBJ_TYPE_GET_SLOT(t, f) (_MP_OBJ_TYPE_SLOT_TYPE_##f(t)->slots[(t)->slot_index_##f - 1]) +#define MP_OBJ_TYPE_GET_SLOT_OR_NULL(t, f) (_MP_OBJ_TYPE_SLOT_TYPE_##f(MP_OBJ_TYPE_HAS_SLOT(t, f) ? MP_OBJ_TYPE_GET_SLOT(t, f) : NULL)) +#define MP_OBJ_TYPE_SET_SLOT(t, f, v, n) ((t)->slot_index_##f = (n) + 1, (t)->slots[(n)] = (void *)v) +#define MP_OBJ_TYPE_OFFSETOF_SLOT(f) (offsetof(mp_obj_type_t, slot_index_##f)) +#define MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(t, offset) (*(uint8_t *)((char *)(t) + (offset)) != 0) + +// Workaround for https://docs.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=msvc-160#macro-arguments-are-unpacked +#define MP_DEFINE_CONST_OBJ_TYPE_EXPAND(x) x + +// This macro evaluates to MP_DEFINE_CONST_OBJ_TYPE_NARGS_##N, where N is the value +// of the 29th argument (29 is 13*2 + 3). +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, N, ...) MP_DEFINE_CONST_OBJ_TYPE_NARGS_##N + +// This macros is used to define a object type in ROM. +// Invoke as MP_DEFINE_CONST_OBJ_TYPE(_typename, _name, _flags, _make_new [, slot, func]*) +// It uses the number of arguments to select which MP_DEFINE_CONST_OBJ_TYPE_* +// macro to use based on the number of arguments. It works by shifting the +// numeric values 12, 11, ... 0 by the number of arguments, such that the +// 29th argument ends up being the number to use. The _INV values are +// placeholders because the slot arguments come in pairs. +#define MP_DEFINE_CONST_OBJ_TYPE(...) MP_DEFINE_CONST_OBJ_TYPE_EXPAND(MP_DEFINE_CONST_OBJ_TYPE_NARGS(__VA_ARGS__, _INV, 12, _INV, 11, _INV, 10, _INV, 9, _INV, 8, _INV, 7, _INV, 6, _INV, 5, _INV, 4, _INV, 3, _INV, 2, _INV, 1, _INV, 0)(mp_obj_type_t, __VA_ARGS__)) // Constant types, globally accessible extern const mp_obj_type_t mp_type_type; @@ -736,18 +842,11 @@ extern const mp_obj_type_t mp_type_zip; extern const mp_obj_type_t mp_type_array; extern const mp_obj_type_t mp_type_super; extern const mp_obj_type_t mp_type_gen_wrap; -#if MICROPY_EMIT_NATIVE -extern const mp_obj_type_t mp_type_native_gen_wrap; -#endif -extern const mp_obj_type_t mp_type_gen_instance; -// CIRCUITPY -#if MICROPY_PY_ASYNC_AWAIT extern const mp_obj_type_t mp_type_coro_wrap; -#if MICROPY_EMIT_NATIVE +extern const mp_obj_type_t mp_type_native_gen_wrap; extern const mp_obj_type_t mp_type_native_coro_wrap; -#endif +extern const mp_obj_type_t mp_type_gen_instance; extern const mp_obj_type_t mp_type_coro_instance; -#endif extern const mp_obj_type_t mp_type_fun_builtin_0; extern const mp_obj_type_t mp_type_fun_builtin_1; extern const mp_obj_type_t mp_type_fun_builtin_2; @@ -762,6 +861,9 @@ extern const mp_obj_type_t mp_type_stringio; extern const mp_obj_type_t mp_type_bytesio; extern const mp_obj_type_t mp_type_reversed; extern const mp_obj_type_t mp_type_polymorph_iter; +#if MICROPY_ENABLE_FINALISER +extern const mp_obj_type_t mp_type_polymorph_iter_with_finaliser; +#endif // Exceptions extern const mp_obj_type_t mp_type_BaseException; @@ -782,7 +884,6 @@ extern const mp_obj_type_t mp_type_MemoryError; extern const mp_obj_type_t mp_type_NameError; extern const mp_obj_type_t mp_type_NotImplementedError; extern const mp_obj_type_t mp_type_OSError; -extern const mp_obj_type_t mp_type_TimeoutError; extern const mp_obj_type_t mp_type_ConnectionError; extern const mp_obj_type_t mp_type_BrokenPipeError; extern const mp_obj_type_t mp_type_OverflowError; @@ -791,6 +892,7 @@ extern const mp_obj_type_t mp_type_StopAsyncIteration; extern const mp_obj_type_t mp_type_StopIteration; extern const mp_obj_type_t mp_type_SyntaxError; extern const mp_obj_type_t mp_type_SystemExit; +extern const mp_obj_type_t mp_type_TimeoutError; extern const mp_obj_type_t mp_type_TypeError; extern const mp_obj_type_t mp_type_UnicodeError; extern const mp_obj_type_t mp_type_ValueError; @@ -825,11 +927,11 @@ extern const struct _mp_obj_bool_t mp_const_true_obj; extern const struct _mp_obj_str_t mp_const_empty_bytes_obj; extern const struct _mp_obj_tuple_t mp_const_empty_tuple_obj; extern const struct _mp_obj_dict_t mp_const_empty_dict_obj; -extern const struct _mp_obj_traceback_t mp_const_empty_traceback_obj; extern const struct _mp_obj_singleton_t mp_const_ellipsis_obj; +extern const struct _mp_obj_traceback_t mp_const_empty_traceback_obj; extern const struct _mp_obj_singleton_t mp_const_notimplemented_obj; #if MICROPY_CONST_GENERATOREXIT_OBJ -extern const struct _mp_obj_exception_t mp_static_GeneratorExit_obj; +extern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj; #endif // Fixed empty map. Useful when calling keyword-receiving functions @@ -848,23 +950,37 @@ void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type); // check for more specific object types. // Note: these are kept as macros because inline functions sometimes use much // more code space than the equivalent macros, depending on the compiler. -#define mp_obj_is_type(o, t) (mp_obj_is_obj(o) && (&(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->name) == &((t)->name))) // this does not work for checking int, str or fun; use below macros for that +// don't use mp_obj_is_exact_type directly; use mp_obj_is_type which provides additional safety checks. +// use the former only if you need to bypass these checks (because you've already checked everything else) +#define mp_obj_is_exact_type(o, t) (mp_obj_is_obj(o) && (((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type == (t))) + +// Type checks are split to a separate, constant result macro. This is so it doesn't hinder the compilers's +// optimizations (other tricks like using ({ expr; exper; }) or (exp, expr, expr) in mp_obj_is_type() result +// in missed optimizations) +#define mp_type_assert_not_bool_int_str_nonetype(t) ( \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_bool), assert((t) != &mp_type_bool), \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_int), assert((t) != &mp_type_int), \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_str), assert((t) != &mp_type_str), \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_NoneType), assert((t) != &mp_type_NoneType), \ + 1) + +#define mp_obj_is_type(o, t) (mp_type_assert_not_bool_int_str_nonetype(t) && mp_obj_is_exact_type(o, t)) #if MICROPY_OBJ_IMMEDIATE_OBJS // bool's are immediates, not real objects, so test for the 2 possible values. #define mp_obj_is_bool(o) ((o) == mp_const_false || (o) == mp_const_true) #else -#define mp_obj_is_bool(o) mp_obj_is_type(o, &mp_type_bool) +#define mp_obj_is_bool(o) mp_obj_is_exact_type(o, &mp_type_bool) #endif -#define mp_obj_is_int(o) (mp_obj_is_small_int(o) || mp_obj_is_type(o, &mp_type_int)) -#define mp_obj_is_str(o) (mp_obj_is_qstr(o) || mp_obj_is_type(o, &mp_type_str)) -#define mp_obj_is_str_or_bytes(o) (mp_obj_is_qstr(o) || (mp_obj_is_obj(o) && mp_type_get_binary_op_slot(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type) == mp_obj_str_binary_op)) -#define mp_obj_is_dict_or_ordereddict(o) (mp_obj_is_obj(o) && ((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->make_new == mp_obj_dict_make_new) +#define mp_obj_is_int(o) (mp_obj_is_small_int(o) || mp_obj_is_exact_type(o, &mp_type_int)) +#define mp_obj_is_str(o) (mp_obj_is_qstr(o) || mp_obj_is_exact_type(o, &mp_type_str)) +#define mp_obj_is_str_or_bytes(o) (mp_obj_is_qstr(o) || (mp_obj_is_obj(o) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type, binary_op) == mp_obj_str_binary_op)) +bool mp_obj_is_dict_or_ordereddict(mp_obj_t o); #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)) -// type check is done on getiter method to allow tuple, namedtuple, attrtuple -#define mp_obj_is_tuple_compatible(o) (mp_type_get_getiter_slot(mp_obj_get_type(o)) == mp_obj_tuple_getiter) +// type check is done on iter method to allow tuple, namedtuple, attrtuple +#define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), iter) == mp_obj_tuple_getiter) mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict); -static MP_INLINE mp_obj_t mp_obj_new_bool(mp_int_t x) { +static inline mp_obj_t mp_obj_new_bool(mp_int_t x) { return x ? mp_const_true : mp_const_false; } mp_obj_t mp_obj_new_cell(mp_obj_t obj); @@ -873,17 +989,26 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value); mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base); mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception) mp_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) -mp_obj_t mp_obj_new_str(const char *data, size_t len); -mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len); -mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr); +mp_obj_t mp_obj_new_str(const char *data, size_t len); // will check utf-8 (raises UnicodeError) +mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len); // input data must be valid utf-8 +mp_obj_t mp_obj_new_str_from_vstr(vstr_t *vstr); // will check utf-8 (raises UnicodeError) +#if MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK +mp_obj_t mp_obj_new_str_from_utf8_vstr(vstr_t *vstr); // input data must be valid utf-8 +#else +#define mp_obj_new_str_from_utf8_vstr mp_obj_new_str_from_vstr +#endif +mp_obj_t mp_obj_new_bytes_from_vstr(vstr_t *vstr); mp_obj_t mp_obj_new_bytes(const byte *data, size_t len); +// CIRCUITPY mp_obj_t mp_obj_new_bytes_of_zeros(size_t len); -mp_obj_t mp_obj_new_bytearray(size_t n, void *items); -mp_obj_t mp_obj_new_bytearray_of_zeros(size_t n); +mp_obj_t mp_obj_new_bytearray(size_t n, const void *items); +mp_obj_t mp_obj_new_bytearray_of_zeros(size_t n); // CIRCUITPY mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items); #if MICROPY_PY_BUILTINS_FLOAT mp_obj_t mp_obj_new_int_from_float(mp_float_t val); mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag); + +// CIRCUITPY: our own conversion routines that don't bring double routines extern mp_float_t uint64_to_float(uint64_t ui64); extern uint64_t float_to_uint64(float f); #endif @@ -894,18 +1019,15 @@ mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, #define mp_obj_new_exception_msg_varg(exc_type, ...) mp_obj_new_exception(exc_type) #else mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const compressed_string_t *msg); -mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, ...); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!) +mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, ...); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!) #endif #ifdef va_start -mp_obj_t mp_obj_new_exception_msg_vlist(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, va_list ap); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!) +mp_obj_t mp_obj_new_exception_msg_vlist(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, va_list arg); // same fmt restrictions as above #endif -// Only use this string version from native MPY files with static error strings. -mp_obj_t mp_obj_new_exception_msg_str(const mp_obj_type_t *exc_type, const char *msg); -mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun, bool is_coroutine); +mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun); mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed, const mp_obj_t *closed); mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items); mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items); -mp_obj_t mp_obj_new_list_from_iter(mp_obj_t iterable); mp_obj_t mp_obj_new_dict(size_t n_args); mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items); mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step); @@ -915,7 +1037,6 @@ mp_obj_t mp_obj_new_module(qstr module_name); mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items); const mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in); -const mp_obj_full_type_t *mp_obj_get_full_type(mp_const_obj_t o_in); const char *mp_obj_get_type_str(mp_const_obj_t o_in); #define mp_obj_get_type_qstr(o_in) (mp_obj_get_type((o_in))->name) bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects @@ -932,7 +1053,7 @@ mp_obj_t mp_obj_equal_not_equal(mp_binary_op_t op, mp_obj_t o1, mp_obj_t o2); bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2); // returns true if o is bool, small int or long int -static MP_INLINE bool mp_obj_is_integer(mp_const_obj_t o) { +static inline bool mp_obj_is_integer(mp_const_obj_t o) { return mp_obj_is_int(o) || mp_obj_is_bool(o); } @@ -955,8 +1076,21 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val); mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in); // cell -mp_obj_t mp_obj_cell_get(mp_obj_t self_in); -void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj); + +typedef struct _mp_obj_cell_t { + mp_obj_base_t base; + mp_obj_t obj; +} mp_obj_cell_t; + +static inline mp_obj_t mp_obj_cell_get(mp_obj_t self_in) { + mp_obj_cell_t *self = (mp_obj_cell_t *)MP_OBJ_TO_PTR(self_in); + return self->obj; +} + +static inline void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) { + mp_obj_cell_t *self = (mp_obj_cell_t *)MP_OBJ_TO_PTR(self_in); + self->obj = obj; +} // int // For long int, returns value truncated to mp_int_t @@ -967,7 +1101,7 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in); mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in); // exception -#define mp_obj_is_native_exception_instance(o) (mp_obj_get_type(o)->make_new == mp_obj_exception_make_new) +bool mp_obj_is_native_exception_instance(mp_obj_t self_in); bool mp_obj_is_exception_type(mp_obj_t self_in); bool mp_obj_is_exception_instance(mp_obj_t self_in); bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type); @@ -979,8 +1113,8 @@ mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in); mp_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); mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in); void mp_init_emergency_exception_buf(void); -static MP_INLINE mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) { - assert(exc_type->make_new == mp_obj_exception_make_new); +static inline mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) { + assert(MP_OBJ_TYPE_GET_SLOT_OR_NULL(exc_type, make_new) == mp_obj_exception_make_new); return mp_obj_exception_make_new(exc_type, 1, 0, &arg); } @@ -996,42 +1130,42 @@ void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t s #if MICROPY_PY_BUILTINS_FLOAT // float #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT -static MP_INLINE float mp_obj_get_float_to_f(mp_obj_t o) { +static inline float mp_obj_get_float_to_f(mp_obj_t o) { return mp_obj_get_float(o); } -static MP_INLINE double mp_obj_get_float_to_d(mp_obj_t o) { +static inline double mp_obj_get_float_to_d(mp_obj_t o) { return (double)mp_obj_get_float(o); } -static MP_INLINE mp_obj_t mp_obj_new_float_from_f(float o) { +static inline mp_obj_t mp_obj_new_float_from_f(float o) { return mp_obj_new_float(o); } -static MP_INLINE mp_obj_t mp_obj_new_float_from_d(double o) { +static inline mp_obj_t mp_obj_new_float_from_d(double o) { return mp_obj_new_float((mp_float_t)o); } #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE -static MP_INLINE float mp_obj_get_float_to_f(mp_obj_t o) { +static inline float mp_obj_get_float_to_f(mp_obj_t o) { return (float)mp_obj_get_float(o); } -static MP_INLINE double mp_obj_get_float_to_d(mp_obj_t o) { +static inline double mp_obj_get_float_to_d(mp_obj_t o) { return mp_obj_get_float(o); } -static MP_INLINE mp_obj_t mp_obj_new_float_from_f(float o) { +static inline mp_obj_t mp_obj_new_float_from_f(float o) { return mp_obj_new_float((mp_float_t)o); } -static MP_INLINE mp_obj_t mp_obj_new_float_from_d(double o) { +static inline mp_obj_t mp_obj_new_float_from_d(double o) { return mp_obj_new_float(o); } #endif #if MICROPY_FLOAT_HIGH_QUALITY_HASH mp_int_t mp_float_hash(mp_float_t val); #else -static MP_INLINE mp_int_t mp_float_hash(mp_float_t val) { +static inline mp_int_t mp_float_hash(mp_float_t val) { return (mp_int_t)val; } #endif @@ -1070,7 +1204,7 @@ mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index); mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value); mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key); mp_obj_t mp_obj_dict_copy(mp_obj_t self_in); -static MP_INLINE mp_map_t *mp_obj_dict_get_map(mp_obj_t dict) { +static inline mp_map_t *mp_obj_dict_get_map(mp_obj_t dict) { return &((mp_obj_dict_t *)MP_OBJ_TO_PTR(dict))->map; } @@ -1118,19 +1252,19 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun); mp_obj_t mp_identity(mp_obj_t self); MP_DECLARE_CONST_FUN_OBJ_1(mp_identity_obj); -mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf); // Generic iterator that uses unary op and subscr to iterate over a native type. It will be slower // than a custom iterator but applies broadly. -mp_obj_t mp_obj_new_generic_iterator(mp_obj_t self, mp_obj_iter_buf_t *iter_buf); +mp_obj_t mp_obj_generic_subscript_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf); // module typedef struct _mp_obj_module_t { mp_obj_base_t base; mp_obj_dict_t *globals; } mp_obj_module_t; -mp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t self_in); -void mp_obj_module_set_globals(mp_obj_t self_in, mp_obj_dict_t *globals); +static inline mp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t module) { + return ((mp_obj_module_t *)MP_OBJ_TO_PTR(module))->globals; +} // check if given module object is a package bool mp_obj_is_package(mp_obj_t module); @@ -1177,4 +1311,16 @@ mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t memmove(((char *)dest) + (beg + slice_len) * (item_sz), ((char *)dest) + (end) * (item_sz), ((dest_len) + (len_adj) - ((beg) + (slice_len))) * (item_sz)); \ memmove(((char *)dest) + (beg) * (item_sz), slice, slice_len * (item_sz)); +// Provide translation for legacy API +#define MP_OBJ_IS_SMALL_INT mp_obj_is_small_int +#define MP_OBJ_IS_QSTR mp_obj_is_qstr +#define MP_OBJ_IS_OBJ mp_obj_is_obj +#define MP_OBJ_IS_INT mp_obj_is_int +#define MP_OBJ_IS_TYPE mp_obj_is_type +#define MP_OBJ_IS_STR mp_obj_is_str +#define MP_OBJ_IS_STR_OR_BYTES mp_obj_is_str_or_bytes +#define MP_OBJ_IS_FUN mp_obj_is_fun +#define MP_MAP_SLOT_IS_FILLED mp_map_slot_is_filled +#define MP_SET_SLOT_IS_FILLED mp_set_slot_is_filled + #endif // MICROPY_INCLUDED_PY_OBJ_H diff --git a/py/objarray.c b/py/objarray.c index b8ea9992bb..d54f586e1e 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -31,12 +31,9 @@ #include "py/runtime.h" #include "py/binary.h" -#include "py/objproperty.h" #include "py/objstr.h" #include "py/objarray.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW // About memoryview object: We want to reuse as much code as possible from @@ -56,6 +53,7 @@ #if MICROPY_PY_BUILTINS_MEMORYVIEW #define TYPECODE_MASK (0x7f) #define memview_offset free +#define memview_offset_max ((1LL << MP_OBJ_ARRAY_FREE_SIZE_BITS) - 1) #else // make (& TYPECODE_MASK) a null operation if memorview not enabled #define TYPECODE_MASK (~(size_t)0) @@ -190,12 +188,14 @@ STATIC mp_obj_t array_make_new(const mp_obj_type_t *type_in, size_t n_args, size #if MICROPY_PY_BUILTINS_BYTEARRAY STATIC 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) { (void)type_in; + // Can take 2nd/3rd arg if constructs from str mp_arg_check_num(n_args, n_kw, 0, 3, false); if (n_args == 0) { // no args: construct an empty bytearray return MP_OBJ_FROM_PTR(array_new(BYTEARRAY_TYPECODE, 0)); } else if (mp_obj_is_int(args[0])) { + // CIRCUITPY error checks this if (n_args > 1) { mp_raise_TypeError(MP_ERROR_TEXT("wrong number of arguments")); } @@ -206,6 +206,14 @@ STATIC mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args, return MP_OBJ_FROM_PTR(o); } else { // 1 arg: construct the bytearray from that + if (mp_obj_is_str(args[0]) && n_args == 1) { + #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE + // Match bytes_make_new. + mp_raise_TypeError(MP_ERROR_TEXT("wrong number of arguments")); + #else + mp_raise_TypeError(MP_ERROR_TEXT("string argument without an encoding")); + #endif + } return array_construct(BYTEARRAY_TYPECODE, args[0]); } } @@ -250,6 +258,7 @@ STATIC mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args, return MP_OBJ_FROM_PTR(self); } +// CIRCUITPY adds cast #if MICROPY_CPYTHON_COMPAT STATIC mp_obj_t memoryview_cast(const mp_obj_t self_in, const mp_obj_t typecode_in) { mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); @@ -273,13 +282,21 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(memoryview_cast_obj, memoryview_cast); #endif #if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE -STATIC mp_obj_t memoryview_itemsize_get(mp_obj_t self_in) { - mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); - return MP_OBJ_NEW_SMALL_INT(mp_binary_get_size('@', self->typecode & TYPECODE_MASK, NULL)); +STATIC void memoryview_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + if (dest[0] != MP_OBJ_NULL) { + return; + } + if (attr == MP_QSTR_itemsize) { + mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); + dest[0] = MP_OBJ_NEW_SMALL_INT(mp_binary_get_size('@', self->typecode & TYPECODE_MASK, NULL)); + } + #if MICROPY_PY_BUILTINS_BYTES_HEX || MICROPY_CPYTHON_COMPAT + else { + // Need to forward to locals dict. + dest[1] = MP_OBJ_SENTINEL; + } + #endif } -MP_DEFINE_CONST_FUN_OBJ_1(memoryview_itemsize_get_obj, memoryview_itemsize_get); - -MP_PROPERTY_GETTER(memoryview_itemsize_obj, (mp_obj_t)&memoryview_itemsize_get_obj); #endif #endif @@ -310,6 +327,7 @@ STATIC int typecode_for_comparison(int typecode, bool *is_unsigned) { STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in); switch (op) { + // CIRCUITPY does multiply case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: { if (!mp_obj_is_int(rhs_in)) { @@ -449,7 +467,7 @@ STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) { self->free--; return mp_const_none; // return None, as per CPython } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_append_obj, array_append); +MP_DEFINE_CONST_FUN_OBJ_2(mp_obj_array_append_obj, array_append); STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { // self is not a memoryview, so we don't need to use (& TYPECODE_MASK) @@ -459,6 +477,7 @@ STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { // allow to extend by anything that has the buffer protocol (extension to CPython) mp_buffer_info_t arg_bufinfo; + // CIRCUITPY: allow appending an iterable if (mp_get_buffer(arg_in, &arg_bufinfo, MP_BUFFER_READ)) { size_t sz = mp_binary_get_size('@', self->typecode, NULL); @@ -487,7 +506,7 @@ STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_extend_obj, array_extend); +MP_DEFINE_CONST_FUN_OBJ_2(mp_obj_array_extend_obj, array_extend); #endif #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_CPYTHON_COMPAT @@ -529,6 +548,7 @@ STATIC mp_obj_t buffer_finder(size_t n_args, const mp_obj_t *args, int direction return MP_OBJ_NEW_SMALL_INT(p - (const byte *)haystack_bufinfo.buf); } +// CIRCUITPY provides find, rfind, index STATIC mp_obj_t buffer_find(size_t n_args, const mp_obj_t *args) { return buffer_finder(n_args, args, 1, false); } @@ -571,7 +591,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value size_t src_len; void *src_items; size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL); - if (mp_obj_is_obj(value) && mp_type_get_subscr_slot(((mp_obj_base_t *)MP_OBJ_TO_PTR(value))->type) == array_subscr) { + if (mp_obj_is_obj(value) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(value))->type, subscr) == array_subscr) { // value is array, bytearray or memoryview mp_obj_array_t *src_slice = MP_OBJ_TO_PTR(value); if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) { @@ -644,6 +664,9 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value assert(sz > 0); #if MICROPY_PY_BUILTINS_MEMORYVIEW if (o->base.type == &mp_type_memoryview) { + if (slice.start > memview_offset_max) { + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("memoryview offset too large")); + } res = m_new_obj(mp_obj_array_t); *res = *o; res->memview_offset += slice.start; @@ -717,22 +740,10 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(array_decode_obj, 1, 3, array_decode); #endif -#if MICROPY_PY_ARRAY -STATIC const mp_rom_map_elem_t array_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&array_append_obj) }, - { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&array_extend_obj) }, - #if MICROPY_CPYTHON_COMPAT - { MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&bytes_decode_obj) }, - #endif -}; - -STATIC MP_DEFINE_CONST_DICT(array_locals_dict, array_locals_dict_table); -#endif - #if MICROPY_PY_BUILTINS_BYTEARRAY STATIC const mp_rom_map_elem_t bytearray_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&array_append_obj) }, - { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&array_extend_obj) }, + { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&mp_obj_array_append_obj) }, + { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&mp_obj_array_extend_obj) }, #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&buffer_find_obj) }, @@ -744,78 +755,78 @@ STATIC const mp_rom_map_elem_t bytearray_locals_dict_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(bytearray_locals_dict, bytearray_locals_dict_table); +MP_DEFINE_CONST_DICT(bytearray_locals_dict, bytearray_locals_dict_table); #endif #if MICROPY_PY_ARRAY -const mp_obj_type_t mp_type_array = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_array, - .print = array_print, - .make_new = array_make_new, - .locals_dict = (mp_obj_dict_t *)&array_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = array_iterator_new, - .unary_op = array_unary_op, - .binary_op = array_binary_op, - .subscr = array_subscr, - .buffer_p = { .get_buffer = array_get_buffer }, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_array, + MP_QSTR_array, + MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, array_make_new, + print, array_print, + iter, array_iterator_new, + unary_op, array_unary_op, + binary_op, array_binary_op, + subscr, array_subscr, + buffer, array_get_buffer, + locals_dict, &mp_obj_array_locals_dict + ); #endif #if MICROPY_PY_BUILTINS_BYTEARRAY -const mp_obj_type_t mp_type_bytearray = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_bytearray, - .print = array_print, - .make_new = bytearray_make_new, - .locals_dict = (mp_obj_dict_t *)&bytearray_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = array_iterator_new, - .unary_op = array_unary_op, - .binary_op = array_binary_op, - .subscr = array_subscr, - .buffer_p = { .get_buffer = array_get_buffer }, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bytearray, + MP_QSTR_bytearray, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, bytearray_make_new, + print, array_print, + iter, array_iterator_new, + unary_op, array_unary_op, + binary_op, array_binary_op, + subscr, array_subscr, + buffer, array_get_buffer, + locals_dict, &mp_obj_bytearray_locals_dict + ); #endif #if MICROPY_PY_BUILTINS_MEMORYVIEW +#if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE +#define MEMORYVIEW_TYPE_ATTR attr, memoryview_attr, +#else +#define MEMORYVIEW_TYPE_ATTR +#endif -#if MICROPY_CPYTHON_COMPAT || MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE +#if MICROPY_CPYTHON_COMPAT // CIRCUITPY provides csat STATIC const mp_rom_map_elem_t memoryview_locals_dict_table[] = { - #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR_cast), MP_ROM_PTR(&memoryview_cast_obj) }, - #endif - #if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE - { MP_ROM_QSTR(MP_QSTR_itemsize), MP_ROM_PTR(&memoryview_itemsize_obj) }, + #if MICROPY_PY_BUILTINS_BYTES_HEX + { MP_ROM_QSTR(MP_QSTR_hex), MP_ROM_PTR(&mp_obj_bytes_hex_as_str_obj) }, #endif }; - -STATIC MP_DEFINE_CONST_DICT(memoryview_locals_dict, memoryview_locals_dict_table); +MP_DEFINE_CONST_DICT(memoryview_locals_dict, memoryview_locals_dict_table); +#define MEMORYVIEW_TYPE_LOCALS_DICT locals_dict, &memoryview_locals_dict, +#elif MICROPY_PY_BUILTINS_BYTES_HEX +#define MEMORYVIEW_TYPE_LOCALS_DICT locals_dict, &mp_obj_memoryview_locals_dict, +#else +#define MEMORYVIEW_TYPE_LOCALS_DICT #endif -const mp_obj_type_t mp_type_memoryview = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_memoryview, - .make_new = memoryview_make_new, - #if MICROPY_CPYTHON_COMPAT || MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE - .locals_dict = (mp_obj_dict_t *)&memoryview_locals_dict, - #endif - MP_TYPE_EXTENDED_FIELDS( - .getiter = array_iterator_new, - .unary_op = array_unary_op, - .binary_op = array_binary_op, - .subscr = array_subscr, - .buffer_p = { .get_buffer = array_get_buffer }, - ), -}; -#endif +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_memoryview, + MP_QSTR_memoryview, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, memoryview_make_new, + iter, array_iterator_new, + unary_op, array_unary_op, + binary_op, array_binary_op, + MEMORYVIEW_TYPE_LOCALS_DICT + MEMORYVIEW_TYPE_ATTR + subscr, array_subscr, + buffer, array_get_buffer + ); +#endif // MICROPY_PY_BUILTINS_MEMORYVIEW /* unused size_t mp_obj_array_len(mp_obj_t self_in) { @@ -824,7 +835,7 @@ size_t mp_obj_array_len(mp_obj_t self_in) { */ #if MICROPY_PY_BUILTINS_BYTEARRAY -mp_obj_t mp_obj_new_bytearray(size_t n, void *items) { +mp_obj_t mp_obj_new_bytearray(size_t n, const void *items) { mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n); memcpy(o->items, items, n); return MP_OBJ_FROM_PTR(o); @@ -866,15 +877,12 @@ STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) { } } -STATIC const mp_obj_type_t mp_type_array_it = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_iterator, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = array_it_iternext, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_array_it, + MP_QSTR_iterator, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + iter, array_it_iternext + ); STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_array_t) <= sizeof(mp_obj_iter_buf_t)); diff --git a/py/objarray.h b/py/objarray.h index 94c31c9693..4a0e8a983f 100644 --- a/py/objarray.h +++ b/py/objarray.h @@ -32,6 +32,9 @@ // Used only for memoryview types, set in "typecode" to indicate a writable memoryview #define MP_OBJ_ARRAY_TYPECODE_FLAG_RW (0x80) +// Bit size used for mp_obj_array_t.free member. +#define MP_OBJ_ARRAY_FREE_SIZE_BITS (8 * sizeof(size_t) - 8) + // This structure is used for all of bytearray, array.array, memoryview // objects. Note that memoryview has different meaning for some fields, // see comment at the beginning of objarray.c. @@ -44,7 +47,7 @@ typedef struct _mp_obj_array_t { // parent object. (Union is not used to not go into a complication of // union-of-bitfields with different toolchains). See comments in // objarray.c. - size_t free : (8 * sizeof(size_t) - 8); + size_t free : MP_OBJ_ARRAY_FREE_SIZE_BITS; size_t len; // in elements void *items; } mp_obj_array_t; @@ -59,4 +62,9 @@ static inline void mp_obj_memoryview_init(mp_obj_array_t *self, size_t typecode, } #endif +#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY +MP_DECLARE_CONST_FUN_OBJ_2(mp_obj_array_append_obj); +MP_DECLARE_CONST_FUN_OBJ_2(mp_obj_array_extend_obj); +#endif + #endif // MICROPY_INCLUDED_PY_OBJARRAY_H diff --git a/py/objattrtuple.c b/py/objattrtuple.c index c288727d48..fbe04bedb8 100644 --- a/py/objattrtuple.c +++ b/py/objattrtuple.c @@ -80,18 +80,17 @@ mp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *item return MP_OBJ_FROM_PTR(o); } -const mp_obj_type_t mp_type_attrtuple = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_tuple, // reuse tuple to save on a qstr - .print = mp_obj_attrtuple_print, - .attr = mp_obj_attrtuple_attr, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_attrtuple, + MP_QSTR_tuple, + MP_TYPE_FLAG_ITER_IS_GETITER, + // reuse tuple to save on a qstr + print, mp_obj_attrtuple_print, + unary_op, mp_obj_tuple_unary_op, + binary_op, mp_obj_tuple_binary_op, + attr, mp_obj_attrtuple_attr, + subscr, mp_obj_tuple_subscr, + iter, mp_obj_tuple_getiter + ); #endif // MICROPY_PY_ATTRTUPLE diff --git a/py/objbool.c b/py/objbool.c index e450270fd9..3267ff98bb 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -84,17 +84,16 @@ STATIC mp_obj_t bool_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_ return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(value), rhs_in); } -const mp_obj_type_t mp_type_bool = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EXTENDED, // can match all numeric types - .name = MP_QSTR_bool, - .print = bool_print, - .make_new = bool_make_new, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = bool_unary_op, - .binary_op = bool_binary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + // can match all numeric types + mp_type_bool, + MP_QSTR_bool, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + make_new, bool_make_new, + print, bool_print, + unary_op, bool_unary_op, + binary_op, bool_binary_op + ); #if !MICROPY_OBJ_IMMEDIATE_OBJS const mp_obj_bool_t mp_const_false_obj = {{&mp_type_bool}, false}; diff --git a/py/objboundmeth.c b/py/objboundmeth.c index edc37462dd..8486f876f9 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -95,20 +95,26 @@ STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } #endif -STATIC const mp_obj_type_t mp_type_bound_meth = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_bound_method, - #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED - .print = bound_meth_print, - #endif - MP_TYPE_EXTENDED_FIELDS( - .call = bound_meth_call, - ), - #if MICROPY_PY_FUNCTION_ATTRS - .attr = bound_meth_attr, - #endif -}; +#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED +#define BOUND_METH_TYPE_PRINT print, bound_meth_print, +#else +#define BOUND_METH_TYPE_PRINT +#endif + +#if MICROPY_PY_FUNCTION_ATTRS +#define BOUND_METH_TYPE_ATTR attr, bound_meth_attr, +#else +#define BOUND_METH_TYPE_ATTR +#endif + +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bound_meth, + MP_QSTR_bound_method, + MP_TYPE_FLAG_NONE, + BOUND_METH_TYPE_PRINT + BOUND_METH_TYPE_ATTR + call, bound_meth_call + ); mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) { mp_obj_bound_meth_t *o = mp_obj_malloc(mp_obj_bound_meth_t, &mp_type_bound_meth); diff --git a/py/objcell.c b/py/objcell.c index 2702ca5350..0a74e29d20 100644 --- a/py/objcell.c +++ b/py/objcell.c @@ -26,21 +26,6 @@ #include "py/obj.h" -typedef struct _mp_obj_cell_t { - mp_obj_base_t base; - mp_obj_t obj; -} mp_obj_cell_t; - -mp_obj_t mp_obj_cell_get(mp_obj_t self_in) { - mp_obj_cell_t *self = MP_OBJ_TO_PTR(self_in); - return self->obj; -} - -void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) { - mp_obj_cell_t *self = MP_OBJ_TO_PTR(self_in); - self->obj = obj; -} - #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; @@ -55,13 +40,17 @@ STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t k } #endif -STATIC const mp_obj_type_t mp_type_cell = { - { &mp_type_type }, - .name = MP_QSTR_, // cell representation is just value in < > - #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED - .print = cell_print, - #endif -}; +#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED +#define CELL_TYPE_PRINT , print, cell_print +#else +#define CELL_TYPE_PRINT +#endif + +STATIC MP_DEFINE_CONST_OBJ_TYPE( + // cell representation is just value in < > + mp_type_cell, MP_QSTR_, MP_TYPE_FLAG_NONE + CELL_TYPE_PRINT + ); mp_obj_t mp_obj_new_cell(mp_obj_t obj) { mp_obj_cell_t *o = mp_obj_malloc(mp_obj_cell_t, &mp_type_cell); diff --git a/py/objclosure.c b/py/objclosure.c index 309dd2b826..6059d18100 100644 --- a/py/objclosure.c +++ b/py/objclosure.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -78,17 +78,31 @@ STATIC void closure_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_ } #endif -const mp_obj_type_t mp_type_closure = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_closure, - #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED - .print = closure_print, - #endif - MP_TYPE_EXTENDED_FIELDS( - .call = closure_call, - ) -}; +#if MICROPY_PY_FUNCTION_ATTRS +STATIC void mp_obj_closure_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + // forward to self_in->fun + mp_obj_closure_t *o = MP_OBJ_TO_PTR(self_in); + mp_load_method_maybe(o->fun, attr, dest); +} +#define CLOSURE_TYPE_ATTR attr, mp_obj_closure_attr, +#else +#define CLOSURE_TYPE_ATTR +#endif + +#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED +#define CLOSURE_TYPE_PRINT print, closure_print, +#else +#define CLOSURE_TYPE_PRINT +#endif + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_closure, + MP_QSTR_closure, + MP_TYPE_FLAG_BINDS_SELF, + CLOSURE_TYPE_ATTR + CLOSURE_TYPE_PRINT + call, closure_call + ); mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed_over, const mp_obj_t *closed) { mp_obj_closure_t *o = mp_obj_malloc_var(mp_obj_closure_t, mp_obj_t, n_closed_over, &mp_type_closure); diff --git a/py/objcomplex.c b/py/objcomplex.c index 570f9f746f..9c71455a97 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -31,8 +31,6 @@ #include "py/parsenum.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_COMPLEX #include @@ -88,13 +86,14 @@ STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, si // a string, parse it size_t l; const char *s = mp_obj_str_get_data(args[0], &l); - return mp_parse_num_decimal(s, l, true, true, NULL); + return mp_parse_num_complex(s, l, NULL); } else if (mp_obj_is_type(args[0], &mp_type_complex)) { // a complex, just return it return args[0]; } else { - // something else, try to cast it to a complex - return mp_obj_new_complex(mp_obj_get_float(args[0]), 0); + mp_float_t real, imag; + mp_obj_get_complex(args[0], &real, &imag); + return mp_obj_new_complex(real, imag); } case 2: @@ -155,18 +154,14 @@ STATIC void complex_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_complex = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_complex, - .print = complex_print, - .make_new = complex_make_new, - .attr = complex_attr, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = complex_unary_op, - .binary_op = complex_binary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_complex, MP_QSTR_complex, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + make_new, complex_make_new, + print, complex_print, + unary_op, complex_unary_op, + binary_op, complex_binary_op, + attr, complex_attr + ); mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag) { mp_obj_complex_t *o = mp_obj_malloc(mp_obj_complex_t, &mp_type_complex); @@ -210,13 +205,13 @@ mp_obj_t mp_obj_complex_binary_op(mp_binary_op_t op, mp_float_t lhs_real, mp_flo } case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: - mp_raise_TypeError(MP_ERROR_TEXT("can't do truncated division of a complex number")); + mp_raise_TypeError(MP_ERROR_TEXT("can't truncate-divide a complex number")); case MP_BINARY_OP_TRUE_DIVIDE: case MP_BINARY_OP_INPLACE_TRUE_DIVIDE: if (rhs_imag == 0) { if (rhs_real == 0) { - mp_raise_ZeroDivisionError(); + mp_raise_msg(&mp_type_ZeroDivisionError, MP_ERROR_TEXT("complex divide by zero")); } lhs_real /= rhs_real; lhs_imag /= rhs_real; @@ -267,6 +262,4 @@ mp_obj_t mp_obj_complex_binary_op(mp_binary_op_t op, mp_float_t lhs_real, mp_flo return mp_obj_new_complex(lhs_real, lhs_imag); } -#pragma GCC diagnostic pop - #endif diff --git a/py/objdeque.c b/py/objdeque.c index 621b7b60b0..67a5baa257 100644 --- a/py/objdeque.c +++ b/py/objdeque.c @@ -28,7 +28,6 @@ #include #include "py/mpconfig.h" -#include "supervisor/shared/translate/translate.h" #if MICROPY_PY_COLLECTIONS_DEQUE @@ -157,15 +156,13 @@ STATIC const mp_rom_map_elem_t deque_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(deque_locals_dict, deque_locals_dict_table); -const mp_obj_type_t mp_type_deque = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_deque, - .make_new = deque_make_new, - .locals_dict = (mp_obj_dict_t *)&deque_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = deque_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_deque, + MP_QSTR_deque, + MP_TYPE_FLAG_NONE, + make_new, deque_make_new, + unary_op, deque_unary_op, + locals_dict, &deque_locals_dict + ); #endif // MICROPY_PY_COLLECTIONS_DEQUE diff --git a/py/objdict.c b/py/objdict.c index e4e9711c60..f378fd3e87 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -33,8 +33,9 @@ #include "py/objtype.h" #include "py/objstr.h" -#include "supervisor/linker.h" -#include "supervisor/shared/translate/translate.h" +bool mp_obj_is_dict_or_ordereddict(mp_obj_t o) { + return mp_obj_is_obj(o) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type, make_new) == mp_obj_dict_make_new; +} const mp_obj_dict_t mp_const_empty_dict_obj = { .base = { .type = &mp_type_dict }, @@ -125,7 +126,14 @@ STATIC mp_obj_t dict_new_typed(const mp_obj_type_t *type, const size_t n) { } mp_obj_t mp_obj_dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_obj_t dict_out = dict_new_typed(type, 0); + mp_obj_t dict_out = mp_obj_new_dict(0); + mp_obj_dict_t *dict = MP_OBJ_TO_PTR(dict_out); + dict->base.type = type; + #if MICROPY_PY_COLLECTIONS_ORDEREDDICT + if (type == &mp_type_ordereddict) { + dict->map.is_ordered = 1; + } + #endif if (n_args > 0 || n_kw > 0) { mp_obj_t args2[2] = {dict_out, args[0]}; // args[0] is always valid, even if it's not a positional arg mp_map_t kwargs; @@ -175,6 +183,7 @@ STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_ return e1 == NULL && e2 == NULL ? mp_const_true : mp_const_false; } #endif + if (mp_obj_is_type(rhs_in, &mp_type_dict)) { mp_obj_dict_t *rhs = MP_OBJ_TO_PTR(rhs_in); if (o->map.used != rhs->map.used) { @@ -195,6 +204,17 @@ STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_ return mp_const_false; } } + #if MICROPY_CPYTHON_COMPAT + case MP_BINARY_OP_INPLACE_OR: + case MP_BINARY_OP_OR: { + if (op == MP_BINARY_OP_OR) { + lhs_in = mp_obj_dict_copy(lhs_in); + } + mp_obj_t dicts[2] = {lhs_in, rhs_in}; + dict_update(2, dicts, (mp_map_t *)&mp_const_empty_map); + return lhs_in; + } + #endif default: // op not supported return MP_OBJ_NULL; @@ -468,7 +488,6 @@ STATIC mp_obj_t dict_move_to_end(size_t n_args, const mp_obj_t *pos_args, mp_map STATIC MP_DEFINE_CONST_FUN_OBJ_KW(dict_move_to_end_obj, 1, dict_move_to_end); #endif - /******************************************************************************/ /* dict views */ @@ -518,15 +537,12 @@ STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) { } } -STATIC const mp_obj_type_t mp_type_dict_view_it = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_iterator, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = dict_view_it_iternext, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_dict_view_it, + MP_QSTR_iterator, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + iter, dict_view_it_iternext + ); STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t)); @@ -572,16 +588,14 @@ STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t return dict_binary_op(op, o->dict, rhs_in); } -STATIC const mp_obj_type_t mp_type_dict_view = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_dict_view, - .print = dict_view_print, - MP_TYPE_EXTENDED_FIELDS( - .binary_op = dict_view_binary_op, - .getiter = dict_view_getiter, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_dict_view, + MP_QSTR_dict_view, + MP_TYPE_FLAG_ITER_IS_GETITER, + print, dict_view_print, + binary_op, dict_view_binary_op, + iter, dict_view_getiter + ); STATIC mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) { mp_obj_dict_view_t *o = mp_obj_malloc(mp_obj_dict_view_t, &mp_type_dict_view); @@ -651,37 +665,33 @@ STATIC const mp_rom_map_elem_t dict_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table); -const mp_obj_type_t mp_type_dict = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_dict, - .print = dict_print, - .make_new = mp_obj_dict_make_new, - .locals_dict = (mp_obj_dict_t *)&dict_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = dict_unary_op, - .binary_op = dict_binary_op, - .subscr = dict_subscr, - .getiter = dict_getiter, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_dict, + MP_QSTR_dict, + MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, mp_obj_dict_make_new, + print, dict_print, + unary_op, dict_unary_op, + binary_op, dict_binary_op, + subscr, dict_subscr, + iter, dict_getiter, + locals_dict, &dict_locals_dict + ); #if MICROPY_PY_COLLECTIONS_ORDEREDDICT -const mp_obj_type_t mp_type_ordereddict = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_OrderedDict, - .print = dict_print, - .make_new = mp_obj_dict_make_new, - .parent = &mp_type_dict, - .locals_dict = (mp_obj_dict_t *)&dict_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = dict_unary_op, - .binary_op = dict_binary_op, - .subscr = dict_subscr, - .getiter = dict_getiter, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_ordereddict, + MP_QSTR_OrderedDict, + MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, mp_obj_dict_make_new, + print, dict_print, + unary_op, dict_unary_op, + binary_op, dict_binary_op, + subscr, dict_subscr, + iter, dict_getiter, + parent, &mp_type_dict, + locals_dict, &dict_locals_dict + ); #endif void mp_obj_dict_init(mp_obj_dict_t *dict, size_t n_args) { @@ -700,7 +710,7 @@ size_t mp_obj_dict_len(mp_obj_t self_in) { return self->map.used; } -mp_obj_t PLACE_IN_ITCM(mp_obj_dict_store)(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) { +mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) { mp_check_self(mp_obj_is_dict_or_ordereddict(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_ensure_not_fixed(self); diff --git a/py/objenumerate.c b/py/objenumerate.c index 2ef553adb5..40bed919ed 100644 --- a/py/objenumerate.c +++ b/py/objenumerate.c @@ -67,16 +67,13 @@ STATIC mp_obj_t enumerate_make_new(const mp_obj_type_t *type, size_t n_args, siz return MP_OBJ_FROM_PTR(o); } -const mp_obj_type_t mp_type_enumerate = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_enumerate, - .make_new = enumerate_make_new, - MP_TYPE_EXTENDED_FIELDS( - .iternext = enumerate_iternext, - .getiter = mp_identity_getiter, - ) -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_enumerate, + MP_QSTR_enumerate, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + make_new, enumerate_make_new, + iter, enumerate_iternext + ); STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in) { assert(mp_obj_is_type(self_in, &mp_type_enumerate)); diff --git a/py/objexcept.c b/py/objexcept.c index 282740ae44..0890afa3c6 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -39,7 +39,15 @@ #include "py/gc.h" #include "py/mperrno.h" -#include "supervisor/shared/translate/translate.h" +#if MICROPY_ROM_TEXT_COMPRESSION && !defined(NO_QSTR) +// Extract the MP_MAX_UNCOMPRESSED_TEXT_LEN macro from "genhdr/compressed.data.h". +// Only need this if compression enabled and in a regular build (i.e. not during QSTR extraction). +#define MP_MATCH_COMPRESSED(...) // Ignore +#define MP_COMPRESSED_DATA(...) // Ignore +#include "genhdr/compressed.data.h" +#undef MP_MATCH_COMPRESSED +#undef MP_COMPRESSED_DATA +#endif // Number of items per traceback entry (file, line, block) #define TRACEBACK_ENTRY_LEN (3) @@ -104,6 +112,10 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) { #endif #endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF +bool mp_obj_is_native_exception_instance(mp_obj_t self_in) { + return MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(self_in), make_new) == mp_obj_exception_make_new; +} + mp_obj_exception_t *mp_obj_exception_get_native(mp_obj_t self_in) { assert(mp_obj_is_exception_instance(self_in)); if (mp_obj_is_native_exception_instance(self_in)) { @@ -113,6 +125,40 @@ mp_obj_exception_t *mp_obj_exception_get_native(mp_obj_t self_in) { } } +STATIC void decompress_error_text_maybe(mp_obj_exception_t *o) { + #if MICROPY_ROM_TEXT_COMPRESSION + if (o->args->len == 1 && mp_obj_is_exact_type(o->args->items[0], &mp_type_str)) { + mp_obj_str_t *o_str = MP_OBJ_TO_PTR(o->args->items[0]); + if (MP_IS_COMPRESSED_ROM_STRING(o_str->data)) { + byte *buf = m_new_maybe(byte, MP_MAX_UNCOMPRESSED_TEXT_LEN + 1); + if (!buf) { + #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF + // Try and use the emergency exception buf if enough space is available. + buf = (byte *)((uint8_t *)MP_STATE_VM(mp_emergency_exception_buf) + EMG_BUF_STR_BUF_OFFSET); + size_t avail = (uint8_t *)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - buf; + if (avail < MP_MAX_UNCOMPRESSED_TEXT_LEN + 1) { + // No way to decompress, fallback to no message text. + o->args = (mp_obj_tuple_t *)&mp_const_empty_tuple_obj; + return; + } + #else + o->args = (mp_obj_tuple_t *)&mp_const_empty_tuple_obj; + return; + #endif + } + mp_decompress_rom_string(buf, (mp_rom_error_text_t)o_str->data); + o_str->data = buf; + o_str->len = strlen((const char *)buf); + o_str->hash = 0; + } + // Lazily compute the string hash. + if (o_str->hash == 0) { + o_str->hash = qstr_compute_hash(o_str->data, o_str->len); + } + } + #endif +} + void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_exception_t *o = MP_OBJ_TO_PTR(o_in); mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS; @@ -125,14 +171,18 @@ void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kin mp_print_str(print, ": "); } + decompress_error_text_maybe(o); + if (k == PRINT_STR || k == PRINT_EXC) { if (o->args == NULL || o->args->len == 0) { mp_print_str(print, ""); return; } + #if MICROPY_PY_UERRNO // try to provide a nice OSError error message if (o->base.type == &mp_type_OSError && o->args->len > 0 && o->args->len < 3 && mp_obj_is_small_int(o->args->items[0])) { + // CIRCUITPY can print a whole string, not just the errno qstr char decompressed[50]; const char *msg = mp_common_errno_to_str(o->args->items[0], decompressed, sizeof(decompressed)); if (msg != NULL) { @@ -155,6 +205,7 @@ void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kin mp_obj_tuple_print(print, MP_OBJ_FROM_PTR(o->args), kind); } +// CIRCUITPY void mp_obj_exception_initialize0(mp_obj_exception_t *o_exc, const mp_obj_type_t *type) { o_exc->base.type = type; o_exc->args = (mp_obj_tuple_t *)&mp_const_empty_tuple_obj; @@ -216,6 +267,7 @@ mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in) { if (self->args->len == 0) { return mp_const_none; } else { + decompress_error_text_maybe(self); return self->args->items[0]; } } @@ -225,7 +277,7 @@ void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // store/delete attribute #if MICROPY_CONST_GENERATOREXIT_OBJ - if (self == &mp_static_GeneratorExit_obj) { + if (self == &mp_const_GeneratorExit_obj) { mp_raise_AttributeError(MP_ERROR_TEXT("can't set attribute")); } #endif @@ -267,6 +319,7 @@ void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { return; } if (attr == MP_QSTR_args) { + decompress_error_text_maybe(self); dest[0] = MP_OBJ_FROM_PTR(self->args); } else if (attr == MP_QSTR_value && self->base.type == &mp_type_StopIteration) { dest[0] = mp_obj_exception_get_value(self_in); @@ -308,13 +361,14 @@ void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_BaseException = { - { &mp_type_type }, - .name = MP_QSTR_BaseException, - .print = mp_obj_exception_print, - .make_new = mp_obj_exception_make_new, - .attr = mp_obj_exception_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_BaseException, + MP_QSTR_BaseException, + MP_TYPE_FLAG_NONE, + make_new, mp_obj_exception_make_new, + print, mp_obj_exception_print, + attr, mp_obj_exception_attr + ); // *FORMAT-OFF* @@ -322,51 +376,62 @@ const mp_obj_type_t mp_type_BaseException = { // http://docs.python.org/3/library/exceptions.html MP_DEFINE_EXCEPTION(SystemExit, BaseException) MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException) +// CIRCUITPY MP_DEFINE_EXCEPTION(ReloadException, BaseException) MP_DEFINE_EXCEPTION(GeneratorExit, BaseException) MP_DEFINE_EXCEPTION(Exception, BaseException) -#if MICROPY_PY_ASYNC_AWAIT + #if MICROPY_PY_ASYNC_AWAIT MP_DEFINE_EXCEPTION(StopAsyncIteration, Exception) -#endif + #endif MP_DEFINE_EXCEPTION(StopIteration, Exception) MP_DEFINE_EXCEPTION(ArithmeticError, Exception) - // MP_DEFINE_EXCEPTION(FloatingPointError, ArithmeticError) + //MP_DEFINE_EXCEPTION(FloatingPointError, ArithmeticError) MP_DEFINE_EXCEPTION(OverflowError, ArithmeticError) MP_DEFINE_EXCEPTION(ZeroDivisionError, ArithmeticError) MP_DEFINE_EXCEPTION(AssertionError, Exception) MP_DEFINE_EXCEPTION(AttributeError, Exception) - // MP_DEFINE_EXCEPTION(BufferError, Exception) - // MP_DEFINE_EXCEPTION(EnvironmentError, Exception) use OSError instead + //MP_DEFINE_EXCEPTION(BufferError, Exception) MP_DEFINE_EXCEPTION(EOFError, Exception) MP_DEFINE_EXCEPTION(ImportError, Exception) - // MP_DEFINE_EXCEPTION(IOError, Exception) use OSError instead MP_DEFINE_EXCEPTION(LookupError, Exception) MP_DEFINE_EXCEPTION(IndexError, LookupError) MP_DEFINE_EXCEPTION(KeyError, LookupError) MP_DEFINE_EXCEPTION(MemoryError, Exception) MP_DEFINE_EXCEPTION(NameError, Exception) - // MP_DEFINE_EXCEPTION(UnboundLocalError, NameError) + /* + MP_DEFINE_EXCEPTION(UnboundLocalError, NameError) + */ MP_DEFINE_EXCEPTION(OSError, Exception) + /* + MP_DEFINE_EXCEPTION(BlockingIOError, OSError) + MP_DEFINE_EXCEPTION(ChildProcessError, OSError) + */ MP_DEFINE_EXCEPTION(ConnectionError, OSError) MP_DEFINE_EXCEPTION(BrokenPipeError, ConnectionError) - // MP_DEFINE_EXCEPTION(ConnectionAbortedError, ConnectionError) - // MP_DEFINE_EXCEPTION(ConnectionRefusedError, ConnectionError) - // MP_DEFINE_EXCEPTION(ConnectionResetError, ConnectionError) - // MP_DEFINE_EXCEPTION(FileExistsError, OSError) - MP_DEFINE_EXCEPTION(FileNotFoundError, OSError) - // MP_DEFINE_EXCEPTION(InterruptedError, OSError) - // MP_DEFINE_EXCEPTION(IsADirectoryError, OSError) - // MP_DEFINE_EXCEPTION(NotADirectoryError, OSError) - // MP_DEFINE_EXCEPTION(PermissionError, OSError) - // MP_DEFINE_EXCEPTION(ProcessLookupError, OSError) - // MP_DEFINE_EXCEPTION(ReferenceError, Exception) + /* + MP_DEFINE_EXCEPTION(ConnectionAbortedError, ConnectionError) + MP_DEFINE_EXCEPTION(ConnectionRefusedError, ConnectionError) + MP_DEFINE_EXCEPTION(ConnectionResetError, ConnectionError) + MP_DEFINE_EXCEPTION(InterruptedError, OSError) + MP_DEFINE_EXCEPTION(IsADirectoryError, OSError) + MP_DEFINE_EXCEPTION(NotADirectoryError, OSError) + MP_DEFINE_EXCEPTION(PermissionError, OSError) + MP_DEFINE_EXCEPTION(ProcessLookupError, OSError) + */ MP_DEFINE_EXCEPTION(TimeoutError, OSError) + /* + MP_DEFINE_EXCEPTION(FileExistsError, OSError) + MP_DEFINE_EXCEPTION(FileNotFoundError, OSError) + MP_DEFINE_EXCEPTION(ReferenceError, Exception) + */ MP_DEFINE_EXCEPTION(RuntimeError, Exception) MP_DEFINE_EXCEPTION(NotImplementedError, RuntimeError) MP_DEFINE_EXCEPTION(SyntaxError, Exception) MP_DEFINE_EXCEPTION(IndentationError, SyntaxError) - // MP_DEFINE_EXCEPTION(TabError, IndentationError) - // MP_DEFINE_EXCEPTION(SystemError, Exception) + /* + MP_DEFINE_EXCEPTION(TabError, IndentationError) + */ + //MP_DEFINE_EXCEPTION(SystemError, Exception) MP_DEFINE_EXCEPTION(TypeError, Exception) #if MICROPY_EMIT_NATIVE MP_DEFINE_EXCEPTION(ViperTypeError, TypeError) @@ -396,12 +461,12 @@ MP_DEFINE_EXCEPTION(DeepSleepRequest, BaseException) // *FORMAT-ON* mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type) { - assert(exc_type->make_new == mp_obj_exception_make_new); + assert(MP_OBJ_TYPE_GET_SLOT_OR_NULL(exc_type, make_new) == mp_obj_exception_make_new); return mp_obj_exception_make_new(exc_type, 0, 0, NULL); } mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, const mp_obj_t *args) { - assert(exc_type->make_new == mp_obj_exception_make_new); + assert(MP_OBJ_TYPE_GET_SLOT_OR_NULL(exc_type, make_new) == mp_obj_exception_make_new); return mp_obj_exception_make_new(exc_type, n_args, 0, args); } @@ -409,7 +474,6 @@ mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const compressed_string_t *msg) { return mp_obj_new_exception_msg_varg(exc_type, msg); } -#endif // The following struct and function implement a simple printer that conservatively // allocates memory and truncates the output data if no more memory can be obtained. @@ -444,20 +508,19 @@ STATIC void exc_add_strn(void *data, const char *str, size_t len) { pr->len += len; } - mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, ...) { - va_list ap; - va_start(ap, fmt); - mp_obj_t exception = mp_obj_new_exception_msg_vlist(exc_type, fmt, ap); - va_end(ap); - return exception; + va_list args; + va_start(args, fmt); + mp_obj_t exc = mp_obj_new_exception_msg_vlist(exc_type, fmt, args); + va_end(args); + return exc; } mp_obj_t mp_obj_new_exception_msg_vlist(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, va_list ap) { assert(fmt != NULL); // Check that the given type is an exception type - assert(exc_type->make_new == mp_obj_exception_make_new); + assert(MP_OBJ_TYPE_GET_SLOT_OR_NULL(exc_type, make_new) == mp_obj_exception_make_new); // Try to allocate memory for the message mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); @@ -502,53 +565,22 @@ mp_obj_t mp_obj_new_exception_msg_vlist(const mp_obj_type_t *exc_type, const com // Create the string object and call mp_obj_exception_make_new to create the exception o_str->base.type = &mp_type_str; + #if MICROPY_ROM_TEXT_COMPRESSION + o_str->hash = 0; // will be computed only if string object is accessed + #else o_str->hash = qstr_compute_hash(o_str->data, o_str->len); - mp_obj_t arg = MP_OBJ_FROM_PTR(o_str); - return mp_obj_exception_make_new(exc_type, 1, 0, &arg); -} - -mp_obj_t mp_obj_new_exception_msg_str(const mp_obj_type_t *exc_type, const char *msg) { - assert(msg != NULL); - - // Check that the given type is an exception type - assert(exc_type->make_new == mp_obj_exception_make_new); - - // Try to allocate memory for the message - mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); - - #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF - // If memory allocation failed and there is an emergency buffer then try to use - // that buffer to store the string object and its data (at least 16 bytes for - // the string data), reserving room at the start for the traceback and 1-tuple. - if (o_str == NULL - && mp_emergency_exception_buf_size >= EMG_BUF_STR_OFFSET + sizeof(mp_obj_str_t) + 16) { - o_str = (mp_obj_str_t *)((uint8_t *)MP_STATE_VM(mp_emergency_exception_buf) - + EMG_BUF_STR_OFFSET); - } #endif - - if (o_str == NULL) { - // No memory for the string object so create the exception with no args - return mp_obj_exception_make_new(exc_type, 0, 0, NULL); - } - - // Assume the message is statically allocated. - o_str->len = strlen(msg); - o_str->data = (const byte *)msg; - - // Create the string object and call mp_obj_exception_make_new to create the exception - o_str->base.type = &mp_type_str; - o_str->hash = qstr_compute_hash(o_str->data, o_str->len); mp_obj_t arg = MP_OBJ_FROM_PTR(o_str); return mp_obj_exception_make_new(exc_type, 1, 0, &arg); } +#endif // return true if the given object is an exception type bool mp_obj_is_exception_type(mp_obj_t self_in) { if (mp_obj_is_type(self_in, &mp_type_type)) { // optimisation when self_in is a builtin exception mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); - if (self->make_new == mp_obj_exception_make_new) { + if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(self, make_new) == mp_obj_exception_make_new) { return true; } } @@ -589,6 +621,9 @@ void mp_obj_exception_clear_traceback(mp_obj_t self_in) { void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block) { mp_obj_exception_t *self = mp_obj_exception_get_native(self_in); + // append this traceback info to traceback data + // if memory allocation fails (eg because gc is locked), just return + #if MICROPY_PY_SYS_TRACEBACKLIMIT mp_int_t max_traceback = MP_OBJ_SMALL_INT_VALUE(MP_STATE_VM(sys_mutable[MP_SYS_MUTABLE_TRACEBACKLIMIT])); if (max_traceback <= 0) { @@ -672,23 +707,7 @@ void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values #if MICROPY_PY_SYS_EXC_INFO STATIC const mp_obj_namedtuple_type_t code_type_obj = { - .base = { - .base = { - .type = &mp_type_type - }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_code, - .print = namedtuple_print, - .make_new = namedtuple_make_new, - .parent = &mp_type_tuple, - .attr = namedtuple_attr, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - ), - }, + NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_code), .n_fields = 15, .fields = { MP_QSTR_co_argcount, @@ -732,22 +751,7 @@ STATIC mp_obj_t code_make_new(qstr file, qstr block) { } STATIC const mp_obj_namedtuple_type_t frame_type_obj = { - .base = { - .base = { - .type = &mp_type_type - }, - .name = MP_QSTR_frame, - .print = namedtuple_print, - .make_new = namedtuple_make_new, - .parent = &mp_type_tuple, - .attr = namedtuple_attr, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - ), - }, + NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_frame), .n_fields = 8, .fields = { MP_QSTR_f_back, @@ -777,23 +781,7 @@ STATIC mp_obj_t frame_make_new(mp_obj_t f_code, int f_lineno) { } STATIC const mp_obj_namedtuple_type_t traceback_type_obj = { - .base = { - .base = { - .type = &mp_type_type - }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_traceback, - .print = namedtuple_print, - .make_new = namedtuple_make_new, - .parent = &mp_type_tuple, - .attr = namedtuple_attr, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - ), - }, + NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_traceback), .n_fields = 4, .fields = { MP_QSTR_tb_frame, diff --git a/py/objexcept.h b/py/objexcept.h index 80c06e90e0..c7e1d89f2d 100644 --- a/py/objexcept.h +++ b/py/objexcept.h @@ -47,13 +47,11 @@ void mp_obj_exception_initialize0(mp_obj_exception_t *o_exc, const mp_obj_type_t mp_obj_exception_t *mp_obj_exception_get_native(mp_obj_t self_in); #define MP_DEFINE_EXCEPTION(exc_name, base_name) \ - const mp_obj_type_t mp_type_##exc_name = { \ - { &mp_type_type }, \ - .name = MP_QSTR_##exc_name, \ - .print = mp_obj_exception_print, \ - .make_new = mp_obj_exception_make_new, \ - .attr = mp_obj_exception_attr, \ - .parent = &mp_type_##base_name, \ - }; + MP_DEFINE_CONST_OBJ_TYPE(mp_type_##exc_name, MP_QSTR_##exc_name, MP_TYPE_FLAG_NONE, \ + make_new, mp_obj_exception_make_new, \ + print, mp_obj_exception_print, \ + attr, mp_obj_exception_attr, \ + parent, &mp_type_##base_name \ + ); #endif // MICROPY_INCLUDED_PY_OBJEXCEPT_H diff --git a/py/objfilter.c b/py/objfilter.c index 5292cfc550..2a657fde4b 100644 --- a/py/objfilter.c +++ b/py/objfilter.c @@ -60,15 +60,12 @@ STATIC mp_obj_t filter_iternext(mp_obj_t self_in) { return MP_OBJ_STOP_ITERATION; } -const mp_obj_type_t mp_type_filter = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_filter, - .make_new = filter_make_new, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = filter_iternext, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_filter, + MP_QSTR_filter, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + make_new, filter_make_new, + iter, filter_iternext + ); #endif // MICROPY_PY_BUILTINS_FILTER diff --git a/py/objfloat.c b/py/objfloat.c index 5666f3f5c2..90aeef648b 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -32,8 +32,6 @@ #include "py/parsenum.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_FLOAT #include @@ -142,7 +140,7 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size mp_buffer_info_t bufinfo; if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) { // a textual representation, parse it - return mp_parse_num_decimal(bufinfo.buf, bufinfo.len, false, false, NULL); + return mp_parse_num_float(bufinfo.buf, bufinfo.len, false, NULL); } else if (mp_obj_is_float(args[0])) { // a float, just return it return args[0]; @@ -187,17 +185,13 @@ STATIC mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs return mp_obj_float_binary_op(op, lhs_val, rhs_in); } -const mp_obj_type_t mp_type_float = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_float, - .print = float_print, - .make_new = float_make_new, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = float_unary_op, - .binary_op = float_binary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_float, MP_QSTR_float, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + make_new, float_make_new, + print, float_print, + unary_op, float_unary_op, + binary_op, float_binary_op + ); #if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D @@ -352,6 +346,7 @@ mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t return mp_obj_new_float(lhs_val); } +// CIRCUITPY // Convert a uint64_t to a 32-bit float without invoking the double-precision math routines, // which are large. mp_float_t uint64_to_float(uint64_t ui64) { @@ -359,6 +354,7 @@ mp_float_t uint64_to_float(uint64_t ui64) { return (mp_float_t)((uint32_t)(ui64 >> 32) * 4294967296.0f + (uint32_t)(ui64 & 0xffffffff)); } +// CIRCUITPY // Convert a uint64_t to a 32-bit float to a uint64_t without invoking extra math routines. // which are large. // Assume f >= 0. diff --git a/py/objfun.c b/py/objfun.c index eb4a2bfe25..e10b79d089 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -34,8 +34,6 @@ #include "py/bc.h" #include "py/stackctrl.h" -#include "supervisor/linker.h" - #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #else // don't print debugging info @@ -58,15 +56,11 @@ STATIC mp_obj_t PLACE_IN_ITCM(fun_builtin_0_call)(mp_obj_t self_in, size_t n_arg return self->fun._0(); } -const mp_obj_type_t mp_type_fun_builtin_0 = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_function, - MP_TYPE_EXTENDED_FIELDS( - .call = fun_builtin_0_call, - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_builtin_0, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, + call, fun_builtin_0_call, + unary_op, mp_generic_unary_op + ); STATIC mp_obj_t PLACE_IN_ITCM(fun_builtin_1_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_1)); @@ -75,32 +69,24 @@ STATIC mp_obj_t PLACE_IN_ITCM(fun_builtin_1_call)(mp_obj_t self_in, size_t n_arg return self->fun._1(args[0]); } -const mp_obj_type_t mp_type_fun_builtin_1 = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_function, - MP_TYPE_EXTENDED_FIELDS( - .call = fun_builtin_1_call, - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_builtin_1, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, + call, fun_builtin_1_call, + unary_op, mp_generic_unary_op + ); -STATIC mp_obj_t PLACE_IN_ITCM(fun_builtin_2_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +STATIC 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) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_2)); mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); mp_arg_check_num(n_args, n_kw, 2, 2, false); return self->fun._2(args[0], args[1]); } -const mp_obj_type_t mp_type_fun_builtin_2 = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_function, - MP_TYPE_EXTENDED_FIELDS( - .call = fun_builtin_2_call, - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_builtin_2, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, + call, fun_builtin_2_call, + unary_op, mp_generic_unary_op + ); STATIC mp_obj_t PLACE_IN_ITCM(fun_builtin_3_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_3)); @@ -109,17 +95,13 @@ STATIC mp_obj_t PLACE_IN_ITCM(fun_builtin_3_call)(mp_obj_t self_in, size_t n_arg return self->fun._3(args[0], args[1], args[2]); } -const mp_obj_type_t mp_type_fun_builtin_3 = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_function, - MP_TYPE_EXTENDED_FIELDS( - .call = fun_builtin_3_call, - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_builtin_3, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, + call, fun_builtin_3_call, + unary_op, mp_generic_unary_op + ); -STATIC mp_obj_t PLACE_IN_ITCM(fun_builtin_var_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +STATIC 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) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_var)); mp_obj_fun_builtin_var_t *self = MP_OBJ_TO_PTR(self_in); @@ -142,15 +124,11 @@ STATIC mp_obj_t PLACE_IN_ITCM(fun_builtin_var_call)(mp_obj_t self_in, size_t n_a } } -const mp_obj_type_t mp_type_fun_builtin_var = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_function, - MP_TYPE_EXTENDED_FIELDS( - .call = fun_builtin_var_call, - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_builtin_var, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, + call, fun_builtin_var_call, + unary_op, mp_generic_unary_op + ); /******************************************************************************/ /* byte code functions */ @@ -374,21 +352,27 @@ void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } #endif -const mp_obj_type_t mp_type_fun_bc = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_function, - #if MICROPY_CPYTHON_COMPAT - .print = fun_bc_print, - #endif - #if MICROPY_PY_FUNCTION_ATTRS - .attr = mp_obj_fun_bc_attr, - #endif - MP_TYPE_EXTENDED_FIELDS( - .call = fun_bc_call, - .unary_op = mp_generic_unary_op, - ), -}; +#if MICROPY_CPYTHON_COMPAT +#define FUN_BC_TYPE_PRINT print, fun_bc_print, +#else +#define FUN_BC_TYPE_PRINT +#endif + +#if MICROPY_PY_FUNCTION_ATTRS +#define FUN_BC_TYPE_ATTR attr, mp_obj_fun_bc_attr, +#else +#define FUN_BC_TYPE_ATTR +#endif + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_bc, + MP_QSTR_function, + MP_TYPE_FLAG_BINDS_SELF, + FUN_BC_TYPE_PRINT + FUN_BC_TYPE_ATTR + call, fun_bc_call, + unary_op, mp_generic_unary_op + ); mp_obj_t mp_obj_new_fun_bc(const mp_obj_t *def_args, const byte *code, const mp_module_context_t *context, struct _mp_raw_code_t *const *child_table) { size_t n_def_args = 0; @@ -431,15 +415,26 @@ STATIC mp_obj_t PLACE_IN_ITCM(fun_native_call)(mp_obj_t self_in, size_t n_args, return fun(self_in, n_args, n_kw, args); } -STATIC const mp_obj_type_t mp_type_fun_native = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_function, - MP_TYPE_EXTENDED_FIELDS( - .call = fun_native_call, - .unary_op = mp_generic_unary_op, - ), -}; +#if MICROPY_CPYTHON_COMPAT +#define FUN_BC_TYPE_PRINT print, fun_bc_print, +#else +#define FUN_BC_TYPE_PRINT +#endif +#if MICROPY_PY_FUNCTION_ATTRS +#define FUN_BC_TYPE_ATTR attr, mp_obj_fun_bc_attr, +#else +#define FUN_BC_TYPE_ATTR +#endif + +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_native, + MP_QSTR_function, + MP_TYPE_FLAG_BINDS_SELF, + FUN_BC_TYPE_PRINT + FUN_BC_TYPE_ATTR + call, fun_native_call, + unary_op, mp_generic_unary_op + ); mp_obj_t mp_obj_new_fun_native(const mp_obj_t *def_args, const void *fun_data, const mp_module_context_t *mc, struct _mp_raw_code_t *const *child_table) { mp_obj_fun_bc_t *o = MP_OBJ_TO_PTR(mp_obj_new_fun_bc(def_args, (const byte *)fun_data, mc, child_table)); @@ -478,7 +473,7 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { return 0; } else if (obj == mp_const_true) { return 1; - } else if (mp_obj_is_type(obj, &mp_type_int)) { + } else if (mp_obj_is_exact_type(obj, &mp_type_int)) { return mp_obj_int_get_truncated(obj); } else if (mp_obj_is_str(obj)) { // pointer to the string (it's probably constant though!) @@ -541,15 +536,13 @@ STATIC mp_obj_t PLACE_IN_ITCM(fun_asm_call)(mp_obj_t self_in, size_t n_args, siz return mp_native_to_obj(ret, self->type_sig); } -STATIC const mp_obj_type_t mp_type_fun_asm = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_function, - MP_TYPE_EXTENDED_FIELDS( - .call = fun_asm_call, - .unary_op = mp_generic_unary_op, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_asm, + MP_QSTR_function, + MP_TYPE_FLAG_BINDS_SELF, + call, fun_asm_call, + unary_op, mp_generic_unary_op + ); mp_obj_t mp_obj_new_fun_asm(size_t n_args, const void *fun_data, mp_uint_t type_sig) { mp_obj_fun_asm_t *o = mp_obj_malloc(mp_obj_fun_asm_t, &mp_type_fun_asm); diff --git a/py/objgenerator.c b/py/objgenerator.c index 4443f81ce1..e1873040f9 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -35,13 +35,11 @@ #include "py/objfun.h" #include "py/stackctrl.h" -#include "supervisor/shared/translate/translate.h" - // Instance of GeneratorExit exception - needed by generator.close() // CIRCUITPY: https://github.com/adafruit/circuitpython/pull/7069 fix #if MICROPY_CONST_GENERATOREXIT_OBJ const -mp_obj_exception_t mp_static_GeneratorExit_obj = {{&mp_type_GeneratorExit}, (mp_obj_tuple_t *)&mp_const_empty_tuple_obj, (mp_obj_traceback_t *)&mp_const_empty_traceback_obj}; +mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, (mp_obj_tuple_t *)&mp_const_empty_tuple_obj, (mp_obj_traceback_t *)&mp_const_empty_traceback_obj}; #else static mp_obj_exception_t mp_static_GeneratorExit_obj; @@ -85,32 +83,30 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons return MP_OBJ_FROM_PTR(o); } -const mp_obj_type_t mp_type_gen_wrap = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_generator, - #if MICROPY_PY_FUNCTION_ATTRS - .attr = mp_obj_fun_bc_attr, - #endif - MP_TYPE_EXTENDED_FIELDS( - .call = gen_wrap_call, - .unary_op = mp_generic_unary_op, - ), -}; +#if MICROPY_PY_FUNCTION_ATTRS +#define GEN_WRAP_TYPE_ATTR attr, mp_obj_fun_bc_attr, +#else +#define GEN_WRAP_TYPE_ATTR +#endif + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_gen_wrap, + MP_QSTR_generator, + MP_TYPE_FLAG_BINDS_SELF, + GEN_WRAP_TYPE_ATTR + call, gen_wrap_call, + unary_op, mp_generic_unary_op + ); #if MICROPY_PY_ASYNC_AWAIT -const mp_obj_type_t mp_type_coro_wrap = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_coroutine, - #if MICROPY_PY_FUNCTION_ATTRS - .attr = mp_obj_fun_bc_attr, - #endif - MP_TYPE_EXTENDED_FIELDS( - .call = gen_wrap_call, - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_coro_wrap, + MP_QSTR_coroutine, + MP_TYPE_FLAG_BINDS_SELF, + GEN_WRAP_TYPE_ATTR + call, gen_wrap_call, + unary_op, mp_generic_unary_op + ); #endif /******************************************************************************/ @@ -175,32 +171,31 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k return MP_OBJ_FROM_PTR(o); } -const mp_obj_type_t mp_type_native_gen_wrap = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_generator, - #if MICROPY_PY_FUNCTION_ATTRS - .attr = mp_obj_fun_bc_attr, - #endif - MP_TYPE_EXTENDED_FIELDS( - .call = native_gen_wrap_call, - .unary_op = mp_generic_unary_op, - ), -}; +#if MICROPY_PY_FUNCTION_ATTRS +#define NATIVE_GEN_WRAP_TYPE_ATTR attr, mp_obj_fun_bc_attr, +#else +#define NATIVE_GEN_WRAP_TYPE_ATTR +#endif + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_native_gen_wrap, + MP_QSTR_generator, + MP_TYPE_FLAG_BINDS_SELF, + call, native_gen_wrap_call, + NATIVE_GEN_WRAP_TYPE_ATTR + unary_op, mp_generic_unary_op + ); + #if MICROPY_PY_ASYNC_AWAIT -const mp_obj_type_t mp_type_native_coro_wrap = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_coroutine, - #if MICROPY_PY_FUNCTION_ATTRS - .attr = mp_obj_fun_bc_attr, - #endif - MP_TYPE_EXTENDED_FIELDS( - .call = native_gen_wrap_call, - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_native_coro_wrap, + MP_QSTR_coroutine, + MP_TYPE_FLAG_BINDS_SELF, + GEN_WRAP_TYPE_ATTR + call, native_gen_wrap_call, + unary_op, mp_generic_unary_op + ); #endif #endif // MICROPY_EMIT_NATIVE @@ -241,6 +236,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ *ret_val = mp_const_none; return MP_VM_RETURN_NORMAL; } + // Ensure the generator cannot be reentered during execution if (self->pend_exc == MP_OBJ_NULL) { mp_raise_ValueError(MP_ERROR_TEXT("generator already executing")); @@ -337,7 +333,6 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, bool raise_stop_iteration) { mp_obj_t ret; switch (mp_obj_gen_resume(self_in, send_value, throw_value, &ret)) { - case MP_VM_RETURN_NORMAL: default: // A normal return is a StopIteration, either raise it or return @@ -401,8 +396,10 @@ static mp_obj_t generatorexit(void) { #if MICROPY_CPYTHON_EXCEPTION_CHAIN MP_STATIC_ASSERT(!MICROPY_CONST_GENERATOREXIT_OBJ); mp_obj_exception_initialize0(&mp_static_GeneratorExit_obj, &mp_type_GeneratorExit); - #endif return MP_OBJ_FROM_PTR(&mp_static_GeneratorExit_obj); + #else + return MP_OBJ_FROM_PTR(&mp_const_GeneratorExit_obj); + #endif } STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { @@ -450,18 +447,15 @@ STATIC const mp_rom_map_elem_t gen_instance_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_table); -const mp_obj_type_t mp_type_gen_instance = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_generator, - .print = gen_instance_print, - .locals_dict = (mp_obj_dict_t *)&gen_instance_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_generic_unary_op, - .getiter = mp_identity_getiter, - .iternext = gen_instance_iternext, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_gen_instance, + MP_QSTR_generator, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + print, gen_instance_print, + unary_op, mp_generic_unary_op, + iter, gen_instance_iternext, + locals_dict, &gen_instance_locals_dict + ); #if MICROPY_PY_ASYNC_AWAIT // CIRCUITPY @@ -474,23 +468,18 @@ STATIC const mp_rom_map_elem_t coro_instance_locals_dict_table[] = { #if MICROPY_PY_GENERATOR_PEND_THROW { MP_ROM_QSTR(MP_QSTR_pend_throw), MP_ROM_PTR(&gen_instance_pend_throw_obj) }, #endif - #if MICROPY_PY_ASYNC_AWAIT { MP_ROM_QSTR(MP_QSTR___await__), MP_ROM_PTR(&coro_instance_await_obj) }, - #endif }; STATIC MP_DEFINE_CONST_DICT(coro_instance_locals_dict, coro_instance_locals_dict_table); -const mp_obj_type_t mp_type_coro_instance = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_coroutine, - .print = coro_instance_print, - .locals_dict = (mp_obj_dict_t *)&coro_instance_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_generic_unary_op, - .getiter = mp_identity_getiter, - .iternext = gen_instance_iternext, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_coro_instance, + MP_QSTR_coroutine, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + print, coro_instance_print, + unary_op, mp_generic_unary_op, + iter, gen_instance_iternext, + locals_dict, &coro_instance_locals_dict + ); #endif diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c index d841212649..c598d1daac 100644 --- a/py/objgetitemiter.c +++ b/py/objgetitemiter.c @@ -56,15 +56,12 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) { } } -STATIC const mp_obj_type_t mp_type_it = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_iterator, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = it_iternext, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_it, + MP_QSTR_iterator, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + iter, it_iternext + ); // args are those returned from mp_load_method_maybe (ie either an attribute or a method) mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf) { diff --git a/py/objint.c b/py/objint.c index 83987d690a..68541353d8 100644 --- a/py/objint.c +++ b/py/objint.c @@ -35,8 +35,6 @@ #include "py/runtime.h" #include "py/binary.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_FLOAT #include #endif @@ -142,9 +140,9 @@ mp_obj_t mp_obj_new_int_from_float(mp_float_t val) { if (u.p.exp == ((1 << MP_FLOAT_EXP_BITS) - 1)) { // ...then number is Inf (positive or negative) if fraction is 0, else NaN. if (u.p.frc == 0) { - mp_raise_OverflowError_varg(MP_ERROR_TEXT("can't convert %q to %q"), MP_QSTR_inf, MP_QSTR_int); + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert inf to int")); } else { - mp_raise_ValueError_varg(MP_ERROR_TEXT("can't convert %q to %q"), MP_QSTR_NaN, MP_QSTR_int); + mp_raise_ValueError(MP_ERROR_TEXT("can't convert NaN to int")); } } else { mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val); @@ -234,7 +232,7 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co // A small int; get the integer value to format. num = MP_OBJ_SMALL_INT_VALUE(self_in); } else { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); // Not a small int. #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG const mp_obj_int_t *self = self_in; @@ -485,8 +483,8 @@ STATIC mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *pos_args, mp_map_t enum { ARG_bytes, ARG_byteorder, ARG_signed }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_bytes, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_byteorder, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_bytes, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = NULL} }, + { MP_QSTR_byteorder, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = NULL} }, { MP_QSTR_signed, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -568,7 +566,7 @@ STATIC mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *pos_args, mp_map_t * mp_binary_set_int(l, big_endian, data + (big_endian ? (len - l) : 0), val); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(int_to_bytes_obj, 3, int_to_bytes); @@ -582,15 +580,13 @@ STATIC const mp_rom_map_elem_t int_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table); -const mp_obj_type_t mp_type_int = { - { &mp_type_type }, - .name = MP_QSTR_int, - .flags = MP_TYPE_FLAG_EXTENDED, - .print = mp_obj_int_print, - .make_new = mp_obj_int_make_new, - .locals_dict = (mp_obj_dict_t *)&int_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_int_unary_op, - .binary_op = mp_obj_int_binary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_int, + MP_QSTR_int, + MP_TYPE_FLAG_NONE, + make_new, mp_obj_int_make_new, + print, mp_obj_int_print, + unary_op, mp_obj_int_unary_op, + binary_op, mp_obj_int_binary_op, + locals_dict, &int_locals_dict + ); diff --git a/py/objint_longlong.c b/py/objint_longlong.c index ba23825abf..a2d6e8382b 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -32,8 +32,6 @@ #include "py/objint.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_FLOAT #include #endif @@ -71,7 +69,7 @@ mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf } void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); mp_obj_int_t *self = self_in; long long val = self->val; if (big_endian) { @@ -144,13 +142,13 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i if (mp_obj_is_small_int(lhs_in)) { lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs_in); } else { - assert(mp_obj_is_type(lhs_in, &mp_type_int)); + assert(mp_obj_is_exact_type(lhs_in, &mp_type_int)); lhs_val = ((mp_obj_int_t *)lhs_in)->val; } if (mp_obj_is_small_int(rhs_in)) { rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs_in); - } else if (mp_obj_is_type(rhs_in, &mp_type_int)) { + } else if (mp_obj_is_exact_type(rhs_in, &mp_type_int)) { rhs_val = ((mp_obj_int_t *)rhs_in)->val; } else { // delegate to generic function to check for extra cases @@ -297,7 +295,7 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); mp_obj_int_t *self = self_in; return self->val; } diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 603a5b986c..81293b0593 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -33,8 +33,6 @@ #include "py/objint.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_FLOAT #include #endif @@ -93,7 +91,7 @@ mp_obj_int_t *mp_obj_int_new_mpz(void) { // This particular routine should only be called for the mpz representation of the int. char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma) { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); size_t needed_size = mp_int_format_size(mpz_max_num_bits(&self->mpz), base, prefix, comma); @@ -109,7 +107,7 @@ char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, } mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in) { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(mpz_num_bits(&self->mpz)); } @@ -121,7 +119,7 @@ mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf } void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); mpz_as_bytes(&self->mpz, big_endian, len, buf); } @@ -189,7 +187,7 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(lhs_in)); zlhs = &z_int; } else { - assert(mp_obj_is_type(lhs_in, &mp_type_int)); + assert(mp_obj_is_exact_type(lhs_in, &mp_type_int)); zlhs = &((mp_obj_int_t *)MP_OBJ_TO_PTR(lhs_in))->mpz; } @@ -197,7 +195,7 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i if (mp_obj_is_small_int(rhs_in)) { mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(rhs_in)); zrhs = &z_int; - } else if (mp_obj_is_type(rhs_in, &mp_type_int)) { + } else if (mp_obj_is_exact_type(rhs_in, &mp_type_int)) { zrhs = &((mp_obj_int_t *)MP_OBJ_TO_PTR(rhs_in))->mpz; #if MICROPY_PY_BUILTINS_FLOAT } else if (mp_obj_is_float(rhs_in)) { @@ -304,8 +302,7 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i mpz_pow_inpl(&res->mpz, zlhs, zrhs); break; - default: { - assert(op == MP_BINARY_OP_DIVMOD); + case MP_BINARY_OP_DIVMOD: { if (mpz_is_zero(zrhs)) { goto zero_division_error; } @@ -314,6 +311,9 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i mp_obj_t tuple[2] = {MP_OBJ_FROM_PTR(quo), MP_OBJ_FROM_PTR(res)}; return mp_obj_new_tuple(2, tuple); } + + default: + return MP_OBJ_NULL; // op not supported } return MP_OBJ_FROM_PTR(res); @@ -459,7 +459,7 @@ mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) { #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); return mpz_as_float(&self->mpz); } diff --git a/py/objlist.c b/py/objlist.c index f95c322bd5..aa857fbfc0 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -31,8 +31,6 @@ #include "py/runtime.h" #include "py/stackctrl.h" -#include "supervisor/shared/translate/translate.h" - STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur, mp_obj_iter_buf_t *iter_buf); STATIC mp_obj_list_t *list_new(size_t n); STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in); @@ -73,12 +71,7 @@ STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) { return list; } -mp_obj_t mp_obj_new_list_from_iter(mp_obj_t iterable) { - mp_obj_t list = mp_obj_new_list(0, NULL); - return list_extend_from_iter(list, iterable); -} - -STATIC 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) { +mp_obj_t mp_obj_list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 1, false); @@ -468,20 +461,19 @@ STATIC const mp_rom_map_elem_t list_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(list_locals_dict, list_locals_dict_table); -const mp_obj_type_t mp_type_list = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_list, - .print = list_print, - .make_new = list_make_new, - .locals_dict = (mp_obj_dict_t *)&list_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = list_unary_op, - .binary_op = list_binary_op, - .subscr = list_subscr, - .getiter = list_getiter, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_list, + MP_QSTR_list, + MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, mp_obj_list_make_new, + print, list_print, + unary_op, list_unary_op, + binary_op, list_binary_op, + subscr, list_subscr, + iter, list_getiter, + locals_dict, &list_locals_dict + ); + void mp_obj_list_init(mp_obj_list_t *o, size_t n) { o->base.type = &mp_type_list; diff --git a/py/objlist.h b/py/objlist.h index 79ed6c288c..b015261f61 100644 --- a/py/objlist.h +++ b/py/objlist.h @@ -36,6 +36,7 @@ typedef struct _mp_obj_list_t { } mp_obj_list_t; void mp_obj_list_init(mp_obj_list_t *o, size_t n); +mp_obj_t mp_obj_list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args); mp_obj_t mp_obj_list_pop(mp_obj_list_t *self, size_t index); void mp_obj_list_insert(mp_obj_list_t *self, size_t index, mp_obj_t obj); diff --git a/py/objmap.c b/py/objmap.c index d87105c089..e7e594cd2c 100644 --- a/py/objmap.c +++ b/py/objmap.c @@ -63,13 +63,10 @@ STATIC mp_obj_t map_iternext(mp_obj_t self_in) { return mp_call_function_n_kw(self->fun, self->n_iters, 0, nextses); } -const mp_obj_type_t mp_type_map = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_map, - .make_new = map_make_new, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = map_iternext, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_map, + MP_QSTR_map, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + make_new, map_make_new, + iter, map_iternext + ); diff --git a/py/objmodule.c b/py/objmodule.c index 1c281793d6..63e9fa4757 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -89,6 +89,10 @@ STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); if (elem != NULL) { dest[0] = elem->value; + #if MICROPY_CPYTHON_COMPAT + } else if (attr == MP_QSTR___dict__) { + dest[0] = MP_OBJ_FROM_PTR(self->globals); + #endif #if MICROPY_MODULE_GETATTR } else if (attr != MP_QSTR___getattr__) { elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___getattr__), MP_MAP_LOOKUP); @@ -130,12 +134,13 @@ STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_module = { - { &mp_type_type }, - .name = MP_QSTR_module, - .print = module_print, - .attr = module_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_module, + MP_QSTR_module, + MP_TYPE_FLAG_NONE, + print, module_print, + attr, module_attr + ); mp_obj_t mp_obj_new_module(qstr module_name) { mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map; @@ -161,18 +166,6 @@ mp_obj_t mp_obj_new_module(qstr module_name) { return MP_OBJ_FROM_PTR(o); } -mp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t self_in) { - assert(mp_obj_is_type(self_in, &mp_type_module)); - mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in); - return self->globals; -} - -void mp_obj_module_set_globals(mp_obj_t self_in, mp_obj_dict_t *globals) { - assert(mp_obj_is_type(self_in, &mp_type_module)); - mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in); - self->globals = globals; -} - /******************************************************************************/ // Global module table and related functions diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 1139ab2b54..ed2b1de42e 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -33,8 +33,6 @@ #include "py/objnamedtuple.h" #include "py/objtype.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_COLLECTIONS size_t mp_obj_namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name) { @@ -117,9 +115,10 @@ mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t #endif } - // Create a tuple and set the type to this namedtuple - mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_fields, NULL)); - tuple->base.type = type_in; + // Create a namedtuple with explicit malloc. Calling mp_obj_new_tuple + // with num_fields=0 returns a read-only object. + mp_obj_tuple_t *tuple = mp_obj_malloc_var(mp_obj_tuple_t, mp_obj_t, num_fields, type_in); + tuple->len = num_fields; // Copy the positional args into the first slots of the namedtuple memcpy(&tuple->items[0], args, sizeof(mp_obj_t) * n_args); @@ -151,8 +150,7 @@ mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t } mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t *fields) { - mp_obj_namedtuple_type_t *o = m_new_obj_var(mp_obj_namedtuple_type_t, qstr, n_fields); - memset(&o->base, 0, sizeof(o->base)); + mp_obj_namedtuple_type_t *o = m_new_obj_var0(mp_obj_namedtuple_type_t, qstr, n_fields); o->n_fields = n_fields; for (size_t i = 0; i < n_fields; i++) { o->fields[i] = mp_obj_str_get_qstr(fields[i]); @@ -162,17 +160,18 @@ mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t * STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) { mp_obj_namedtuple_type_t *o = mp_obj_new_namedtuple_base(n_fields, fields); - o->base.base.type = &mp_type_type; - o->base.flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EXTENDED; // can match tuple - o->base.name = name; - o->base.print = namedtuple_print; - o->base.make_new = namedtuple_make_new; - o->base.MP_TYPE_UNARY_OP = mp_obj_tuple_unary_op; - o->base.MP_TYPE_BINARY_OP = mp_obj_tuple_binary_op; - o->base.attr = namedtuple_attr; - o->base.MP_TYPE_SUBSCR = mp_obj_tuple_subscr; - o->base.MP_TYPE_GETITER = mp_obj_tuple_getiter; - o->base.parent = &mp_type_tuple; + mp_obj_type_t *type = (mp_obj_type_t *)&o->base; + type->base.type = &mp_type_type; + type->flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE; // can match tuple + type->name = name; + MP_OBJ_TYPE_SET_SLOT(type, make_new, namedtuple_make_new, 0); + MP_OBJ_TYPE_SET_SLOT(type, print, namedtuple_print, 1); + MP_OBJ_TYPE_SET_SLOT(type, unary_op, mp_obj_tuple_unary_op, 2); + MP_OBJ_TYPE_SET_SLOT(type, binary_op, mp_obj_tuple_binary_op, 3); + MP_OBJ_TYPE_SET_SLOT(type, attr, namedtuple_attr, 4); + MP_OBJ_TYPE_SET_SLOT(type, subscr, mp_obj_tuple_subscr, 5); + MP_OBJ_TYPE_SET_SLOT(type, iter, mp_obj_tuple_getiter, 6); + MP_OBJ_TYPE_SET_SLOT(type, parent, &mp_type_tuple, 7); return MP_OBJ_FROM_PTR(o); } diff --git a/py/objnamedtuple.h b/py/objnamedtuple.h index b6c37f3909..d2f304bbfc 100644 --- a/py/objnamedtuple.h +++ b/py/objnamedtuple.h @@ -28,7 +28,6 @@ #include -#include "py/nlr.h" #include "py/objtuple.h" #include "py/runtime.h" #include "py/objstr.h" @@ -36,7 +35,9 @@ #if MICROPY_PY_COLLECTIONS typedef struct _mp_obj_namedtuple_type_t { - mp_obj_full_type_t base; + // This is a mp_obj_type_t with eight slots. + mp_obj_empty_type_t base; + void *slots[8]; size_t n_fields; qstr fields[]; } mp_obj_namedtuple_type_t; @@ -51,6 +52,35 @@ void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest); mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t *fields); 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); +// CIRCUITPY yikes +#define NAMEDTUPLE_TYPE_BASE_AND_SLOTS_MAKE_NEW(type_name, make_new_fun) \ + .base = { \ + .base = { .type = &mp_type_type }, \ + .flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, \ + .name = type_name, \ + .slot_index_make_new = 1, \ + .slot_index_print = 2, \ + .slot_index_unary_op = 3, \ + .slot_index_binary_op = 4, \ + .slot_index_attr = 5, \ + .slot_index_subscr = 6, \ + .slot_index_iter = 7, \ + .slot_index_parent = 8, \ + }, \ + .slots = { \ + make_new_fun, \ + namedtuple_print, \ + mp_obj_tuple_unary_op, \ + mp_obj_tuple_binary_op, \ + namedtuple_attr, \ + mp_obj_tuple_subscr, \ + mp_obj_tuple_getiter, \ + (void *)&mp_type_tuple, \ + } + +#define NAMEDTUPLE_TYPE_BASE_AND_SLOTS(type_name) \ + NAMEDTUPLE_TYPE_BASE_AND_SLOTS_MAKE_NEW(type_name, namedtuple_make_new) + #endif // MICROPY_PY_COLLECTIONS #endif // MICROPY_INCLUDED_PY_OBJNAMEDTUPLE_H diff --git a/py/objnone.c b/py/objnone.c index 9f6960669a..4f8996e897 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -43,15 +43,13 @@ STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ } } -const mp_obj_type_t mp_type_NoneType = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_NoneType, - .print = none_print, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_NoneType, + MP_QSTR_NoneType, + MP_TYPE_FLAG_NONE, + print, none_print, + unary_op, mp_generic_unary_op + ); #if !MICROPY_OBJ_IMMEDIATE_OBJS const mp_obj_none_t mp_const_none_obj = {{&mp_type_NoneType}}; diff --git a/py/objobject.c b/py/objobject.c index 32552775aa..4f296106ce 100644 --- a/py/objobject.c +++ b/py/objobject.c @@ -29,8 +29,6 @@ #include "py/objtype.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - typedef struct _mp_obj_object_t { mp_obj_base_t base; } mp_obj_object_t; @@ -113,11 +111,16 @@ STATIC const mp_rom_map_elem_t object_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(object_locals_dict, object_locals_dict_table); #endif -const mp_obj_type_t mp_type_object = { - { &mp_type_type }, - .name = MP_QSTR_object, - .make_new = object_make_new, - #if MICROPY_CPYTHON_COMPAT - .locals_dict = (mp_obj_dict_t *)&object_locals_dict, - #endif -}; +#if MICROPY_CPYTHON_COMPAT +#define OBJECT_TYPE_LOCALS_DICT , locals_dict, &object_locals_dict +#else +#define OBJECT_TYPE_LOCALS_DICT +#endif + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_object, + MP_QSTR_object, + MP_TYPE_FLAG_NONE, + make_new, object_make_new + OBJECT_TYPE_LOCALS_DICT + ); diff --git a/py/objpolyiter.c b/py/objpolyiter.c index 20f12381d6..78b600abac 100644 --- a/py/objpolyiter.c +++ b/py/objpolyiter.c @@ -45,12 +45,42 @@ STATIC mp_obj_t polymorph_it_iternext(mp_obj_t self_in) { return self->iternext(self_in); } -const mp_obj_type_t mp_type_polymorph_iter = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_iterator, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = polymorph_it_iternext, - ), +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_polymorph_iter, + MP_QSTR_iterator, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + iter, polymorph_it_iternext + ); + +#if MICROPY_ENABLE_FINALISER +// mp_type_polymorph_iter_with_finaliser is a variant of the universal iterator +// above which has a finaliser function attached. This function will be run when +// the GC collects the iter object and can be used to close file handles etc. + +// Any instance should have these 3 fields at the beginning +typedef struct _mp_obj_polymorph_iter_with_finaliser_t { + mp_obj_base_t base; + mp_fun_1_t iternext; + mp_fun_1_t finaliser; +} mp_obj_polymorph_with_finaliser_iter_t; + +STATIC mp_obj_t mp_obj_polymorph_iter_del(mp_obj_t self_in) { + mp_obj_polymorph_with_finaliser_iter_t *self = MP_OBJ_TO_PTR(self_in); + // Redirect call to object instance's finaliser method + return self->finaliser(self_in); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_obj_polymorph_iter_del_obj, mp_obj_polymorph_iter_del); + +STATIC const mp_rom_map_elem_t mp_obj_polymorph_iter_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_obj_polymorph_iter_del_obj) }, }; +STATIC MP_DEFINE_CONST_DICT(mp_obj_polymorph_iter_locals_dict, mp_obj_polymorph_iter_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_polymorph_iter_with_finaliser, + MP_QSTR_iterator, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + iter, polymorph_it_iternext, + locals_dict, &mp_obj_polymorph_iter_locals_dict + ); +#endif diff --git a/py/objproperty.c b/py/objproperty.c index b0436e5c1f..98011f2782 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -87,12 +87,13 @@ STATIC const mp_rom_map_elem_t property_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(property_locals_dict, property_locals_dict_table); -const mp_obj_type_t mp_type_property = { - { &mp_type_type }, - .name = MP_QSTR_property, - .make_new = property_make_new, - .locals_dict = (mp_obj_dict_t *)&property_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_property, + MP_QSTR_property, + MP_TYPE_FLAG_NONE, + make_new, property_make_new, + locals_dict, &property_locals_dict + ); #if MICROPY_PY_OPTIMIZE_PROPERTY_FLASH_SIZE extern const mp_obj_property_t __property_getter_start, __property_getter_end, __property_getset_start, __property_getset_end; diff --git a/py/objrange.c b/py/objrange.c index d83b55d826..bfe95b1f72 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -28,8 +28,6 @@ #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - /******************************************************************************/ /* range iterator */ @@ -52,15 +50,12 @@ STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) { } } -STATIC const mp_obj_type_t mp_type_range_it = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_iterator, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = range_it_iternext, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_range_it, + MP_QSTR_iterator, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + iter, range_it_iternext + ); STATIC 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) { assert(sizeof(mp_obj_range_it_t) <= sizeof(mp_obj_iter_buf_t)); @@ -213,21 +208,27 @@ STATIC void range_attr(mp_obj_t o_in, qstr attr, mp_obj_t *dest) { } #endif -const mp_obj_type_t mp_type_range = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_range, - .print = range_print, - .make_new = range_make_new, - #if MICROPY_PY_BUILTINS_RANGE_ATTRS - .attr = range_attr, - #endif - MP_TYPE_EXTENDED_FIELDS( - .unary_op = range_unary_op, - #if MICROPY_PY_BUILTINS_RANGE_BINOP - .binary_op = range_binary_op, - #endif - .subscr = range_subscr, - .getiter = range_getiter, - ), -}; +#if MICROPY_PY_BUILTINS_RANGE_BINOP +#define RANGE_TYPE_BINOP binary_op, range_binary_op, +#else +#define RANGE_TYPE_BINOP +#endif + +#if MICROPY_PY_BUILTINS_RANGE_ATTRS +#define RANGE_TYPE_ATTR attr, range_attr, +#else +#define RANGE_TYPE_ATTR +#endif + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_range, + MP_QSTR_range, + MP_TYPE_FLAG_NONE, + make_new, range_make_new, + RANGE_TYPE_BINOP + RANGE_TYPE_ATTR + print, range_print, + unary_op, range_unary_op, + subscr, range_subscr, + iter, range_getiter + ); diff --git a/py/objreversed.c b/py/objreversed.c index c9b36bf2a4..c66698f028 100644 --- a/py/objreversed.c +++ b/py/objreversed.c @@ -68,15 +68,12 @@ STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) { return mp_obj_subscr(self->seq, MP_OBJ_NEW_SMALL_INT(self->cur_index), MP_OBJ_SENTINEL); } -const mp_obj_type_t mp_type_reversed = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_reversed, - .make_new = reversed_make_new, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = reversed_iternext, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_reversed, + MP_QSTR_reversed, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + make_new, reversed_make_new, + iter, reversed_iternext + ); #endif // MICROPY_PY_BUILTINS_REVERSED diff --git a/py/objset.c b/py/objset.c index 9557ec76ab..4965eca3b0 100644 --- a/py/objset.c +++ b/py/objset.c @@ -31,8 +31,6 @@ #include "py/runtime.h" #include "py/builtin.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_SET typedef struct _mp_obj_set_t { @@ -542,19 +540,17 @@ STATIC const mp_rom_map_elem_t set_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table); -const mp_obj_type_t mp_type_set = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_set, - .print = set_print, - .make_new = set_make_new, - .locals_dict = (mp_obj_dict_t *)&set_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = set_unary_op, - .binary_op = set_binary_op, - .getiter = set_getiter, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_set, + MP_QSTR_set, + MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, set_make_new, + print, set_print, + unary_op, set_unary_op, + binary_op, set_binary_op, + iter, set_getiter, + locals_dict, &set_locals_dict + ); #if MICROPY_PY_BUILTINS_FROZENSET STATIC const mp_rom_map_elem_t frozenset_locals_dict_table[] = { @@ -570,19 +566,17 @@ STATIC const mp_rom_map_elem_t frozenset_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(frozenset_locals_dict, frozenset_locals_dict_table); -const mp_obj_type_t mp_type_frozenset = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_frozenset, - .print = set_print, - .make_new = set_make_new, - .locals_dict = (mp_obj_dict_t *)&frozenset_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = set_unary_op, - .binary_op = set_binary_op, - .getiter = set_getiter, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_frozenset, + MP_QSTR_frozenset, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, set_make_new, + print, set_print, + unary_op, set_unary_op, + binary_op, set_binary_op, + iter, set_getiter, + locals_dict, &frozenset_locals_dict + ); #endif mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items) { diff --git a/py/objsingleton.c b/py/objsingleton.c index 34a6ebd028..dc73d28c27 100644 --- a/py/objsingleton.c +++ b/py/objsingleton.c @@ -43,15 +43,11 @@ STATIC void singleton_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ mp_printf(print, "%q", self->name); } -const mp_obj_type_t mp_type_singleton = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_, - .print = singleton_print, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_singleton, MP_QSTR_, MP_TYPE_FLAG_NONE, + print, singleton_print, + unary_op, mp_generic_unary_op + ); const mp_obj_singleton_t mp_const_ellipsis_obj = {{&mp_type_singleton}, MP_QSTR_Ellipsis}; #if MICROPY_PY_BUILTINS_NOTIMPLEMENTED diff --git a/py/objslice.c b/py/objslice.c index fe272cfa9b..d165699ecf 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -30,8 +30,6 @@ #include "py/obj.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - /******************************************************************************/ /* slice object */ @@ -122,19 +120,28 @@ STATIC const mp_rom_map_elem_t slice_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(slice_locals_dict, slice_locals_dict_table); #endif -const mp_obj_type_t mp_type_slice = { - { &mp_type_type }, - .name = MP_QSTR_slice, - .print = slice_print, - #if MICROPY_PY_BUILTINS_SLICE_INDICES || MICROPY_PY_BUILTINS_SLICE_ATTRS - .make_new = slice_make_new, - #endif - #if MICROPY_PY_BUILTINS_SLICE_ATTRS - .attr = slice_attr, - #elif MICROPY_PY_BUILTINS_SLICE_INDICES - .locals_dict = (mp_obj_dict_t *)&slice_locals_dict, - #endif -}; +#if MICROPY_PY_BUILTINS_SLICE_ATTRS +#define SLICE_TYPE_ATTR_OR_LOCALS_DICT attr, slice_attr, +#elif MICROPY_PY_BUILTINS_SLICE_INDICES +#define SLICE_TYPE_ATTR_OR_LOCALS_DICT locals_dict, &slice_locals_dict, +#else +#define SLICE_TYPE_ATTR_OR_LOCALS_DICT +#endif + +#if MICROPY_PY_BUILTINS_SLICE_INDICES || MICROPY_PY_BUILTINS_SLICE_ATTRS +#define SLICE_MAKE_NEW make_new, slice_make_new, +#else +#define SLICE_MAKE_NEW +#endif + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_slice, + MP_QSTR_slice, + MP_TYPE_FLAG_NONE, + SLICE_TYPE_ATTR_OR_LOCALS_DICT + SLICE_MAKE_NEW + print, slice_print + ); mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) { mp_obj_slice_t *o = mp_obj_malloc(mp_obj_slice_t, &mp_type_slice); diff --git a/py/objstr.c b/py/objstr.c index 72d44d537c..994194540f 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -31,11 +31,15 @@ #include "py/unicode.h" #include "py/objstr.h" #include "py/objlist.h" -#include "py/objtype.h" #include "py/runtime.h" #include "py/stackctrl.h" -#include "supervisor/shared/translate/translate.h" +// CIRCUITPY +const char nibble_to_hex_upper[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F'}; + +const char nibble_to_hex_lower[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'}; #if MICROPY_PY_BUILTINS_STR_OP_MODULO STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict); @@ -44,11 +48,31 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in); -const char nibble_to_hex_upper[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F'}; +STATIC mp_obj_t mp_obj_new_str_type_from_vstr(const mp_obj_type_t *type, vstr_t *vstr); -const char nibble_to_hex_lower[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f'}; +STATIC void str_check_arg_type(const mp_obj_type_t *self_type, const mp_obj_t arg) { + // String operations generally need the args type to match the object they're called on, + // e.g. str.find(str), byte.startswith(byte) + // with the exception that bytes may be used for bytearray and vice versa. + const mp_obj_type_t *arg_type = mp_obj_get_type(arg); + + #if MICROPY_PY_BUILTINS_BYTEARRAY + if (arg_type == &mp_type_bytearray) { + arg_type = &mp_type_bytes; + } + if (self_type == &mp_type_bytearray) { + self_type = &mp_type_bytes; + } + #endif + + if (arg_type != self_type) { + bad_implicit_conversion(arg); + } +} + +STATIC void check_is_str_or_bytes(mp_obj_t self_in) { + mp_check_self(mp_obj_is_str_or_bytes(self_in)); +} /******************************************************************************/ /* str */ @@ -142,6 +166,12 @@ STATIC void str_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t } mp_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) { + #if MICROPY_CPYTHON_COMPAT + if (n_kw != 0) { + mp_arg_error_unimpl_kw(); + } + #endif + mp_arg_check_num(n_args, n_kw, 0, 3, false); switch (n_args) { @@ -153,7 +183,7 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ mp_print_t print; vstr_init_print(&vstr, 16, &print); mp_obj_print_helper(&print, args[0], PRINT_STR); - return mp_obj_new_str_from_vstr(type, &vstr); + return mp_obj_new_str_type_from_vstr(type, &vstr); } default: // 2 or 3 args @@ -183,11 +213,7 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ } else { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); - #if MICROPY_PY_BUILTINS_STR_UNICODE_CHECK - if (!utf8_check(bufinfo.buf, bufinfo.len)) { - mp_raise_msg(&mp_type_UnicodeError, NULL); - } - #endif + // This will utf-8 check the input. return mp_obj_new_str(bufinfo.buf, bufinfo.len); } } @@ -214,7 +240,11 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size if (mp_obj_is_str(args[0])) { if (n_args < 2 || n_args > 3) { + #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE goto wrong_args; + #else + mp_raise_TypeError(MP_ERROR_TEXT("string argument without an encoding")); + #endif } GET_STR_DATA_LEN(args[0], str_data, str_len); GET_STR_HASH(args[0], str_hash); @@ -239,9 +269,10 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size vstr_t vstr; vstr_init_len(&vstr, len); memset(vstr.buf, 0, len); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } + // CIRCUITPY // check if __bytes__ exists, and if so delegate to it mp_obj_t dest[2]; mp_load_method_maybe(args[0], MP_QSTR___bytes__, dest); @@ -278,7 +309,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size vstr_add_byte(&vstr, val); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); wrong_args: mp_raise_TypeError(MP_ERROR_TEXT("wrong number of arguments")); @@ -350,11 +381,12 @@ mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i return mp_const_empty_bytes; } } + // CIRCUITPY: more careful checking of length size_t new_len = mp_seq_multiply_len(lhs_len, n); vstr_t vstr; vstr_init_len(&vstr, new_len); mp_seq_multiply(lhs_data, sizeof(*lhs_data), lhs_len, n, vstr.buf); - return mp_obj_new_str_from_vstr(lhs_type, &vstr); + return mp_obj_new_str_of_type(lhs_type, (const byte *)vstr.buf, vstr.len); } // From now on all operations allow: @@ -405,7 +437,7 @@ mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i vstr_init_len(&vstr, lhs_len + rhs_len); memcpy(vstr.buf, lhs_data, lhs_len); memcpy(vstr.buf + lhs_len, rhs_data, rhs_len); - return mp_obj_new_str_from_vstr(lhs_type, &vstr); + return mp_obj_new_str_type_from_vstr(lhs_type, &vstr); } case MP_BINARY_OP_CONTAINS: @@ -426,15 +458,6 @@ mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i #if !MICROPY_PY_BUILTINS_STR_UNICODE // objstrunicode defines own version -size_t str_offset_to_index(const mp_obj_type_t *type, const byte *self_data, size_t self_len, - size_t offset) { - if (offset > self_len) { - mp_raise_ValueError(MP_ERROR_TEXT("offset out of bounds")); - } - - return offset; -} - const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len, mp_obj_t index, bool is_slice) { size_t index_val = mp_get_index(type, self_len, index, is_slice); @@ -470,8 +493,9 @@ STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { - mp_check_self(mp_obj_is_str_or_bytes(self_in)); + check_is_str_or_bytes(self_in); const mp_obj_type_t *self_type = mp_obj_get_type(self_in); + const mp_obj_type_t *ret_type = self_type; // get separation string GET_STR_DATA_LEN(self_in, sep_str, sep_len); @@ -483,14 +507,25 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { if (!mp_obj_is_type(arg, &mp_type_list) && !mp_obj_is_type(arg, &mp_type_tuple)) { // arg is not a list nor a tuple, try to convert it to a list // TODO: Try to optimize? - arg = mp_type_list.make_new(&mp_type_list, 1, 0, &arg); + arg = mp_obj_list_make_new(&mp_type_list, 1, 0, &arg); } mp_obj_get_array(arg, &seq_len, &seq_items); // count required length size_t required_len = 0; + #if MICROPY_PY_BUILTINS_BYTEARRAY + if (self_type == &mp_type_bytearray) { + self_type = &mp_type_bytes; + } + #endif for (size_t i = 0; i < seq_len; i++) { - if (mp_obj_get_type(seq_items[i]) != self_type) { + const mp_obj_type_t *seq_type = mp_obj_get_type(seq_items[i]); + #if MICROPY_PY_BUILTINS_BYTEARRAY + if (seq_type == &mp_type_bytearray) { + seq_type = &mp_type_bytes; + } + #endif + if (seq_type != self_type) { mp_raise_TypeError( MP_ERROR_TEXT("join expects a list of str/bytes objects consistent with self object")); } @@ -516,7 +551,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { } // return joined string - return mp_obj_new_str_from_vstr(self_type, &vstr); + return mp_obj_new_str_type_from_vstr(ret_type, &vstr); } MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join); @@ -565,9 +600,7 @@ mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) { } else { // sep given - if (mp_obj_get_type(sep) != self_type) { - bad_implicit_conversion(sep); - } + str_check_arg_type(self_type, sep); size_t sep_len; const char *sep_str = mp_obj_str_get_data(sep, &sep_len); @@ -716,12 +749,10 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit); STATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, bool is_index) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); - mp_check_self(mp_obj_is_str_or_bytes(args[0])); + check_is_str_or_bytes(args[0]); // check argument type - if (mp_obj_get_type(args[1]) != self_type) { - bad_implicit_conversion(args[1]); - } + str_check_arg_type(self_type, args[1]); GET_STR_DATA_LEN(args[0], haystack, haystack_len); GET_STR_DATA_LEN(args[1], needle, needle_len); @@ -814,7 +845,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith); enum { LSTRIP, RSTRIP, STRIP }; STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) { - mp_check_self(mp_obj_is_str_or_bytes(args[0])); + check_is_str_or_bytes(args[0]); const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); const byte *chars_to_del; @@ -825,9 +856,7 @@ STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) { chars_to_del = whitespace; chars_to_del_len = sizeof(whitespace) - 1; } else { - if (mp_obj_get_type(args[1]) != self_type) { - bad_implicit_conversion(args[1]); - } + str_check_arg_type(self_type, args[1]); GET_STR_DATA_LEN(args[1], s, l); chars_to_del = s; chars_to_del_len = l; @@ -912,7 +941,7 @@ STATIC mp_obj_t str_center(mp_obj_t str_in, mp_obj_t width_in) { memset(vstr.buf, ' ', width); int left = (width - str_len) / 2; memcpy(vstr.buf + left, str, str_len); - return mp_obj_new_str_from_vstr(mp_obj_get_type(str_in), &vstr); + return mp_obj_new_str_type_from_vstr(mp_obj_get_type(str_in), &vstr); } MP_DEFINE_CONST_FUN_OBJ_2(str_center_obj, str_center); #endif @@ -1106,7 +1135,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar arg = key_elem->value; } if (field_name < field_name_top) { - mp_raise_NotImplementedError(MP_ERROR_TEXT("attributes not supported yet")); + mp_raise_NotImplementedError(MP_ERROR_TEXT("attributes not supported")); } } else { if (*arg_i < 0) { @@ -1138,7 +1167,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar mp_print_t arg_print; vstr_init_print(&arg_vstr, 16, &arg_print); mp_obj_print_helper(&arg_print, arg, print_kind); - arg = mp_obj_new_str_from_vstr(&mp_type_str, &arg_vstr); + arg = mp_obj_new_str_type_from_vstr(&mp_type_str, &arg_vstr); } char fill = '\0'; @@ -1418,18 +1447,18 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar } mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { - mp_check_self(mp_obj_is_str_or_bytes(args[0])); + check_is_str_or_bytes(args[0]); GET_STR_DATA_LEN(args[0], str, len); int arg_i = 0; vstr_t vstr = mp_obj_str_format_helper((const char *)str, (const char *)str + len, &arg_i, n_args, args, kwargs); - return mp_obj_new_str_from_vstr(mp_obj_get_type(args[0]), &vstr); + return mp_obj_new_str_type_from_vstr(mp_obj_get_type(args[0]), &vstr); } MP_DEFINE_CONST_FUN_OBJ_KW(str_format_obj, 1, mp_obj_str_format); #if MICROPY_PY_BUILTINS_STR_OP_MODULO STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict) { - mp_check_self(mp_obj_is_str_or_bytes(pattern)); + check_is_str_or_bytes(pattern); GET_STR_DATA_LEN(pattern, str, len); #if MICROPY_ERROR_REPORTING > MICROPY_ERROR_REPORTING_TERSE @@ -1628,14 +1657,14 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ mp_raise_TypeError(MP_ERROR_TEXT("not all arguments converted during string formatting")); } - return mp_obj_new_str_from_vstr(is_bytes ? &mp_type_bytes : &mp_type_str, &vstr); + return mp_obj_new_str_type_from_vstr(is_bytes ? &mp_type_bytes : &mp_type_str, &vstr); } #endif // The implementation is optimized, returning the original string if there's // nothing to replace. STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { - mp_check_self(mp_obj_is_str_or_bytes(args[0])); + check_is_str_or_bytes(args[0]); mp_int_t max_rep = -1; if (n_args == 4) { @@ -1653,13 +1682,8 @@ STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); - if (mp_obj_get_type(args[1]) != self_type) { - bad_implicit_conversion(args[1]); - } - - if (mp_obj_get_type(args[2]) != self_type) { - bad_implicit_conversion(args[2]); - } + str_check_arg_type(self_type, args[1]); + str_check_arg_type(self_type, args[2]); // extract string data @@ -1736,19 +1760,17 @@ STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { } } - return mp_obj_new_str_from_vstr(self_type, &vstr); + return mp_obj_new_str_type_from_vstr(self_type, &vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace); #if MICROPY_PY_BUILTINS_STR_COUNT STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); - mp_check_self(mp_obj_is_str_or_bytes(args[0])); + check_is_str_or_bytes(args[0]); // check argument type - if (mp_obj_get_type(args[1]) != self_type) { - bad_implicit_conversion(args[1]); - } + str_check_arg_type(self_type, args[1]); GET_STR_DATA_LEN(args[0], haystack, haystack_len); GET_STR_DATA_LEN(args[1], needle, needle_len); @@ -1767,6 +1789,8 @@ STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { return MP_OBJ_NEW_SMALL_INT(utf8_charlen(start, end - start) + 1); } + bool is_str = self_type == &mp_type_str; + // count the occurrences mp_int_t num_occurrences = 0; for (const byte *haystack_ptr = start; haystack_ptr + needle_len <= end;) { @@ -1774,7 +1798,7 @@ STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { num_occurrences++; haystack_ptr += needle_len; } else { - haystack_ptr = utf8_next_char(haystack_ptr); + haystack_ptr = is_str ? utf8_next_char(haystack_ptr) : haystack_ptr + 1; } } @@ -1785,11 +1809,9 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count); #if MICROPY_PY_BUILTINS_STR_PARTITION STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) { - mp_check_self(mp_obj_is_str_or_bytes(self_in)); + check_is_str_or_bytes(self_in); const mp_obj_type_t *self_type = mp_obj_get_type(self_in); - if (self_type != mp_obj_get_type(arg)) { - bad_implicit_conversion(arg); - } + str_check_arg_type(self_type, arg); GET_STR_DATA_LEN(self_in, str, str_len); GET_STR_DATA_LEN(arg, sep, sep_len); @@ -1815,6 +1837,12 @@ STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) { result[2] = self_in; } + #if MICROPY_PY_BUILTINS_BYTEARRAY + if (mp_obj_get_type(arg) != self_type) { + arg = mp_obj_new_str_of_type(self_type, sep, sep_len); + } + #endif + const byte *position_ptr = find_subbytes(str, str_len, sep, sep_len, direction); if (position_ptr != NULL) { size_t position = position_ptr - str; @@ -1846,7 +1874,7 @@ STATIC mp_obj_t str_caseconv(unichar (*op)(unichar), mp_obj_t self_in) { for (size_t i = 0; i < self_len; i++) { *data++ = op(*self_data++); } - return mp_obj_new_str_from_vstr(mp_obj_get_type(self_in), &vstr); + return mp_obj_new_str_type_from_vstr(mp_obj_get_type(self_in), &vstr); } STATIC mp_obj_t str_lower(mp_obj_t self_in) { @@ -1947,6 +1975,84 @@ STATIC mp_obj_t str_encode(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode); #endif +#if MICROPY_PY_BUILTINS_BYTES_HEX +mp_obj_t mp_obj_bytes_hex(size_t n_args, const mp_obj_t *args, const mp_obj_type_t *type) { + // First argument is the data to convert. + // Second argument is an optional separator to be used between values. + const char *sep = NULL; + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + + // Code below assumes non-zero buffer length when computing size with + // separator, so handle the zero-length case here. + if (bufinfo.len == 0) { + return mp_const_empty_bytes; + } + + vstr_t vstr; + size_t out_len = bufinfo.len * 2; + if (n_args > 1) { + // 1-char separator between hex numbers + out_len += bufinfo.len - 1; + sep = mp_obj_str_get_str(args[1]); + } + vstr_init_len(&vstr, out_len); + byte *in = bufinfo.buf, *out = (byte *)vstr.buf; + for (mp_uint_t i = bufinfo.len; i--;) { + byte d = (*in >> 4); + if (d > 9) { + d += 'a' - '9' - 1; + } + *out++ = d + '0'; + d = (*in++ & 0xf); + if (d > 9) { + d += 'a' - '9' - 1; + } + *out++ = d + '0'; + if (sep != NULL && i != 0) { + *out++ = *sep; + } + } + return mp_obj_new_str_type_from_vstr(type, &vstr); +} + +mp_obj_t mp_obj_bytes_fromhex(mp_obj_t type_in, mp_obj_t data) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); + + if ((bufinfo.len & 1) != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("odd-length string")); + } + vstr_t vstr; + vstr_init_len(&vstr, bufinfo.len / 2); + byte *in = bufinfo.buf, *out = (byte *)vstr.buf; + byte hex_byte = 0; + for (mp_uint_t i = bufinfo.len; i--;) { + byte hex_ch = *in++; + if (unichar_isxdigit(hex_ch)) { + hex_byte += unichar_xdigit_value(hex_ch); + } else { + mp_raise_ValueError(MP_ERROR_TEXT("non-hex digit found")); + } + if (i & 1) { + hex_byte <<= 4; + } else { + *out++ = hex_byte; + hex_byte = 0; + } + } + return mp_obj_new_str_type_from_vstr(MP_OBJ_TO_PTR(type_in), &vstr); +} + +STATIC mp_obj_t bytes_hex_as_str(size_t n_args, const mp_obj_t *args) { + return mp_obj_bytes_hex(n_args, args, &mp_type_str); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_obj_bytes_hex_as_str_obj, 1, 2, bytes_hex_as_str); + +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bytes_fromhex_obj, mp_obj_bytes_fromhex); +STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bytes_fromhex_classmethod_obj, MP_ROM_PTR(&bytes_fromhex_obj)); +#endif // MICROPY_PY_BUILTINS_BYTES_HEX + mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { if (flags == MP_BUFFER_READ) { GET_STR_DATA_LEN(self_in, str_data, str_len); @@ -1960,17 +2066,25 @@ mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_u } } -STATIC const mp_rom_map_elem_t str8_locals_dict_table[] = { +void mp_obj_str_set_data(mp_obj_str_t *str, const byte *data, size_t len) { + str->data = data; + str->len = len; + str->hash = qstr_compute_hash(data, len); +} + +// This locals table is used for the following types: str, bytes, bytearray, array.array. +// Each type takes a different section (start to end offset) of this table. +STATIC const mp_rom_map_elem_t array_bytearray_str_bytes_locals_table[] = { + #if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY + { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&mp_obj_array_append_obj) }, + { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&mp_obj_array_extend_obj) }, + #endif + #if MICROPY_PY_BUILTINS_BYTES_HEX + { MP_ROM_QSTR(MP_QSTR_hex), MP_ROM_PTR(&mp_obj_bytes_hex_as_str_obj) }, + { MP_ROM_QSTR(MP_QSTR_fromhex), MP_ROM_PTR(&bytes_fromhex_classmethod_obj) }, + #endif #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&bytes_decode_obj) }, - #if !MICROPY_PY_BUILTINS_STR_UNICODE - // If we have separate unicode type, then here we have methods only - // for bytes type, and it should not have encode() methods. Otherwise, - // we have non-compliant-but-practical bytestring type, which shares - // method table with bytes, so they both have encode() and decode() - // methods (which should do type checking at runtime). - { MP_ROM_QSTR(MP_QSTR_encode), MP_ROM_PTR(&str_encode_obj) }, - #endif #endif { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&str_find_obj) }, { MP_ROM_QSTR(MP_QSTR_rfind), MP_ROM_PTR(&str_rfind_obj) }, @@ -2006,41 +2120,90 @@ STATIC const mp_rom_map_elem_t str8_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_isdigit), MP_ROM_PTR(&str_isdigit_obj) }, { MP_ROM_QSTR(MP_QSTR_isupper), MP_ROM_PTR(&str_isupper_obj) }, { MP_ROM_QSTR(MP_QSTR_islower), MP_ROM_PTR(&str_islower_obj) }, + #if MICROPY_CPYTHON_COMPAT + { MP_ROM_QSTR(MP_QSTR_encode), MP_ROM_PTR(&str_encode_obj) }, + #endif }; -STATIC MP_DEFINE_CONST_DICT(str8_locals_dict, str8_locals_dict_table); +#if MICROPY_CPYTHON_COMPAT +#define TABLE_ENTRIES_COMPAT 1 +#else +#define TABLE_ENTRIES_COMPAT 0 +#endif + +#if MICROPY_PY_BUILTINS_BYTES_HEX +#define TABLE_ENTRIES_HEX 2 +#else +#define TABLE_ENTRIES_HEX 0 +#endif + +#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY +#define TABLE_ENTRIES_ARRAY 2 +#else +#define TABLE_ENTRIES_ARRAY 0 +#endif + +MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_str_locals_dict, + array_bytearray_str_bytes_locals_table + TABLE_ENTRIES_ARRAY + TABLE_ENTRIES_HEX + TABLE_ENTRIES_COMPAT, + MP_ARRAY_SIZE(array_bytearray_str_bytes_locals_table) - (TABLE_ENTRIES_ARRAY + TABLE_ENTRIES_HEX + TABLE_ENTRIES_COMPAT)); + +#if TABLE_ENTRIES_COMPAT == 0 +#define mp_obj_bytes_locals_dict mp_obj_str_locals_dict +#else +MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_bytes_locals_dict, + array_bytearray_str_bytes_locals_table + TABLE_ENTRIES_ARRAY, + MP_ARRAY_SIZE(array_bytearray_str_bytes_locals_table) - (TABLE_ENTRIES_ARRAY + TABLE_ENTRIES_COMPAT)); +#endif + +#if MICROPY_PY_BUILTINS_BYTEARRAY +MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_bytearray_locals_dict, + array_bytearray_str_bytes_locals_table, + MP_ARRAY_SIZE(array_bytearray_str_bytes_locals_table) - TABLE_ENTRIES_COMPAT); +#endif + +#if MICROPY_PY_ARRAY +MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_array_locals_dict, + array_bytearray_str_bytes_locals_table, + TABLE_ENTRIES_ARRAY); +#endif + +// CIRCUITPY: hex() but no cast() +#if MICROPY_PY_BUILTINS_MEMORYVIEW && MICROPY_PY_BUILTINS_BYTES_HEX && !MICROPY_CPYTHON_COMPAT +MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_memoryview_locals_dict, + array_bytearray_str_bytes_locals_table + TABLE_ENTRIES_ARRAY, + 1); // Just the "hex" entry. +#endif #if !MICROPY_PY_BUILTINS_STR_UNICODE STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); -const mp_obj_type_t mp_type_str = { - { &mp_type_type }, - .name = MP_QSTR_str, - .print = str_print, - .make_new = mp_obj_str_make_new, - .binary_op = mp_obj_str_binary_op, - .subscr = bytes_subscr, - .getiter = mp_obj_new_str_iterator, - .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, - .locals_dict = (mp_obj_dict_t *)&str8_locals_dict, -}; -#endif +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_str, + MP_QSTR_str, + MP_TYPE_FLAG_NONE, + make_new, mp_obj_str_make_new, + print, str_print, + binary_op, mp_obj_str_binary_op, + subscr, bytes_subscr, + iter, mp_obj_new_str_iterator, + buffer, mp_obj_str_get_buffer, + locals_dict, &mp_obj_str_locals_dict + ); +#endif // !MICROPY_PY_BUILTINS_STR_UNICODE -// Reuses most of methods from str -const mp_obj_type_t mp_type_bytes = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_bytes, - .print = str_print, - .make_new = bytes_make_new, - .locals_dict = (mp_obj_dict_t *)&str8_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .binary_op = mp_obj_str_binary_op, - .subscr = bytes_subscr, - .getiter = mp_obj_new_bytes_iterator, - .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, - ), -}; +// Reuses most methods from str +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bytes, + MP_QSTR_bytes, + MP_TYPE_FLAG_NONE, + make_new, bytes_make_new, + print, str_print, + binary_op, mp_obj_str_binary_op, + subscr, bytes_subscr, + iter, mp_obj_new_bytes_iterator, + buffer, mp_obj_str_get_buffer, + locals_dict, &mp_obj_bytes_locals_dict + ); // The zero-length bytes object, with data that includes a null-terminating byte const mp_obj_str_t mp_const_empty_bytes_obj = {{&mp_type_bytes}, 0, 0, (const byte *)""}; @@ -2067,6 +2230,10 @@ mp_obj_t mp_obj_new_str_copy(const mp_obj_type_t *type, const byte *data, size_t mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte *data, size_t len) { if (type == &mp_type_str) { return mp_obj_new_str((const char *)data, len); + #if MICROPY_PY_BUILTINS_BYTEARRAY + } else if (type == &mp_type_bytearray) { + return mp_obj_new_bytearray(len, data); + #endif } else { return mp_obj_new_bytes(data, len); } @@ -2080,7 +2247,7 @@ mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len) { // Create a str/bytes object from the given vstr. The vstr buffer is resized to // the exact length required and then reused for the str/bytes object. The vstr // is cleared and can safely be passed to vstr_free if it was heap allocated. -mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { +STATIC mp_obj_t mp_obj_new_str_type_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { // if not a bytes object, look if a qstr with this data already exists if (type == &mp_type_str) { qstr q = qstr_find_strn(vstr->buf, vstr->len); @@ -2091,22 +2258,53 @@ mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { } } - // make a new str/bytes object - mp_obj_str_t *o = mp_obj_malloc(mp_obj_str_t, type); - o->len = vstr->len; - o->hash = qstr_compute_hash((byte *)vstr->buf, vstr->len); + byte *data; if (vstr->len + 1 == vstr->alloc) { - o->data = (byte *)vstr->buf; + data = (byte *)vstr->buf; } else { - o->data = (byte *)m_renew(char, vstr->buf, vstr->alloc, vstr->len + 1); + data = (byte *)m_renew(char, vstr->buf, vstr->alloc, vstr->len + 1); } - ((byte *)o->data)[o->len] = '\0'; // add null byte + data[vstr->len] = '\0'; // add null byte vstr->buf = NULL; vstr->alloc = 0; + #if MICROPY_PY_BUILTINS_BYTEARRAY + if (type == &mp_type_bytearray) { + return mp_obj_new_bytearray_by_ref(vstr->len, data); + } + #endif + mp_obj_str_t *o = mp_obj_malloc(mp_obj_str_t, type); + o->len = vstr->len; + o->hash = qstr_compute_hash(data, vstr->len); + o->data = data; return MP_OBJ_FROM_PTR(o); } +mp_obj_t mp_obj_new_str_from_vstr(vstr_t *vstr) { + #if MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK + if (!utf8_check((byte *)vstr->buf, vstr->len)) { + mp_raise_msg(&mp_type_UnicodeError, NULL); + } + #endif // MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK + return mp_obj_new_str_type_from_vstr(&mp_type_str, vstr); +} + +#if MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK +mp_obj_t mp_obj_new_str_from_utf8_vstr(vstr_t *vstr) { + // bypasses utf8_check. + return mp_obj_new_str_type_from_vstr(&mp_type_str, vstr); +} +#endif // MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK + +mp_obj_t mp_obj_new_bytes_from_vstr(vstr_t *vstr) { + return mp_obj_new_str_type_from_vstr(&mp_type_bytes, vstr); +} + mp_obj_t mp_obj_new_str(const char *data, size_t len) { + #if MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK + if (!utf8_check((byte *)data, len)) { + mp_raise_msg(&mp_type_UnicodeError, NULL); + } + #endif qstr q = qstr_find_strn(data, len); if (q != MP_QSTRnull) { // qstr with this data already exists @@ -2132,11 +2330,12 @@ mp_obj_t mp_obj_new_bytes(const byte *data, size_t len) { return mp_obj_new_str_copy(&mp_type_bytes, data, len); } +// CIRCUITPY mp_obj_t mp_obj_new_bytes_of_zeros(size_t len) { vstr_t vstr; vstr_init_len(&vstr, len); memset(vstr.buf, 0, len); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } @@ -2174,7 +2373,7 @@ STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in) { qstr mp_obj_str_get_qstr(mp_obj_t self_in) { if (mp_obj_is_qstr(self_in)) { return MP_OBJ_QSTR_VALUE(self_in); - } else if (mp_obj_is_type(self_in, &mp_type_str)) { + } else if (mp_obj_is_exact_type(self_in, &mp_type_str)) { mp_obj_str_t *self = MP_OBJ_TO_PTR(self_in); return qstr_from_strn((char *)self->data, self->len); } else { @@ -2209,6 +2408,7 @@ const byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len) { if (mp_obj_is_qstr(self_in)) { return qstr_data(MP_OBJ_QSTR_VALUE(self_in), len); } else { + MP_STATIC_ASSERT_STR_ARRAY_COMPATIBLE; *len = ((mp_obj_str_t *)MP_OBJ_TO_PTR(self_in))->len; return ((mp_obj_str_t *)MP_OBJ_TO_PTR(self_in))->data; } diff --git a/py/objstr.h b/py/objstr.h index bae32cbffe..810742a97f 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -27,86 +27,102 @@ #define MICROPY_INCLUDED_PY_OBJSTR_H #include "py/obj.h" +#include "py/objarray.h" + +// CIRCUITPY +extern const char nibble_to_hex_upper[16]; +extern const char nibble_to_hex_lower[16]; typedef struct _mp_obj_str_t { mp_obj_base_t base; - mp_uint_t hash; + size_t hash; // len == number of bytes used in data, alloc = len + 1 because (at the moment) we also append a null byte size_t len; const byte *data; } mp_obj_str_t; +// This static assert is used to ensure that mp_obj_str_t and mp_obj_array_t are compatible, +// meaning that their len and data/items entries are at the same offsets in the struct. +// This allows the same code to be used for str/bytes and bytearray. +#define MP_STATIC_ASSERT_STR_ARRAY_COMPATIBLE \ + MP_STATIC_ASSERT(offsetof(mp_obj_str_t, len) == offsetof(mp_obj_array_t, len) \ + && offsetof(mp_obj_str_t, data) == offsetof(mp_obj_array_t, items)) + #define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte *)str} // use this macro to extract the string hash // warning: the hash can be 0, meaning invalid, and must then be explicitly computed from the data #define GET_STR_HASH(str_obj_in, str_hash) \ - mp_uint_t str_hash; if (mp_obj_is_qstr(str_obj_in)) \ - { 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; } + size_t str_hash; \ + if (mp_obj_is_qstr(str_obj_in)) { \ + 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; \ + } // use this macro to extract the string length #define GET_STR_LEN(str_obj_in, str_len) \ - size_t str_len; if (mp_obj_is_qstr(str_obj_in)) \ - { 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; } + size_t str_len; \ + if (mp_obj_is_qstr(str_obj_in)) { \ + 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; \ + } // use this macro to extract the string data and length #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D const byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len); #define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \ - size_t str_len; const byte *str_data = mp_obj_str_get_data_no_check(str_obj_in, &str_len); + size_t str_len; \ + const byte *str_data = mp_obj_str_get_data_no_check(str_obj_in, &str_len); #else #define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \ - const byte *str_data; size_t str_len; if (mp_obj_is_qstr(str_obj_in)) \ - { str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } \ - 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; } + const byte *str_data; \ + size_t str_len; \ + if (mp_obj_is_qstr(str_obj_in)) { \ + str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); \ + } else { \ + MP_STATIC_ASSERT_STR_ARRAY_COMPATIBLE; \ + 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; \ + } #endif mp_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); void mp_str_print_json(const mp_print_t *print, const byte *str_data, size_t str_len); mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args); -mp_obj_t mp_obj_new_str_copy(const mp_obj_type_t *type, const byte *data, size_t len); -mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte *data, size_t len); +mp_obj_t mp_obj_new_str_copy(const mp_obj_type_t *type, const byte *data, size_t len); // for type=str, input data must be valid utf-8 +mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte *data, size_t len); // for type=str, will check utf-8 (raises UnicodeError) mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags); -size_t str_offset_to_index(const mp_obj_type_t *type, const byte *self_data, size_t self_len, - size_t offset); +void mp_obj_str_set_data(mp_obj_str_t *str, const byte *data, size_t len); + const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len, mp_obj_t index, bool is_slice); const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction); -extern const char nibble_to_hex_upper[16]; -extern const char nibble_to_hex_lower[16]; +mp_obj_t mp_obj_bytes_hex(size_t n_args, const mp_obj_t *args, const mp_obj_type_t *type); +mp_obj_t mp_obj_bytes_fromhex(mp_obj_t type_in, mp_obj_t data); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj); -MP_DECLARE_CONST_FUN_OBJ_2(str_join_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj); -MP_DECLARE_CONST_FUN_OBJ_KW(str_splitlines_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj); -MP_DECLARE_CONST_FUN_OBJ_KW(str_format_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj); -MP_DECLARE_CONST_FUN_OBJ_2(str_partition_obj); -MP_DECLARE_CONST_FUN_OBJ_2(str_rpartition_obj); -MP_DECLARE_CONST_FUN_OBJ_2(str_center_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_lower_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_upper_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_isspace_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_isalpha_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_isdigit_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_isupper_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_islower_obj); +extern const mp_obj_dict_t mp_obj_str_locals_dict; + +#if MICROPY_PY_BUILTINS_MEMORYVIEW && MICROPY_PY_BUILTINS_BYTES_HEX +extern const mp_obj_dict_t mp_obj_memoryview_locals_dict; +#endif + +#if MICROPY_PY_BUILTINS_BYTEARRAY +extern const mp_obj_dict_t mp_obj_bytearray_locals_dict; +#endif + +#if MICROPY_PY_ARRAY +extern const mp_obj_dict_t mp_obj_array_locals_dict; +#endif + +// CIRCUITPY MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj); +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_obj_bytes_hex_as_str_obj); #endif // MICROPY_INCLUDED_PY_OBJSTR_H diff --git a/py/objstringio.c b/py/objstringio.c index 563dd149bc..1a083449ba 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -33,8 +33,6 @@ #include "py/runtime.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_IO #if MICROPY_CPYTHON_COMPAT @@ -186,7 +184,7 @@ STATIC mp_obj_stringio_t *stringio_new(const mp_obj_type_t *type) { } STATIC 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) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); + (void)n_kw; // TODO check n_kw==0 mp_uint_t sz = 16; bool initdata = false; @@ -195,18 +193,22 @@ STATIC mp_obj_t stringio_make_new(const mp_obj_type_t *type_in, size_t n_args, s mp_obj_stringio_t *o = stringio_new(type_in); if (n_args > 0) { - mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + if (mp_obj_is_int(args[0])) { + sz = mp_obj_get_int(args[0]); + } else { + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); - if (mp_obj_is_str_or_bytes(args[0])) { - o->vstr = m_new_obj(vstr_t); - vstr_init_fixed_buf(o->vstr, bufinfo.len, bufinfo.buf); - o->vstr->len = bufinfo.len; - o->ref_obj = args[0]; - return MP_OBJ_FROM_PTR(o); + if (mp_obj_is_str_or_bytes(args[0])) { + o->vstr = m_new_obj(vstr_t); + vstr_init_fixed_buf(o->vstr, bufinfo.len, bufinfo.buf); + o->vstr->len = bufinfo.len; + o->ref_obj = args[0]; + return MP_OBJ_FROM_PTR(o); + } + + sz = bufinfo.len; + initdata = true; } - - sz = bufinfo.len; - initdata = true; } o->vstr = vstr_new(sz); @@ -236,48 +238,38 @@ STATIC const mp_rom_map_elem_t stringio_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(stringio_locals_dict, stringio_locals_dict_table); STATIC const mp_stream_p_t stringio_stream_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stringio_read, .write = stringio_write, .ioctl = stringio_ioctl, .is_text = true, }; -const mp_obj_type_t mp_type_stringio = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_StringIO, - .print = stringio_print, - .make_new = stringio_make_new, - .locals_dict = (mp_obj_dict_t *)&stringio_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &stringio_stream_p, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_stringio, + MP_QSTR_StringIO, + MP_TYPE_FLAG_ITER_IS_STREAM, + make_new, stringio_make_new, + print, stringio_print, + protocol, &stringio_stream_p, + locals_dict, &stringio_locals_dict + ); #if MICROPY_PY_IO_BYTESIO STATIC const mp_stream_p_t bytesio_stream_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stringio_read, .write = stringio_write, .ioctl = stringio_ioctl, }; -const mp_obj_type_t mp_type_bytesio = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_BytesIO, - .print = stringio_print, - .make_new = stringio_make_new, - .locals_dict = (mp_obj_dict_t *)&stringio_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &bytesio_stream_p, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bytesio, + MP_QSTR_BytesIO, + MP_TYPE_FLAG_ITER_IS_STREAM, + make_new, stringio_make_new, + print, stringio_print, + protocol, &bytesio_stream_p, + locals_dict, &stringio_locals_dict + ); #endif #endif diff --git a/py/objstrunicode.c b/py/objstrunicode.c index 93277e630d..505380c4b5 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -32,8 +32,6 @@ #include "py/objlist.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_STR_UNICODE STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); @@ -41,13 +39,6 @@ STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_bu /******************************************************************************/ /* str */ - -// These settings approximate CPython's printability. It is not -// exhaustive and may print "unprintable" characters. All ASCII control codes -// are escaped along with variable space widths and paragraph designators. -// Unlike CPython, we do not escape private use codes or reserved characters. -// We assume that the unicode is well formed. -// CPython policy is documented here: https://github.com/python/cpython/blob/bb3e0c240bc60fe08d332ff5955d54197f79751c/Objects/unicodectype.c#L147-L159 STATIC void uni_print_quoted(const mp_print_t *print, const byte *str_data, uint str_len) { // this escapes characters, but it will be very slow to print (calling print many times) bool has_single_quote = false; @@ -74,6 +65,8 @@ STATIC void uni_print_quoted(const mp_print_t *print, const byte *str_data, uint mp_printf(print, "\\%c", quote_char); } else if (ch == '\\') { mp_print_str(print, "\\\\"); + } else if (32 <= ch && ch <= 126) { + mp_printf(print, "%c", ch); } else if (ch == '\n') { mp_print_str(print, "\\n"); } else if (ch == '\r') { @@ -120,33 +113,17 @@ STATIC mp_obj_t uni_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } -size_t str_offset_to_index(const mp_obj_type_t *type, const byte *self_data, size_t self_len, - size_t offset) { - if (offset > self_len) { - mp_raise_ValueError(MP_ERROR_TEXT("offset out of bounds")); - } - - if (type == &mp_type_bytes) { - return offset; - } - - size_t index_val = 0; - const byte *s = self_data; - for (size_t i = 0; i < offset; i++, s++) { - if (!UTF8_IS_CONT(*s)) { - ++index_val; - } - } - return index_val; -} - // Convert an index into a pointer to its lead byte. Out of bounds indexing will raise IndexError or // be capped to the first/last character of the string, depending on is_slice. const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len, mp_obj_t index, bool is_slice) { // All str functions also handle bytes objects, and they call str_index_to_ptr(), // so it must handle bytes. - if (type == &mp_type_bytes) { + if (type == &mp_type_bytes + #if MICROPY_PY_BUILTINS_BYTEARRAY + || type == &mp_type_bytearray + #endif + ) { // Taken from objstr.c:str_index_to_ptr() size_t index_val = mp_get_index(type, self_len, index, is_slice); return self_data + index_val; @@ -159,7 +136,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s if (mp_obj_is_small_int(index)) { i = MP_OBJ_SMALL_INT_VALUE(index); } else if (!mp_obj_get_int_maybe(index, &i)) { - mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q, not %q"), MP_QSTR_index, MP_QSTR_int, mp_obj_get_type(index)->name); + mp_raise_msg_varg(&mp_type_TypeError, MP_ERROR_TEXT("string indices must be integers, not %s"), mp_obj_get_type_str(index)); } const byte *s, *top = self_data + self_len; if (i < 0) { @@ -169,7 +146,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s if (is_slice) { return self_data; } - mp_raise_IndexError_varg(MP_ERROR_TEXT("%q index out of range"), MP_QSTR_str); + mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("string index out of range")); } if (!UTF8_IS_CONT(*s)) { ++i; @@ -188,7 +165,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s if (is_slice) { return top; } - mp_raise_IndexError_varg(MP_ERROR_TEXT("%q index out of range"), MP_QSTR_str); + mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("string index out of range")); } // Then check completion if (i-- == 0) { @@ -255,63 +232,19 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } } -STATIC const mp_rom_map_elem_t struni_locals_dict_table[] = { - #if MICROPY_CPYTHON_COMPAT - { MP_ROM_QSTR(MP_QSTR_encode), MP_ROM_PTR(&str_encode_obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&str_find_obj) }, - { MP_ROM_QSTR(MP_QSTR_rfind), MP_ROM_PTR(&str_rfind_obj) }, - { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&str_index_obj) }, - { MP_ROM_QSTR(MP_QSTR_rindex), MP_ROM_PTR(&str_rindex_obj) }, - { MP_ROM_QSTR(MP_QSTR_join), MP_ROM_PTR(&str_join_obj) }, - { MP_ROM_QSTR(MP_QSTR_split), MP_ROM_PTR(&str_split_obj) }, - #if MICROPY_PY_BUILTINS_STR_SPLITLINES - { MP_ROM_QSTR(MP_QSTR_splitlines), MP_ROM_PTR(&str_splitlines_obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_rsplit), MP_ROM_PTR(&str_rsplit_obj) }, - { MP_ROM_QSTR(MP_QSTR_startswith), MP_ROM_PTR(&str_startswith_obj) }, - { MP_ROM_QSTR(MP_QSTR_endswith), MP_ROM_PTR(&str_endswith_obj) }, - { MP_ROM_QSTR(MP_QSTR_strip), MP_ROM_PTR(&str_strip_obj) }, - { MP_ROM_QSTR(MP_QSTR_lstrip), MP_ROM_PTR(&str_lstrip_obj) }, - { MP_ROM_QSTR(MP_QSTR_rstrip), MP_ROM_PTR(&str_rstrip_obj) }, - { MP_ROM_QSTR(MP_QSTR_format), MP_ROM_PTR(&str_format_obj) }, - { MP_ROM_QSTR(MP_QSTR_replace), MP_ROM_PTR(&str_replace_obj) }, - #if MICROPY_PY_BUILTINS_STR_COUNT - { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&str_count_obj) }, - #endif - #if MICROPY_PY_BUILTINS_STR_PARTITION - { MP_ROM_QSTR(MP_QSTR_partition), MP_ROM_PTR(&str_partition_obj) }, - { MP_ROM_QSTR(MP_QSTR_rpartition), MP_ROM_PTR(&str_rpartition_obj) }, - #endif - #if MICROPY_PY_BUILTINS_STR_CENTER - { MP_ROM_QSTR(MP_QSTR_center), MP_ROM_PTR(&str_center_obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_lower), MP_ROM_PTR(&str_lower_obj) }, - { MP_ROM_QSTR(MP_QSTR_upper), MP_ROM_PTR(&str_upper_obj) }, - { MP_ROM_QSTR(MP_QSTR_isspace), MP_ROM_PTR(&str_isspace_obj) }, - { MP_ROM_QSTR(MP_QSTR_isalpha), MP_ROM_PTR(&str_isalpha_obj) }, - { MP_ROM_QSTR(MP_QSTR_isdigit), MP_ROM_PTR(&str_isdigit_obj) }, - { MP_ROM_QSTR(MP_QSTR_isupper), MP_ROM_PTR(&str_isupper_obj) }, - { MP_ROM_QSTR(MP_QSTR_islower), MP_ROM_PTR(&str_islower_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(struni_locals_dict, struni_locals_dict_table); - -const mp_obj_type_t mp_type_str = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_str, - .print = uni_print, - .make_new = mp_obj_str_make_new, - .locals_dict = (mp_obj_dict_t *)&struni_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = uni_unary_op, - .binary_op = mp_obj_str_binary_op, - .subscr = str_subscr, - .getiter = mp_obj_new_str_iterator, - .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_str, + MP_QSTR_str, + MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, mp_obj_str_make_new, + print, uni_print, + unary_op, uni_unary_op, + binary_op, mp_obj_str_binary_op, + subscr, str_subscr, + iter, mp_obj_new_str_iterator, + buffer, mp_obj_str_get_buffer, + locals_dict, &mp_obj_str_locals_dict + ); /******************************************************************************/ /* str iterator */ diff --git a/py/objtraceback.c b/py/objtraceback.c index 989521a0a6..7fcec9383d 100644 --- a/py/objtraceback.c +++ b/py/objtraceback.c @@ -35,8 +35,9 @@ STATIC void mp_obj_traceback_print(const mp_print_t *print, mp_obj_t o_in, mp_pr mp_printf(print, "<%q object at %p>", MP_QSTR_traceback, o); } -const mp_obj_type_t mp_type_traceback = { - { &mp_type_type }, - .name = MP_QSTR_traceback, - .print = mp_obj_traceback_print, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_traceback, + MP_QSTR_traceback, + MP_TYPE_FLAG_NONE, + print, mp_obj_traceback_print + ); diff --git a/py/objtuple.c b/py/objtuple.c index 275a3e3ed9..d1705982b8 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -3,8 +3,8 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George - * SPDX-FileCopyrightText: Copyright (c) 2014-2017 Paul Sokolovsky + * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,9 +30,6 @@ #include "py/objtuple.h" #include "py/runtime.h" -#include "py/objtype.h" - -#include "supervisor/shared/translate/translate.h" /******************************************************************************/ /* tuple */ @@ -111,7 +108,7 @@ STATIC mp_obj_t tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t anothe mp_check_self(mp_obj_is_tuple_compatible(self_in)); const mp_obj_type_t *another_type = mp_obj_get_type(another_in); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); - if (mp_type_get_getiter_slot(another_type) != mp_obj_tuple_getiter) { + if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(another_type, iter) != mp_obj_tuple_getiter) { // Slow path for user subclasses another_in = mp_obj_cast_to_native_base(another_in, MP_OBJ_FROM_PTR(&mp_type_tuple)); if (another_in == MP_OBJ_NULL) { @@ -165,6 +162,7 @@ mp_obj_t mp_obj_tuple_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { if (n <= 0) { return mp_const_empty_tuple; } + // CIRCUITPY size_t new_len = mp_seq_multiply_len(o->len, n); mp_obj_tuple_t *s = MP_OBJ_TO_PTR(mp_obj_new_tuple(new_len, NULL)); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); @@ -187,7 +185,7 @@ mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { // load mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); // when called with a native type (eg namedtuple) using mp_obj_tuple_subscr, get the native self - if (mp_type_get_subscr_slot(self->base.type) != &mp_obj_tuple_subscr) { + if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(self->base.type, subscr) != &mp_obj_tuple_subscr) { self = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(self_in, MP_OBJ_FROM_PTR(&mp_type_tuple))); } @@ -230,20 +228,18 @@ STATIC const mp_rom_map_elem_t tuple_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(tuple_locals_dict, tuple_locals_dict_table); -const mp_obj_type_t mp_type_tuple = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_tuple, - .print = mp_obj_tuple_print, - .make_new = mp_obj_tuple_make_new, - .locals_dict = (mp_obj_dict_t *)&tuple_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_tuple, + MP_QSTR_tuple, + MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, mp_obj_tuple_make_new, + print, mp_obj_tuple_print, + unary_op, mp_obj_tuple_unary_op, + binary_op, mp_obj_tuple_binary_op, + subscr, mp_obj_tuple_subscr, + iter, mp_obj_tuple_getiter, + locals_dict, &tuple_locals_dict + ); // the zero-length tuple const mp_obj_tuple_t mp_const_empty_tuple_obj = {{&mp_type_tuple}, 0}; diff --git a/py/objtype.c b/py/objtype.c index 0d25aac4e9..89730bb9a0 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -3,8 +3,8 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013-2018 Damien P. George - * SPDX-FileCopyrightText: Copyright (c) 2014-2018 Paul Sokolovsky + * Copyright (c) 2013-2018 Damien P. George + * Copyright (c) 2014-2018 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,9 +33,6 @@ #include "py/objtype.h" #include "py/runtime.h" -#include "supervisor/shared/stack.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf @@ -47,7 +44,7 @@ #define ENABLE_SPECIAL_ACCESSORS \ (MICROPY_PY_DESCRIPTORS || MICROPY_PY_DELATTR_SETATTR || MICROPY_PY_BUILTINS_PROPERTY) -STATIC 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); +STATIC 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); /******************************************************************************/ // instance object @@ -58,20 +55,17 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t if (type == &mp_type_object) { // Not a "real" type, end search here. return count; - } - if (mp_obj_is_native_type(type)) { + } else if (mp_obj_is_native_type(type)) { // Native types don't have parents (at least not from our perspective) so end. *last_native_base = type; return count + 1; - } - const void *parent = mp_type_get_parent_slot(type); - if (parent == NULL) { + } else if (!MP_OBJ_TYPE_HAS_SLOT(type, parent)) { // No parents so end search here. return count; #if MICROPY_MULTIPLE_INHERITANCE - } else if (((mp_obj_base_t *)parent)->type == &mp_type_tuple) { + } else if (((mp_obj_base_t *)MP_OBJ_TYPE_GET_SLOT(type, parent))->type == &mp_type_tuple) { // Multiple parents, search through them all recursively. - const mp_obj_tuple_t *parent_tuple = parent; + const mp_obj_tuple_t *parent_tuple = MP_OBJ_TYPE_GET_SLOT(type, parent); const mp_obj_t *item = parent_tuple->items; const mp_obj_t *top = item + parent_tuple->len; for (; item < top; ++item) { @@ -83,7 +77,7 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t #endif } else { // A single parent, use iteration to continue the search. - type = parent; + type = MP_OBJ_TYPE_GET_SLOT(type, parent); } } } @@ -108,7 +102,7 @@ STATIC mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *pos_args if (n_kw) { memcpy(args2 + n_args, kw_args->table, 2 * n_kw * sizeof(mp_obj_t)); } - self->subobj[0] = native_base->make_new(native_base, n_args, n_kw, args2); + self->subobj[0] = MP_OBJ_TYPE_GET_SLOT(native_base, make_new)(native_base, n_args, n_kw, args2); m_del(mp_obj_t, args2, n_args + 2 * n_kw); return mp_const_none; @@ -151,7 +145,7 @@ void mp_obj_assert_native_inited(mp_obj_t native_object) { // will keep lookup->dest[0]'s value (should be MP_OBJ_NULL on invocation) if attribute // is not found // will set lookup->dest[0] to MP_OBJ_SENTINEL if special method was found in a native -// type base via slot id (as specified by lookup->meth_offset). As there can be only one +// type base via slot id (as specified by lookup->slot_offset). As there can be only one // native base, it's known that it applies to instance->subobj[0]. In most cases, we also // don't need to know which type it was - because instance->subobj[0] is of that type. // The only exception is when object is not yet constructed, then we need to know base @@ -160,7 +154,7 @@ void mp_obj_assert_native_inited(mp_obj_t native_object) { struct class_lookup_data { mp_obj_instance_t *obj; qstr attr; - size_t meth_offset; + size_t slot_offset; mp_obj_t *dest; bool is_type; }; @@ -174,23 +168,22 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t // This avoids extra method_name => slot lookup. On the other hand, // this should not be applied to class types, as will result in extra // lookup either. - if (lookup->meth_offset != 0 && mp_obj_is_native_type(type)) { - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wcast-align" - size_t sz = mp_type_size(type); - if (lookup->meth_offset < sz && *(void **)((char *)type + lookup->meth_offset) != NULL) { - #pragma GCC diagnostic pop + if (lookup->slot_offset != 0 && mp_obj_is_native_type(type)) { + // Check if there is a non-zero value in the specified slot index, + // with a special case for getiter where the slot won't be set + // for MP_TYPE_FLAG_ITER_IS_STREAM. + if (MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(type, lookup->slot_offset) || (lookup->slot_offset == MP_OBJ_TYPE_OFFSETOF_SLOT(iter) && type->flags & MP_TYPE_FLAG_ITER_IS_STREAM)) { DEBUG_printf("mp_obj_class_lookup: Matched special meth slot (off=%d) for %s\n", - lookup->meth_offset, qstr_str(lookup->attr)); + lookup->slot_offset, qstr_str(lookup->attr)); lookup->dest[0] = MP_OBJ_SENTINEL; return; } } - if (type->locals_dict != NULL) { + if (MP_OBJ_TYPE_HAS_SLOT(type, locals_dict)) { // search locals_dict (the set of methods/attributes) - assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(type->locals_dict))); // MicroPython restriction, for now - mp_map_t *locals_map = &type->locals_dict->map; + assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(MP_OBJ_TYPE_GET_SLOT(type, locals_dict)))); // MicroPython restriction, for now + mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->map; mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(lookup->attr), MP_MAP_LOOKUP); if (elem != NULL) { if (lookup->is_type) { @@ -198,12 +191,16 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t // do a lookup, not a (base) type in which we found the class method. const mp_obj_type_t *org_type = (const mp_obj_type_t *)lookup->obj; mp_convert_member_lookup(MP_OBJ_NULL, org_type, elem->value, lookup->dest); - } else if (mp_obj_is_type(elem->value, &mp_type_property)) { - lookup->dest[0] = elem->value; - return; } else { mp_obj_instance_t *obj = lookup->obj; - mp_convert_member_lookup(MP_OBJ_FROM_PTR(obj), type, elem->value, lookup->dest); + mp_obj_t obj_obj; + if (obj != NULL && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) { + // If we're dealing with native base class, then it applies to native sub-object + obj_obj = obj->subobj[0]; + } else { + obj_obj = MP_OBJ_FROM_PTR(obj); + } + mp_convert_member_lookup(obj_obj, type, elem->value, lookup->dest); } #if DEBUG_PRINT DEBUG_printf("mp_obj_class_lookup: Returning: "); @@ -230,14 +227,12 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t // attribute not found, keep searching base classes - const void *parent = mp_type_get_parent_slot(type); - if (parent == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(type, parent)) { DEBUG_printf("mp_obj_class_lookup: No more parents\n"); return; - } #if MICROPY_MULTIPLE_INHERITANCE - if (((mp_obj_base_t *)parent)->type == &mp_type_tuple) { - const mp_obj_tuple_t *parent_tuple = parent; + } else if (((mp_obj_base_t *)MP_OBJ_TYPE_GET_SLOT(type, parent))->type == &mp_type_tuple) { + const mp_obj_tuple_t *parent_tuple = MP_OBJ_TYPE_GET_SLOT(type, parent); const mp_obj_t *item = parent_tuple->items; const mp_obj_t *top = item + parent_tuple->len - 1; for (; item < top; ++item) { @@ -256,10 +251,10 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t // search last base (simple tail recursion elimination) assert(mp_obj_is_type(*item, &mp_type_type)); type = (mp_obj_type_t *)MP_OBJ_TO_PTR(*item); - continue; - } #endif - type = parent; + } else { + type = MP_OBJ_TYPE_GET_SLOT(type, parent); + } if (type == &mp_type_object) { // Not a "real" type return; @@ -274,7 +269,7 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k struct class_lookup_data lookup = { .obj = self, .attr = meth, - .meth_offset = offsetof(mp_obj_type_t, print), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(print), .dest = member, .is_type = false, }; @@ -282,7 +277,7 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k if (member[0] == MP_OBJ_NULL && kind == PRINT_STR) { // If there's no __str__, fall back to __repr__ lookup.attr = MP_QSTR___repr__; - lookup.meth_offset = 0; + lookup.slot_offset = 0; mp_obj_class_lookup(&lookup, self->base.type); } @@ -309,7 +304,7 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k mp_printf(print, "<%q object at %p>", mp_obj_get_type_qstr(self_in), self); } -mp_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) { +STATIC mp_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) { assert(mp_obj_is_instance_type(self)); // look for __new__ function @@ -317,7 +312,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size struct class_lookup_data lookup = { .obj = NULL, .attr = MP_QSTR___new__, - .meth_offset = offsetof(mp_obj_type_t, make_new), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(make_new), .dest = init_fn, .is_type = false, }; @@ -343,7 +338,6 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size mp_obj_t args2[1] = {MP_OBJ_FROM_PTR(self)}; new_ret = mp_call_function_n_kw(init_fn[0], 1, 0, args2); } else { - // TODO(tannewt): Could this be on the stack? It's deleted below. mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_args + 2 * n_kw); args2[0] = MP_OBJ_FROM_PTR(self); memcpy(args2 + 1, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); @@ -368,18 +362,16 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size init_fn[0] = init_fn[1] = MP_OBJ_NULL; lookup.obj = o; lookup.attr = MP_QSTR___init__; - lookup.meth_offset = 0; + lookup.slot_offset = 0; mp_obj_class_lookup(&lookup, self); if (init_fn[0] != MP_OBJ_NULL) { mp_obj_t init_ret; if (n_args == 0 && n_kw == 0) { init_ret = mp_call_method_n_kw(0, 0, init_fn); } else { - // TODO(tannewt): Could this be on the stack? It's deleted below. mp_obj_t *args2 = m_new(mp_obj_t, 2 + n_args + 2 * n_kw); args2[0] = init_fn[0]; args2[1] = init_fn[1]; - // copy in kwargs memcpy(args2 + 2, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); init_ret = mp_call_method_n_kw(n_args, n_kw, args2); m_del(mp_obj_t, args2, 2 + n_args + 2 * n_kw); @@ -388,8 +380,8 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("__init__() should return None")); #else - mp_raise_TypeError_varg(MP_ERROR_TEXT("__init__() should return None, not '%q'"), - mp_obj_get_type_qstr(init_ret)); + mp_raise_msg_varg(&mp_type_TypeError, + MP_ERROR_TEXT("__init__() should return None, not '%s'"), mp_obj_get_type_str(init_ret)); #endif } } @@ -397,7 +389,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size // If the type had a native base that was not explicitly initialised // (constructed) by the Python __init__() method then construct it now. if (native_base != NULL && o->subobj[0] == MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj)) { - o->subobj[0] = native_base->make_new(native_base, n_args, n_kw, args); + o->subobj[0] = MP_OBJ_TYPE_GET_SLOT(native_base, make_new)(native_base, n_args, n_kw, args); } return MP_OBJ_FROM_PTR(o); @@ -416,6 +408,12 @@ const byte mp_unary_op_method_name[MP_UNARY_OP_NUM_RUNTIME] = { [MP_UNARY_OP_INVERT] = MP_QSTR___invert__, [MP_UNARY_OP_ABS] = MP_QSTR___abs__, #endif + #if MICROPY_PY_BUILTINS_FLOAT + [MP_UNARY_OP_FLOAT_MAYBE] = MP_QSTR___float__, + #if MICROPY_PY_BUILTINS_COMPLEX + [MP_UNARY_OP_COMPLEX_MAYBE] = MP_QSTR___complex__, + #endif + #endif #if MICROPY_PY_SYS_GETSIZEOF [MP_UNARY_OP_SIZEOF] = MP_QSTR___sizeof__, #endif @@ -446,7 +444,7 @@ STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) { struct class_lookup_data lookup = { .obj = self, .attr = op_name, - .meth_offset = offsetof(mp_obj_type_t, ext[0].unary_op), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(unary_op), .dest = member, .is_type = false, }; @@ -574,7 +572,7 @@ retry:; struct class_lookup_data lookup = { .obj = lhs, .attr = op_name, - .meth_offset = offsetof(mp_obj_type_t, ext[0].binary_op), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(binary_op), .dest = dest, .is_type = false, }; @@ -640,7 +638,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des struct class_lookup_data lookup = { .obj = self, .attr = attr, - .meth_offset = 0, + .slot_offset = 0, .dest = dest, .is_type = false, }; @@ -726,7 +724,7 @@ STATIC bool mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t val struct class_lookup_data lookup = { .obj = self, .attr = attr, - .meth_offset = 0, + .slot_offset = 0, .dest = member, .is_type = false, }; @@ -849,7 +847,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value mp_obj_t member[4] = {MP_OBJ_NULL, MP_OBJ_NULL, index, value}; struct class_lookup_data lookup = { .obj = self, - .meth_offset = offsetof(mp_obj_type_t, ext[0].subscr), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(subscr), .dest = member, .is_type = false, }; @@ -865,11 +863,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value } mp_obj_class_lookup(&lookup, self->base.type); if (member[0] == MP_OBJ_SENTINEL) { - const mp_obj_type_t *subobj_type = mp_obj_get_type(self->subobj[0]); - mp_obj_t ret = subobj_type->ext[0].subscr(self_in, index, value); - // May have called port specific C code. Make sure it didn't mess up the heap. - assert_heap_ok(); - return ret; + return mp_obj_subscr(self->subobj[0], index, value); } else if (member[0] != MP_OBJ_NULL) { size_t n_args = value == MP_OBJ_NULL || value == MP_OBJ_SENTINEL ? 1 : 2; mp_obj_t ret = mp_call_method_n_kw(n_args, 0, member); @@ -888,7 +882,7 @@ STATIC mp_obj_t mp_obj_instance_get_call(mp_obj_t self_in, mp_obj_t *member) { struct class_lookup_data lookup = { .obj = self, .attr = MP_QSTR___call__, - .meth_offset = offsetof(mp_obj_type_t, ext[0].call), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(call), .dest = member, .is_type = false, }; @@ -927,7 +921,7 @@ mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) struct class_lookup_data lookup = { .obj = self, .attr = MP_QSTR___iter__, - .meth_offset = offsetof(mp_obj_type_t, ext[0].getiter), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(iter), .dest = member, .is_type = false, }; @@ -936,10 +930,14 @@ mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) return MP_OBJ_NULL; } else if (member[0] == MP_OBJ_SENTINEL) { const mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); - if (iter_buf == NULL) { - iter_buf = m_new_obj(mp_obj_iter_buf_t); + if (type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) { + return self->subobj[0]; + } else { + if (iter_buf == NULL) { + iter_buf = m_new_obj(mp_obj_iter_buf_t); + } + return ((mp_getiter_fun_t)MP_OBJ_TYPE_GET_SLOT(type, iter))(self->subobj[0], iter_buf); } - return type->ext[0].getiter(self->subobj[0], iter_buf); } else { return mp_call_method_n_kw(0, 0, member); } @@ -951,14 +949,14 @@ STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, struct class_lookup_data lookup = { .obj = self, .attr = MP_QSTR_, // don't actually look for a method - .meth_offset = offsetof(mp_obj_type_t, ext[0].buffer_p.get_buffer), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(buffer), .dest = member, .is_type = false, }; mp_obj_class_lookup(&lookup, self->base.type); if (member[0] == MP_OBJ_SENTINEL) { const mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); - return type->ext[0].buffer_p.get_buffer(self->subobj[0], bufinfo, flags); + return MP_OBJ_TYPE_GET_SLOT(type, buffer)(self->subobj[0], bufinfo, flags); } else { return 1; // object does not support buffer protocol } @@ -996,21 +994,6 @@ STATIC bool check_for_special_accessors(mp_obj_t key, mp_obj_t value) { #endif return false; } - -STATIC bool map_has_special_accessors(const mp_map_t *map) { - if (map == NULL) { - return false; - } - for (size_t i = 0; i < map->alloc; i++) { - if (mp_map_slot_is_filled(map, i)) { - const mp_map_elem_t *elem = &map->table[i]; - if (check_for_special_accessors(elem->key, elem->value)) { - return true; - } - } - } - return false; -} #endif STATIC void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -1044,7 +1027,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); - if (self->make_new == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(self, make_new)) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("cannot create instance")); #else @@ -1052,7 +1035,8 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp #endif } - mp_obj_t o = self->make_new(self, n_args, n_kw, args); + // make new instance + mp_obj_t o = MP_OBJ_TYPE_GET_SLOT(self, make_new)(self, n_args, n_kw, args); // return new instance return o; @@ -1073,7 +1057,7 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (attr == MP_QSTR___dict__) { // Returns a read-only dict of the class attributes. // If the internal locals is not fixed, a copy will be created. - const mp_obj_dict_t *dict = self->locals_dict; + const mp_obj_dict_t *dict = MP_OBJ_TYPE_GET_SLOT_OR_NULL(self, locals_dict); if (!dict) { dict = &mp_const_empty_dict_obj; } @@ -1092,8 +1076,7 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { dest[0] = mp_const_empty_tuple; return; } - const void *parent = mp_type_get_parent_slot(self); - mp_obj_t parent_obj = parent ? MP_OBJ_FROM_PTR(parent) : MP_OBJ_FROM_PTR(&mp_type_object); + mp_obj_t parent_obj = MP_OBJ_TYPE_HAS_SLOT(self, parent) ? MP_OBJ_FROM_PTR(MP_OBJ_TYPE_GET_SLOT(self, parent)) : MP_OBJ_FROM_PTR(&mp_type_object); #if MICROPY_MULTIPLE_INHERITANCE if (mp_obj_is_type(parent_obj, &mp_type_tuple)) { dest[0] = parent_obj; @@ -1107,7 +1090,7 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { struct class_lookup_data lookup = { .obj = (mp_obj_instance_t *)self, .attr = attr, - .meth_offset = 0, + .slot_offset = 0, .dest = dest, .is_type = true, }; @@ -1115,9 +1098,9 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } else { // delete/store attribute - if (self->locals_dict != NULL) { - assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(self->locals_dict))); // MicroPython restriction, for now - mp_map_t *locals_map = &self->locals_dict->map; + if (MP_OBJ_TYPE_HAS_SLOT(self, locals_dict)) { + assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(MP_OBJ_TYPE_GET_SLOT(self, locals_dict)))); // MicroPython restriction, for now + mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(self, locals_dict)->map; if (locals_map->is_fixed) { // can't apply delete/store to a fixed map return; @@ -1151,18 +1134,16 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_type, - .print = type_print, - .make_new = type_make_new, - .attr = type_attr, - MP_TYPE_EXTENDED_FIELDS( - .call = type_call, - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_type, + MP_QSTR_type, + MP_TYPE_FLAG_NONE, + make_new, type_make_new, + print, type_print, + call, type_call, + unary_op, mp_generic_unary_op, + attr, type_attr + ); mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) { // Verify input objects have expected type @@ -1177,15 +1158,20 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // Basic validation of base classes uint16_t base_flags = MP_TYPE_FLAG_EQ_NOT_REFLEXIVE - | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EQ_HAS_NEQ_TEST | MP_TYPE_FLAG_EXTENDED; + | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE + | MP_TYPE_FLAG_EQ_HAS_NEQ_TEST + | MP_TYPE_FLAG_ITER_IS_GETITER + | MP_TYPE_FLAG_INSTANCE_TYPE; size_t bases_len; mp_obj_t *bases_items; mp_obj_tuple_get(bases_tuple, &bases_len, &bases_items); for (size_t i = 0; i < bases_len; i++) { - mp_arg_validate_type(bases_items[i], &mp_type_type, MP_QSTR___class__); + if (!mp_obj_is_type(bases_items[i], &mp_type_type)) { + mp_raise_TypeError(NULL); + } mp_obj_type_t *t = MP_OBJ_TO_PTR(bases_items[i]); // TODO: Verify with CPy, tested on function type - if (t->make_new == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(t, make_new)) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("type is not an acceptable base type")); #else @@ -1201,47 +1187,58 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) #endif } - mp_obj_full_type_t *o = m_new0(mp_obj_full_type_t, 1); + const void *base_protocol = NULL; + if (bases_len > 0) { + base_protocol = MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_type_t *)MP_OBJ_TO_PTR(bases_items[0])), protocol); + } + + // Allocate a variable-sized mp_obj_type_t with as many slots as we need + // (currently 10, plus 1 for base, plus 1 for base-protocol). + // Note: mp_obj_type_t is (2 + 3 + #slots) words, so going from 11 to 12 slots + // moves from 4 to 5 gc blocks. + mp_obj_type_t *o = m_new_obj_var0(mp_obj_type_t, void *, 10 + (bases_len ? 1 : 0) + (base_protocol ? 1 : 0)); o->base.type = &mp_type_type; o->flags = base_flags; o->name = name; - o->print = instance_print; - o->make_new = mp_obj_instance_make_new; - o->attr = mp_obj_instance_attr; - o->MP_TYPE_CALL = mp_obj_instance_call; - o->MP_TYPE_UNARY_OP = instance_unary_op; - o->MP_TYPE_BINARY_OP = instance_binary_op; - o->MP_TYPE_SUBSCR = instance_subscr; - o->MP_TYPE_GETITER = mp_obj_instance_getiter; - // o->iternext = ; not implemented - o->MP_TYPE_GET_BUFFER = instance_get_buffer; + MP_OBJ_TYPE_SET_SLOT(o, make_new, mp_obj_instance_make_new, 0); + MP_OBJ_TYPE_SET_SLOT(o, print, instance_print, 1); + MP_OBJ_TYPE_SET_SLOT(o, call, mp_obj_instance_call, 2); + MP_OBJ_TYPE_SET_SLOT(o, unary_op, instance_unary_op, 3); + MP_OBJ_TYPE_SET_SLOT(o, binary_op, instance_binary_op, 4); + MP_OBJ_TYPE_SET_SLOT(o, attr, mp_obj_instance_attr, 5); + MP_OBJ_TYPE_SET_SLOT(o, subscr, instance_subscr, 6); + MP_OBJ_TYPE_SET_SLOT(o, iter, mp_obj_instance_getiter, 7); + MP_OBJ_TYPE_SET_SLOT(o, buffer, instance_get_buffer, 8); + + mp_obj_dict_t *locals_ptr = MP_OBJ_TO_PTR(locals_dict); + MP_OBJ_TYPE_SET_SLOT(o, locals_dict, locals_ptr, 9); if (bases_len > 0) { - // Inherit protocol from a base class. This allows to define an - // abstract base class which would translate C-level protocol to - // Python method calls, and any subclass inheriting from it will - // support this feature. - o->MP_TYPE_PROTOCOL = mp_type_get_protocol_slot((mp_obj_type_t *)MP_OBJ_TO_PTR(bases_items[0])); - if (bases_len >= 2) { #if MICROPY_MULTIPLE_INHERITANCE - o->parent = MP_OBJ_TO_PTR(bases_tuple); + MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_tuple), 10); #else mp_raise_NotImplementedError(MP_ERROR_TEXT("multiple inheritance not supported")); #endif } else { - o->parent = MP_OBJ_TO_PTR(bases_items[0]); + MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_items[0]), 10); + } + + // Inherit protocol from a base class. This allows to define an + // abstract base class which would translate C-level protocol to + // Python method calls, and any subclass inheriting from it will + // support this feature. + if (base_protocol) { + MP_OBJ_TYPE_SET_SLOT(o, protocol, base_protocol, 11); } } - o->locals_dict = MP_OBJ_TO_PTR(locals_dict); - #if ENABLE_SPECIAL_ACCESSORS // Check if the class has any special accessor methods if (!(o->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { - for (size_t i = 0; i < o->locals_dict->map.alloc; i++) { - if (mp_map_slot_is_filled(&o->locals_dict->map, i)) { - const mp_map_elem_t *elem = &o->locals_dict->map.table[i]; + for (size_t i = 0; i < locals_ptr->map.alloc; i++) { + if (mp_map_slot_is_filled(&locals_ptr->map, i)) { + const mp_map_elem_t *elem = &locals_ptr->map.table[i]; if (check_for_special_accessors(elem->key, elem->value)) { o->flags |= MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; break; @@ -1252,23 +1249,12 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) #endif const mp_obj_type_t *native_base; - size_t num_native_bases = instance_count_native_bases((mp_obj_type_t *)o, &native_base); + size_t num_native_bases = instance_count_native_bases(o, &native_base); if (num_native_bases > 1) { mp_raise_TypeError(MP_ERROR_TEXT("multiple bases have instance lay-out conflict")); } - mp_map_t *locals_map = &o->locals_dict->map; - #if ENABLE_SPECIAL_ACCESSORS - // Check if the class has any special accessor methods - if (!(o->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS) && - (map_has_special_accessors(locals_map) || - (num_native_bases == 1 && - native_base->locals_dict != NULL && - map_has_special_accessors(&native_base->locals_dict->map)))) { - o->flags |= MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; - } - #endif - + mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(o, locals_dict)->map; mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP); if (elem != NULL) { // __new__ slot exists; check if it is a function @@ -1329,22 +1315,21 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { struct class_lookup_data lookup = { .obj = MP_OBJ_TO_PTR(self->obj), .attr = attr, - .meth_offset = 0, + .slot_offset = 0, .dest = dest, .is_type = false, }; - // Allow a call super().__init__() to reach any native base classes + // Allow a call super().__init__() to reach any native base classes. if (attr == MP_QSTR___init__) { - lookup.meth_offset = offsetof(mp_obj_type_t, make_new); + lookup.slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(make_new); } - const void *parent = mp_type_get_parent_slot(type); - if (parent == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(type, parent)) { // no parents, do nothing #if MICROPY_MULTIPLE_INHERITANCE - } else if (((mp_obj_base_t *)parent)->type == &mp_type_tuple) { - const mp_obj_tuple_t *parent_tuple = parent; + } else if (((mp_obj_base_t *)MP_OBJ_TYPE_GET_SLOT(type, parent))->type == &mp_type_tuple) { + const mp_obj_tuple_t *parent_tuple = MP_OBJ_TYPE_GET_SLOT(type, parent); size_t len = parent_tuple->len; const mp_obj_t *items = parent_tuple->items; for (size_t i = 0; i < len; i++) { @@ -1354,14 +1339,15 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { // and we don't want to lookup native methods in object. continue; } + mp_obj_class_lookup(&lookup, (mp_obj_type_t *)MP_OBJ_TO_PTR(items[i])); if (dest[0] != MP_OBJ_NULL) { break; } } #endif - } else if (parent != &mp_type_object) { - mp_obj_class_lookup(&lookup, parent); + } else if (MP_OBJ_TYPE_GET_SLOT(type, parent) != &mp_type_object) { + mp_obj_class_lookup(&lookup, MP_OBJ_TYPE_GET_SLOT(type, parent)); } if (dest[0] != MP_OBJ_NULL) { @@ -1369,6 +1355,7 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { // Looked up native __init__ so defer to it dest[0] = MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj); dest[1] = self->obj; + // CIRCUITPY better support for properties } else { mp_obj_t member = dest[0]; // changes to mp_obj_instance_load_attr may require changes @@ -1397,20 +1384,21 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { return; } - // Reset meth_offset so we don't look up any native methods in object, + // Reset slot_offset so we don't look up any native methods in object, // because object never takes up the native base-class slot. - lookup.meth_offset = 0; + lookup.slot_offset = 0; mp_obj_class_lookup(&lookup, &mp_type_object); } -const mp_obj_type_t mp_type_super = { - { &mp_type_type }, - .name = MP_QSTR_super, - .print = super_print, - .make_new = super_make_new, - .attr = super_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_super, + MP_QSTR_super, + MP_TYPE_FLAG_NONE, + make_new, super_make_new, + print, super_print, + attr, super_attr + ); void mp_load_super_method(qstr attr, mp_obj_t *dest) { mp_obj_super_t super = {{&mp_type_super}, dest[1], dest[2]}; @@ -1436,15 +1424,14 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) { } const mp_obj_type_t *self = MP_OBJ_TO_PTR(object); - const void *parent = mp_type_get_parent_slot(self); - if (parent == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(self, parent)) { // type has no parents return false; #if MICROPY_MULTIPLE_INHERITANCE - } else if (((mp_obj_base_t *)parent)->type == &mp_type_tuple) { + } else if (((mp_obj_base_t *)MP_OBJ_TYPE_GET_SLOT(self, parent))->type == &mp_type_tuple) { // get the base objects (they should be type objects) - const mp_obj_tuple_t *parent_tuple = parent; + const mp_obj_tuple_t *parent_tuple = MP_OBJ_TYPE_GET_SLOT(self, parent); const mp_obj_t *item = parent_tuple->items; const mp_obj_t *top = item + parent_tuple->len - 1; @@ -1460,7 +1447,7 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) { #endif } else { // type has 1 parent - object = MP_OBJ_FROM_PTR(parent); + object = MP_OBJ_FROM_PTR(MP_OBJ_TYPE_GET_SLOT(self, parent)); } } } @@ -1527,14 +1514,16 @@ STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self, size_t n return MP_OBJ_FROM_PTR(o); } -const mp_obj_type_t mp_type_staticmethod = { - { &mp_type_type }, - .name = MP_QSTR_staticmethod, - .make_new = static_class_method_make_new, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_staticmethod, + MP_QSTR_staticmethod, + MP_TYPE_FLAG_NONE, + make_new, static_class_method_make_new + ); -const mp_obj_type_t mp_type_classmethod = { - { &mp_type_type }, - .name = MP_QSTR_classmethod, - .make_new = static_class_method_make_new, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_classmethod, + MP_QSTR_classmethod, + MP_TYPE_FLAG_NONE, + make_new, static_class_method_make_new + ); diff --git a/py/objtype.h b/py/objtype.h index 17b8048c19..d30d5f60de 100644 --- a/py/objtype.h +++ b/py/objtype.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,8 +37,6 @@ typedef struct _mp_obj_instance_t { // TODO maybe cache __getattr__ and __setattr__ for efficient lookup of them } mp_obj_instance_t; -void mp_obj_assert_native_inited(mp_obj_t native_object); - #if MICROPY_CPYTHON_COMPAT // this is needed for object.__new__ mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *cls, const mp_obj_type_t **native_base); @@ -48,12 +46,13 @@ mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *cls, const mp_obj_ty bool mp_obj_instance_is_callable(mp_obj_t self_in); mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); -#define mp_obj_is_instance_type(type) ((type)->make_new == mp_obj_instance_make_new) -#define mp_obj_is_native_type(type) ((type)->make_new != mp_obj_instance_make_new) -// this needs to be exposed for the above macros to work correctly -mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); +#define mp_obj_is_instance_type(type) ((type)->flags & MP_TYPE_FLAG_INSTANCE_TYPE) +#define mp_obj_is_native_type(type) (!((type)->flags & MP_TYPE_FLAG_INSTANCE_TYPE)) // this needs to be exposed for mp_getiter mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); +// CIRCUITPY addition +void mp_obj_assert_native_inited(mp_obj_t native_object); + #endif // MICROPY_INCLUDED_PY_OBJTYPE_H diff --git a/py/objzip.c b/py/objzip.c index 69aca29e9a..3c3138180a 100644 --- a/py/objzip.c +++ b/py/objzip.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -66,13 +66,10 @@ STATIC mp_obj_t zip_iternext(mp_obj_t self_in) { return MP_OBJ_FROM_PTR(tuple); } -const mp_obj_type_t mp_type_zip = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_zip, - .make_new = zip_make_new, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = zip_iternext, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_zip, + MP_QSTR_zip, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + make_new, zip_make_new, + iter, zip_iternext + ); diff --git a/py/opmethods.c b/py/opmethods.c index 6ebd469113..c3931fd358 100644 --- a/py/opmethods.c +++ b/py/opmethods.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,25 +29,28 @@ STATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) { const mp_obj_type_t *type = mp_obj_get_type(self_in); - return type->ext[0].subscr(self_in, key_in, MP_OBJ_SENTINEL); + // Note: assumes type must have subscr (only used by dict). + return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_SENTINEL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem); STATIC mp_obj_t op_setitem(mp_obj_t self_in, mp_obj_t key_in, mp_obj_t value_in) { const mp_obj_type_t *type = mp_obj_get_type(self_in); - return type->ext[0].subscr(self_in, key_in, value_in); + // Note: assumes type must have subscr (only used by dict). + return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, value_in); } MP_DEFINE_CONST_FUN_OBJ_3(mp_op_setitem_obj, op_setitem); STATIC mp_obj_t op_delitem(mp_obj_t self_in, mp_obj_t key_in) { const mp_obj_type_t *type = mp_obj_get_type(self_in); - return type->ext[0].subscr(self_in, key_in, MP_OBJ_NULL); + // Note: assumes type must have subscr (only used by dict). + return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_NULL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_delitem_obj, op_delitem); STATIC mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) { const mp_obj_type_t *type = mp_obj_get_type(lhs_in); - mp_binary_op_fun_t binary_op = mp_type_get_binary_op_slot(type); - return binary_op(MP_BINARY_OP_CONTAINS, lhs_in, rhs_in); + // Note: assumes type must have binary_op (only used by set/frozenset). + return MP_OBJ_TYPE_GET_SLOT(type, binary_op)(MP_BINARY_OP_CONTAINS, lhs_in, rhs_in); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_contains_obj, op_contains); diff --git a/py/parse.c b/py/parse.c index c8a3b29bb5..50f9586835 100644 --- a/py/parse.c +++ b/py/parse.c @@ -39,8 +39,6 @@ #include "py/objstr.h" #include "py/builtin.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_ENABLE_COMPILER #define RULE_ACT_ARG_MASK (0x0f) @@ -340,16 +338,6 @@ STATIC uint8_t peek_rule(parser_t *parser, size_t n) { } #endif -bool mp_parse_node_is_const_false(mp_parse_node_t pn) { - return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE) - || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0); -} - -bool mp_parse_node_is_const_true(mp_parse_node_t pn) { - return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE) - || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) != 0); -} - bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) { if (MP_PARSE_NODE_IS_SMALL_INT(pn)) { *o = MP_OBJ_NEW_SMALL_INT(MP_PARSE_NODE_LEAF_SMALL_INT(pn)); @@ -433,6 +421,24 @@ STATIC mp_obj_t mp_parse_node_convert_to_obj(mp_parse_node_t pn) { } #endif +STATIC bool parse_node_is_const_bool(mp_parse_node_t pn, bool value) { + // Returns true if 'pn' is a constant whose boolean value is equivalent to 'value' + #if MICROPY_COMP_CONST_TUPLE || MICROPY_COMP_CONST + return mp_parse_node_is_const(pn) && mp_obj_is_true(mp_parse_node_convert_to_obj(pn)) == value; + #else + return MP_PARSE_NODE_IS_TOKEN_KIND(pn, value ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE) + || (MP_PARSE_NODE_IS_SMALL_INT(pn) && !!MP_PARSE_NODE_LEAF_SMALL_INT(pn) == value); + #endif +} + +bool mp_parse_node_is_const_false(mp_parse_node_t pn) { + return parse_node_is_const_bool(pn, false); +} + +bool mp_parse_node_is_const_true(mp_parse_node_t pn) { + return parse_node_is_const_bool(pn, true); +} + size_t mp_parse_node_extract_list(mp_parse_node_t *pn, size_t pn_kind, mp_parse_node_t **nodes) { if (MP_PARSE_NODE_IS_NULL(*pn)) { *nodes = NULL; @@ -597,7 +603,7 @@ STATIC void push_result_token(parser_t *parser, uint8_t rule_id) { mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex); pn = make_node_const_object_optimised(parser, lex->tok_line, o); } else if (lex->tok_kind == MP_TOKEN_FLOAT_OR_IMAG) { - mp_obj_t o = mp_parse_num_decimal(lex->vstr.buf, lex->vstr.len, true, false, lex); + mp_obj_t o = mp_parse_num_float(lex->vstr.buf, lex->vstr.len, true, lex); pn = make_node_const_object(parser, lex->tok_line, o); } else if (lex->tok_kind == MP_TOKEN_STRING) { // Don't automatically intern all strings. Doc strings (which are usually large) diff --git a/py/parsenum.c b/py/parsenum.c index 24d46705a7..b2658eac77 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -32,8 +32,6 @@ #include "py/parsenum.h" #include "py/smallint.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_PY_BUILTINS_FLOAT #include #endif @@ -162,43 +160,79 @@ value_error: mp_printf(&print, "invalid syntax for integer with base %d: ", base); mp_str_print_quoted(&print, str_val_start, top - str_val_start, true); mp_obj_t exc = mp_obj_new_exception_arg1(&mp_type_ValueError, - mp_obj_new_str_from_vstr(&mp_type_str, &vstr)); + mp_obj_new_str_from_utf8_vstr(&vstr)); raise_exc(exc, lex); #endif } } +enum { + REAL_IMAG_STATE_START = 0, + REAL_IMAG_STATE_HAVE_REAL = 1, + REAL_IMAG_STATE_HAVE_IMAG = 2, +}; + typedef enum { PARSE_DEC_IN_INTG, PARSE_DEC_IN_FRAC, PARSE_DEC_IN_EXP, } parse_dec_in_t; -mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex) { - #if MICROPY_PY_BUILTINS_FLOAT - +#if MICROPY_PY_BUILTINS_FLOAT // DEC_VAL_MAX only needs to be rough and is used to retain precision while not overflowing // SMALL_NORMAL_VAL is the smallest power of 10 that is still a normal float // EXACT_POWER_OF_10 is the largest value of x so that 10^x can be stored exactly in a float // Note: EXACT_POWER_OF_10 is at least floor(log_5(2^mantissa_length)). Indeed, 10^n = 2^n * 5^n // so we only have to store the 5^n part in the mantissa (the 2^n part will go into the float's // exponent). - #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #define DEC_VAL_MAX 1e20F #define SMALL_NORMAL_VAL (1e-37F) #define SMALL_NORMAL_EXP (-37) #define EXACT_POWER_OF_10 (9) - #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE #define DEC_VAL_MAX 1e200 #define SMALL_NORMAL_VAL (1e-307) #define SMALL_NORMAL_EXP (-307) #define EXACT_POWER_OF_10 (22) - #endif +#endif + +// Break out inner digit accumulation routine to ease trailing zero deferral. +static void accept_digit(mp_float_t *p_dec_val, int dig, int *p_exp_extra, int in) { + // Core routine to ingest an additional digit. + if (*p_dec_val < DEC_VAL_MAX) { + // dec_val won't overflow so keep accumulating + *p_dec_val = 10 * *p_dec_val + dig; + if (in == PARSE_DEC_IN_FRAC) { + --(*p_exp_extra); + } + } else { + // dec_val might overflow and we anyway can't represent more digits + // of precision, so ignore the digit and just adjust the exponent + if (in == PARSE_DEC_IN_INTG) { + ++(*p_exp_extra); + } + } +} +#endif // MICROPY_BUILTINS_FLOAT + +#if MICROPY_PY_BUILTINS_COMPLEX +mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex) +#else +mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lexer_t *lex) +#endif +{ + #if MICROPY_PY_BUILTINS_FLOAT const char *top = str + len; mp_float_t dec_val = 0; bool dec_neg = false; - bool imag = false; + + #if MICROPY_PY_BUILTINS_COMPLEX + unsigned int real_imag_state = REAL_IMAG_STATE_START; + mp_float_t dec_real = 0; +parse_start: + #endif // skip leading space for (; str < top && unichar_isspace(*str); str++) { @@ -241,6 +275,7 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool bool exp_neg = false; int exp_val = 0; int exp_extra = 0; + int trailing_zeros_intg = 0, trailing_zeros_frac = 0; while (str < top) { unsigned int dig = *str++; if ('0' <= dig && dig <= '9') { @@ -253,18 +288,25 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool exp_val = 10 * exp_val + dig; } } else { - if (dec_val < DEC_VAL_MAX) { - // dec_val won't overflow so keep accumulating - dec_val = 10 * dec_val + dig; - if (in == PARSE_DEC_IN_FRAC) { - --exp_extra; + if (dig == 0 || dec_val >= DEC_VAL_MAX) { + // Defer treatment of zeros in fractional part. If nothing comes afterwards, ignore them. + // Also, once we reach DEC_VAL_MAX, treat every additional digit as a trailing zero. + if (in == PARSE_DEC_IN_INTG) { + ++trailing_zeros_intg; + } else { + ++trailing_zeros_frac; } } else { - // dec_val might overflow and we anyway can't represent more digits - // of precision, so ignore the digit and just adjust the exponent - if (in == PARSE_DEC_IN_INTG) { - ++exp_extra; + // Time to un-defer any trailing zeros. Intg zeros first. + while (trailing_zeros_intg) { + accept_digit(&dec_val, 0, &exp_extra, PARSE_DEC_IN_INTG); + --trailing_zeros_intg; } + while (trailing_zeros_frac) { + accept_digit(&dec_val, 0, &exp_extra, PARSE_DEC_IN_FRAC); + --trailing_zeros_frac; + } + accept_digit(&dec_val, dig, &exp_extra, in); } } } else if (in == PARSE_DEC_IN_INTG && dig == '.') { @@ -282,9 +324,6 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool if (str == top) { goto value_error; } - } else if (allow_imag && (dig | 0x20) == 'j') { - imag = true; - break; } else if (dig == '_') { continue; } else { @@ -300,7 +339,7 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool } // apply the exponent, making sure it's not a subnormal value - exp_val += exp_extra; + exp_val += exp_extra + trailing_zeros_intg; if (exp_val < SMALL_NORMAL_EXP) { exp_val -= SMALL_NORMAL_EXP; dec_val *= SMALL_NORMAL_VAL; @@ -318,6 +357,19 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool } } + if (allow_imag && str < top && (*str | 0x20) == 'j') { + #if MICROPY_PY_BUILTINS_COMPLEX + if (str == str_val_start) { + // Convert "j" to "1j". + dec_val = 1; + } + ++str; + real_imag_state |= REAL_IMAG_STATE_HAVE_IMAG; + #else + raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, MP_ERROR_TEXT("complex values not supported")), lex); + #endif + } + // negate value if needed if (dec_neg) { dec_val = -dec_val; @@ -334,24 +386,36 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool // check we reached the end of the string if (str != top) { + #if MICROPY_PY_BUILTINS_COMPLEX + if (force_complex && real_imag_state == REAL_IMAG_STATE_START) { + // If we've only seen a real so far, keep parsing for the imaginary part. + dec_real = dec_val; + dec_val = 0; + real_imag_state |= REAL_IMAG_STATE_HAVE_REAL; + goto parse_start; + } + #endif goto value_error; } - // return the object #if MICROPY_PY_BUILTINS_COMPLEX - if (imag) { - return mp_obj_new_complex(0, dec_val); + if (real_imag_state == REAL_IMAG_STATE_HAVE_REAL) { + // We're on the second part, but didn't get the expected imaginary number. + goto value_error; + } + #endif + + // return the object + + #if MICROPY_PY_BUILTINS_COMPLEX + if (real_imag_state != REAL_IMAG_STATE_START) { + return mp_obj_new_complex(dec_real, dec_val); } else if (force_complex) { return mp_obj_new_complex(dec_val, 0); } - #else - if (imag || force_complex) { - raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, MP_ERROR_TEXT("complex values not supported")), lex); - } #endif - else { - return mp_obj_new_float(dec_val); - } + + return mp_obj_new_float(dec_val); value_error: raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, MP_ERROR_TEXT("invalid syntax for number")), lex); diff --git a/py/parsenum.h b/py/parsenum.h index a91ca532da..a0c738659c 100644 --- a/py/parsenum.h +++ b/py/parsenum.h @@ -31,7 +31,21 @@ #include "py/obj.h" // these functions raise a SyntaxError if lex!=NULL, else a ValueError + mp_obj_t mp_parse_num_integer(const char *restrict str, size_t len, int base, mp_lexer_t *lex); + +#if MICROPY_PY_BUILTINS_COMPLEX mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex); +static inline mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lexer_t *lex) { + return mp_parse_num_decimal(str, len, allow_imag, false, lex); +} + +static inline mp_obj_t mp_parse_num_complex(const char *str, size_t len, mp_lexer_t *lex) { + return mp_parse_num_decimal(str, len, true, true, lex); +} +#else +mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lexer_t *lex); +#endif + #endif // MICROPY_INCLUDED_PY_PARSENUM_H diff --git a/py/persistentcode.c b/py/persistentcode.c index 272298274f..abbf8033a4 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013-2020 Damien P. George + * Copyright (c) 2013-2020 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -208,12 +208,16 @@ STATIC mp_obj_t load_obj(mp_reader_t *reader) { read_bytes(reader, (byte *)vstr.buf, len); if (obj_type == MP_PERSISTENT_OBJ_STR || obj_type == MP_PERSISTENT_OBJ_BYTES) { read_byte(reader); // skip null terminator - return mp_obj_new_str_from_vstr(obj_type == MP_PERSISTENT_OBJ_STR ? &mp_type_str : &mp_type_bytes, &vstr); + if (obj_type == MP_PERSISTENT_OBJ_STR) { + return mp_obj_new_str_from_utf8_vstr(&vstr); + } else { + return mp_obj_new_bytes_from_vstr(&vstr); + } } else if (obj_type == MP_PERSISTENT_OBJ_INT) { return mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL); } else { assert(obj_type == MP_PERSISTENT_OBJ_FLOAT || obj_type == MP_PERSISTENT_OBJ_COMPLEX); - return mp_parse_num_decimal(vstr.buf, vstr.len, obj_type == MP_PERSISTENT_OBJ_COMPLEX, false, NULL); + return mp_parse_num_float(vstr.buf, vstr.len, obj_type == MP_PERSISTENT_OBJ_COMPLEX, NULL); } } } @@ -392,64 +396,66 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co return rc; } -mp_compiled_module_t mp_raw_code_load(mp_reader_t *reader, mp_module_context_t *context) { +void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *cm) { byte header[4]; read_bytes(reader, header, sizeof(header)); + byte arch = MPY_FEATURE_DECODE_ARCH(header[2]); if (header[0] != 'C' || header[1] != MPY_VERSION - || MPY_FEATURE_DECODE_FLAGS(header[2]) != MPY_FEATURE_FLAGS + || (arch != MP_NATIVE_ARCH_NONE && MPY_FEATURE_DECODE_SUB_VERSION(header[2]) != MPY_SUB_VERSION) || header[3] > MP_SMALL_INT_BITS) { mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file")); } if (MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE) { - byte arch = MPY_FEATURE_DECODE_ARCH(header[2]); if (!MPY_FEATURE_ARCH_TEST(arch)) { - mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy arch")); + if (MPY_FEATURE_ARCH_TEST(MP_NATIVE_ARCH_NONE)) { + // On supported ports this can be resolved by enabling feature, eg + // mpconfigboard.h: MICROPY_EMIT_THUMB (1) + mp_raise_ValueError(MP_ERROR_TEXT("native code in .mpy unsupported")); + } else { + mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy arch")); + } } } size_t n_qstr = read_uint(reader); size_t n_obj = read_uint(reader); - mp_module_context_alloc_tables(context, n_qstr, n_obj); + mp_module_context_alloc_tables(cm->context, n_qstr, n_obj); // Load qstrs. for (size_t i = 0; i < n_qstr; ++i) { - context->constants.qstr_table[i] = load_qstr(reader); + cm->context->constants.qstr_table[i] = load_qstr(reader); } // Load constant objects. for (size_t i = 0; i < n_obj; ++i) { - context->constants.obj_table[i] = load_obj(reader); + cm->context->constants.obj_table[i] = load_obj(reader); } // Load top-level module. - mp_compiled_module_t cm2; - cm2.rc = load_raw_code(reader, context); - cm2.context = context; + cm->rc = load_raw_code(reader, cm->context); #if MICROPY_PERSISTENT_CODE_SAVE - cm2.has_native = MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE; - cm2.n_qstr = n_qstr; - cm2.n_obj = n_obj; + cm->has_native = MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE; + cm->n_qstr = n_qstr; + cm->n_obj = n_obj; #endif reader->close(reader->data); - - return cm2; } -mp_compiled_module_t mp_raw_code_load_mem(const byte *buf, size_t len, mp_module_context_t *context) { +void mp_raw_code_load_mem(const byte *buf, size_t len, mp_compiled_module_t *context) { mp_reader_t reader; mp_reader_new_mem(&reader, buf, len, 0); - return mp_raw_code_load(&reader, context); + mp_raw_code_load(&reader, context); } #if MICROPY_HAS_FILE_READER -mp_compiled_module_t mp_raw_code_load_file(const char *filename, mp_module_context_t *context) { +void mp_raw_code_load_file(const char *filename, mp_compiled_module_t *context) { mp_reader_t reader; mp_reader_new_file(&reader, filename); - return mp_raw_code_load(&reader, context); + mp_raw_code_load(&reader, context); } #endif // MICROPY_HAS_FILE_READER @@ -585,23 +591,20 @@ STATIC void save_raw_code(mp_print_t *print, const mp_raw_code_t *rc) { void mp_raw_code_save(mp_compiled_module_t *cm, mp_print_t *print) { // header contains: - // byte 'C' + // byte 'C' (CIRCUITPY) // byte version - // byte feature flags + // byte native arch (and sub-version if native) // byte number of bits in a small int byte header[4] = { 'C', MPY_VERSION, - MPY_FEATURE_ENCODE_FLAGS(MPY_FEATURE_FLAGS_DYNAMIC), + cm->has_native ? MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH_DYNAMIC) : 0, #if MICROPY_DYNAMIC_COMPILER mp_dynamic_compiler.small_int_bits, #else MP_SMALL_INT_BITS, #endif }; - if (cm->has_native) { - header[2] |= MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH_DYNAMIC); - } mp_print_bytes(print, header, sizeof(header)); // Number of entries in constant table. @@ -640,6 +643,9 @@ void mp_raw_code_save_file(mp_compiled_module_t *cm, const char *filename) { MP_THREAD_GIL_EXIT(); int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); MP_THREAD_GIL_ENTER(); + if (fd < 0) { + mp_raise_OSError_with_filename(errno, filename); + } mp_print_t fd_print = {(void *)(intptr_t)fd, fd_print_strn}; mp_raw_code_save(cm, &fd_print); MP_THREAD_GIL_EXIT(); @@ -650,3 +656,8 @@ void mp_raw_code_save_file(mp_compiled_module_t *cm, const char *filename) { #endif // MICROPY_PERSISTENT_CODE_SAVE_FILE #endif // MICROPY_PERSISTENT_CODE_SAVE + +#if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE +// An mp_obj_list_t that tracks relocated native code to prevent the GC from reclaiming them. +MP_REGISTER_ROOT_POINTER(mp_obj_t track_reloc_code_list); +#endif diff --git a/py/persistentcode.h b/py/persistentcode.h index 7ba86c1eb7..f68ce1a7e1 100644 --- a/py/persistentcode.h +++ b/py/persistentcode.h @@ -30,24 +30,23 @@ #include "py/reader.h" #include "py/emitglue.h" -// The current version of .mpy files +// The current version of .mpy files. A bytecode-only .mpy file can be loaded +// as long as MPY_VERSION matches, but a native .mpy (i.e. one with an arch +// set) must also match MPY_SUB_VERSION. This allows 3 additional updates to +// the native ABI per bytecode revision. #define MPY_VERSION 6 +#define MPY_SUB_VERSION 1 -// Macros to encode/decode flags to/from the feature byte -#define MPY_FEATURE_ENCODE_FLAGS(flags) (flags) -#define MPY_FEATURE_DECODE_FLAGS(feat) ((feat) & 3) +// Macros to encode/decode sub-version to/from the feature byte. This replaces +// the bits previously used to encode the flags (map caching and unicode) +// which are no longer used starting at .mpy version 6. +#define MPY_FEATURE_ENCODE_SUB_VERSION(version) (version) +#define MPY_FEATURE_DECODE_SUB_VERSION(feat) ((feat) & 3) // Macros to encode/decode native architecture to/from the feature byte #define MPY_FEATURE_ENCODE_ARCH(arch) ((arch) << 2) #define MPY_FEATURE_DECODE_ARCH(feat) ((feat) >> 2) -// The feature flag bits encode the compile-time config options that affect -// the generate bytecode. Note: no longer used. -// (formerly MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE and MICROPY_PY_BUILTINS_STR_UNICODE). -#define MPY_FEATURE_FLAGS (0) -// This is a version of the flags that can be configured at runtime. -#define MPY_FEATURE_FLAGS_DYNAMIC (0) - // Define the host architecture #if MICROPY_EMIT_X86 #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X86) @@ -82,7 +81,7 @@ // 16-bit little-endian integer with the second and third bytes of supported .mpy files #define MPY_FILE_HEADER_INT (MPY_VERSION \ - | (MPY_FEATURE_ENCODE_FLAGS(MPY_FEATURE_FLAGS) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH)) << 8) + | (MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH)) << 8) enum { MP_NATIVE_ARCH_NONE = 0, @@ -112,9 +111,9 @@ enum { MP_PERSISTENT_OBJ_TUPLE, }; -mp_compiled_module_t mp_raw_code_load(mp_reader_t *reader, mp_module_context_t *ctx); -mp_compiled_module_t mp_raw_code_load_mem(const byte *buf, size_t len, mp_module_context_t *ctx); -mp_compiled_module_t mp_raw_code_load_file(const char *filename, mp_module_context_t *ctx); +void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *ctx); +void mp_raw_code_load_mem(const byte *buf, size_t len, mp_compiled_module_t *ctx); +void mp_raw_code_load_file(const char *filename, mp_compiled_module_t *ctx); void mp_raw_code_save(mp_compiled_module_t *cm, mp_print_t *print); void mp_raw_code_save_file(mp_compiled_module_t *cm, const char *filename); diff --git a/py/profile.c b/py/profile.c index 4e23e9eac4..fd2d61caa9 100644 --- a/py/profile.c +++ b/py/profile.c @@ -172,13 +172,14 @@ STATIC void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_settrace_codeobj = { - { &mp_type_type }, - .name = MP_QSTR_code, - .print = code_print, - .unary_op = mp_generic_unary_op, - .attr = code_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_settrace_codeobj, + MP_QSTR_code, + MP_TYPE_FLAG_NONE, + print, code_print, + unary_op, mp_generic_unary_op, + attr, code_attr + ); mp_obj_t mp_obj_new_code(const mp_module_context_t *context, const mp_raw_code_t *rc) { mp_obj_code_t *o = m_new_obj_maybe(mp_obj_code_t); @@ -241,13 +242,14 @@ STATIC void frame_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_frame = { - { &mp_type_type }, - .name = MP_QSTR_frame, - .print = frame_print, - .unary_op = mp_generic_unary_op, - .attr = frame_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_frame, + MP_QSTR_frame, + MP_TYPE_FLAG_NONE, + print, frame_print, + unary_op, mp_generic_unary_op, + attr, frame_attr + ); mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state) { if (gc_is_locked()) { diff --git a/py/proto.c b/py/proto.c index d70a9d2aac..14fbaeee8d 100644 --- a/py/proto.c +++ b/py/proto.c @@ -28,12 +28,10 @@ #include "py/proto.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - #ifndef MICROPY_UNSAFE_PROTO const void *mp_proto_get(uint16_t name, mp_const_obj_t obj) { const mp_obj_type_t *type = mp_obj_get_type(obj); - const void *protocol = mp_type_get_protocol_slot(type); + const void *protocol = MP_OBJ_TYPE_GET_SLOT_OR_NULL(type, protocol); if (!protocol) { return NULL; } diff --git a/py/proto.h b/py/proto.h index a7b9b523f2..19e75a67fc 100644 --- a/py/proto.h +++ b/py/proto.h @@ -31,7 +31,7 @@ #define MP_PROTOCOL_HEAD /* NOTHING */ #define MP_PROTO_IMPLEMENT(name) /* NOTHING */ static inline void *mp_proto_get(uint16_t name, mp_const_obj_type_t obj) { - return mp_type_get_protocol_slot(mp_obj_get_type(obj)); + return MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(obj), protocol); } #else #define MP_PROTOCOL_HEAD \ diff --git a/py/py.cmake b/py/py.cmake index 6f0514e0e3..d33e8a801f 100644 --- a/py/py.cmake +++ b/py/py.cmake @@ -53,6 +53,7 @@ set(MICROPY_SOURCE_PY ${MICROPY_PY_DIR}/mpz.c ${MICROPY_PY_DIR}/nativeglue.c ${MICROPY_PY_DIR}/nlr.c + ${MICROPY_PY_DIR}/nlrmips.c ${MICROPY_PY_DIR}/nlrpowerpc.c ${MICROPY_PY_DIR}/nlrsetjmp.c ${MICROPY_PY_DIR}/nlrthumb.c diff --git a/py/py.mk b/py/py.mk index 5cbc213414..bf258b678f 100644 --- a/py/py.mk +++ b/py/py.mk @@ -34,33 +34,58 @@ endif ifneq ($(USER_C_MODULES),) # pre-define USERMOD variables as expanded so that variables are immediate # expanded as they're added to them -SRC_USERMOD := + +# C/C++ files that are included in the QSTR/module build +SRC_USERMOD_C := SRC_USERMOD_CXX := +# Other C/C++ files (e.g. libraries or helpers) +SRC_USERMOD_LIB_C := +SRC_USERMOD_LIB_CXX := +# Optionally set flags CFLAGS_USERMOD := CXXFLAGS_USERMOD := LDFLAGS_USERMOD := + +# Backwards compatibility with older user c modules that set SRC_USERMOD +# added to SRC_USERMOD_C below +SRC_USERMOD := + $(foreach module, $(wildcard $(USER_C_MODULES)/*/micropython.mk), \ $(eval USERMOD_DIR = $(patsubst %/,%,$(dir $(module))))\ $(info Including User C Module from $(USERMOD_DIR))\ $(eval include $(module))\ ) -SRC_MOD += $(patsubst $(USER_C_MODULES)/%.c,%.c,$(SRC_USERMOD)) -SRC_MOD_CXX += $(patsubst $(USER_C_MODULES)/%.cpp,%.cpp,$(SRC_USERMOD_CXX)) -CFLAGS_MOD += $(CFLAGS_USERMOD) -CXXFLAGS_MOD += $(CXXFLAGS_USERMOD) -LDFLAGS_MOD += $(LDFLAGS_USERMOD) -endif +SRC_USERMOD_C += $(SRC_USERMOD) +SRC_USERMOD_PATHFIX_C += $(patsubst $(USER_C_MODULES)/%.c,%.c,$(SRC_USERMOD_C)) +SRC_USERMOD_PATHFIX_CXX += $(patsubst $(USER_C_MODULES)/%.cpp,%.cpp,$(SRC_USERMOD_CXX)) +SRC_USERMOD_PATHFIX_LIB_C += $(patsubst $(USER_C_MODULES)/%.c,%.c,$(SRC_USERMOD_LIB_C)) +SRC_USERMOD_PATHFIX_LIB_CXX += $(patsubst $(USER_C_MODULES)/%.cpp,%.cpp,$(SRC_USERMOD_LIB_CXX)) + +CFLAGS += $(CFLAGS_USERMOD) +CXXFLAGS += $(CXXFLAGS_USERMOD) +LDFLAGS += $(LDFLAGS_USERMOD) + +SRC_QSTR += $(SRC_USERMOD_PATHFIX_C) $(SRC_USERMOD_PATHFIX_CXX) +PY_O += $(addprefix $(BUILD)/, $(SRC_USERMOD_PATHFIX_C:.c=.o)) +PY_O += $(addprefix $(BUILD)/, $(SRC_USERMOD_PATHFIX_CXX:.cpp=.o)) +PY_O += $(addprefix $(BUILD)/, $(SRC_USERMOD_PATHFIX_LIB_C:.c=.o)) +PY_O += $(addprefix $(BUILD)/, $(SRC_USERMOD_PATHFIX_LIB_CXX:.cpp=.o)) +endif # USER_C_MODULES + +# CIRCUITPY ifeq ($(CIRCUITPY_ULAB),1) ULAB_SRCS := $(shell find $(TOP)/extmod/ulab/code -type f -name "*.c") -SRC_MOD += $(patsubst $(TOP)/%,%,$(ULAB_SRCS)) +ULAB_SRC_PATHFIX := $(patsubst $(TOP)/%,%,$(ULAB_SRCS)) +SRC_MOD += $(ULAB_SRC_PATHFIX) +SRC_QSTR += $(ULAB_SRC_PATHFIX) CFLAGS_MOD += -DCIRCUITPY_ULAB=1 -DMODULE_ULAB_ENABLED=1 -DULAB_HAS_USER_MODULE=0 -iquote $(TOP)/extmod/ulab/code $(BUILD)/extmod/ulab/code/%.o: CFLAGS += -Wno-missing-declarations -Wno-missing-prototypes -Wno-unused-parameter -Wno-float-equal -Wno-sign-compare -Wno-cast-align -Wno-shadow -DCIRCUITPY ifeq ($(CIRCUITPY_ULAB_OPTIMIZE_SIZE),1) $(BUILD)/extmod/ulab/code/%.o: CFLAGS += -Os -endif -endif +endif # CIRCUITPY_ULAB_OPTIMIZE_SIZE +endif # CIRCUITPY_ULAB # py object files PY_CORE_O_BASENAME = $(addprefix py/,\ @@ -70,6 +95,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ nlrx64.o \ nlrthumb.o \ nlraarch64.o \ + nlrmips.o \ nlrpowerpc.o \ nlrxtensa.o \ nlrsetjmp.o \ @@ -88,6 +114,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ compile.o \ emitcommon.o \ emitbc.o \ + enum.o \ asmbase.o \ asmx64.o \ emitnx64.o \ @@ -105,6 +132,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ formatfloat.o \ parsenumbase.o \ parsenum.o \ + proto.o \ emitglue.o \ persistentcode.o \ runtime.o \ @@ -118,7 +146,6 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ warning.o \ profile.o \ map.o \ - enum.o \ obj.o \ objarray.o \ objattrtuple.o \ @@ -160,7 +187,6 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ objtype.o \ objzip.o \ opmethods.o \ - proto.o \ sequence.o \ stream.o \ binary.o \ @@ -187,37 +213,11 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ frozenmod.o \ ) -PY_EXTMOD_O_BASENAME = \ - extmod/moduasyncio.o \ - extmod/moductypes.o \ - extmod/modujson.o \ - extmod/moduos.o \ - extmod/modure.o \ - extmod/moduzlib.o \ - extmod/moduheapq.o \ - extmod/moduhashlib.o \ - extmod/modubinascii.o \ - extmod/modurandom.o \ - extmod/moduselect.o \ - extmod/vfs.o \ - extmod/vfs_blockdev.o \ - extmod/vfs_reader.o \ - extmod/vfs_posix.o \ - extmod/vfs_posix_file.o \ - extmod/vfs_fat.o \ - extmod/vfs_fat_diskio.o \ - extmod/vfs_fat_file.o \ - extmod/vfs_lfs.o \ - extmod/utime_mphal.o \ - shared/libc/abort_.o \ - shared/libc/printf.o \ - # prepend the build destination prefix to the py object files PY_CORE_O = $(addprefix $(BUILD)/, $(PY_CORE_O_BASENAME)) -PY_EXTMOD_O = $(addprefix $(BUILD)/, $(PY_EXTMOD_O_BASENAME)) # this is a convenience variable for ports that want core, extmod and frozen code -PY_O = $(PY_CORE_O) $(PY_EXTMOD_O) +PY_O += $(PY_CORE_O) # object file for frozen code specified via a manifest ifneq ($(FROZEN_MANIFEST),) @@ -226,14 +226,13 @@ endif # Sources that may contain qstrings SRC_QSTR_IGNORE = py/nlr% -SRC_QSTR += $(SRC_MOD) $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) $(PY_EXTMOD_O_BASENAME:.o=.c) +SRC_QSTR += $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) # Anything that depends on FORCE will be considered out-of-date FORCE: .PHONY: FORCE $(HEADER_BUILD)/mpversion.h: FORCE | $(HEADER_BUILD) - $(STEPECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makeversionhdr.py $@ # mpconfigport.mk is optional, but changes to it may drastically change @@ -255,7 +254,7 @@ $(HEADER_BUILD)/compressed.data.h: $(HEADER_BUILD)/compressed.collected $(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makecompresseddata.py $< > $@ -// CIRCUITPY: for translations +# CIRCUITPY: for translations $(HEADER_BUILD)/$(TRANSLATION).mo: $(TOP)/locale/$(TRANSLATION).po | $(HEADER_BUILD) $(Q)$(PYTHON) $(TOP)/tools/msgfmt.py -o $@ $^ @@ -276,9 +275,14 @@ PY_CORE_O += $(PY_BUILD)/translations-$(TRANSLATION).o # build a list of registered modules for py/objmodule.c. $(HEADER_BUILD)/moduledefs.h: $(HEADER_BUILD)/moduledefs.collected - @$(STEPECHO) "GEN $@" + @$(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makemoduledefs.py $< > $@ +# build a list of registered root pointers for py/mpstate.h. +$(HEADER_BUILD)/root_pointers.h: $(HEADER_BUILD)/root_pointers.collected $(PY_SRC)/make_root_pointers.py + @$(ECHO) "GEN $@" + $(Q)$(PYTHON) $(PY_SRC)/make_root_pointers.py $< > $@ + # Standard C functions like memset need to be compiled with special flags so # the compiler does not optimise these functions in terms of themselves. CFLAGS_BUILTIN ?= -ffreestanding -fno-builtin -fno-lto diff --git a/py/qstr.c b/py/qstr.c index 6b7aead5c8..f7a5e33bfb 100644 --- a/py/qstr.c +++ b/py/qstr.c @@ -33,9 +33,6 @@ #include "py/gc.h" #include "py/runtime.h" -#include "supervisor/linker.h" -#include "supervisor/shared/translate/translate.h" - // NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings) // ultimately we will replace this with a static hash table of some kind @@ -63,9 +60,9 @@ #define MICROPY_ALLOC_QSTR_ENTRIES_INIT (10) // this must match the equivalent function in makeqstrdata.py -mp_uint_t qstr_compute_hash(const byte *data, size_t len) { +size_t qstr_compute_hash(const byte *data, size_t len) { // djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html - mp_uint_t hash = 5381; + size_t hash = 5381; for (const byte *top = data + len; data < top; data++) { hash = ((hash << 5) + hash) ^ (*data); // hash * 33 ^ data } @@ -194,7 +191,7 @@ STATIC qstr qstr_add(mp_uint_t hash, mp_uint_t len, const char *q_ptr) { qstr qstr_find_strn(const char *str, size_t str_len) { // work out hash of str - mp_uint_t str_hash = qstr_compute_hash((const byte *)str, str_len); + size_t str_hash = qstr_compute_hash((const byte *)str, str_len); // search pools for the data for (const qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL; pool = pool->prev) { @@ -267,7 +264,7 @@ qstr qstr_from_strn(const char *str, size_t len) { MP_STATE_VM(qstr_last_used) += n_bytes; // store the interned strings' data - mp_uint_t hash = qstr_compute_hash((const byte *)str, len); + size_t hash = qstr_compute_hash((const byte *)str, len); memcpy(q_ptr, str, len); q_ptr[len] = '\0'; q = qstr_add(hash, len, q_ptr); diff --git a/py/qstr.h b/py/qstr.h index 24e0e756a3..20a6d2f28e 100644 --- a/py/qstr.h +++ b/py/qstr.h @@ -81,7 +81,7 @@ typedef struct _qstr_pool_t { void qstr_reset(void); void qstr_init(void); -mp_uint_t qstr_compute_hash(const byte *data, size_t len); +size_t qstr_compute_hash(const byte *data, size_t len); qstr qstr_find_strn(const char *str, size_t str_len); // returns MP_QSTRnull if not found qstr qstr_from_str(const char *str); @@ -96,7 +96,7 @@ void qstr_pool_info(size_t *n_pool, size_t *n_qstr, size_t *n_str_data_bytes, si void qstr_dump_data(void); #if MICROPY_ROM_TEXT_COMPRESSION -void mp_decompress_rom_string(byte *dst, mp_rom_error_text_t src); +void mp_decompress_rom_string(byte *dst, const mp_rom_error_text_t src); #define MP_IS_COMPRESSED_ROM_STRING(s) (*(byte *)(s) == 0xff) #endif diff --git a/py/reader.c b/py/reader.c index d68406b1c6..57b12b3b65 100644 --- a/py/reader.c +++ b/py/reader.c @@ -139,7 +139,7 @@ void mp_reader_new_file(mp_reader_t *reader, const char *filename) { int fd = open(filename, O_RDONLY, 0644); MP_THREAD_GIL_ENTER(); if (fd < 0) { - mp_raise_OSError(errno); + mp_raise_OSError_with_filename(errno, filename); } mp_reader_new_file_from_fd(reader, fd, true); } diff --git a/py/runtime.c b/py/runtime.c index eaeb9eb0ac..d83e624be1 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -44,10 +44,9 @@ #include "py/runtime.h" #include "py/builtin.h" #include "py/stackctrl.h" +#include "py/stream.h" #include "py/gc.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf @@ -64,6 +63,8 @@ const mp_obj_module_t mp_module___main__ = { MP_REGISTER_MODULE(MP_QSTR___main__, mp_module___main__); +#define TYPE_HAS_ITERNEXT(type) (type->flags & (MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_ITER_IS_CUSTOM | MP_TYPE_FLAG_ITER_IS_STREAM)) + void mp_init(void) { qstr_init(); @@ -89,6 +90,7 @@ void mp_init(void) { #if MICROPY_KBD_EXCEPTION // initialise the exception object for raising KeyboardInterrupt + // CIRCUITPY chained exception support mp_obj_exception_initialize0(&MP_STATE_VM(mp_kbd_exception), &mp_type_KeyboardInterrupt); #endif @@ -133,6 +135,19 @@ void mp_init(void) { sizeof(MP_STATE_VM(fs_user_mount)) - MICROPY_FATFS_NUM_PERSISTENT); #endif + #if MICROPY_PY_OS_DUPTERM + for (size_t i = 0; i < MICROPY_PY_OS_DUPTERM; ++i) { + MP_STATE_VM(dupterm_objs[i]) = MP_OBJ_NULL; + } + #endif + + // CIRCUITPY: do not unmount / + #if MICROPY_VFS && 0 + // initialise the VFS sub-system + MP_STATE_VM(vfs_cur) = NULL; + MP_STATE_VM(vfs_mount_table) = NULL; + #endif + #if MICROPY_PY_SYS_PATH_ARGV_DEFAULTS mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) @@ -307,9 +322,8 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) { return MP_OBJ_NEW_SMALL_INT(h); } else { const mp_obj_type_t *type = mp_obj_get_type(arg); - mp_unary_op_fun_t unary_op = mp_type_get_unary_op_slot(type); - if (unary_op != NULL) { - mp_obj_t result = unary_op(op, arg); + if (MP_OBJ_TYPE_HAS_SLOT(type, unary_op)) { + mp_obj_t result = MP_OBJ_TYPE_GET_SLOT(type, unary_op)(op, arg); if (result != MP_OBJ_NULL) { return result; } @@ -320,6 +334,15 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) { // if arg==mp_const_none. return mp_const_true; } + #if MICROPY_PY_BUILTINS_FLOAT + if (op == MP_UNARY_OP_FLOAT_MAYBE + #if MICROPY_PY_BUILTINS_COMPLEX + || op == MP_UNARY_OP_COMPLEX_MAYBE + #endif + ) { + return MP_OBJ_NULL; + } + #endif // With MP_UNARY_OP_INT, mp_unary_op() becomes a fallback for mp_obj_get_int(). // In this case provide a more focused error message to not confuse, e.g. chr(1.0) #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE @@ -603,9 +626,8 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs const mp_obj_type_t *type; generic_binary_op: type = mp_obj_get_type(lhs); - mp_binary_op_fun_t binary_op = mp_type_get_binary_op_slot(type); - if (binary_op != NULL) { - mp_obj_t result = binary_op(op, lhs, rhs); + if (MP_OBJ_TYPE_HAS_SLOT(type, binary_op)) { + mp_obj_t result = MP_OBJ_TYPE_GET_SLOT(type, binary_op)(op, lhs, rhs); if (result != MP_OBJ_NULL) { return result; } @@ -680,9 +702,8 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, cons const mp_obj_type_t *type = mp_obj_get_type(fun_in); // do the call - mp_call_fun_t call = mp_type_get_call_slot(type); - if (call) { - return call(fun_in, n_args, n_kw, args); + if (MP_OBJ_TYPE_HAS_SLOT(type, call)) { + return MP_OBJ_TYPE_GET_SLOT(type, call)(fun_in, n_args, n_kw, args); } #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE @@ -805,7 +826,7 @@ void PLACE_IN_ITCM(mp_call_prepare_args_n_kw_var)(bool have_self, size_t n_args_ mp_obj_t iterable = mp_getiter(arg, &iter_buf); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - if (args2_len >= args2_alloc) { + if (args2_len + (n_args - i) >= args2_alloc) { args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t), args2_alloc * 2 * sizeof(mp_obj_t)); args2_alloc *= 2; @@ -1064,14 +1085,12 @@ STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c return mp_call_function_n_kw(self->fun, n_args, n_kw, args); } -STATIC const mp_obj_type_t mp_type_checked_fun = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_function, - MP_TYPE_EXTENDED_FIELDS( - .call = checked_fun_call, - ) -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_checked_fun, + MP_QSTR_function, + MP_TYPE_FLAG_BINDS_SELF, + call, checked_fun_call + ); STATIC mp_obj_t mp_obj_new_checked_fun(const mp_obj_type_t *type, mp_obj_t fun) { mp_obj_checked_fun_t *o = mp_obj_malloc(mp_obj_checked_fun_t, &mp_type_checked_fun); @@ -1180,16 +1199,14 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) { } #endif - if (attr == MP_QSTR___next__ && mp_type_get_iternext_slot(type) != NULL) { + if (attr == MP_QSTR___next__ && TYPE_HAS_ITERNEXT(type)) { dest[0] = MP_OBJ_FROM_PTR(&mp_builtin_next_obj); dest[1] = obj; return; } - mp_attr_fun_t attr_fun = mp_type_get_attr_slot(type); - if (attr_fun != NULL) { + if (MP_OBJ_TYPE_HAS_SLOT(type, attr)) { // this type can do its own load, so call it - attr_fun(obj, attr, dest); - + MP_OBJ_TYPE_GET_SLOT(type, attr)(obj, attr, dest); // If type->attr has set dest[1] = MP_OBJ_SENTINEL, we should proceed // with lookups below (i.e. in locals_dict). If not, return right away. if (dest[1] != MP_OBJ_SENTINEL) { @@ -1198,11 +1215,11 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) { // Clear the fail flag set by type->attr so it's like it never ran. dest[1] = MP_OBJ_NULL; } - if (type->locals_dict != NULL) { + if (MP_OBJ_TYPE_HAS_SLOT(type, locals_dict)) { // generic method lookup // this is a lookup in the object (ie not class or type) - assert(type->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now - mp_map_t *locals_map = &type->locals_dict->map; + assert(MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->base.type == &mp_type_dict); // MicroPython restriction, for now + mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->map; mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); if (elem != NULL) { mp_convert_member_lookup(obj, type, elem->value, dest); @@ -1254,20 +1271,19 @@ void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catc void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value); const mp_obj_type_t *type = mp_obj_get_type(base); - mp_attr_fun_t attr_fun = mp_type_get_attr_slot(type); - if (attr_fun != NULL) { + if (MP_OBJ_TYPE_HAS_SLOT(type, attr)) { mp_obj_t dest[2] = {MP_OBJ_SENTINEL, value}; - attr_fun(base, attr, dest); + MP_OBJ_TYPE_GET_SLOT(type, attr)(base, attr, dest); if (dest[0] == MP_OBJ_NULL) { // success return; } #if MICROPY_PY_BUILTINS_PROPERTY - } else if (type->locals_dict != NULL) { + } else if (MP_OBJ_TYPE_HAS_SLOT(type, locals_dict)) { // generic method lookup // this is a lookup in the object (ie not class or type) - assert(type->locals_dict->base.type == &mp_type_dict); // Micro Python restriction, for now - mp_map_t *locals_map = &type->locals_dict->map; + assert(MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->base.type == &mp_type_dict); // Micro Python restriction, for now + mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->map; mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); // If base is MP_OBJ_NULL, we looking at the class itself, not an instance. if (elem != NULL && mp_obj_is_type(elem->value, &mp_type_property) && base != MP_OBJ_NULL) { @@ -1306,20 +1322,26 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { assert(o_in); const mp_obj_type_t *type = mp_obj_get_type(o_in); - mp_getiter_fun_t getiter = mp_type_get_getiter_slot(type); - // Check for native getiter which is the identity. We handle this case explicitly + + // Most types that use iternext just use the identity getiter. We handle this case explicitly // so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used. - if (getiter == mp_identity_getiter) { + if ((type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) == MP_TYPE_FLAG_ITER_IS_ITERNEXT || (type->flags & MP_TYPE_FLAG_ITER_IS_STREAM) == MP_TYPE_FLAG_ITER_IS_STREAM) { return o_in; } - // check for native getiter (corresponds to __iter__) - if (getiter != NULL) { - if (iter_buf == NULL && getiter != mp_obj_instance_getiter) { + if (MP_OBJ_TYPE_HAS_SLOT(type, iter)) { + // check for native getiter (corresponds to __iter__) + if (iter_buf == NULL && MP_OBJ_TYPE_GET_SLOT(type, iter) != mp_obj_instance_getiter) { // if caller did not provide a buffer then allocate one on the heap // mp_obj_instance_getiter is special, it will allocate only if needed iter_buf = m_new_obj(mp_obj_iter_buf_t); } + mp_getiter_fun_t getiter; + if (type->flags & MP_TYPE_FLAG_ITER_IS_CUSTOM) { + getiter = ((mp_getiter_iternext_custom_t *)MP_OBJ_TYPE_GET_SLOT(type, iter))->getiter; + } else { + getiter = (mp_getiter_fun_t)MP_OBJ_TYPE_GET_SLOT(type, iter); + } mp_obj_t iter = getiter(o_in, iter_buf); if (iter != MP_OBJ_NULL) { return iter; @@ -1345,16 +1367,28 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { mp_raise_TypeError_varg( MP_ERROR_TEXT("'%q' object is not iterable"), mp_obj_get_type_qstr(o_in)); #endif + +} + +STATIC mp_fun_1_t type_get_iternext(const mp_obj_type_t *type) { + if ((type->flags & MP_TYPE_FLAG_ITER_IS_STREAM) == MP_TYPE_FLAG_ITER_IS_STREAM) { + return mp_stream_unbuffered_iter; + } else if (type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) { + return (mp_fun_1_t)MP_OBJ_TYPE_GET_SLOT(type, iter); + } else if (type->flags & MP_TYPE_FLAG_ITER_IS_CUSTOM) { + return ((mp_getiter_iternext_custom_t *)MP_OBJ_TYPE_GET_SLOT(type, iter))->iternext; + } else { + return NULL; + } } // may return MP_OBJ_STOP_ITERATION as an optimisation instead of raise StopIteration() // may also raise StopIteration() mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { const mp_obj_type_t *type = mp_obj_get_type(o_in); - mp_fun_1_t iternext = mp_type_get_iternext_slot(type); - if (iternext != NULL) { + if (TYPE_HAS_ITERNEXT(type)) { MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL; - return iternext(o_in); + return type_get_iternext(type)(o_in); } else { // check for __next__ method mp_obj_t dest[2]; @@ -1378,10 +1412,9 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { mp_obj_t mp_iternext(mp_obj_t o_in) { MP_STACK_CHECK(); // enumerate, filter, map and zip can recursively call mp_iternext const mp_obj_type_t *type = mp_obj_get_type(o_in); - mp_fun_1_t iternext = mp_type_get_iternext_slot(type); - if (iternext != NULL) { + if (TYPE_HAS_ITERNEXT(type)) { MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL; - return iternext(o_in); + return type_get_iternext(type)(o_in); } else { // check for __next__ method mp_obj_t dest[2]; @@ -1424,10 +1457,9 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th return mp_obj_gen_resume(self_in, send_value, throw_value, ret_val); } - mp_fun_1_t iternext = mp_type_get_iternext_slot(type); - if (iternext != NULL && send_value == mp_const_none) { + if (TYPE_HAS_ITERNEXT(type) && send_value == mp_const_none) { MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL; - mp_obj_t ret = iternext(self_in); + mp_obj_t ret = type_get_iternext(type)(self_in); *ret_val = ret; if (ret != MP_OBJ_STOP_ITERATION) { return MP_VM_RETURN_YIELD; @@ -1551,7 +1583,8 @@ mp_obj_t __attribute__((noinline, )) mp_import_from(mp_obj_t module, qstr name) if (dest[1] != MP_OBJ_NULL) { // Hopefully we can't import bound method from an object - mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("cannot import name %q"), name); + import_error: + mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("can't import name %q"), name); } if (dest[0] != MP_OBJ_NULL) { @@ -1562,7 +1595,7 @@ mp_obj_t __attribute__((noinline, )) mp_import_from(mp_obj_t module, qstr name) // See if it's a package, then can try FS import if (!mp_obj_is_package(module)) { - mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("cannot import name %q"), name); + goto import_error; } mp_load_method_maybe(module, MP_QSTR___name__, dest); @@ -1583,12 +1616,12 @@ mp_obj_t __attribute__((noinline, )) mp_import_from(mp_obj_t module, qstr name) #else // Package import not supported with external imports disabled - mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("cannot import name %q"), name); + goto import_error; #endif } -void __attribute__((noinline)) mp_import_all(mp_obj_t module) { +void mp_import_all(mp_obj_t module) { DEBUG_printf("import all %p\n", module); // TODO: Support __all__ @@ -1703,7 +1736,7 @@ NORETURN MP_COLD void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char if (msg == NULL) { nlr_raise(mp_obj_new_exception(exc_type)); } else { - nlr_raise(mp_obj_new_exception_msg_str(exc_type, msg)); + nlr_raise(mp_obj_new_exception_msg_varg(exc_type, MP_ERROR_TEXT("%s"), msg)); } } @@ -1822,14 +1855,21 @@ NORETURN MP_COLD void mp_raise_OSError(int errno_) { mp_raise_type_arg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno_)); } -#endif +NORETURN MP_COLD void mp_raise_OSError_with_filename(int errno_, const char *filename) { + vstr_t vstr; + vstr_init(&vstr, 32); + vstr_printf(&vstr, "can't open %s", filename); + mp_obj_t o_str = mp_obj_new_str_from_vstr(&vstr); + mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(errno_), MP_OBJ_FROM_PTR(o_str)}; + nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args)); +} +NORETURN MP_COLD void mp_raise_ZeroDivisionError(void) { + mp_raise_msg(&mp_type_ZeroDivisionError, MP_ERROR_TEXT("division by zero")); +} #if MICROPY_STACK_CHECK || MICROPY_ENABLE_PYSTACK NORETURN MP_COLD void mp_raise_recursion_depth(void) { mp_raise_RuntimeError(MP_ERROR_TEXT("maximum recursion depth exceeded")); } #endif - -NORETURN MP_COLD void mp_raise_ZeroDivisionError(void) { - mp_raise_msg(&mp_type_ZeroDivisionError, MP_ERROR_TEXT("division by zero")); -} +#endif diff --git a/py/runtime.h b/py/runtime.h index 5ecab91e99..770e892de7 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -32,7 +32,6 @@ #include "py/pystack.h" #include "supervisor/linker.h" - #include "supervisor/shared/translate/translate.h" typedef enum { @@ -96,14 +95,12 @@ bool mp_sched_schedule_node(mp_sched_node_t *node, mp_sched_callback_t callback) int 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); void mp_arg_check_num_sig(size_t n_args, size_t n_kw, uint32_t sig); -static MP_INLINE void 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) { +static inline void 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) { mp_arg_check_num_sig(n_args, n_kw, MP_OBJ_FUN_MAKE_SIG(n_args_min, n_args_max, takes_kw)); } void 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); void 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); -#if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE NORETURN void mp_arg_error_terse_mismatch(void); -#endif NORETURN void mp_arg_error_unimpl_kw(void); NORETURN void mp_arg_error_invalid(qstr arg_name); @@ -128,16 +125,16 @@ mp_obj_t mp_arg_validate_type_or_none(mp_obj_t obj, const mp_obj_type_t *type, q mp_int_t mp_arg_validate_type_int(mp_obj_t obj, qstr arg_name); mp_obj_t mp_arg_validate_type_string(mp_obj_t obj, qstr arg_name); -static MP_INLINE mp_obj_dict_t *mp_locals_get(void) { +static inline mp_obj_dict_t *mp_locals_get(void) { return MP_STATE_THREAD(dict_locals); } -static MP_INLINE void mp_locals_set(mp_obj_dict_t *d) { +static inline void mp_locals_set(mp_obj_dict_t *d) { MP_STATE_THREAD(dict_locals) = d; } -static MP_INLINE mp_obj_dict_t *mp_globals_get(void) { +static inline mp_obj_dict_t *mp_globals_get(void) { return MP_STATE_THREAD(dict_globals); } -static MP_INLINE void mp_globals_set(mp_obj_dict_t *d) { +static inline void mp_globals_set(mp_obj_dict_t *d) { MP_STATE_THREAD(dict_globals) = d; } @@ -194,7 +191,7 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o); // may return MP_OBJ_STOP_ITERATIO mp_obj_t mp_iternext(mp_obj_t o); // will always return MP_OBJ_STOP_ITERATION instead of raising StopIteration(...) mp_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); -static MP_INLINE mp_obj_t mp_make_stop_iteration(mp_obj_t o) { +static inline mp_obj_t mp_make_stop_iteration(mp_obj_t o) { MP_STATE_THREAD(stop_iteration_arg) = o; return MP_OBJ_STOP_ITERATION; } @@ -217,35 +214,44 @@ NORETURN void mp_raise_NotImplementedError_no_msg(void); #define mp_raise_NotImplementedError(msg) mp_raise_NotImplementedError_no_msg() #else #define mp_raise_type(exc_type) mp_raise_msg(exc_type, NULL) -NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg); NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const compressed_string_t *msg); NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, ...); +NORETURN void mp_raise_ValueError(const compressed_string_t *msg); +NORETURN void mp_raise_TypeError(const compressed_string_t *msg); +NORETURN void mp_raise_NotImplementedError(const compressed_string_t *msg); +#endif + +NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg); +NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const compressed_string_t *msg); +NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, const compressed_string_t *fmt + , ...); NORETURN void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, va_list argptr); // Only use this string version in native mpy files. Otherwise, use the compressed string version. NORETURN void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char *msg); -NORETURN void mp_raise_ValueError(const compressed_string_t *msg); -NORETURN void mp_raise_ValueError_varg(const compressed_string_t *fmt, ...); -NORETURN void mp_raise_TypeError(const compressed_string_t *msg); -NORETURN void mp_raise_TypeError_varg(const compressed_string_t *fmt, ...); + NORETURN void mp_raise_AttributeError(const compressed_string_t *msg); -NORETURN void mp_raise_RuntimeError(const compressed_string_t *msg); -NORETURN void mp_raise_RuntimeError_varg(const compressed_string_t *fmt, ...); +NORETURN void mp_raise_BrokenPipeError(void); +NORETURN void mp_raise_ConnectionError(const compressed_string_t *msg); NORETURN void mp_raise_ImportError(const compressed_string_t *msg); NORETURN void mp_raise_IndexError(const compressed_string_t *msg); NORETURN void mp_raise_IndexError_varg(const compressed_string_t *msg, ...); -NORETURN void mp_raise_StopIteration(mp_obj_t arg); -NORETURN void mp_raise_OSError(int errno_); -NORETURN void mp_raise_OSError_errno_str(int errno_, mp_obj_t str); -NORETURN void mp_raise_OSError_msg(const compressed_string_t *msg); -NORETURN void mp_raise_OSError_msg_varg(const compressed_string_t *fmt, ...); -NORETURN void mp_raise_ConnectionError(const compressed_string_t *msg); -NORETURN void mp_raise_BrokenPipeError(void); NORETURN void mp_raise_NotImplementedError(const compressed_string_t *msg); NORETURN void mp_raise_NotImplementedError_varg(const compressed_string_t *fmt, ...); +NORETURN void mp_raise_OSError_errno_str(int errno_, mp_obj_t str); +NORETURN void mp_raise_OSError(int errno_); +NORETURN void mp_raise_OSError_msg(const compressed_string_t *msg); +NORETURN void mp_raise_OSError_msg_varg(const compressed_string_t *fmt, ...); +NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename); NORETURN void mp_raise_OverflowError_varg(const compressed_string_t *fmt, ...); NORETURN void mp_raise_recursion_depth(void); +NORETURN void mp_raise_RuntimeError(const compressed_string_t *msg); +NORETURN void mp_raise_RuntimeError_varg(const compressed_string_t *fmt, ...); +NORETURN void mp_raise_StopIteration(mp_obj_t arg); +NORETURN void mp_raise_TypeError(const compressed_string_t *msg); +NORETURN void mp_raise_TypeError_varg(const compressed_string_t *fmt, ...); +NORETURN void mp_raise_ValueError(const compressed_string_t *msg); +NORETURN void mp_raise_ValueError_varg(const compressed_string_t *fmt, ...); NORETURN void mp_raise_ZeroDivisionError(void); -#endif #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG #undef mp_check_self diff --git a/py/runtime0.h b/py/runtime0.h index 218820fd70..994c7d9324 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -79,6 +79,8 @@ typedef enum { MP_UNARY_OP_HASH, // __hash__; must return a small int MP_UNARY_OP_ABS, // __abs__ MP_UNARY_OP_INT, // __int__ + MP_UNARY_OP_FLOAT_MAYBE, // __float__ + MP_UNARY_OP_COMPLEX_MAYBE, // __complex__ MP_UNARY_OP_SIZEOF, // for sys.getsizeof() } mp_unary_op_t; diff --git a/py/scheduler.c b/py/scheduler.c index 2aa28bd335..41001d6af9 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -32,7 +32,11 @@ // sources such as interrupts and UNIX signal handlers). void MICROPY_WRAP_MP_SCHED_EXCEPTION(mp_sched_exception)(mp_obj_t exc) { MP_STATE_MAIN_THREAD(mp_pending_exception) = exc; - #if MICROPY_ENABLE_SCHEDULER + + #if MICROPY_ENABLE_SCHEDULER && !MICROPY_PY_THREAD + // Optimisation for the case where we have scheduler but no threading. + // Allows the VM to do a single check to exclude both pending exception + // and queued tasks. if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; } @@ -47,6 +51,12 @@ void MICROPY_WRAP_MP_SCHED_KEYBOARD_INTERRUPT(mp_sched_keyboard_interrupt)(void) } #endif +#if MICROPY_ENABLE_VM_ABORT +void MICROPY_WRAP_MP_SCHED_VM_ABORT(mp_sched_vm_abort)(void) { + MP_STATE_VM(vm_abort) = true; +} +#endif + #if MICROPY_ENABLE_SCHEDULER #define IDX_MASK(i) ((i) & (MICROPY_SCHEDULER_DEPTH - 1)) @@ -62,33 +72,17 @@ static inline bool mp_sched_empty(void) { return mp_sched_num_pending() == 0; } -// A variant of this is inlined in the VM at the pending exception check -void mp_handle_pending(bool raise_exc) { - if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { - mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); - // Re-check state is still pending now that we're in the atomic section. - if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { - mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception); - if (obj != MP_OBJ_NULL) { - MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; - if (!mp_sched_num_pending()) { - MP_STATE_VM(sched_state) = MP_SCHED_IDLE; - } - if (raise_exc) { - MICROPY_END_ATOMIC_SECTION(atomic_state); - nlr_raise(obj); - } - } - mp_handle_pending_tail(atomic_state); - } else { - MICROPY_END_ATOMIC_SECTION(atomic_state); - } +static inline void mp_sched_run_pending(void) { + mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + if (MP_STATE_VM(sched_state) != MP_SCHED_PENDING) { + // Something else (e.g. hard IRQ) locked the scheduler while we + // acquired the lock. + MICROPY_END_ATOMIC_SECTION(atomic_state); + return; } -} -// This function should only be called by mp_handle_pending, -// or by the VM's inlined version of that function. -void mp_handle_pending_tail(mp_uint_t atomic_state) { + // Equivalent to mp_sched_lock(), but we're already in the atomic + // section and know that we're pending. MP_STATE_VM(sched_state) = MP_SCHED_LOCKED; #if MICROPY_SCHEDULER_STATIC_NODES @@ -118,14 +112,21 @@ void mp_handle_pending_tail(mp_uint_t atomic_state) { MICROPY_END_ATOMIC_SECTION(atomic_state); } + // Restore MP_STATE_VM(sched_state) to idle (or pending if there are still + // tasks in the queue). mp_sched_unlock(); } +// Locking the scheduler prevents tasks from executing (does not prevent new +// tasks from being added). We lock the scheduler while executing scheduled +// tasks and also in hard interrupts or GC finalisers. void mp_sched_lock(void) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); if (MP_STATE_VM(sched_state) < 0) { + // Already locked, increment lock (recursive lock). --MP_STATE_VM(sched_state); } else { + // Pending or idle. MP_STATE_VM(sched_state) = MP_SCHED_LOCKED; } MICROPY_END_ATOMIC_SECTION(atomic_state); @@ -135,12 +136,17 @@ void mp_sched_unlock(void) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); assert(MP_STATE_VM(sched_state) < 0); if (++MP_STATE_VM(sched_state) == 0) { - // vm became unlocked - if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL - #if MICROPY_SCHEDULER_STATIC_NODES - || MP_STATE_VM(sched_head) != NULL + // Scheduler became unlocked. Check if there are still tasks in the + // queue and set sched_state accordingly. + if ( + #if !MICROPY_PY_THREAD + // See optimisation in mp_sched_exception. + MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL || #endif - || mp_sched_num_pending()) { + #if MICROPY_SCHEDULER_STATIC_NODES + MP_STATE_VM(sched_head) != NULL || + #endif + mp_sched_num_pending()) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; } else { MP_STATE_VM(sched_state) = MP_SCHED_IDLE; @@ -196,17 +202,41 @@ bool mp_sched_schedule_node(mp_sched_node_t *node, mp_sched_callback_t callback) } #endif -#else // MICROPY_ENABLE_SCHEDULER - -// A variant of this is inlined in the VM at the pending exception check -void mp_handle_pending(bool raise_exc) { - if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) { - mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception); - MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; - if (raise_exc) { - nlr_raise(obj); - } - } -} +MP_REGISTER_ROOT_POINTER(mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH]); #endif // MICROPY_ENABLE_SCHEDULER + +// Called periodically from the VM or from "waiting" code (e.g. sleep) to +// process background tasks and pending exceptions (e.g. KeyboardInterrupt). +void mp_handle_pending(bool raise_exc) { + // Handle pending VM abort. + #if MICROPY_ENABLE_VM_ABORT + if (MP_STATE_VM(vm_abort) && mp_thread_is_main_thread()) { + MP_STATE_VM(vm_abort) = false; + if (raise_exc && nlr_get_abort() != NULL) { + nlr_jump_abort(); + } + } + #endif + + // Handle any pending exception. + if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) { + mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception); + if (obj != MP_OBJ_NULL) { + MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; + if (raise_exc) { + MICROPY_END_ATOMIC_SECTION(atomic_state); + nlr_raise(obj); + } + } + MICROPY_END_ATOMIC_SECTION(atomic_state); + } + + // Handle any pending callbacks. + #if MICROPY_ENABLE_SCHEDULER + if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { + mp_sched_run_pending(); + } + #endif +} diff --git a/py/sequence.c b/py/sequence.c index faed558723..2d42e1c6c4 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -28,7 +28,6 @@ #include #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" // Helpers for sequence types diff --git a/py/stream.c b/py/stream.c index a008e2f969..6dd8f90970 100644 --- a/py/stream.c +++ b/py/stream.c @@ -31,8 +31,6 @@ #include "py/objstr.h" #include "py/stream.h" #include "py/runtime.h" -#include "py/unicode.h" -#include "supervisor/shared/translate/translate.h" // This file defines generic Python stream read/write methods which // dispatch to the underlying stream interface of an object. @@ -42,15 +40,6 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in); -#define STREAM_CONTENT_TYPE(stream) (((stream)->is_text) ? &mp_type_str : &mp_type_bytes) - -static mp_obj_t mp_obj_new_str_from_vstr_check(const mp_obj_type_t *type, vstr_t *vstr) { - if (type == &mp_type_str && !utf8_check((void *)vstr->buf, vstr->len)) { - mp_raise_msg(&mp_type_UnicodeError, NULL); - } - return mp_obj_new_str_from_vstr(type, vstr); -} - // Returns error condition in *errcode, if non-zero, return value is number of bytes written // before error condition occurred. If *errcode == 0, returns total bytes written (which will // be equal to input size). @@ -93,41 +82,31 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode return done; } -const mp_stream_p_t *mp_get_stream(mp_const_obj_t self) { - return mp_proto_get(MP_QSTR_protocol_stream, self); -} - const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { - const mp_stream_p_t *stream_p = mp_proto_get(MP_QSTR_protocol_stream, self_in); - if (stream_p == NULL - || ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL) - || ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) - || ((flags & MP_STREAM_OP_IOCTL) && stream_p->ioctl == NULL)) { - // CPython: io.UnsupportedOperation, OSError subclass - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("stream operation not supported")); + const mp_obj_type_t *type = mp_obj_get_type(self_in); + if (MP_OBJ_TYPE_HAS_SLOT(type, protocol)) { + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(type, protocol); + if (!((flags & MP_STREAM_OP_READ) && stream_p->read == NULL) + && !((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) + && !((flags & MP_STREAM_OP_IOCTL) && stream_p->ioctl == NULL)) { + return stream_p; + } } - return stream_p; + // CPython: io.UnsupportedOperation, OSError subclass + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("stream operation not supported")); } STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte flags) { // What to do if sz < -1? Python docs don't specify this case. - // CPython does a readall, let's do the same. + // CPython does a readall, but here we silently let negatives through, + // and they will cause a MemoryError. mp_int_t sz; - const mp_stream_p_t *stream_p = mp_get_stream(args[0]); - if (stream_p->pyserial_read_compatibility) { - // Pyserial defaults to sz=1 if not specified. - if (n_args == 1) { - sz = 1; - } else { - // Pyserial treats negative size as 0. - sz = MAX(0, mp_obj_get_int(args[1])); - } - } else { - if (n_args == 1 || args[1] == mp_const_none || (sz = mp_obj_get_int(args[1])) <= -1) { - return stream_readall(args[0]); - } + if (n_args == 1 || ((sz = mp_obj_get_int(args[1])) == -1)) { + return stream_readall(args[0]); } + const mp_stream_p_t *stream_p = mp_get_stream(args[0]); + #if MICROPY_PY_BUILTINS_STR_UNICODE if (stream_p->is_text) { // We need to read sz number of unicode characters. Because we don't have any @@ -209,7 +188,8 @@ STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte fl } } } - return mp_obj_new_str_from_vstr_check(&mp_type_str, &vstr); + + return mp_obj_new_str_from_vstr(&vstr); } #endif @@ -230,7 +210,11 @@ STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte fl mp_raise_OSError(error); } else { vstr.len = out_sz; - return mp_obj_new_str_from_vstr_check(STREAM_CONTENT_TYPE(stream_p), &vstr); + if (stream_p->is_text) { + return mp_obj_new_str_from_vstr(&vstr); + } else { + return mp_obj_new_bytes_from_vstr(&vstr); + } } } @@ -268,9 +252,6 @@ void mp_stream_write_adaptor(void *self, const char *buf, size_t len) { STATIC mp_obj_t stream_write_method(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); - if (!mp_get_stream(args[0])->is_text && mp_obj_is_str(args[1])) { - mp_raise_ValueError(MP_ERROR_TEXT("string not supported; use bytes or bytearray")); - } size_t max_len = (size_t)-1; size_t off = 0; if (n_args == 3) { @@ -303,9 +284,6 @@ STATIC mp_obj_t stream_readinto(size_t n_args, const mp_obj_t *args) { // https://docs.python.org/3/library/socket.html#socket.socket.recv_into mp_uint_t len = bufinfo.len; if (n_args > 2) { - if (mp_get_stream(args[0])->pyserial_readinto_compatibility) { - mp_raise_ValueError(MP_ERROR_TEXT("length argument not allowed for this type")); - } len = mp_obj_get_int(args[2]); if (len > bufinfo.len) { len = bufinfo.len; @@ -316,10 +294,7 @@ STATIC mp_obj_t stream_readinto(size_t n_args, const mp_obj_t *args) { mp_uint_t out_sz = mp_stream_read_exactly(args[0], bufinfo.buf, len, &error); if (error != 0) { if (mp_is_nonblocking_error(error)) { - // pyserial readinto never returns None, just 0. - return mp_get_stream(args[0])->pyserial_dont_return_none_compatibility - ? MP_OBJ_NEW_SMALL_INT(0) - : mp_const_none; + return mp_const_none; } mp_raise_OSError(error); } else { @@ -345,10 +320,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) { // If we read nothing, return None, just like read(). // Otherwise, return data read so far. if (total_size == 0) { - // pyserial read() never returns None, just b''. - return stream_p->pyserial_dont_return_none_compatibility - ? mp_const_empty_bytes - : mp_const_none; + return mp_const_none; } break; } @@ -365,13 +337,14 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) { p = vstr_extend(&vstr, DEFAULT_BUFFER_SIZE); current_read = DEFAULT_BUFFER_SIZE; } - #ifdef RUN_BACKGROUND_TASKS - RUN_BACKGROUND_TASKS; - #endif } vstr.len = total_size; - return mp_obj_new_str_from_vstr_check(STREAM_CONTENT_TYPE(stream_p), &vstr); + if (stream_p->is_text) { + return mp_obj_new_str_from_vstr(&vstr); + } else { + return mp_obj_new_bytes_from_vstr(&vstr); + } } // Unbuffered, inefficient implementation of readline() for raw I/O files. @@ -424,7 +397,11 @@ STATIC mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args) } } - return mp_obj_new_str_from_vstr_check(STREAM_CONTENT_TYPE(stream_p), &vstr); + if (stream_p->is_text) { + return mp_obj_new_str_from_vstr(&vstr); + } else { + return mp_obj_new_bytes_from_vstr(&vstr); + } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj, 1, 2, stream_unbuffered_readline); @@ -498,9 +475,6 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_tell_obj, stream_tell); mp_obj_t mp_stream_flush(mp_obj_t self) { const mp_stream_p_t *stream_p = mp_get_stream(self); int error; - if (stream_p->ioctl == NULL) { - mp_raise_OSError(MP_EINVAL); - } mp_uint_t res = stream_p->ioctl(self, MP_STREAM_FLUSH, 0, &error); if (res == MP_STREAM_ERROR) { mp_raise_OSError(error); @@ -542,10 +516,10 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj, 2, 3, stream_ioctl); #include -ssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len) { - mp_obj_base_t *o = (mp_obj_base_t *)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = mp_get_stream(o); - mp_uint_t out_sz = stream_p->write(stream, buf, len, &errno); +ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) { + mp_obj_base_t *o = stream; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); + mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &errno); if (out_sz == MP_STREAM_ERROR) { return -1; } else { @@ -553,10 +527,10 @@ ssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len) { } } -ssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len) { - mp_obj_base_t *o = (mp_obj_base_t *)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = mp_get_stream(o); - mp_uint_t out_sz = stream_p->read(stream, buf, len, &errno); +ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) { + mp_obj_base_t *o = stream; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); + mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &errno); if (out_sz == MP_STREAM_ERROR) { return -1; } else { @@ -564,9 +538,9 @@ ssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len) { } } -off_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence) { - const mp_obj_base_t *o = (mp_obj_base_t *)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = mp_get_stream(o); +off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) { + const mp_obj_base_t *o = stream; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); struct mp_stream_seek_t seek_s; seek_s.offset = offset; seek_s.whence = whence; @@ -577,10 +551,10 @@ off_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence) { return seek_s.offset; } -int mp_stream_posix_fsync(mp_obj_t stream) { - mp_obj_base_t *o = (mp_obj_base_t *)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = mp_get_stream(o); - mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_FLUSH, 0, &errno); +int mp_stream_posix_fsync(void *stream) { + mp_obj_base_t *o = stream; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); + mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &errno); if (res == MP_STREAM_ERROR) { return -1; } diff --git a/py/stream.h b/py/stream.h index e9e8770127..e776d8d5d1 100644 --- a/py/stream.h +++ b/py/stream.h @@ -99,7 +99,9 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj); #define MP_STREAM_OP_IOCTL (4) // Object is assumed to have a non-NULL stream protocol with valid r/w/ioctl methods -const mp_stream_p_t *mp_get_stream(mp_const_obj_t self); +static inline const mp_stream_p_t *mp_get_stream(mp_const_obj_t self) { + return (const mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(((const mp_obj_base_t *)MP_OBJ_TO_PTR(self))->type, protocol); +} const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags); mp_obj_t mp_stream_close(mp_obj_t stream); @@ -118,7 +120,7 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf, mp_uint_t size, int *errcode, #define mp_stream_read_exactly(stream, buf, size, err) mp_stream_rw(stream, buf, size, err, MP_STREAM_RW_READ) void mp_stream_write_adaptor(void *self, const char *buf, size_t len); -mp_obj_t mp_stream_flush(mp_obj_t self); +mp_obj_t mp_stream_flush(mp_obj_t self); // CIRCUITPY #if MICROPY_STREAMS_POSIX_API #include diff --git a/py/vm.c b/py/vm.c index 7f1ea1ee4b..0e6c1c249d 100644 --- a/py/vm.c +++ b/py/vm.c @@ -36,9 +36,6 @@ #include "py/bc0.h" #include "py/profile.h" -#include "supervisor/linker.h" -#include "supervisor/shared/translate/translate.h" - // *FORMAT-OFF* #if 0 @@ -214,13 +211,28 @@ STATIC mp_obj_t get_active_exception(mp_exc_stack_t *exc_sp, mp_exc_stack_t *exc // MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp // MP_VM_RETURN_EXCEPTION, exception in state[0] mp_vm_return_kind_t MICROPY_WRAP_MP_EXECUTE_BYTECODE(mp_execute_bytecode)(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) { + #define SELECTIVE_EXC_IP (0) +// When disabled, code_state->ip is updated unconditionally during op +// dispatch, and this is subsequently used in the exception handler +// (either NLR jump or direct RAISE). This is good for code size because it +// happens in a single place but is more work than necessary, as many opcodes +// cannot raise. Enabling SELECTIVE_EXC_IP means that code_state->ip +// is "selectively" updated only during handling of opcodes that might raise. +// This costs about 360 bytes on PYBV11 for a 1-3% performance gain (e.g. 3% +// in bm_fft.py). On rp2040, there is zero code size diff for a 0-1% gain. +// (Both with computed goto enabled). #if SELECTIVE_EXC_IP -#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */ +// Note: Because ip has already been advanced by one byte in the dispatch, the +// value of ip here is one byte past the last opcode. +#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } +// No need to update in dispatch. #define MARK_EXC_IP_GLOBAL() #else #define MARK_EXC_IP_SELECTIVE() -#define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } /* stores ip pointing to last opcode */ +// Immediately before dispatch, save the current ip, which will be the opcode +// about to be dispatched. +#define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } #endif #if MICROPY_OPT_COMPUTED_GOTO #include "py/vmentrytable.h" @@ -313,14 +325,14 @@ outer_dispatch_loop: // loop to execute byte code for (;;) { dispatch_loop: -#if MICROPY_OPT_COMPUTED_GOTO + #if MICROPY_OPT_COMPUTED_GOTO ONE_TRUE_DISPATCH(); -#else + #else TRACE(ip); MARK_EXC_IP_GLOBAL(); TRACE_TICK(ip, sp, false); switch (*ip++) { -#endif + #endif ENTRY(MP_BC_LOAD_CONST_FALSE): PUSH(mp_const_false); @@ -680,7 +692,7 @@ unwind_jump:; assert(exc_sp >= exc_stack); if (MP_TAGPTR_TAG1(exc_sp->val_sp)) { - if (exc_sp->handler > ip) { + if (exc_sp->handler >= ip) { // Found a finally handler that isn't active; run it. // Getting here the stack looks like: // (..., X, dest_ip) @@ -797,7 +809,7 @@ unwind_jump:; } #endif } - DISPATCH_WITH_PEND_EXC_CHECK(); + DISPATCH(); } ENTRY(MP_BC_POP_EXCEPT_JUMP): { @@ -837,7 +849,7 @@ unwind_jump:; mp_obj_dict_store(sp[0], sp[2], sp[1]); DISPATCH(); -#if MICROPY_PY_BUILTINS_SET + #if MICROPY_PY_BUILTINS_SET ENTRY(MP_BC_BUILD_SET): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; @@ -845,9 +857,9 @@ unwind_jump:; SET_TOP(mp_obj_new_set(unum, sp)); DISPATCH(); } -#endif + #endif -#if MICROPY_PY_BUILTINS_SLICE + #if MICROPY_PY_BUILTINS_SLICE ENTRY(MP_BC_BUILD_SLICE): { MARK_EXC_IP_SELECTIVE(); mp_obj_t step = mp_const_none; @@ -860,7 +872,7 @@ unwind_jump:; SET_TOP(mp_obj_new_slice(start, stop, step)); DISPATCH(); } -#endif + #endif ENTRY(MP_BC_STORE_COMP): { MARK_EXC_IP_SELECTIVE(); @@ -1046,6 +1058,7 @@ unwind_jump:; } #endif SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp)); + // CIRCUITPY DISPATCH_WITH_PEND_EXC_CHECK(); } @@ -1101,7 +1114,7 @@ unwind_return: // Search for and execute finally handlers that aren't already active while (exc_sp >= exc_stack) { if (MP_TAGPTR_TAG1(exc_sp->val_sp)) { - if (exc_sp->handler > ip) { + if (exc_sp->handler >= ip) { // Found a finally handler that isn't active; run it. // Getting here the stack looks like: // (..., X, [iter0, iter1, ...,] ret_val) @@ -1204,9 +1217,6 @@ yield: ENTRY(MP_BC_YIELD_FROM): { MARK_EXC_IP_SELECTIVE(); -//#define EXC_MATCH(exc, type) mp_obj_is_type(exc, type) -#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type) -#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { mp_obj_t raise_t = mp_make_raise_obj(t); RAISE(raise_t); } mp_vm_return_kind_t ret_kind; mp_obj_t send_value = POP(); mp_obj_t t_exc = MP_OBJ_NULL; @@ -1230,11 +1240,14 @@ yield: SET_TOP(ret_value); // If we injected GeneratorExit downstream, then even // if it was swallowed, we re-raise GeneratorExit - GENERATOR_EXIT_IF_NEEDED(t_exc); + if (t_exc != MP_OBJ_NULL && mp_obj_exception_match(t_exc, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { + mp_obj_t raise_t = mp_make_raise_obj(t_exc); + RAISE(raise_t); + } DISPATCH(); } else { assert(ret_kind == MP_VM_RETURN_EXCEPTION); - assert(!EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))); + assert(!mp_obj_exception_match(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))); // Pop exhausted gen sp--; RAISE(ret_value); @@ -1264,7 +1277,7 @@ yield: mp_import_all(POP()); DISPATCH(); -#if MICROPY_OPT_COMPUTED_GOTO + #if MICROPY_OPT_COMPUTED_GOTO ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI): PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS)); DISPATCH(); @@ -1292,7 +1305,7 @@ yield: ENTRY_DEFAULT: MARK_EXC_IP_SELECTIVE(); -#else + #else ENTRY_DEFAULT: if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + MP_BC_LOAD_CONST_SMALL_INT_MULTI_NUM) { PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS)); @@ -1312,9 +1325,8 @@ yield: SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs)); DISPATCH(); } else -#endif + #endif // MICROPY_OPT_COMPUTED_GOTO { - mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, MP_ERROR_TEXT("opcode")); nlr_pop(); code_state->state[0] = obj; @@ -1322,46 +1334,46 @@ yield: return MP_VM_RETURN_EXCEPTION; } -#if !MICROPY_OPT_COMPUTED_GOTO - } // switch -#endif + #if !MICROPY_OPT_COMPUTED_GOTO + } // switch + #endif pending_exception_check: + // We've just done a branch, use this as a convenient point to + // run periodic code/checks and/or bounce the GIL.. i.e. + // not _every_ instruction but on average a branch should + // occur every few instructions. MICROPY_VM_HOOK_LOOP + // Check for pending exceptions or scheduled tasks to run. + // Note: it's safe to just call mp_handle_pending(true), but + // we can inline the check for the common case where there is + // neither. + if ( #if MICROPY_ENABLE_SCHEDULER - // This is an inlined variant of mp_handle_pending - if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { - mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); - // Re-check state is still pending now that we're in the atomic section. - if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { - MARK_EXC_IP_SELECTIVE(); - mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception); - if (obj != MP_OBJ_NULL) { - MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; - if (!mp_sched_num_pending()) { - MP_STATE_VM(sched_state) = MP_SCHED_IDLE; - } - MICROPY_END_ATOMIC_SECTION(atomic_state); - RAISE(obj); - } - mp_handle_pending_tail(atomic_state); - } else { - MICROPY_END_ATOMIC_SECTION(atomic_state); - } - } + #if MICROPY_PY_THREAD + // Scheduler + threading: Scheduler and pending exceptions are independent, check both. + MP_STATE_VM(sched_state) == MP_SCHED_PENDING || MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL #else - // This is an inlined variant of mp_handle_pending - if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) { - MARK_EXC_IP_SELECTIVE(); - mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception); - MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; - RAISE(obj); - } + // Scheduler + non-threading: Optimisation: pending exception sets sched_state, only check sched_state. + MP_STATE_VM(sched_state) == MP_SCHED_PENDING #endif + #else + // No scheduler: Just check pending exception. + MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL + #endif + #if MICROPY_ENABLE_VM_ABORT + // Check if the VM should abort execution. + || MP_STATE_VM(vm_abort) + #endif + ) { + MARK_EXC_IP_SELECTIVE(); + mp_handle_pending(true); + } #if MICROPY_PY_THREAD_GIL #if MICROPY_PY_THREAD_GIL_VM_DIVISOR + // Don't bounce the GIL too frequently (default every 32 branches). if (--gil_divisor == 0) #endif { @@ -1373,8 +1385,8 @@ pending_exception_check: if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) #endif { - MP_THREAD_GIL_EXIT(); - MP_THREAD_GIL_ENTER(); + MP_THREAD_GIL_EXIT(); + MP_THREAD_GIL_ENTER(); } } #endif @@ -1395,22 +1407,20 @@ exception_handler: #endif 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))) { - if (code_state->ip) { - // check if it's a StopIteration within a for block - if (*code_state->ip == MP_BC_FOR_ITER) { - const byte *ip = code_state->ip + 1; - DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward - code_state->ip = ip + ulab; // jump to after for-block - code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator - goto outer_dispatch_loop; // continue with dispatch loop - } else if (*code_state->ip == MP_BC_YIELD_FROM) { - // StopIteration inside yield from call means return a value of - // yield from, so inject exception's value as yield from's result - // (Instead of stack pop then push we just replace exhausted gen with value) - *code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); - code_state->ip++; // yield from is over, move to next instruction - goto outer_dispatch_loop; // continue with dispatch loop - } + // check if it's a StopIteration within a for block + if (*code_state->ip == MP_BC_FOR_ITER) { + const byte *ip = code_state->ip + 1; + DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward + code_state->ip = ip + ulab; // jump to after for-block + code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator + goto outer_dispatch_loop; // continue with dispatch loop + } else if (*code_state->ip == MP_BC_YIELD_FROM) { + // StopIteration inside yield from call means return a value of + // yield from, so inject exception's value as yield from's result + // (Instead of stack pop then push we just replace exhausted gen with value) + *code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); + code_state->ip++; // yield from is over, move to next instruction + goto outer_dispatch_loop; // continue with dispatch loop } } @@ -1429,8 +1439,9 @@ unwind_loop: // - exceptions re-raised by END_FINALLY // - exceptions re-raised explicitly by "raise" if ( true + // CIRCUITPY #if MICROPY_CONST_GENERATOREXIT_OBJ - && nlr.ret_val != &mp_static_GeneratorExit_obj + && nlr.ret_val != &mp_const_GeneratorExit_obj #endif && *code_state->ip != MP_BC_END_FINALLY && *code_state->ip != MP_BC_RAISE_LAST) { @@ -1471,6 +1482,7 @@ unwind_loop: // catch exception and pass to byte code code_state->ip = exc_sp->handler; mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp); + //CIRCUITPY #if MICROPY_CPYTHON_EXCEPTION_CHAIN mp_obj_t active_exception = get_active_exception(exc_sp, exc_stack); #endif diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index a45f17ca2c..6b90258111 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -468,9 +468,10 @@ STATIC const mp_rom_map_elem_t bleio_adapter_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(bleio_adapter_locals_dict, bleio_adapter_locals_dict_table); -const mp_obj_type_t bleio_adapter_type = { - .base = { &mp_type_type }, - .name = MP_QSTR_Adapter, - .make_new = bleio_adapter_make_new, - .locals_dict = (mp_obj_t)&bleio_adapter_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_adapter_type, + MP_QSTR_Adapter, + MP_TYPE_FLAG_NONE, + make_new, bleio_adapter_make_new, + locals_dict, &bleio_adapter_locals_dict + ); diff --git a/shared-bindings/_bleio/Address.c b/shared-bindings/_bleio/Address.c index cae1b9a235..623bc7aaed 100644 --- a/shared-bindings/_bleio/Address.c +++ b/shared-bindings/_bleio/Address.c @@ -199,15 +199,13 @@ STATIC const mp_rom_map_elem_t bleio_address_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(bleio_address_locals_dict, bleio_address_locals_dict_table); -const mp_obj_type_t bleio_address_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Address, - .make_new = bleio_address_make_new, - .print = bleio_address_print, - .locals_dict = (mp_obj_dict_t *)&bleio_address_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = bleio_address_unary_op, - .binary_op = bleio_address_binary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_address_type, + MP_QSTR_Address, + MP_TYPE_FLAG_NONE, + make_new, bleio_address_make_new, + print, bleio_address_print, + locals_dict, &bleio_address_locals_dict, + unary_op, bleio_address_unary_op, + binary_op, bleio_address_binary_op + ); diff --git a/shared-bindings/_bleio/Attribute.c b/shared-bindings/_bleio/Attribute.c index 176198d450..b060757951 100644 --- a/shared-bindings/_bleio/Attribute.c +++ b/shared-bindings/_bleio/Attribute.c @@ -74,8 +74,9 @@ STATIC const mp_rom_map_elem_t bleio_attribute_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(bleio_attribute_locals_dict, bleio_attribute_locals_dict_table); -const mp_obj_type_t bleio_attribute_type = { - { &mp_type_type }, - .name = MP_QSTR_Attribute, - .locals_dict = (mp_obj_dict_t *)&bleio_attribute_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_attribute_type, + MP_QSTR_Attribute, + MP_TYPE_FLAG_NONE, + locals_dict, &bleio_attribute_locals_dict + ); diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c index 1f752577c1..8b14acd7df 100644 --- a/shared-bindings/_bleio/Characteristic.c +++ b/shared-bindings/_bleio/Characteristic.c @@ -325,9 +325,10 @@ STATIC void bleio_characteristic_print(const mp_print_t *print, mp_obj_t self_in } } -const mp_obj_type_t bleio_characteristic_type = { - { &mp_type_type }, - .name = MP_QSTR_Characteristic, - .print = bleio_characteristic_print, - .locals_dict = (mp_obj_dict_t *)&bleio_characteristic_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_characteristic_type, + MP_QSTR_Characteristic, + MP_TYPE_FLAG_NONE, + print, bleio_characteristic_print, + locals_dict, &bleio_characteristic_locals_dict + ); diff --git a/shared-bindings/_bleio/CharacteristicBuffer.c b/shared-bindings/_bleio/CharacteristicBuffer.c index 842ea4cc58..474a07f7b9 100644 --- a/shared-bindings/_bleio/CharacteristicBuffer.c +++ b/shared-bindings/_bleio/CharacteristicBuffer.c @@ -222,15 +222,12 @@ STATIC const mp_stream_p_t characteristic_buffer_stream_p = { }; -const mp_obj_type_t bleio_characteristic_buffer_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_CharacteristicBuffer, - .make_new = bleio_characteristic_buffer_make_new, - .locals_dict = (mp_obj_dict_t *)&bleio_characteristic_buffer_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &characteristic_buffer_stream_p, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_characteristic_buffer_type, + MP_QSTR_CharacteristicBuffer, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + make_new, bleio_characteristic_buffer_make_new, + locals_dict, &bleio_characteristic_buffer_locals_dict, + iter, mp_stream_unbuffered_iter, + protocol, &characteristic_buffer_stream_p + ); diff --git a/shared-bindings/_bleio/Connection.c b/shared-bindings/_bleio/Connection.c index f76ecc8167..cec1c4a851 100644 --- a/shared-bindings/_bleio/Connection.c +++ b/shared-bindings/_bleio/Connection.c @@ -244,12 +244,10 @@ STATIC const mp_rom_map_elem_t bleio_connection_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(bleio_connection_locals_dict, bleio_connection_locals_dict_table); -const mp_obj_type_t bleio_connection_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Connection, - .locals_dict = (mp_obj_dict_t *)&bleio_connection_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_connection_type, + MP_QSTR_Connection, + MP_TYPE_FLAG_NONE, + locals_dict, &bleio_connection_locals_dict, + unary_op, mp_generic_unary_op + ); diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c index 813ef8f9fe..093b51100e 100644 --- a/shared-bindings/_bleio/Descriptor.c +++ b/shared-bindings/_bleio/Descriptor.c @@ -211,9 +211,10 @@ STATIC void bleio_descriptor_print(const mp_print_t *print, mp_obj_t self_in, mp } } -const mp_obj_type_t bleio_descriptor_type = { - { &mp_type_type }, - .name = MP_QSTR_Descriptor, - .print = bleio_descriptor_print, - .locals_dict = (mp_obj_dict_t *)&bleio_descriptor_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_descriptor_type, + MP_QSTR_Descriptor, + MP_TYPE_FLAG_NONE, + print, bleio_descriptor_print, + locals_dict, &bleio_descriptor_locals_dict + ); diff --git a/shared-bindings/_bleio/PacketBuffer.c b/shared-bindings/_bleio/PacketBuffer.c index 2c03a6855e..c97e97b410 100644 --- a/shared-bindings/_bleio/PacketBuffer.c +++ b/shared-bindings/_bleio/PacketBuffer.c @@ -229,9 +229,10 @@ STATIC const mp_rom_map_elem_t bleio_packet_buffer_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(bleio_packet_buffer_locals_dict, bleio_packet_buffer_locals_dict_table); -const mp_obj_type_t bleio_packet_buffer_type = { - { &mp_type_type }, - .name = MP_QSTR_PacketBuffer, - .make_new = bleio_packet_buffer_make_new, - .locals_dict = (mp_obj_dict_t *)&bleio_packet_buffer_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_packet_buffer_type, + MP_QSTR_PacketBuffer, + MP_TYPE_FLAG_NONE, + make_new, bleio_packet_buffer_make_new, + locals_dict, &bleio_packet_buffer_locals_dict + ); diff --git a/shared-bindings/_bleio/ScanEntry.c b/shared-bindings/_bleio/ScanEntry.c index 83966d1719..f859f22be1 100644 --- a/shared-bindings/_bleio/ScanEntry.c +++ b/shared-bindings/_bleio/ScanEntry.c @@ -136,8 +136,9 @@ STATIC const mp_rom_map_elem_t bleio_scanentry_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(bleio_scanentry_locals_dict, bleio_scanentry_locals_dict_table); -const mp_obj_type_t bleio_scanentry_type = { - { &mp_type_type }, - .name = MP_QSTR_ScanEntry, - .locals_dict = (mp_obj_dict_t *)&bleio_scanentry_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_scanentry_type, + MP_QSTR_ScanEntry, + MP_TYPE_FLAG_NONE, + locals_dict, &bleio_scanentry_locals_dict + ); diff --git a/shared-bindings/_bleio/ScanResults.c b/shared-bindings/_bleio/ScanResults.c index ec4e0c72e8..81d4e66bce 100644 --- a/shared-bindings/_bleio/ScanResults.c +++ b/shared-bindings/_bleio/ScanResults.c @@ -59,12 +59,9 @@ STATIC mp_obj_t scanresults_iternext(mp_obj_t self_in) { //| ... //| -const mp_obj_type_t bleio_scanresults_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_ScanResults, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = scanresults_iternext, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_scanresults_type, + MP_QSTR_ScanResults, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + iter, scanresults_iternext + ); diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c index f107b068e0..f5ffa982f6 100644 --- a/shared-bindings/_bleio/Service.c +++ b/shared-bindings/_bleio/Service.c @@ -140,10 +140,11 @@ STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_pr } } -const mp_obj_type_t bleio_service_type = { - { &mp_type_type }, - .name = MP_QSTR_Service, - .make_new = bleio_service_make_new, - .print = bleio_service_print, - .locals_dict = (mp_obj_dict_t *)&bleio_service_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_service_type, + MP_QSTR_Service, + MP_TYPE_FLAG_NONE, + make_new, bleio_service_make_new, + print, bleio_service_print, + locals_dict, &bleio_service_locals_dict + ); diff --git a/shared-bindings/_bleio/UUID.c b/shared-bindings/_bleio/UUID.c index b7fc05fbc6..c177e096f5 100644 --- a/shared-bindings/_bleio/UUID.c +++ b/shared-bindings/_bleio/UUID.c @@ -280,15 +280,13 @@ void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t } } -const mp_obj_type_t bleio_uuid_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_UUID, - .print = bleio_uuid_print, - .make_new = bleio_uuid_make_new, - .locals_dict = (mp_obj_dict_t *)&bleio_uuid_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = bleio_uuid_unary_op, - .binary_op = bleio_uuid_binary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + bleio_uuid_type, + MP_QSTR_UUID, + MP_TYPE_FLAG_NONE, + print, bleio_uuid_print, + make_new, bleio_uuid_make_new, + locals_dict, &bleio_uuid_locals_dict, + unary_op, bleio_uuid_unary_op, + binary_op, bleio_uuid_binary_op + ); diff --git a/shared-bindings/_bleio/__init__.h b/shared-bindings/_bleio/__init__.h index f34df306b7..1a917793eb 100644 --- a/shared-bindings/_bleio/__init__.h +++ b/shared-bindings/_bleio/__init__.h @@ -29,6 +29,7 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H +#include "py/obj.h" #include "py/objlist.h" #include "shared-bindings/_bleio/Adapter.h" @@ -41,14 +42,12 @@ extern bleio_adapter_obj_t common_hal_bleio_adapter_obj; void bleio_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind); #define MP_DEFINE_BLEIO_EXCEPTION(exc_name, base_name) \ - const mp_obj_type_t mp_type_bleio_##exc_name = { \ - { &mp_type_type }, \ - .name = MP_QSTR_##exc_name, \ - .print = bleio_exception_print, \ - .make_new = mp_obj_exception_make_new, \ - .attr = mp_obj_exception_attr, \ - .parent = &mp_type_##base_name, \ - }; + MP_DEFINE_CONST_OBJ_TYPE(mp_type_bleio_##exc_name, MP_QSTR_##exc_name, MP_TYPE_FLAG_NONE, \ + make_new, mp_obj_exception_make_new, \ + print, bleio_exception_print, \ + attr, mp_obj_exception_attr, \ + parent, &mp_type_##base_name \ + ); extern const mp_obj_type_t mp_type_bleio_BluetoothError; extern const mp_obj_type_t mp_type_bleio_RoleError; diff --git a/shared-bindings/_eve/__init__.c b/shared-bindings/_eve/__init__.c index 203a9cbfd2..ed1ddd961a 100644 --- a/shared-bindings/_eve/__init__.c +++ b/shared-bindings/_eve/__init__.c @@ -1064,12 +1064,13 @@ STATIC mp_obj_t _EVE_make_new(const mp_obj_type_t *type, size_t n_args, size_t n return MP_OBJ_FROM_PTR(o); } -STATIC const mp_obj_type_t _EVE_type = { - { &mp_type_type }, - .name = MP_QSTR__EVE, - .make_new = _EVE_make_new, - .locals_dict = (void *)&_EVE_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + _EVE_type, + MP_QSTR__EVE, + MP_TYPE_FLAG_NONE, + make_new, _EVE_make_new, + locals_dict, &_EVE_locals_dict + ); STATIC const mp_rom_map_elem_t mp_module__eve_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__eve) }, diff --git a/shared-bindings/_pew/PewPew.c b/shared-bindings/_pew/PewPew.c index 229fb24381..5309baa0e2 100644 --- a/shared-bindings/_pew/PewPew.c +++ b/shared-bindings/_pew/PewPew.c @@ -32,7 +32,6 @@ #include "shared-bindings/util.h" #include "PewPew.h" #include "common-hal/_pew/PewPew.h" -#include "supervisor/shared/translate/translate.h" //| class PewPew: //| """This is an internal module to be used by the ``pew.py`` library from @@ -130,9 +129,11 @@ STATIC mp_obj_t pewpew_make_new(const mp_obj_type_t *type, size_t n_args, size_t STATIC const mp_rom_map_elem_t pewpew_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pewpew_locals_dict, pewpew_locals_dict_table); -const mp_obj_type_t pewpew_type = { - { &mp_type_type }, - .name = MP_QSTR_PewPew, - .make_new = pewpew_make_new, - .locals_dict = (mp_obj_dict_t *)&pewpew_locals_dict, -}; + +MP_DEFINE_CONST_OBJ_TYPE( + pewpew_type, + MP_QSTR_PewPew, + MP_TYPE_FLAG_NONE, + make_new, pewpew_make_new, + locals_dict, &pewpew_locals_dict + ); diff --git a/shared-bindings/_pew/__init__.c b/shared-bindings/_pew/__init__.c index 435f50151a..9a0620ebab 100644 --- a/shared-bindings/_pew/__init__.c +++ b/shared-bindings/_pew/__init__.c @@ -62,3 +62,5 @@ const mp_obj_module_t pew_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t *)&pew_module_globals, }; + +MP_REGISTER_ROOT_POINTER(mp_obj_t pew_singleton); diff --git a/shared-bindings/_pixelmap/PixelMap.c b/shared-bindings/_pixelmap/PixelMap.c index 5de918bbbe..4d06fe64fa 100644 --- a/shared-bindings/_pixelmap/PixelMap.c +++ b/shared-bindings/_pixelmap/PixelMap.c @@ -255,14 +255,12 @@ STATIC const mp_rom_map_elem_t pixelmap_pixelmap_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pixelmap_pixelmap_locals_dict, pixelmap_pixelmap_locals_dict_table); -const mp_obj_type_t pixelmap_pixelmap_type = { - { &mp_type_type }, - .name = MP_QSTR_PixelMap, - .flags = MP_TYPE_FLAG_EXTENDED, - .locals_dict = (mp_obj_t)&pixelmap_pixelmap_locals_dict, - .make_new = pixelmap_pixelmap_make_new, - MP_TYPE_EXTENDED_FIELDS( - .subscr = pixelmap_pixelmap_subscr, - .unary_op = pixelmap_pixelmap_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + pixelmap_pixelmap_type, + MP_QSTR_PixelMap, + MP_TYPE_FLAG_NONE, + locals_dict, &pixelmap_pixelmap_locals_dict, + make_new, pixelmap_pixelmap_make_new, + subscr, pixelmap_pixelmap_subscr, + unary_op, pixelmap_pixelmap_unary_op + ); diff --git a/shared-bindings/_stage/Layer.c b/shared-bindings/_stage/Layer.c index a5dd130dac..d2780ac352 100644 --- a/shared-bindings/_stage/Layer.c +++ b/shared-bindings/_stage/Layer.c @@ -24,11 +24,10 @@ * THE SOFTWARE. */ -#include +#include "py/runtime.h" #include "__init__.h" #include "Layer.h" -#include "supervisor/shared/translate/translate.h" //| class Layer: //| """Keep information about a single layer of graphics""" @@ -125,9 +124,10 @@ STATIC const mp_rom_map_elem_t layer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(layer_locals_dict, layer_locals_dict_table); -const mp_obj_type_t mp_type_layer = { - { &mp_type_type }, - .name = MP_QSTR_Layer, - .make_new = layer_make_new, - .locals_dict = (mp_obj_dict_t *)&layer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_layer, + MP_QSTR_Layer, + MP_TYPE_FLAG_NONE, + make_new, layer_make_new, + locals_dict, &layer_locals_dict + ); diff --git a/shared-bindings/_stage/Text.c b/shared-bindings/_stage/Text.c index 0c54f123d7..1b003d93f7 100644 --- a/shared-bindings/_stage/Text.c +++ b/shared-bindings/_stage/Text.c @@ -28,7 +28,6 @@ #include "__init__.h" #include "Text.h" -#include "supervisor/shared/translate/translate.h" //| class Text: //| """Keep information about a single grid of text""" @@ -105,9 +104,10 @@ STATIC const mp_rom_map_elem_t text_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(text_locals_dict, text_locals_dict_table); -const mp_obj_type_t mp_type_text = { - { &mp_type_type }, - .name = MP_QSTR_Text, - .make_new = text_make_new, - .locals_dict = (mp_obj_dict_t *)&text_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_text, + MP_QSTR_Text, + MP_TYPE_FLAG_NONE, + make_new, text_make_new, + locals_dict, &text_locals_dict + ); diff --git a/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c b/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c index 7dd5e09868..0da8c48fcf 100644 --- a/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c +++ b/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c @@ -36,7 +36,6 @@ #include "shared/runtime/context_manager_helpers.h" #include "py/runtime.h" #include "py/smallint.h" -#include "supervisor/shared/translate/translate.h" //| class I2CDevice: @@ -285,9 +284,10 @@ STATIC const mp_rom_map_elem_t adafruit_bus_device_i2cdevice_locals_dict_table[] STATIC MP_DEFINE_CONST_DICT(adafruit_bus_device_i2cdevice_locals_dict, adafruit_bus_device_i2cdevice_locals_dict_table); -const mp_obj_type_t adafruit_bus_device_i2cdevice_type = { - { &mp_type_type }, - .name = MP_QSTR_I2CDevice, - .make_new = adafruit_bus_device_i2cdevice_make_new, - .locals_dict = (mp_obj_dict_t *)&adafruit_bus_device_i2cdevice_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + adafruit_bus_device_i2cdevice_type, + MP_QSTR_I2CDevice, + MP_TYPE_FLAG_NONE, + make_new, adafruit_bus_device_i2cdevice_make_new, + locals_dict, &adafruit_bus_device_i2cdevice_locals_dict + ); diff --git a/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c b/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c index 47f93f3230..34b2c0e25b 100644 --- a/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c +++ b/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c @@ -35,8 +35,6 @@ #include "shared/runtime/buffer_helper.h" #include "shared/runtime/context_manager_helpers.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" - //| class SPIDevice: //| """SPI Device Manager""" @@ -144,9 +142,10 @@ STATIC const mp_rom_map_elem_t adafruit_bus_device_spidevice_locals_dict_table[] STATIC MP_DEFINE_CONST_DICT(adafruit_bus_device_spidevice_locals_dict, adafruit_bus_device_spidevice_locals_dict_table); -const mp_obj_type_t adafruit_bus_device_spidevice_type = { - { &mp_type_type }, - .name = MP_QSTR_SPIDevice, - .make_new = adafruit_bus_device_spidevice_make_new, - .locals_dict = (mp_obj_dict_t *)&adafruit_bus_device_spidevice_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + adafruit_bus_device_spidevice_type, + MP_QSTR_SPIDevice, + MP_TYPE_FLAG_NONE, + make_new, adafruit_bus_device_spidevice_make_new, + locals_dict, &adafruit_bus_device_spidevice_locals_dict + ); diff --git a/shared-bindings/adafruit_pixelbuf/PixelBuf.c b/shared-bindings/adafruit_pixelbuf/PixelBuf.c index d259b57dbb..20455026b4 100644 --- a/shared-bindings/adafruit_pixelbuf/PixelBuf.c +++ b/shared-bindings/adafruit_pixelbuf/PixelBuf.c @@ -368,15 +368,13 @@ STATIC const mp_rom_map_elem_t pixelbuf_pixelbuf_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pixelbuf_pixelbuf_locals_dict, pixelbuf_pixelbuf_locals_dict_table); -const mp_obj_type_t pixelbuf_pixelbuf_type = { - { &mp_type_type }, - .name = MP_QSTR_PixelBuf, - .flags = MP_TYPE_FLAG_EXTENDED, - .locals_dict = (mp_obj_t)&pixelbuf_pixelbuf_locals_dict, - .make_new = pixelbuf_pixelbuf_make_new, - MP_TYPE_EXTENDED_FIELDS( - .subscr = pixelbuf_pixelbuf_subscr, - .unary_op = pixelbuf_pixelbuf_unary_op, - .getiter = mp_obj_new_generic_iterator, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + pixelbuf_pixelbuf_type, + MP_QSTR_PixelBuf, + MP_TYPE_FLAG_ITER_IS_GETITER, + locals_dict, &pixelbuf_pixelbuf_locals_dict, + make_new, pixelbuf_pixelbuf_make_new, + subscr, pixelbuf_pixelbuf_subscr, + unary_op, pixelbuf_pixelbuf_unary_op, + iter, mp_obj_generic_subscript_getiter + ); diff --git a/shared-bindings/aesio/aes.c b/shared-bindings/aesio/aes.c index 7a6a2f47ed..8344c43c9b 100644 --- a/shared-bindings/aesio/aes.c +++ b/shared-bindings/aesio/aes.c @@ -249,9 +249,10 @@ STATIC const mp_rom_map_elem_t aesio_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(aesio_locals_dict, aesio_locals_dict_table); -const mp_obj_type_t aesio_aes_type = { - {&mp_type_type}, - .name = MP_QSTR_AES, - .make_new = aesio_aes_make_new, - .locals_dict = (mp_obj_dict_t *)&aesio_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + aesio_aes_type, + MP_QSTR_AES, + MP_TYPE_FLAG_NONE, + make_new, aesio_aes_make_new, + locals_dict, &aesio_locals_dict + ); diff --git a/shared-bindings/alarm/SleepMemory.c b/shared-bindings/alarm/SleepMemory.c index 0304abfbcc..ab4659629a 100644 --- a/shared-bindings/alarm/SleepMemory.c +++ b/shared-bindings/alarm/SleepMemory.c @@ -31,7 +31,6 @@ #include "py/runtime0.h" #include "shared-bindings/alarm/SleepMemory.h" -#include "supervisor/shared/translate/translate.h" //| class SleepMemory: //| """Store raw bytes in RAM that persists during deep sleep. @@ -170,13 +169,11 @@ STATIC mp_obj_t alarm_sleep_memory_subscr(mp_obj_t self_in, mp_obj_t index_in, m } } -const mp_obj_type_t alarm_sleep_memory_type = { - { &mp_type_type }, - .name = MP_QSTR_SleepMemory, - .flags = MP_TYPE_FLAG_EXTENDED, - .locals_dict = (mp_obj_t)&alarm_sleep_memory_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .subscr = alarm_sleep_memory_subscr, - .unary_op = alarm_sleep_memory_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + alarm_sleep_memory_type, + MP_QSTR_SleepMemory, + MP_TYPE_FLAG_NONE, + locals_dict, &alarm_sleep_memory_locals_dict, + subscr, alarm_sleep_memory_subscr, + unary_op, alarm_sleep_memory_unary_op + ); diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c index b0e21771c5..2e9441c725 100644 --- a/shared-bindings/alarm/pin/PinAlarm.c +++ b/shared-bindings/alarm/pin/PinAlarm.c @@ -33,7 +33,6 @@ #include "py/obj.h" #include "py/objproperty.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class PinAlarm: //| """Trigger an alarm when a pin changes state.""" @@ -118,9 +117,10 @@ STATIC const mp_rom_map_elem_t alarm_pin_pinalarm_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(alarm_pin_pinalarm_locals_dict, alarm_pin_pinalarm_locals_dict_table); -const mp_obj_type_t alarm_pin_pinalarm_type = { - { &mp_type_type }, - .name = MP_QSTR_PinAlarm, - .make_new = alarm_pin_pinalarm_make_new, - .locals_dict = (mp_obj_t)&alarm_pin_pinalarm_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + alarm_pin_pinalarm_type, + MP_QSTR_PinAlarm, + MP_TYPE_FLAG_NONE, + make_new, alarm_pin_pinalarm_make_new, + locals_dict, &alarm_pin_pinalarm_locals_dict + ); diff --git a/shared-bindings/alarm/time/TimeAlarm.c b/shared-bindings/alarm/time/TimeAlarm.c index aed14613ea..9a6440d451 100644 --- a/shared-bindings/alarm/time/TimeAlarm.c +++ b/shared-bindings/alarm/time/TimeAlarm.c @@ -33,8 +33,6 @@ #include "shared-bindings/rtc/__init__.h" #include "shared-bindings/time/__init__.h" -#include "supervisor/shared/translate/translate.h" - #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE mp_obj_t MP_WEAK rtc_get_time_source_time(void) { mp_raise_RuntimeError(translate("RTC is not supported on this board")); @@ -133,9 +131,10 @@ STATIC const mp_rom_map_elem_t alarm_time_timealarm_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(alarm_time_timealarm_locals_dict, alarm_time_timealarm_locals_dict_table); -const mp_obj_type_t alarm_time_timealarm_type = { - { &mp_type_type }, - .name = MP_QSTR_TimeAlarm, - .make_new = alarm_time_timealarm_make_new, - .locals_dict = (mp_obj_t)&alarm_time_timealarm_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + alarm_time_timealarm_type, + MP_QSTR_TimeAlarm, + MP_TYPE_FLAG_NONE, + make_new, alarm_time_timealarm_make_new, + locals_dict, &alarm_time_timealarm_locals_dict + ); diff --git a/shared-bindings/alarm/touch/TouchAlarm.c b/shared-bindings/alarm/touch/TouchAlarm.c index 71fcb67a4f..6433e1d845 100644 --- a/shared-bindings/alarm/touch/TouchAlarm.c +++ b/shared-bindings/alarm/touch/TouchAlarm.c @@ -79,9 +79,10 @@ STATIC const mp_rom_map_elem_t alarm_touch_touchalarm_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(alarm_touch_touchalarm_locals_dict, alarm_touch_touchalarm_locals_dict_table); -const mp_obj_type_t alarm_touch_touchalarm_type = { - { &mp_type_type }, - .name = MP_QSTR_TouchAlarm, - .make_new = alarm_touch_touchalarm_make_new, - .locals_dict = (mp_obj_t)&alarm_touch_touchalarm_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + alarm_touch_touchalarm_type, + MP_QSTR_TouchAlarm, + MP_TYPE_FLAG_NONE, + make_new, alarm_touch_touchalarm_make_new, + locals_dict, &alarm_touch_touchalarm_locals_dict + ); diff --git a/shared-bindings/analogbufio/BufferedIn.c b/shared-bindings/analogbufio/BufferedIn.c index 4641df6891..1e64dc6d7b 100644 --- a/shared-bindings/analogbufio/BufferedIn.c +++ b/shared-bindings/analogbufio/BufferedIn.c @@ -164,9 +164,10 @@ STATIC const mp_rom_map_elem_t analogbufio_bufferedin_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(analogbufio_bufferedin_locals_dict, analogbufio_bufferedin_locals_dict_table); -const mp_obj_type_t analogbufio_bufferedin_type = { - { &mp_type_type }, - .name = MP_QSTR_BufferedIn, - .make_new = analogbufio_bufferedin_make_new, - .locals_dict = (mp_obj_t)&analogbufio_bufferedin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + analogbufio_bufferedin_type, + MP_QSTR_BufferedIn, + MP_TYPE_FLAG_NONE, + make_new, analogbufio_bufferedin_make_new, + locals_dict, &analogbufio_bufferedin_locals_dict + ); diff --git a/shared-bindings/analogio/AnalogIn.c b/shared-bindings/analogio/AnalogIn.c index faf085905e..c99d48fd56 100644 --- a/shared-bindings/analogio/AnalogIn.c +++ b/shared-bindings/analogio/AnalogIn.c @@ -149,9 +149,10 @@ STATIC const mp_rom_map_elem_t analogio_analogin_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(analogio_analogin_locals_dict, analogio_analogin_locals_dict_table); -const mp_obj_type_t analogio_analogin_type = { - { &mp_type_type }, - .name = MP_QSTR_AnalogIn, - .make_new = analogio_analogin_make_new, - .locals_dict = (mp_obj_t)&analogio_analogin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + analogio_analogin_type, + MP_QSTR_AnalogIn, + MP_TYPE_FLAG_NONE, + make_new, analogio_analogin_make_new, + locals_dict, &analogio_analogin_locals_dict + ); diff --git a/shared-bindings/analogio/AnalogOut.c b/shared-bindings/analogio/AnalogOut.c index 36a6532b7c..facf45cf98 100644 --- a/shared-bindings/analogio/AnalogOut.c +++ b/shared-bindings/analogio/AnalogOut.c @@ -34,7 +34,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/analogio/AnalogOut.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class AnalogOut: //| """Output analog values (a specific voltage). @@ -131,9 +130,10 @@ STATIC const mp_rom_map_elem_t analogio_analogout_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(analogio_analogout_locals_dict, analogio_analogout_locals_dict_table); -const mp_obj_type_t analogio_analogout_type = { - { &mp_type_type }, - .name = MP_QSTR_AnalogOut, - .make_new = analogio_analogout_make_new, - .locals_dict = (mp_obj_t)&analogio_analogout_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + analogio_analogout_type, + MP_QSTR_AnalogOut, + MP_TYPE_FLAG_NONE, + make_new, analogio_analogout_make_new, + locals_dict, &analogio_analogout_locals_dict + ); diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c index 34e18e9cf2..1306e423c2 100644 --- a/shared-bindings/audiobusio/I2SOut.c +++ b/shared-bindings/audiobusio/I2SOut.c @@ -33,7 +33,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/audiobusio/I2SOut.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class I2SOut: //| """Output an I2S audio signal""" @@ -273,9 +272,10 @@ STATIC const mp_rom_map_elem_t audiobusio_i2sout_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(audiobusio_i2sout_locals_dict, audiobusio_i2sout_locals_dict_table); -const mp_obj_type_t audiobusio_i2sout_type = { - { &mp_type_type }, - .name = MP_QSTR_I2SOut, - .make_new = audiobusio_i2sout_make_new, - .locals_dict = (mp_obj_dict_t *)&audiobusio_i2sout_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + audiobusio_i2sout_type, + MP_QSTR_I2SOut, + MP_TYPE_FLAG_NONE, + make_new, audiobusio_i2sout_make_new, + locals_dict, &audiobusio_i2sout_locals_dict + ); diff --git a/shared-bindings/audiobusio/PDMIn.c b/shared-bindings/audiobusio/PDMIn.c index f5105b367a..601b0c2f84 100644 --- a/shared-bindings/audiobusio/PDMIn.c +++ b/shared-bindings/audiobusio/PDMIn.c @@ -34,7 +34,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/audiobusio/PDMIn.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class PDMIn: //| """Record an input PDM audio stream""" @@ -242,11 +241,12 @@ STATIC const mp_rom_map_elem_t audiobusio_pdmin_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(audiobusio_pdmin_locals_dict, audiobusio_pdmin_locals_dict_table); #endif -const mp_obj_type_t audiobusio_pdmin_type = { - { &mp_type_type }, - .name = MP_QSTR_PDMIn, - .make_new = audiobusio_pdmin_make_new, +MP_DEFINE_CONST_OBJ_TYPE( + audiobusio_pdmin_type, + MP_QSTR_PDMIn, + MP_TYPE_FLAG_NONE, + make_new, audiobusio_pdmin_make_new #if CIRCUITPY_AUDIOBUSIO_PDMIN - .locals_dict = (mp_obj_dict_t *)&audiobusio_pdmin_locals_dict, + , locals_dict, &audiobusio_pdmin_locals_dict #endif -}; + ); diff --git a/shared-bindings/audiocore/RawSample.c b/shared-bindings/audiocore/RawSample.c index 58ec83fe35..265515c3e1 100644 --- a/shared-bindings/audiocore/RawSample.c +++ b/shared-bindings/audiocore/RawSample.c @@ -32,7 +32,6 @@ #include "py/runtime.h" #include "shared-bindings/util.h" #include "shared-bindings/audiocore/RawSample.h" -#include "supervisor/shared/translate/translate.h" //| class RawSample: //| """A raw audio sample buffer in memory""" @@ -73,7 +72,7 @@ STATIC mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_buffer, ARG_channel_count, ARG_sample_rate }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL } }, { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } }, { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} }, }; @@ -175,13 +174,11 @@ STATIC const audiosample_p_t audioio_rawsample_proto = { .get_buffer_structure = (audiosample_get_buffer_structure_fun)audioio_rawsample_get_buffer_structure, }; -const mp_obj_type_t audioio_rawsample_type = { - { &mp_type_type }, - .name = MP_QSTR_RawSample, - .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = audioio_rawsample_make_new, - .locals_dict = (mp_obj_dict_t *)&audioio_rawsample_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &audioio_rawsample_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + audioio_rawsample_type, + MP_QSTR_RawSample, + MP_TYPE_FLAG_NONE, + make_new, audioio_rawsample_make_new, + locals_dict, &audioio_rawsample_locals_dict, + protocol, &audioio_rawsample_proto + ); diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c index aa50321040..a07e74809a 100644 --- a/shared-bindings/audiocore/WaveFile.c +++ b/shared-bindings/audiocore/WaveFile.c @@ -31,7 +31,6 @@ #include "py/runtime.h" #include "shared-bindings/audiocore/WaveFile.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" #include "extmod/vfs_posix.h" //| class WaveFile: @@ -80,7 +79,7 @@ STATIC mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_ar } audioio_wavefile_obj_t *self = mp_obj_malloc(audioio_wavefile_obj_t, &audioio_wavefile_type); - if (!mp_obj_is_type(arg, &mp_type_fileio)) { + if (!mp_obj_is_type(arg, &mp_type_vfs_fat_fileio)) { mp_raise_TypeError(translate("file must be a file opened in byte mode")); } uint8_t *buffer = NULL; @@ -201,13 +200,11 @@ STATIC const audiosample_p_t audioio_wavefile_proto = { }; -const mp_obj_type_t audioio_wavefile_type = { - { &mp_type_type }, - .name = MP_QSTR_WaveFile, - .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = audioio_wavefile_make_new, - .locals_dict = (mp_obj_dict_t *)&audioio_wavefile_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &audioio_wavefile_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + audioio_wavefile_type, + MP_QSTR_WaveFile, + MP_TYPE_FLAG_NONE, + make_new, audioio_wavefile_make_new, + locals_dict, &audioio_wavefile_locals_dict, + protocol, &audioio_wavefile_proto + ); diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c index c66f109f9a..3df62dbe02 100644 --- a/shared-bindings/audioio/AudioOut.c +++ b/shared-bindings/audioio/AudioOut.c @@ -34,7 +34,6 @@ #include "shared-bindings/audioio/AudioOut.h" #include "shared-bindings/audiocore/RawSample.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class AudioOut: //| """Output an analog audio signal""" @@ -259,9 +258,10 @@ STATIC const mp_rom_map_elem_t audioio_audioout_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(audioio_audioout_locals_dict, audioio_audioout_locals_dict_table); -const mp_obj_type_t audioio_audioout_type = { - { &mp_type_type }, - .name = MP_QSTR_AudioOut, - .make_new = audioio_audioout_make_new, - .locals_dict = (mp_obj_dict_t *)&audioio_audioout_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + audioio_audioout_type, + MP_QSTR_AudioOut, + MP_TYPE_FLAG_NONE, + make_new, audioio_audioout_make_new, + locals_dict, &audioio_audioout_locals_dict + ); diff --git a/shared-bindings/audiomixer/Mixer.c b/shared-bindings/audiomixer/Mixer.c index 6ddc5c3641..3698dc4b7e 100644 --- a/shared-bindings/audiomixer/Mixer.c +++ b/shared-bindings/audiomixer/Mixer.c @@ -34,7 +34,6 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class Mixer: //| """Mixes one or more audio samples together into one sample.""" @@ -108,7 +107,7 @@ STATIC mp_obj_t audiomixer_mixer_make_new(const mp_obj_type_t *type, size_t n_ar common_hal_audiomixer_mixer_construct(self, voice_count, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate); for (int v = 0; v < voice_count; v++) { - self->voice[v] = audiomixer_mixervoice_type.make_new(&audiomixer_mixervoice_type, 0, 0, NULL); + self->voice[v] = MP_OBJ_TYPE_GET_SLOT(&audiomixer_mixervoice_type, make_new)(&audiomixer_mixervoice_type, 0, 0, NULL); common_hal_audiomixer_mixervoice_set_parent(self->voice[v], self); } self->voice_tuple = mp_obj_new_tuple(self->voice_count, self->voice); @@ -202,7 +201,7 @@ MP_PROPERTY_GETTER(audiomixer_mixer_voice_obj, STATIC mp_obj_t audiomixer_mixer_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_sample, ARG_voice, ARG_loop }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, { MP_QSTR_voice, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, }; @@ -273,13 +272,11 @@ STATIC const audiosample_p_t audiomixer_mixer_proto = { .get_buffer_structure = (audiosample_get_buffer_structure_fun)audiomixer_mixer_get_buffer_structure, }; -const mp_obj_type_t audiomixer_mixer_type = { - { &mp_type_type }, - .name = MP_QSTR_Mixer, - .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = audiomixer_mixer_make_new, - .locals_dict = (mp_obj_dict_t *)&audiomixer_mixer_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &audiomixer_mixer_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + audiomixer_mixer_type, + MP_QSTR_Mixer, + MP_TYPE_FLAG_NONE, + make_new, audiomixer_mixer_make_new, + locals_dict, &audiomixer_mixer_locals_dict, + protocol, &audiomixer_mixer_proto + ); diff --git a/shared-bindings/audiomixer/MixerVoice.c b/shared-bindings/audiomixer/MixerVoice.c index 74b9c6745d..aaa5aedb58 100644 --- a/shared-bindings/audiomixer/MixerVoice.c +++ b/shared-bindings/audiomixer/MixerVoice.c @@ -33,7 +33,6 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class MixerVoice: //| """Voice objects used with Mixer @@ -65,7 +64,7 @@ STATIC mp_obj_t audiomixer_mixervoice_make_new(const mp_obj_type_t *type, size_t STATIC mp_obj_t audiomixer_mixervoice_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_sample, ARG_loop }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, }; audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -106,7 +105,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixervoice_get_level_obj, audiomixer_mixerv STATIC mp_obj_t audiomixer_mixervoice_obj_set_level(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_level }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_level, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_level, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, }; audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -154,9 +153,10 @@ STATIC const mp_rom_map_elem_t audiomixer_mixervoice_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(audiomixer_mixervoice_locals_dict, audiomixer_mixervoice_locals_dict_table); -const mp_obj_type_t audiomixer_mixervoice_type = { - { &mp_type_type }, - .name = MP_QSTR_MixerVoice, - .make_new = audiomixer_mixervoice_make_new, - .locals_dict = (mp_obj_dict_t *)&audiomixer_mixervoice_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + audiomixer_mixervoice_type, + MP_QSTR_MixerVoice, + MP_TYPE_FLAG_NONE, + make_new, audiomixer_mixervoice_make_new, + locals_dict, &audiomixer_mixervoice_locals_dict + ); diff --git a/shared-bindings/audiomp3/MP3Decoder.c b/shared-bindings/audiomp3/MP3Decoder.c index ef5445a1de..1acab44a61 100644 --- a/shared-bindings/audiomp3/MP3Decoder.c +++ b/shared-bindings/audiomp3/MP3Decoder.c @@ -32,7 +32,6 @@ #include "py/runtime.h" #include "shared-bindings/audiomp3/MP3Decoder.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class MP3Decoder: //| """Load a mp3 file for audio playback @@ -284,13 +283,11 @@ STATIC const audiosample_p_t audiomp3_mp3file_proto = { .get_buffer_structure = (audiosample_get_buffer_structure_fun)audiomp3_mp3file_get_buffer_structure, }; -const mp_obj_type_t audiomp3_mp3file_type = { - { &mp_type_type }, - .name = MP_QSTR_MP3Decoder, - .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = audiomp3_mp3file_make_new, - .locals_dict = (mp_obj_dict_t *)&audiomp3_mp3file_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &audiomp3_mp3file_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + audiomp3_mp3file_type, + MP_QSTR_MP3Decoder, + MP_TYPE_FLAG_NONE, + make_new, audiomp3_mp3file_make_new, + locals_dict, &audiomp3_mp3file_locals_dict, + protocol, &audiomp3_mp3file_proto + ); diff --git a/shared-bindings/audiopwmio/PWMAudioOut.c b/shared-bindings/audiopwmio/PWMAudioOut.c index ce35374618..f0837b5620 100644 --- a/shared-bindings/audiopwmio/PWMAudioOut.c +++ b/shared-bindings/audiopwmio/PWMAudioOut.c @@ -34,7 +34,6 @@ #include "shared-bindings/audiopwmio/PWMAudioOut.h" #include "shared-bindings/audiocore/RawSample.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class PWMAudioOut: //| """Output an analog audio signal by varying the PWM duty cycle.""" @@ -269,9 +268,10 @@ STATIC const mp_rom_map_elem_t audiopwmio_pwmaudioout_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(audiopwmio_pwmaudioout_locals_dict, audiopwmio_pwmaudioout_locals_dict_table); -const mp_obj_type_t audiopwmio_pwmaudioout_type = { - { &mp_type_type }, - .name = MP_QSTR_PWMAudioOut, - .make_new = audiopwmio_pwmaudioout_make_new, - .locals_dict = (mp_obj_dict_t *)&audiopwmio_pwmaudioout_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + audiopwmio_pwmaudioout_type, + MP_QSTR_PWMAudioOut, + MP_TYPE_FLAG_NONE, + make_new, audiopwmio_pwmaudioout_make_new, + locals_dict, &audiopwmio_pwmaudioout_locals_dict + ); diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c index 390e1c0c98..5ca950c3e3 100644 --- a/shared-bindings/bitbangio/I2C.c +++ b/shared-bindings/bitbangio/I2C.c @@ -36,7 +36,6 @@ #include "py/binary.h" #include "py/mperrno.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class I2C: //| """Two wire serial protocol""" @@ -363,9 +362,10 @@ STATIC const mp_rom_map_elem_t bitbangio_i2c_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(bitbangio_i2c_locals_dict, bitbangio_i2c_locals_dict_table); -const mp_obj_type_t bitbangio_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .make_new = bitbangio_i2c_make_new, - .locals_dict = (mp_obj_dict_t *)&bitbangio_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + bitbangio_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + make_new, bitbangio_i2c_make_new, + locals_dict, &bitbangio_i2c_locals_dict + ); diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c index 2ec2220bef..e78b96bc09 100644 --- a/shared-bindings/bitbangio/SPI.c +++ b/shared-bindings/bitbangio/SPI.c @@ -38,7 +38,6 @@ #include "py/binary.h" #include "py/mperrno.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class SPI: //| """A 3-4 wire serial protocol @@ -411,9 +410,10 @@ STATIC const mp_rom_map_elem_t bitbangio_spi_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(bitbangio_spi_locals_dict, bitbangio_spi_locals_dict_table); -const mp_obj_type_t bitbangio_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .make_new = bitbangio_spi_make_new, - .locals_dict = (mp_obj_dict_t *)&bitbangio_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + bitbangio_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + make_new, bitbangio_spi_make_new, + locals_dict, &bitbangio_spi_locals_dict + ); diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index a6fc785a68..eef80a654a 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -970,11 +970,11 @@ STATIC mp_obj_t bitmaptools_obj_draw_circle(size_t n_args, const mp_obj_t *pos_a enum {ARG_dest_bitmap, ARG_x, ARG_y, ARG_radius, ARG_value}; static const mp_arg_t allowed_args[] = { - {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ}, - {MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT}, - {MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT}, - {MP_QSTR_radius, MP_ARG_REQUIRED | MP_ARG_INT}, - {MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT}, + {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {}}, + {MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {}}, + {MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {}}, + {MP_QSTR_radius, MP_ARG_REQUIRED | MP_ARG_INT, {}}, + {MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT, {}}, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c index 14ec7093a5..376969847f 100644 --- a/shared-bindings/busio/I2C.c +++ b/shared-bindings/busio/I2C.c @@ -35,7 +35,6 @@ #include "shared/runtime/context_manager_helpers.h" #include "py/binary.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class I2C: //| """Two wire serial protocol""" @@ -389,9 +388,10 @@ STATIC const mp_rom_map_elem_t busio_i2c_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(busio_i2c_locals_dict, busio_i2c_locals_dict_table); -const mp_obj_type_t busio_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .make_new = busio_i2c_make_new, - .locals_dict = (mp_obj_dict_t *)&busio_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + busio_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + make_new, busio_i2c_make_new, + locals_dict, &busio_i2c_locals_dict + ); diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index 9ca4bc08e0..39dff26c3b 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -39,7 +39,6 @@ #include "py/mperrno.h" #include "py/objproperty.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class SPI: @@ -490,12 +489,13 @@ STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(busio_spi_locals_dict, busio_spi_locals_dict_table); -const mp_obj_type_t busio_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .make_new = busio_spi_make_new, - .locals_dict = (mp_obj_dict_t *)&busio_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + busio_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + make_new, busio_spi_make_new, + locals_dict, &busio_spi_locals_dict + ); busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj, qstr arg_name) { return mp_arg_validate_type(obj, &busio_spi_type, arg_name); diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index 56cd7ac071..3bb9d6eb78 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -38,7 +38,6 @@ #include "py/objtype.h" #include "py/runtime.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" #define STREAM_DEBUG(...) (void)0 // #define STREAM_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__) @@ -418,12 +417,13 @@ STATIC void busio_uart_parity_print(const mp_print_t *print, mp_obj_t self_in, m mp_printf(print, "%q.%q.%q.%q", MP_QSTR_busio, MP_QSTR_UART, MP_QSTR_Parity, parity); } -const mp_obj_type_t busio_uart_parity_type = { - { &mp_type_type }, - .name = MP_QSTR_Parity, - .print = busio_uart_parity_print, - .locals_dict = (mp_obj_dict_t *)&busio_uart_parity_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + busio_uart_parity_type, + MP_QSTR_Parity, + MP_TYPE_FLAG_NONE, + print, busio_uart_parity_print, + locals_dict, &busio_uart_parity_locals_dict + ); STATIC const mp_rom_map_elem_t busio_uart_locals_dict_table[] = { #if CIRCUITPY_BUSIO_UART @@ -462,23 +462,21 @@ STATIC const mp_stream_p_t uart_stream_p = { .pyserial_readinto_compatibility = true, }; -const mp_obj_type_t busio_uart_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_UART, - .make_new = busio_uart_make_new, - .locals_dict = (mp_obj_dict_t *)&busio_uart_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &uart_stream_p, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + busio_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + make_new, busio_uart_make_new, + locals_dict, &busio_uart_locals_dict, + iter, mp_stream_unbuffered_iter, + protocol, &uart_stream_p + ); #else -const mp_obj_type_t busio_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .make_new = busio_uart_make_new, - .locals_dict = (mp_obj_dict_t *)&busio_uart_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + busio_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + make_new, busio_uart_make_new, + locals_dict, &busio_uart_locals_dict + ); #endif // CIRCUITPY_BUSIO_UART diff --git a/shared-bindings/camera/Camera.c b/shared-bindings/camera/Camera.c index eea22a0d81..3934c80208 100644 --- a/shared-bindings/camera/Camera.c +++ b/shared-bindings/camera/Camera.c @@ -121,9 +121,10 @@ STATIC const mp_rom_map_elem_t camera_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(camera_locals_dict, camera_locals_dict_table); -const mp_obj_type_t camera_type = { - { &mp_type_type }, - .name = MP_QSTR_Camera, - .make_new = camera_make_new, - .locals_dict = (mp_obj_dict_t *)&camera_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + camera_type, + MP_QSTR_Camera, + MP_TYPE_FLAG_NONE, + make_new, camera_make_new, + locals_dict, &camera_locals_dict + ); diff --git a/shared-bindings/camera/ImageFormat.c b/shared-bindings/camera/ImageFormat.c index 1a0c3c88d6..0bf29bb184 100644 --- a/shared-bindings/camera/ImageFormat.c +++ b/shared-bindings/camera/ImageFormat.c @@ -83,9 +83,10 @@ STATIC void camera_imageformat_print(const mp_print_t *print, mp_obj_t self_in, mp_printf(print, "%q.%q.%q", MP_QSTR_camera, MP_QSTR_ImageSize, format); } -const mp_obj_type_t camera_imageformat_type = { - { &mp_type_type }, - .name = MP_QSTR_ImageFormat, - .print = camera_imageformat_print, - .locals_dict = (mp_obj_t)&camera_imageformat_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + camera_imageformat_type, + MP_QSTR_ImageFormat, + MP_TYPE_FLAG_NONE, + print, camera_imageformat_print, + locals_dict, &camera_imageformat_locals_dict + ); diff --git a/shared-bindings/canio/CAN.c b/shared-bindings/canio/CAN.c index 912255adf4..f82b06216f 100644 --- a/shared-bindings/canio/CAN.c +++ b/shared-bindings/canio/CAN.c @@ -343,9 +343,10 @@ STATIC const mp_rom_map_elem_t canio_can_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(canio_can_locals_dict, canio_can_locals_dict_table); -const mp_obj_type_t canio_can_type = { - { &mp_type_type }, - .name = MP_QSTR_CAN, - .make_new = canio_can_make_new, - .locals_dict = (mp_obj_t)&canio_can_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + canio_can_type, + MP_QSTR_CAN, + MP_TYPE_FLAG_NONE, + make_new, canio_can_make_new, + locals_dict, &canio_can_locals_dict + ); diff --git a/shared-bindings/canio/Listener.c b/shared-bindings/canio/Listener.c index e10f7fde6f..ac28ea0df2 100644 --- a/shared-bindings/canio/Listener.c +++ b/shared-bindings/canio/Listener.c @@ -166,13 +166,10 @@ STATIC const mp_rom_map_elem_t canio_listener_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(canio_listener_locals_dict, canio_listener_locals_dict_table); -const mp_obj_type_t canio_listener_type = { - { &mp_type_type }, - .name = MP_QSTR_Listener, - .flags = MP_TYPE_FLAG_EXTENDED, - .locals_dict = (mp_obj_dict_t *)&canio_listener_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = canio_iternext, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + canio_listener_type, + MP_QSTR_Listener, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + locals_dict, &canio_listener_locals_dict, + iter, canio_iternext + ); diff --git a/shared-bindings/canio/Match.c b/shared-bindings/canio/Match.c index 1a9cd34916..4ead5d75c2 100644 --- a/shared-bindings/canio/Match.c +++ b/shared-bindings/canio/Match.c @@ -113,9 +113,10 @@ STATIC const mp_rom_map_elem_t canio_match_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(canio_match_locals_dict, canio_match_locals_dict_table); -const mp_obj_type_t canio_match_type = { - { &mp_type_type }, - .name = MP_QSTR_Match, - .make_new = canio_match_make_new, - .locals_dict = (mp_obj_dict_t *)&canio_match_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + canio_match_type, + MP_QSTR_Match, + MP_TYPE_FLAG_NONE, + make_new, canio_match_make_new, + locals_dict, &canio_match_locals_dict + ); diff --git a/shared-bindings/canio/Message.c b/shared-bindings/canio/Message.c index 432b10b4e8..b53181e0dd 100644 --- a/shared-bindings/canio/Message.c +++ b/shared-bindings/canio/Message.c @@ -136,9 +136,10 @@ STATIC const mp_rom_map_elem_t canio_message_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(canio_message_locals_dict, canio_message_locals_dict_table); -const mp_obj_type_t canio_message_type = { - { &mp_type_type }, - .name = MP_QSTR_Message, - .make_new = canio_message_make_new, - .locals_dict = (mp_obj_t)&canio_message_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + canio_message_type, + MP_QSTR_Message, + MP_TYPE_FLAG_NONE, + make_new, canio_message_make_new, + locals_dict, &canio_message_locals_dict + ); diff --git a/shared-bindings/canio/RemoteTransmissionRequest.c b/shared-bindings/canio/RemoteTransmissionRequest.c index 4b55bf2e75..3920942bfe 100644 --- a/shared-bindings/canio/RemoteTransmissionRequest.c +++ b/shared-bindings/canio/RemoteTransmissionRequest.c @@ -136,9 +136,10 @@ STATIC const mp_rom_map_elem_t canio_remote_transmission_request_locals_dict_tab }; STATIC MP_DEFINE_CONST_DICT(canio_remote_transmission_request_locals_dict, canio_remote_transmission_request_locals_dict_table); -const mp_obj_type_t canio_remote_transmission_request_type = { - { &mp_type_type }, - .name = MP_QSTR_RemoteTransmissionRequest, - .make_new = canio_remote_transmission_request_make_new, - .locals_dict = (mp_obj_t)&canio_remote_transmission_request_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + canio_remote_transmission_request_type, + MP_QSTR_RemoteTransmissionRequest, + MP_TYPE_FLAG_NONE, + make_new, canio_remote_transmission_request_make_new, + locals_dict, &canio_remote_transmission_request_locals_dict + ); diff --git a/shared-bindings/countio/Counter.c b/shared-bindings/countio/Counter.c index 2b646a83a7..fc7a9ca11d 100644 --- a/shared-bindings/countio/Counter.c +++ b/shared-bindings/countio/Counter.c @@ -145,9 +145,10 @@ STATIC const mp_rom_map_elem_t countio_counter_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(countio_counter_locals_dict, countio_counter_locals_dict_table); -const mp_obj_type_t countio_counter_type = { - { &mp_type_type }, - .name = MP_QSTR_Counter, - .make_new = countio_counter_make_new, - .locals_dict = (mp_obj_dict_t *)&countio_counter_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + countio_counter_type, + MP_QSTR_Counter, + MP_TYPE_FLAG_NONE, + make_new, countio_counter_make_new, + locals_dict, &countio_counter_locals_dict + ); diff --git a/shared-bindings/digitalio/DigitalInOut.c b/shared-bindings/digitalio/DigitalInOut.c index 832f16558a..07f6bc40a4 100644 --- a/shared-bindings/digitalio/DigitalInOut.c +++ b/shared-bindings/digitalio/DigitalInOut.c @@ -41,7 +41,6 @@ #include "shared-bindings/digitalio/DriveMode.h" #include "shared-bindings/digitalio/Pull.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" #if CIRCUITPY_CYW43 #include "bindings/cyw43/__init__.h" @@ -360,12 +359,13 @@ STATIC const mp_rom_map_elem_t digitalio_digitalinout_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(digitalio_digitalinout_locals_dict, digitalio_digitalinout_locals_dict_table); -const mp_obj_type_t digitalio_digitalinout_type = { - { &mp_type_type }, - .name = MP_QSTR_DigitalInOut, - .make_new = digitalio_digitalinout_make_new, - .locals_dict = (mp_obj_dict_t *)&digitalio_digitalinout_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + digitalio_digitalinout_type, + MP_QSTR_DigitalInOut, + MP_TYPE_FLAG_NONE, + make_new, digitalio_digitalinout_make_new, + locals_dict, &digitalio_digitalinout_locals_dict + ); // Helper for validating digitalio.DigitalInOut arguments digitalio_digitalinout_obj_t *assert_digitalinout(mp_obj_t obj) { diff --git a/shared-bindings/digitalio/Direction.c b/shared-bindings/digitalio/Direction.c index 78552e025c..a9cca3441f 100644 --- a/shared-bindings/digitalio/Direction.c +++ b/shared-bindings/digitalio/Direction.c @@ -75,9 +75,10 @@ STATIC void digitalio_direction_print(const mp_print_t *print, mp_obj_t self_in, mp_printf(print, "%q.%q.%q", MP_QSTR_digitalio, MP_QSTR_Direction, direction); } -const mp_obj_type_t digitalio_direction_type = { - { &mp_type_type }, - .name = MP_QSTR_Direction, - .print = digitalio_direction_print, - .locals_dict = (mp_obj_dict_t *)&digitalio_direction_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + digitalio_direction_type, + MP_QSTR_Direction, + MP_TYPE_FLAG_NONE, + print, digitalio_direction_print, + locals_dict, &digitalio_direction_locals_dict + ); diff --git a/shared-bindings/digitalio/DriveMode.c b/shared-bindings/digitalio/DriveMode.c index 1ebf51daea..c7cde494c8 100644 --- a/shared-bindings/digitalio/DriveMode.c +++ b/shared-bindings/digitalio/DriveMode.c @@ -64,9 +64,10 @@ STATIC void digitalio_drive_mode_print(const mp_print_t *print, mp_obj_t self_in mp_printf(print, "%q.%q.%q", MP_QSTR_digitalio, MP_QSTR_DriveMode, drive_mode); } -const mp_obj_type_t digitalio_drive_mode_type = { - { &mp_type_type }, - .name = MP_QSTR_DriveMode, - .print = digitalio_drive_mode_print, - .locals_dict = (mp_obj_dict_t *)&digitalio_drive_mode_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + digitalio_drive_mode_type, + MP_QSTR_DriveMode, + MP_TYPE_FLAG_NONE, + print, digitalio_drive_mode_print, + locals_dict, &digitalio_drive_mode_locals_dict + ); diff --git a/shared-bindings/digitalio/Pull.c b/shared-bindings/digitalio/Pull.c index 3c7a036d1e..3be38ef78c 100644 --- a/shared-bindings/digitalio/Pull.c +++ b/shared-bindings/digitalio/Pull.c @@ -26,7 +26,6 @@ #include "py/runtime.h" #include "shared-bindings/digitalio/Pull.h" -#include "supervisor/shared/translate/translate.h" //| class Pull: //| """Defines the pull of a digital input pin""" @@ -67,12 +66,13 @@ STATIC void digitalio_pull_print(const mp_print_t *print, mp_obj_t self_in, mp_p mp_printf(print, "%q.%q.%q", MP_QSTR_digitalio, MP_QSTR_Pull, pull); } -const mp_obj_type_t digitalio_pull_type = { - { &mp_type_type }, - .name = MP_QSTR_Pull, - .print = digitalio_pull_print, - .locals_dict = (mp_obj_dict_t *)&digitalio_pull_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + digitalio_pull_type, + MP_QSTR_Pull, + MP_TYPE_FLAG_NONE, + print, digitalio_pull_print, + locals_dict, &digitalio_pull_locals_dict + ); digitalio_pull_t validate_pull(mp_rom_obj_t obj, qstr arg_name) { if (obj == MP_ROM_PTR(&digitalio_pull_up_obj)) { diff --git a/shared-bindings/displayio/Bitmap.c b/shared-bindings/displayio/Bitmap.c index 7a314f0098..0b8b445a4f 100644 --- a/shared-bindings/displayio/Bitmap.c +++ b/shared-bindings/displayio/Bitmap.c @@ -34,7 +34,6 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class Bitmap: //| """Stores values of a certain size in a 2D array @@ -287,14 +286,12 @@ STATIC mp_int_t bitmap_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, m return common_hal_displayio_bitmap_get_buffer(self, bufinfo, flags); } -const mp_obj_type_t displayio_bitmap_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Bitmap, - .make_new = displayio_bitmap_make_new, - .locals_dict = (mp_obj_dict_t *)&displayio_bitmap_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .subscr = bitmap_subscr, - .buffer_p = { .get_buffer = bitmap_get_buffer }, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + displayio_bitmap_type, + MP_QSTR_Bitmap, + MP_TYPE_FLAG_NONE, + make_new, displayio_bitmap_make_new, + locals_dict, &displayio_bitmap_locals_dict, + subscr, bitmap_subscr, + buffer, bitmap_get_buffer + ); diff --git a/shared-bindings/displayio/ColorConverter.c b/shared-bindings/displayio/ColorConverter.c index 0ec78779ee..8962a58fa8 100644 --- a/shared-bindings/displayio/ColorConverter.c +++ b/shared-bindings/displayio/ColorConverter.c @@ -34,7 +34,6 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class ColorConverter: //| """Converts one color format to another.""" @@ -136,9 +135,10 @@ STATIC const mp_rom_map_elem_t displayio_colorconverter_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(displayio_colorconverter_locals_dict, displayio_colorconverter_locals_dict_table); -const mp_obj_type_t displayio_colorconverter_type = { - { &mp_type_type }, - .name = MP_QSTR_ColorConverter, - .make_new = displayio_colorconverter_make_new, - .locals_dict = (mp_obj_dict_t *)&displayio_colorconverter_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + displayio_colorconverter_type, + MP_QSTR_ColorConverter, + MP_TYPE_FLAG_NONE, + make_new, displayio_colorconverter_make_new, + locals_dict, &displayio_colorconverter_locals_dict + ); diff --git a/shared-bindings/displayio/Display.c b/shared-bindings/displayio/Display.c index 6b73ad2b6f..6bb391960d 100644 --- a/shared-bindings/displayio/Display.c +++ b/shared-bindings/displayio/Display.c @@ -37,7 +37,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/util.h" #include "shared-module/displayio/__init__.h" -#include "supervisor/shared/translate/translate.h" //| _DisplayBus = Union["FourWire", "paralleldisplay.ParallelBus", "I2CDisplay"] //| """:py:class:`FourWire`, :py:class:`paralleldisplay.ParallelBus` or :py:class:`I2CDisplay`""" @@ -500,9 +499,10 @@ STATIC const mp_rom_map_elem_t displayio_display_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(displayio_display_locals_dict, displayio_display_locals_dict_table); -const mp_obj_type_t displayio_display_type = { - { &mp_type_type }, - .name = MP_QSTR_Display, - .make_new = displayio_display_make_new, - .locals_dict = (mp_obj_dict_t *)&displayio_display_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + displayio_display_type, + MP_QSTR_Display, + MP_TYPE_FLAG_NONE, + make_new, displayio_display_make_new, + locals_dict, &displayio_display_locals_dict + ); diff --git a/shared-bindings/displayio/EPaperDisplay.c b/shared-bindings/displayio/EPaperDisplay.c index afda693c7e..0263538cf7 100644 --- a/shared-bindings/displayio/EPaperDisplay.c +++ b/shared-bindings/displayio/EPaperDisplay.c @@ -37,7 +37,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/util.h" #include "shared-module/displayio/__init__.h" -#include "supervisor/shared/translate/translate.h" //| class EPaperDisplay: //| """Manage updating an epaper display over a display bus @@ -403,9 +402,10 @@ STATIC const mp_rom_map_elem_t displayio_epaperdisplay_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(displayio_epaperdisplay_locals_dict, displayio_epaperdisplay_locals_dict_table); -const mp_obj_type_t displayio_epaperdisplay_type = { - { &mp_type_type }, - .name = MP_QSTR_EPaperDisplay, - .make_new = displayio_epaperdisplay_make_new, - .locals_dict = (mp_obj_dict_t *)&displayio_epaperdisplay_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + displayio_epaperdisplay_type, + MP_QSTR_EPaperDisplay, + MP_TYPE_FLAG_NONE, + make_new, displayio_epaperdisplay_make_new, + locals_dict, &displayio_epaperdisplay_locals_dict + ); diff --git a/shared-bindings/displayio/FourWire.c b/shared-bindings/displayio/FourWire.c index 29cdf09299..42f7dc352c 100644 --- a/shared-bindings/displayio/FourWire.c +++ b/shared-bindings/displayio/FourWire.c @@ -37,7 +37,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/util.h" #include "shared-module/displayio/__init__.h" -#include "supervisor/shared/translate/translate.h" //| class FourWire: //| """Manage updating a display over SPI four wire protocol in the background while Python code runs. @@ -166,9 +165,10 @@ STATIC const mp_rom_map_elem_t displayio_fourwire_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(displayio_fourwire_locals_dict, displayio_fourwire_locals_dict_table); -const mp_obj_type_t displayio_fourwire_type = { - { &mp_type_type }, - .name = MP_QSTR_FourWire, - .make_new = displayio_fourwire_make_new, - .locals_dict = (mp_obj_dict_t *)&displayio_fourwire_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + displayio_fourwire_type, + MP_QSTR_FourWire, + MP_TYPE_FLAG_NONE, + make_new, displayio_fourwire_make_new, + locals_dict, &displayio_fourwire_locals_dict + ); diff --git a/shared-bindings/displayio/Group.c b/shared-bindings/displayio/Group.c index 0800f4c861..177d62f83a 100644 --- a/shared-bindings/displayio/Group.c +++ b/shared-bindings/displayio/Group.c @@ -33,7 +33,6 @@ #include "py/objproperty.h" #include "py/objtype.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class Group: //| """Manage a group of sprites and groups and how they are inter-related.""" @@ -349,15 +348,13 @@ STATIC const mp_rom_map_elem_t displayio_group_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(displayio_group_locals_dict, displayio_group_locals_dict_table); -const mp_obj_type_t displayio_group_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Group, - .make_new = displayio_group_make_new, - .locals_dict = (mp_obj_dict_t *)&displayio_group_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .subscr = group_subscr, - .unary_op = group_unary_op, - .getiter = mp_obj_new_generic_iterator, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + displayio_group_type, + MP_QSTR_Group, + MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, displayio_group_make_new, + locals_dict, &displayio_group_locals_dict, + subscr, group_subscr, + unary_op, group_unary_op, + iter, mp_obj_generic_subscript_getiter + ); diff --git a/shared-bindings/displayio/I2CDisplay.c b/shared-bindings/displayio/I2CDisplay.c index ca5968421c..3356333688 100644 --- a/shared-bindings/displayio/I2CDisplay.c +++ b/shared-bindings/displayio/I2CDisplay.c @@ -37,7 +37,6 @@ #include "shared-bindings/busio/I2C.h" #include "shared-bindings/util.h" #include "shared-module/displayio/__init__.h" -#include "supervisor/shared/translate/translate.h" //| class I2CDisplay: //| """Manage updating a display over I2C in the background while Python code runs. @@ -130,9 +129,10 @@ STATIC const mp_rom_map_elem_t displayio_i2cdisplay_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(displayio_i2cdisplay_locals_dict, displayio_i2cdisplay_locals_dict_table); -const mp_obj_type_t displayio_i2cdisplay_type = { - { &mp_type_type }, - .name = MP_QSTR_I2CDisplay, - .make_new = displayio_i2cdisplay_make_new, - .locals_dict = (mp_obj_dict_t *)&displayio_i2cdisplay_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + displayio_i2cdisplay_type, + MP_QSTR_I2CDisplay, + MP_TYPE_FLAG_NONE, + make_new, displayio_i2cdisplay_make_new, + locals_dict, &displayio_i2cdisplay_locals_dict + ); diff --git a/shared-bindings/displayio/OnDiskBitmap.c b/shared-bindings/displayio/OnDiskBitmap.c index 99cf3c4576..a8fd2658fa 100644 --- a/shared-bindings/displayio/OnDiskBitmap.c +++ b/shared-bindings/displayio/OnDiskBitmap.c @@ -30,7 +30,7 @@ #include "py/runtime.h" #include "py/objproperty.h" -#include "supervisor/shared/translate/translate.h" + #include "shared-bindings/displayio/OnDiskBitmap.h" //| class OnDiskBitmap: @@ -148,9 +148,10 @@ STATIC const mp_rom_map_elem_t displayio_ondiskbitmap_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(displayio_ondiskbitmap_locals_dict, displayio_ondiskbitmap_locals_dict_table); -const mp_obj_type_t displayio_ondiskbitmap_type = { - { &mp_type_type }, - .name = MP_QSTR_OnDiskBitmap, - .make_new = displayio_ondiskbitmap_make_new, - .locals_dict = (mp_obj_dict_t *)&displayio_ondiskbitmap_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + displayio_ondiskbitmap_type, + MP_QSTR_OnDiskBitmap, + MP_TYPE_FLAG_NONE, + make_new, displayio_ondiskbitmap_make_new, + locals_dict, &displayio_ondiskbitmap_locals_dict + ); diff --git a/shared-bindings/displayio/Palette.c b/shared-bindings/displayio/Palette.c index abe5e369dd..2c0e7ee3a1 100644 --- a/shared-bindings/displayio/Palette.c +++ b/shared-bindings/displayio/Palette.c @@ -34,7 +34,6 @@ #include "py/runtime.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class Palette: //| """Map a pixel palette_index to a full color. Colors are transformed to the display's format internally to @@ -142,7 +141,7 @@ STATIC mp_obj_t palette_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t val // Convert a tuple or list to a bytearray. if (mp_obj_is_type(value, &mp_type_tuple) || mp_obj_is_type(value, &mp_type_list)) { - value = mp_type_bytes.make_new(&mp_type_bytes, 1, 0, &value); + value = MP_OBJ_TYPE_GET_SLOT(&mp_type_bytes, make_new)(&mp_type_bytes, 1, 0, &value); } uint32_t color; @@ -216,15 +215,13 @@ STATIC const mp_rom_map_elem_t displayio_palette_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(displayio_palette_locals_dict, displayio_palette_locals_dict_table); -const mp_obj_type_t displayio_palette_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Palette, - .make_new = displayio_palette_make_new, - .locals_dict = (mp_obj_dict_t *)&displayio_palette_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .subscr = palette_subscr, - .unary_op = group_unary_op, - .getiter = mp_obj_new_generic_iterator, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + displayio_palette_type, + MP_QSTR_Palette, + MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, displayio_palette_make_new, + locals_dict, &displayio_palette_locals_dict, + subscr, palette_subscr, + unary_op, group_unary_op, + iter, mp_obj_generic_subscript_getiter + ); diff --git a/shared-bindings/displayio/Shape.c b/shared-bindings/displayio/Shape.c index 572ed216b8..767185f6c9 100644 --- a/shared-bindings/displayio/Shape.c +++ b/shared-bindings/displayio/Shape.c @@ -32,7 +32,6 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class Shape: //| """Represents a shape made by defining boundaries that may be mirrored.""" @@ -94,9 +93,10 @@ STATIC const mp_rom_map_elem_t displayio_shape_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(displayio_shape_locals_dict, displayio_shape_locals_dict_table); -const mp_obj_type_t displayio_shape_type = { - { &mp_type_type }, - .name = MP_QSTR_Shape, - .make_new = displayio_shape_make_new, - .locals_dict = (mp_obj_dict_t *)&displayio_shape_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + displayio_shape_type, + MP_QSTR_Shape, + MP_TYPE_FLAG_NONE, + make_new, displayio_shape_make_new, + locals_dict, &displayio_shape_locals_dict + ); diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c index 67ed6d4b0a..ed19fd34d7 100644 --- a/shared-bindings/displayio/TileGrid.c +++ b/shared-bindings/displayio/TileGrid.c @@ -38,7 +38,6 @@ #include "shared-bindings/displayio/OnDiskBitmap.h" #include "shared-bindings/displayio/Palette.h" #include "shared-bindings/displayio/Shape.h" -#include "supervisor/shared/translate/translate.h" //| class TileGrid: //| """A grid of tiles sourced out of one bitmap @@ -504,13 +503,11 @@ STATIC const mp_rom_map_elem_t displayio_tilegrid_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(displayio_tilegrid_locals_dict, displayio_tilegrid_locals_dict_table); -const mp_obj_type_t displayio_tilegrid_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_TileGrid, - .make_new = displayio_tilegrid_make_new, - .locals_dict = (mp_obj_dict_t *)&displayio_tilegrid_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .subscr = tilegrid_subscr, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + displayio_tilegrid_type, + MP_QSTR_TileGrid, + MP_TYPE_FLAG_NONE, + make_new, displayio_tilegrid_make_new, + locals_dict, &displayio_tilegrid_locals_dict, + subscr, tilegrid_subscr + ); diff --git a/shared-bindings/dotclockframebuffer/DotClockFramebuffer.c b/shared-bindings/dotclockframebuffer/DotClockFramebuffer.c index 6799618efa..3a55166f8b 100644 --- a/shared-bindings/dotclockframebuffer/DotClockFramebuffer.c +++ b/shared-bindings/dotclockframebuffer/DotClockFramebuffer.c @@ -382,14 +382,12 @@ STATIC const mp_rom_map_elem_t dotclockframebuffer_framebuffer_locals_dict_table }; STATIC MP_DEFINE_CONST_DICT(dotclockframebuffer_framebuffer_locals_dict, dotclockframebuffer_framebuffer_locals_dict_table); -const mp_obj_type_t dotclockframebuffer_framebuffer_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_DotClockFramebuffer, - .make_new = dotclockframebuffer_framebuffer_make_new, - .locals_dict = (mp_obj_dict_t *)&dotclockframebuffer_framebuffer_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .buffer_p = { .get_buffer = dotclockframebuffer_framebuffer_get_buffer, }, - .protocol = &dotclockframebuffer_framebuffer_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + dotclockframebuffer_framebuffer_type, + MP_QSTR_DotClockFramebuffer, + MP_TYPE_FLAG_NONE, + make_new, dotclockframebuffer_framebuffer_make_new, + locals_dict, &dotclockframebuffer_framebuffer_locals_dict, + buffer, dotclockframebuffer_framebuffer_get_buffer, + protocol, &dotclockframebuffer_framebuffer_proto + ); diff --git a/shared-bindings/fontio/BuiltinFont.c b/shared-bindings/fontio/BuiltinFont.c index cf28b6f223..53d92df995 100644 --- a/shared-bindings/fontio/BuiltinFont.c +++ b/shared-bindings/fontio/BuiltinFont.c @@ -34,7 +34,6 @@ #include "py/runtime.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| from typing_extensions import Protocol # for compat with python < 3.8 //| @@ -107,8 +106,9 @@ STATIC const mp_rom_map_elem_t fontio_builtinfont_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(fontio_builtinfont_locals_dict, fontio_builtinfont_locals_dict_table); -const mp_obj_type_t fontio_builtinfont_type = { - { &mp_type_type }, - .name = MP_QSTR_BuiltinFont, - .locals_dict = (mp_obj_dict_t *)&fontio_builtinfont_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + fontio_builtinfont_type, + MP_QSTR_BuiltinFont, + MP_TYPE_FLAG_NONE, + locals_dict, &fontio_builtinfont_locals_dict + ); diff --git a/shared-bindings/fontio/Glyph.c b/shared-bindings/fontio/Glyph.c index 9fd49cfb1a..4fc3a12b92 100644 --- a/shared-bindings/fontio/Glyph.c +++ b/shared-bindings/fontio/Glyph.c @@ -55,23 +55,7 @@ //| ... //| const mp_obj_namedtuple_type_t fontio_glyph_type = { - .base = { - .base = { - .type = &mp_type_type - }, - .name = MP_QSTR_Glyph, - .flags = MP_TYPE_FLAG_EXTENDED, - .print = namedtuple_print, - .make_new = namedtuple_make_new, - .parent = &mp_type_tuple, - .attr = namedtuple_attr, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - ), - }, + NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_Glyph), .n_fields = 8, .fields = { MP_QSTR_bitmap, diff --git a/shared-bindings/framebufferio/FramebufferDisplay.c b/shared-bindings/framebufferio/FramebufferDisplay.c index 955761c273..dfbc41f6c8 100644 --- a/shared-bindings/framebufferio/FramebufferDisplay.c +++ b/shared-bindings/framebufferio/FramebufferDisplay.c @@ -38,7 +38,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/util.h" #include "shared-module/displayio/__init__.h" -#include "supervisor/shared/translate/translate.h" //| class FramebufferDisplay: //| """Manage updating a display with framebuffer in RAM @@ -364,9 +363,10 @@ STATIC const mp_rom_map_elem_t framebufferio_framebufferdisplay_locals_dict_tabl }; STATIC MP_DEFINE_CONST_DICT(framebufferio_framebufferdisplay_locals_dict, framebufferio_framebufferdisplay_locals_dict_table); -const mp_obj_type_t framebufferio_framebufferdisplay_type = { - { &mp_type_type }, - .name = MP_QSTR_FramebufferDisplay, - .make_new = framebufferio_framebufferdisplay_make_new, - .locals_dict = (mp_obj_dict_t *)&framebufferio_framebufferdisplay_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + framebufferio_framebufferdisplay_type, + MP_QSTR_FramebufferDisplay, + MP_TYPE_FLAG_NONE, + make_new, framebufferio_framebufferdisplay_make_new, + locals_dict, &framebufferio_framebufferdisplay_locals_dict + ); diff --git a/shared-bindings/frequencyio/FrequencyIn.c b/shared-bindings/frequencyio/FrequencyIn.c index c3ce5e94a7..569361a566 100644 --- a/shared-bindings/frequencyio/FrequencyIn.c +++ b/shared-bindings/frequencyio/FrequencyIn.c @@ -33,7 +33,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/frequencyio/FrequencyIn.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class FrequencyIn: //| """Read a frequency signal @@ -218,9 +217,10 @@ STATIC const mp_rom_map_elem_t frequencyio_frequencyin_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(frequencyio_frequencyin_locals_dict, frequencyio_frequencyin_locals_dict_table); -const mp_obj_type_t frequencyio_frequencyin_type = { - { &mp_type_type }, - .name = MP_QSTR_frequencyin, - .make_new = frequencyio_frequencyin_make_new, - .locals_dict = (mp_obj_dict_t *)&frequencyio_frequencyin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + frequencyio_frequencyin_type, + MP_QSTR_frequencyin, + MP_TYPE_FLAG_NONE, + make_new, frequencyio_frequencyin_make_new, + locals_dict, &frequencyio_frequencyin_locals_dict + ); diff --git a/shared-bindings/gifio/GifWriter.c b/shared-bindings/gifio/GifWriter.c index e28d48bb99..a230478bb7 100644 --- a/shared-bindings/gifio/GifWriter.c +++ b/shared-bindings/gifio/GifWriter.c @@ -158,9 +158,10 @@ STATIC const mp_rom_map_elem_t gifio_gifwriter_locals_table[] = { STATIC MP_DEFINE_CONST_DICT(gifio_gifwriter_locals, gifio_gifwriter_locals_table); -const mp_obj_type_t gifio_gifwriter_type = { - { &mp_type_type }, - .name = MP_QSTR_GifWriter, - .make_new = gifio_gifwriter_make_new, - .locals_dict = (mp_obj_dict_t *)&gifio_gifwriter_locals, -}; +MP_DEFINE_CONST_OBJ_TYPE( + gifio_gifwriter_type, + MP_QSTR_GifWriter, + MP_TYPE_FLAG_NONE, + make_new, gifio_gifwriter_make_new, + locals_dict, &gifio_gifwriter_locals + ); diff --git a/shared-bindings/gifio/OnDiskGif.c b/shared-bindings/gifio/OnDiskGif.c index 840d58e410..a7a7b62dae 100644 --- a/shared-bindings/gifio/OnDiskGif.c +++ b/shared-bindings/gifio/OnDiskGif.c @@ -32,7 +32,6 @@ #include "py/objproperty.h" #include "shared/runtime/context_manager_helpers.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" #include "shared-bindings/gifio/OnDiskGif.h" //| class OnDiskGif: @@ -321,9 +320,10 @@ STATIC const mp_rom_map_elem_t gifio_ondiskgif_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(gifio_ondiskgif_locals_dict, gifio_ondiskgif_locals_dict_table); -const mp_obj_type_t gifio_ondiskgif_type = { - { &mp_type_type }, - .name = MP_QSTR_OnDiskGif, - .make_new = gifio_ondiskgif_make_new, - .locals_dict = (mp_obj_dict_t *)&gifio_ondiskgif_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + gifio_ondiskgif_type, + MP_QSTR_OnDiskGif, + MP_TYPE_FLAG_NONE, + make_new, gifio_ondiskgif_make_new, + locals_dict, &gifio_ondiskgif_locals_dict + ); diff --git a/shared-bindings/gnss/GNSS.c b/shared-bindings/gnss/GNSS.c index 54b3f0b46c..a3b2f464d9 100644 --- a/shared-bindings/gnss/GNSS.c +++ b/shared-bindings/gnss/GNSS.c @@ -169,9 +169,10 @@ STATIC const mp_rom_map_elem_t gnss_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(gnss_locals_dict, gnss_locals_dict_table); -const mp_obj_type_t gnss_type = { - { &mp_type_type }, - .name = MP_QSTR_GNSS, - .make_new = gnss_make_new, - .locals_dict = (mp_obj_dict_t *)&gnss_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + gnss_type, + MP_QSTR_GNSS, + MP_TYPE_FLAG_NONE, + make_new, gnss_make_new, + locals_dict, &gnss_locals_dict + ); diff --git a/shared-bindings/gnss/PositionFix.c b/shared-bindings/gnss/PositionFix.c index 35d4971b66..d63623eb6a 100644 --- a/shared-bindings/gnss/PositionFix.c +++ b/shared-bindings/gnss/PositionFix.c @@ -71,9 +71,10 @@ STATIC void gnss_positionfix_print(const mp_print_t *print, mp_obj_t self_in, mp mp_printf(print, "%q.%q.%q", MP_QSTR_gnss, MP_QSTR_PositionFix, posfix); } -const mp_obj_type_t gnss_positionfix_type = { - { &mp_type_type }, - .name = MP_QSTR_PositionFix, - .print = gnss_positionfix_print, - .locals_dict = (mp_obj_t)&gnss_positionfix_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + gnss_positionfix_type, + MP_QSTR_PositionFix, + MP_TYPE_FLAG_NONE, + print, gnss_positionfix_print, + locals_dict, &gnss_positionfix_locals_dict + ); diff --git a/shared-bindings/gnss/SatelliteSystem.c b/shared-bindings/gnss/SatelliteSystem.c index 4bf0d6cf4b..c9e71f2c8f 100644 --- a/shared-bindings/gnss/SatelliteSystem.c +++ b/shared-bindings/gnss/SatelliteSystem.c @@ -104,9 +104,10 @@ STATIC void gnss_satellitesystem_print(const mp_print_t *print, mp_obj_t self_in mp_printf(print, "%q.%q.%q", MP_QSTR_gnss, MP_QSTR_SatelliteSystem, system); } -const mp_obj_type_t gnss_satellitesystem_type = { - { &mp_type_type }, - .name = MP_QSTR_SatelliteSystem, - .print = gnss_satellitesystem_print, - .locals_dict = (mp_obj_t)&gnss_satellitesystem_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + gnss_satellitesystem_type, + MP_QSTR_SatelliteSystem, + MP_TYPE_FLAG_NONE, + print, gnss_satellitesystem_print, + locals_dict, &gnss_satellitesystem_locals_dict + ); diff --git a/shared-bindings/hashlib/Hash.c b/shared-bindings/hashlib/Hash.c index e3cbbc39d3..6ab23e1613 100644 --- a/shared-bindings/hashlib/Hash.c +++ b/shared-bindings/hashlib/Hash.c @@ -89,8 +89,9 @@ STATIC const mp_rom_map_elem_t hashlib_hash_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(hashlib_hash_locals_dict, hashlib_hash_locals_dict_table); -const mp_obj_type_t hashlib_hash_type = { - { &mp_type_type }, - .name = MP_QSTR_Hash, - .locals_dict = (mp_obj_dict_t *)&hashlib_hash_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + hashlib_hash_type, + MP_QSTR_Hash, + MP_TYPE_FLAG_NONE, + locals_dict, &hashlib_hash_locals_dict + ); diff --git a/shared-bindings/hashlib/__init__.c b/shared-bindings/hashlib/__init__.c index 87f6df495a..4179926ea5 100644 --- a/shared-bindings/hashlib/__init__.c +++ b/shared-bindings/hashlib/__init__.c @@ -31,7 +31,6 @@ #include "py/runtime.h" #include "shared-bindings/hashlib/__init__.h" #include "shared-bindings/hashlib/Hash.h" -#include "supervisor/shared/translate/translate.h" //| """Hashing related functions //| diff --git a/shared-bindings/i2ctarget/I2CTarget.c b/shared-bindings/i2ctarget/I2CTarget.c index 1bc672032d..79d234c5dc 100644 --- a/shared-bindings/i2ctarget/I2CTarget.c +++ b/shared-bindings/i2ctarget/I2CTarget.c @@ -214,12 +214,13 @@ STATIC const mp_rom_map_elem_t i2ctarget_i2c_target_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(i2ctarget_i2c_target_locals_dict, i2ctarget_i2c_target_locals_dict_table); -const mp_obj_type_t i2ctarget_i2c_target_type = { - { &mp_type_type }, - .name = MP_QSTR_I2CTarget, - .make_new = i2ctarget_i2c_target_make_new, - .locals_dict = (mp_obj_dict_t *)&i2ctarget_i2c_target_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + i2ctarget_i2c_target_type, + MP_QSTR_I2CTarget, + MP_TYPE_FLAG_NONE, + make_new, i2ctarget_i2c_target_make_new, + locals_dict, &i2ctarget_i2c_target_locals_dict + ); //| class I2CTargetRequest: //| def __init__( @@ -416,9 +417,10 @@ STATIC const mp_rom_map_elem_t i2ctarget_i2c_target_request_locals_dict_table[] STATIC MP_DEFINE_CONST_DICT(i2ctarget_i2c_target_request_locals_dict, i2ctarget_i2c_target_request_locals_dict_table); -const mp_obj_type_t i2ctarget_i2c_target_request_type = { - { &mp_type_type }, - .name = MP_QSTR_I2CTargetRequest, - .make_new = i2ctarget_i2c_target_request_make_new, - .locals_dict = (mp_obj_dict_t *)&i2ctarget_i2c_target_request_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + i2ctarget_i2c_target_request_type, + MP_QSTR_I2CTargetRequest, + MP_TYPE_FLAG_NONE, + make_new, i2ctarget_i2c_target_request_make_new, + locals_dict, &i2ctarget_i2c_target_request_locals_dict + ); diff --git a/shared-bindings/imagecapture/ParallelImageCapture.c b/shared-bindings/imagecapture/ParallelImageCapture.c index 56d7bfbc48..e79d989712 100644 --- a/shared-bindings/imagecapture/ParallelImageCapture.c +++ b/shared-bindings/imagecapture/ParallelImageCapture.c @@ -189,9 +189,10 @@ STATIC const mp_rom_map_elem_t imagecapture_parallelimagecapture_locals_dict_tab STATIC MP_DEFINE_CONST_DICT(imagecapture_parallelimagecapture_locals_dict, imagecapture_parallelimagecapture_locals_dict_table); -const mp_obj_type_t imagecapture_parallelimagecapture_type = { - { &mp_type_type }, - .name = MP_QSTR_ParallelImageCapture, - .make_new = imagecapture_parallelimagecapture_make_new, - .locals_dict = (mp_obj_dict_t *)&imagecapture_parallelimagecapture_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + imagecapture_parallelimagecapture_type, + MP_QSTR_ParallelImageCapture, + MP_TYPE_FLAG_NONE, + make_new, imagecapture_parallelimagecapture_make_new, + locals_dict, &imagecapture_parallelimagecapture_locals_dict + ); diff --git a/shared-bindings/ipaddress/IPv4Address.c b/shared-bindings/ipaddress/IPv4Address.c index 4f7cfc3853..13cc165c4d 100644 --- a/shared-bindings/ipaddress/IPv4Address.c +++ b/shared-bindings/ipaddress/IPv4Address.c @@ -175,15 +175,13 @@ STATIC const mp_rom_map_elem_t ipaddress_ipv4address_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ipaddress_ipv4address_locals_dict, ipaddress_ipv4address_locals_dict_table); -const mp_obj_type_t ipaddress_ipv4address_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Address, - .make_new = ipaddress_ipv4address_make_new, - .locals_dict = (mp_obj_dict_t *)&ipaddress_ipv4address_locals_dict, - .print = ipaddress_ipv4address_print, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = ipaddress_ipv4address_unary_op, - .binary_op = ipaddress_ipv4address_binary_op, - ) -}; +MP_DEFINE_CONST_OBJ_TYPE( + ipaddress_ipv4address_type, + MP_QSTR_Address, + MP_TYPE_FLAG_NONE, + make_new, ipaddress_ipv4address_make_new, + locals_dict, &ipaddress_ipv4address_locals_dict, + print, ipaddress_ipv4address_print, + unary_op, ipaddress_ipv4address_unary_op, + binary_op, ipaddress_ipv4address_binary_op + ); diff --git a/shared-bindings/is31fl3741/FrameBuffer.c b/shared-bindings/is31fl3741/FrameBuffer.c index 02a783fd15..a7725ff65e 100644 --- a/shared-bindings/is31fl3741/FrameBuffer.c +++ b/shared-bindings/is31fl3741/FrameBuffer.c @@ -292,14 +292,12 @@ STATIC mp_int_t is31fl3741_FrameBuffer_get_buffer(mp_obj_t self_in, mp_buffer_in return 0; } -const mp_obj_type_t is31fl3741_FrameBuffer_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_is31fl3741, - .locals_dict = (mp_obj_dict_t *)&is31fl3741_FrameBuffer_locals_dict, - .make_new = is31fl3741_FrameBuffer_make_new, - MP_TYPE_EXTENDED_FIELDS( - .buffer_p = { .get_buffer = is31fl3741_FrameBuffer_get_buffer, }, - .protocol = &is31fl3741_FrameBuffer_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + is31fl3741_FrameBuffer_type, + MP_QSTR_is31fl3741, + MP_TYPE_FLAG_NONE, + locals_dict, &is31fl3741_FrameBuffer_locals_dict, + make_new, is31fl3741_FrameBuffer_make_new, + buffer, is31fl3741_FrameBuffer_get_buffer, + protocol, &is31fl3741_FrameBuffer_proto + ); diff --git a/shared-bindings/is31fl3741/IS31FL3741.c b/shared-bindings/is31fl3741/IS31FL3741.c index 79982b4c90..6debc82dc5 100644 --- a/shared-bindings/is31fl3741/IS31FL3741.c +++ b/shared-bindings/is31fl3741/IS31FL3741.c @@ -172,9 +172,10 @@ STATIC const mp_rom_map_elem_t is31fl3741_IS31FL3741_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(is31fl3741_IS31FL3741_locals_dict, is31fl3741_IS31FL3741_locals_dict_table); -const mp_obj_type_t is31fl3741_IS31FL3741_type = { - { &mp_type_type }, - .name = MP_QSTR_is31fl3741, - .locals_dict = (mp_obj_dict_t *)&is31fl3741_IS31FL3741_locals_dict, - .make_new = is31fl3741_IS31FL3741_make_new, -}; +MP_DEFINE_CONST_OBJ_TYPE( + is31fl3741_IS31FL3741_type, + MP_QSTR_is31fl3741, + MP_TYPE_FLAG_NONE, + locals_dict, &is31fl3741_IS31FL3741_locals_dict, + make_new, is31fl3741_IS31FL3741_make_new + ); diff --git a/shared-bindings/keypad/Event.c b/shared-bindings/keypad/Event.c index 1a3db1c61f..ea6dd0018b 100644 --- a/shared-bindings/keypad/Event.c +++ b/shared-bindings/keypad/Event.c @@ -180,15 +180,13 @@ STATIC const mp_rom_map_elem_t keypad_event_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(keypad_event_locals_dict, keypad_event_locals_dict_table); -const mp_obj_type_t keypad_event_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Event, - .make_new = keypad_event_make_new, - .print = keypad_event_print, - .locals_dict = (mp_obj_dict_t *)&keypad_event_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = keypad_event_unary_op, - .binary_op = keypad_event_binary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + keypad_event_type, + MP_QSTR_Event, + MP_TYPE_FLAG_NONE, + make_new, keypad_event_make_new, + print, keypad_event_print, + locals_dict, &keypad_event_locals_dict, + unary_op, keypad_event_unary_op, + binary_op, keypad_event_binary_op + ); diff --git a/shared-bindings/keypad/EventQueue.c b/shared-bindings/keypad/EventQueue.c index d09d5db129..9293f8390b 100644 --- a/shared-bindings/keypad/EventQueue.c +++ b/shared-bindings/keypad/EventQueue.c @@ -165,15 +165,13 @@ STATIC const mp_stream_p_t eventqueue_p = { #endif -const mp_obj_type_t keypad_eventqueue_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_EventQueue, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = keypad_eventqueue_unary_op, - #if MICROPY_PY_USELECT - .protocol = &eventqueue_p, - #endif - ), - .locals_dict = (mp_obj_t)&keypad_eventqueue_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + keypad_eventqueue_type, + MP_QSTR_EventQueue, + MP_TYPE_FLAG_NONE, + unary_op, keypad_eventqueue_unary_op, + #if MICROPY_PY_USELECT + protocol, &eventqueue_p, + #endif + locals_dict, &keypad_eventqueue_locals_dict + ); diff --git a/shared-bindings/keypad/KeyMatrix.c b/shared-bindings/keypad/KeyMatrix.c index 8261d6abc7..3da3773455 100644 --- a/shared-bindings/keypad/KeyMatrix.c +++ b/shared-bindings/keypad/KeyMatrix.c @@ -250,11 +250,12 @@ STATIC MP_DEFINE_CONST_DICT(keypad_keymatrix_locals_dict, keypad_keymatrix_local #endif -const mp_obj_type_t keypad_keymatrix_type = { - { &mp_type_type }, - .name = MP_QSTR_KeyMatrix, - .make_new = keypad_keymatrix_make_new, +MP_DEFINE_CONST_OBJ_TYPE( + keypad_keymatrix_type, + MP_QSTR_KeyMatrix, + MP_TYPE_FLAG_NONE, + make_new, keypad_keymatrix_make_new #if CIRCUITPY_KEYPAD_KEYMATRIX - .locals_dict = (mp_obj_t)&keypad_keymatrix_locals_dict, + , locals_dict, &keypad_keymatrix_locals_dict #endif -}; + ); diff --git a/shared-bindings/keypad/Keys.c b/shared-bindings/keypad/Keys.c index 6b1aaa1138..870ee03b3f 100644 --- a/shared-bindings/keypad/Keys.c +++ b/shared-bindings/keypad/Keys.c @@ -184,11 +184,12 @@ STATIC const mp_rom_map_elem_t keypad_keys_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(keypad_keys_locals_dict, keypad_keys_locals_dict_table); #endif -const mp_obj_type_t keypad_keys_type = { - { &mp_type_type }, - .name = MP_QSTR_Keys, - .make_new = keypad_keys_make_new, +MP_DEFINE_CONST_OBJ_TYPE( + keypad_keys_type, + MP_QSTR_Keys, + MP_TYPE_FLAG_NONE, + make_new, keypad_keys_make_new #if CIRCUITPY_KEYPAD_KEYS - .locals_dict = (mp_obj_t)&keypad_keys_locals_dict, + , locals_dict, &keypad_keys_locals_dict #endif -}; + ); diff --git a/shared-bindings/keypad/ShiftRegisterKeys.c b/shared-bindings/keypad/ShiftRegisterKeys.c index 9e9a1bb0c0..18e0565fcf 100644 --- a/shared-bindings/keypad/ShiftRegisterKeys.c +++ b/shared-bindings/keypad/ShiftRegisterKeys.c @@ -236,11 +236,12 @@ STATIC const mp_rom_map_elem_t keypad_shiftregisterkeys_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(keypad_shiftregisterkeys_locals_dict, keypad_shiftregisterkeys_locals_dict_table); #endif -const mp_obj_type_t keypad_shiftregisterkeys_type = { - { &mp_type_type }, - .name = MP_QSTR_ShiftRegisterKeys, - .make_new = keypad_shiftregisterkeys_make_new, +MP_DEFINE_CONST_OBJ_TYPE( + keypad_shiftregisterkeys_type, + MP_QSTR_ShiftRegisterKeys, + MP_TYPE_FLAG_NONE, + make_new, keypad_shiftregisterkeys_make_new #if CIRCUITPY_KEYPAD_SHIFTREGISTERKEYS - .locals_dict = (mp_obj_t)&keypad_shiftregisterkeys_locals_dict, + , locals_dict, &keypad_shiftregisterkeys_locals_dict #endif -}; + ); diff --git a/shared-bindings/math/__init__.c b/shared-bindings/math/__init__.c index 2c17532197..1ab07170f3 100644 --- a/shared-bindings/math/__init__.c +++ b/shared-bindings/math/__init__.c @@ -27,7 +27,6 @@ #include "py/builtin.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #if MICROPY_PY_BUILTINS_FLOAT diff --git a/shared-bindings/mdns/RemoteService.c b/shared-bindings/mdns/RemoteService.c index c1d7b25783..defd055722 100644 --- a/shared-bindings/mdns/RemoteService.c +++ b/shared-bindings/mdns/RemoteService.c @@ -135,8 +135,9 @@ STATIC const mp_rom_map_elem_t mdns_remoteservice_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(mdns_remoteservice_locals_dict, mdns_remoteservice_locals_dict_table); -const mp_obj_type_t mdns_remoteservice_type = { - { &mp_type_type }, - .name = MP_QSTR_RemoteService, - .locals_dict = (mp_obj_dict_t *)&mdns_remoteservice_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + mdns_remoteservice_type, + MP_QSTR_RemoteService, + MP_TYPE_FLAG_NONE, + locals_dict, &mdns_remoteservice_locals_dict + ); diff --git a/shared-bindings/mdns/Server.c b/shared-bindings/mdns/Server.c index 2afc64e02b..d9afe891e6 100644 --- a/shared-bindings/mdns/Server.c +++ b/shared-bindings/mdns/Server.c @@ -213,9 +213,10 @@ STATIC const mp_rom_map_elem_t mdns_server_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(mdns_server_locals_dict, mdns_server_locals_dict_table); -const mp_obj_type_t mdns_server_type = { - .base = { &mp_type_type }, - .name = MP_QSTR_Server, - .make_new = mdns_server_make_new, - .locals_dict = (mp_obj_t)&mdns_server_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mdns_server_type, + MP_QSTR_Server, + MP_TYPE_FLAG_NONE, + make_new, mdns_server_make_new, + locals_dict, &mdns_server_locals_dict + ); diff --git a/shared-bindings/memorymap/AddressRange.c b/shared-bindings/memorymap/AddressRange.c index 4ea7c680f5..fc3465a4e7 100644 --- a/shared-bindings/memorymap/AddressRange.c +++ b/shared-bindings/memorymap/AddressRange.c @@ -29,7 +29,6 @@ #include "py/runtime.h" #include "py/runtime0.h" #include "shared-bindings/memorymap/AddressRange.h" -#include "supervisor/shared/translate/translate.h" //| class AddressRange: //| r"""Presents a range of addresses as a bytearray. @@ -94,7 +93,7 @@ STATIC mp_obj_t memorymap_addressrange_make_new(const mp_obj_type_t *type, size_ size_t start; if (mp_obj_is_small_int(args[ARG_start].u_obj)) { start = MP_OBJ_SMALL_INT_VALUE(args[ARG_start].u_obj); - } else if (mp_obj_is_type(args[ARG_start].u_obj, &mp_type_int)) { + } else if (mp_obj_is_exact_type(args[ARG_start].u_obj, &mp_type_int)) { start = mp_obj_int_get_uint_checked(args[ARG_start].u_obj); } else { mp_obj_t arg = mp_unary_op(MP_UNARY_OP_INT, args[ARG_start].u_obj); @@ -229,14 +228,12 @@ STATIC mp_obj_t memorymap_addressrange_subscr(mp_obj_t self_in, mp_obj_t index_i } } -const mp_obj_type_t memorymap_addressrange_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_AddressRange, - .make_new = memorymap_addressrange_make_new, - .locals_dict = (mp_obj_t)&memorymap_addressrange_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .subscr = memorymap_addressrange_subscr, - .unary_op = memorymap_addressrange_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + memorymap_addressrange_type, + MP_QSTR_AddressRange, + MP_TYPE_FLAG_NONE, + make_new, memorymap_addressrange_make_new, + locals_dict, (mp_obj_t)&memorymap_addressrange_locals_dict, + subscr, memorymap_addressrange_subscr, + unary_op, memorymap_addressrange_unary_op + ); diff --git a/shared-bindings/memorymonitor/AllocationAlarm.c b/shared-bindings/memorymonitor/AllocationAlarm.c index a21a14b2f0..1ba59a0354 100644 --- a/shared-bindings/memorymonitor/AllocationAlarm.c +++ b/shared-bindings/memorymonitor/AllocationAlarm.c @@ -31,7 +31,6 @@ #include "py/runtime0.h" #include "shared-bindings/memorymonitor/AllocationAlarm.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class AllocationAlarm: //| def __init__(self, *, minimum_block_count: int = 1) -> None: @@ -124,9 +123,10 @@ STATIC const mp_rom_map_elem_t memorymonitor_allocationalarm_locals_dict_table[] }; STATIC MP_DEFINE_CONST_DICT(memorymonitor_allocationalarm_locals_dict, memorymonitor_allocationalarm_locals_dict_table); -const mp_obj_type_t memorymonitor_allocationalarm_type = { - { &mp_type_type }, - .name = MP_QSTR_AllocationAlarm, - .make_new = memorymonitor_allocationalarm_make_new, - .locals_dict = (mp_obj_dict_t *)&memorymonitor_allocationalarm_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + memorymonitor_allocationalarm_type, + MP_QSTR_AllocationAlarm, + MP_TYPE_FLAG_NONE, + make_new, memorymonitor_allocationalarm_make_new, + locals_dict, &memorymonitor_allocationalarm_locals_dict + ); diff --git a/shared-bindings/memorymonitor/AllocationSize.c b/shared-bindings/memorymonitor/AllocationSize.c index 3340f51615..fe82a91553 100644 --- a/shared-bindings/memorymonitor/AllocationSize.c +++ b/shared-bindings/memorymonitor/AllocationSize.c @@ -31,7 +31,6 @@ #include "py/runtime0.h" #include "shared-bindings/memorymonitor/AllocationSize.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class AllocationSize: //| def __init__(self) -> None: @@ -165,12 +164,13 @@ STATIC const mp_rom_map_elem_t memorymonitor_allocationsize_locals_dict_table[] }; STATIC MP_DEFINE_CONST_DICT(memorymonitor_allocationsize_locals_dict, memorymonitor_allocationsize_locals_dict_table); -const mp_obj_type_t memorymonitor_allocationsize_type = { - { &mp_type_type }, - .name = MP_QSTR_AllocationSize, - .make_new = memorymonitor_allocationsize_make_new, - .subscr = memorymonitor_allocationsize_subscr, - .unary_op = memorymonitor_allocationsize_unary_op, - .getiter = mp_obj_new_generic_iterator, - .locals_dict = (mp_obj_dict_t *)&memorymonitor_allocationsize_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + memorymonitor_allocationsize_type, + MP_QSTR_AllocationSize, + MP_TYPE_FLAG_ITER_IS_GETITER, + make_new, memorymonitor_allocationsize_make_new, + subscr, memorymonitor_allocationsize_subscr, + unary_op, memorymonitor_allocationsize_unary_op, + iter, mp_obj_generic_subscript_getiter, + locals_dict, &memorymonitor_allocationsize_locals_dict + ); diff --git a/shared-bindings/microcontroller/Pin.c b/shared-bindings/microcontroller/Pin.c index ea27df9812..5d33b6a590 100644 --- a/shared-bindings/microcontroller/Pin.c +++ b/shared-bindings/microcontroller/Pin.c @@ -31,7 +31,6 @@ #include "py/nlr.h" #include "py/obj.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class Pin: //| """Identifies an IO pin on the microcontroller.""" @@ -83,15 +82,13 @@ void shared_bindings_microcontroller_pin_print(const mp_print_t *print, mp_obj_t } } -const mp_obj_type_t mcu_pin_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Pin, - .print = shared_bindings_microcontroller_pin_print, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_generic_unary_op, - ) -}; +MP_DEFINE_CONST_OBJ_TYPE( + mcu_pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + print, shared_bindings_microcontroller_pin_print, + unary_op, mp_generic_unary_op + ); const mcu_pin_obj_t *validate_obj_is_pin(mp_obj_t obj, qstr arg_name) { return MP_OBJ_TO_PTR(mp_arg_validate_type(obj, &mcu_pin_type, arg_name)); diff --git a/shared-bindings/microcontroller/Processor.c b/shared-bindings/microcontroller/Processor.c index e4819047da..80064f75a0 100644 --- a/shared-bindings/microcontroller/Processor.c +++ b/shared-bindings/microcontroller/Processor.c @@ -38,7 +38,6 @@ #include "py/objtype.h" #include "py/objproperty.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class Processor: @@ -171,8 +170,9 @@ STATIC const mp_rom_map_elem_t mcu_processor_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(mcu_processor_locals_dict, mcu_processor_locals_dict_table); -const mp_obj_type_t mcu_processor_type = { - { &mp_type_type }, - .name = MP_QSTR_Processor, - .locals_dict = (mp_obj_dict_t *)&mcu_processor_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mcu_processor_type, + MP_QSTR_Processor, + MP_TYPE_FLAG_NONE, + locals_dict, &mcu_processor_locals_dict + ); diff --git a/shared-bindings/microcontroller/RunMode.c b/shared-bindings/microcontroller/RunMode.c index b29670576b..e4e8282234 100644 --- a/shared-bindings/microcontroller/RunMode.c +++ b/shared-bindings/microcontroller/RunMode.c @@ -92,9 +92,10 @@ STATIC void mcu_runmode_print(const mp_print_t *print, mp_obj_t self_in, mp_prin runmode); } -const mp_obj_type_t mcu_runmode_type = { - { &mp_type_type }, - .name = MP_QSTR_RunMode, - .print = mcu_runmode_print, - .locals_dict = (mp_obj_dict_t *)&mcu_runmode_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mcu_runmode_type, + MP_QSTR_RunMode, + MP_TYPE_FLAG_NONE, + print, mcu_runmode_print, + locals_dict, &mcu_runmode_locals_dict + ); diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c index 3858cad776..51940a3dab 100644 --- a/shared-bindings/microcontroller/__init__.c +++ b/shared-bindings/microcontroller/__init__.c @@ -39,8 +39,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Processor.h" -#include "supervisor/shared/translate/translate.h" - //| """Pin references and cpu functionality //| //| The `microcontroller` module defines the pins and other bare-metal hardware diff --git a/shared-bindings/msgpack/ExtType.c b/shared-bindings/msgpack/ExtType.c index 15e30c1575..36b342a594 100644 --- a/shared-bindings/msgpack/ExtType.c +++ b/shared-bindings/msgpack/ExtType.c @@ -108,9 +108,10 @@ STATIC mp_rom_map_elem_t mod_msgpack_exttype_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(mod_msgpack_exttype_locals_dict, mod_msgpack_exttype_locals_dict_table); -const mp_obj_type_t mod_msgpack_exttype_type = { - { &mp_type_type }, - .name = MP_QSTR_ExtType, - .make_new = mod_msgpack_exttype_make_new, - .locals_dict = (mp_obj_dict_t *)&mod_msgpack_exttype_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mod_msgpack_exttype_type, + MP_QSTR_ExtType, + MP_TYPE_FLAG_NONE, + make_new, mod_msgpack_exttype_make_new, + locals_dict, &mod_msgpack_exttype_locals_dict + ); diff --git a/shared-bindings/neopixel_write/__init__.c b/shared-bindings/neopixel_write/__init__.c index 8a471f26ff..3c307f5c71 100644 --- a/shared-bindings/neopixel_write/__init__.c +++ b/shared-bindings/neopixel_write/__init__.c @@ -30,7 +30,6 @@ #include "py/runtime.h" #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" // RGB LED timing information: diff --git a/shared-bindings/nvm/ByteArray.c b/shared-bindings/nvm/ByteArray.c index e7c3fc37e8..f5b3f83e08 100644 --- a/shared-bindings/nvm/ByteArray.c +++ b/shared-bindings/nvm/ByteArray.c @@ -29,7 +29,6 @@ #include "py/runtime.h" #include "py/runtime0.h" #include "shared-bindings/nvm/ByteArray.h" -#include "supervisor/shared/translate/translate.h" //| class ByteArray: //| r"""Presents a stretch of non-volatile memory as a bytearray. @@ -159,13 +158,11 @@ STATIC mp_obj_t nvm_bytearray_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj } } -const mp_obj_type_t nvm_bytearray_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_ByteArray, - .locals_dict = (mp_obj_t)&nvm_bytearray_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .subscr = nvm_bytearray_subscr, - .unary_op = nvm_bytearray_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + nvm_bytearray_type, + MP_QSTR_ByteArray, + MP_TYPE_FLAG_NONE, + locals_dict, &nvm_bytearray_locals_dict, + subscr, nvm_bytearray_subscr, + unary_op, nvm_bytearray_unary_op + ); diff --git a/shared-bindings/onewireio/OneWire.c b/shared-bindings/onewireio/OneWire.c index f52ebb4c6a..88b9111bf2 100644 --- a/shared-bindings/onewireio/OneWire.c +++ b/shared-bindings/onewireio/OneWire.c @@ -152,9 +152,10 @@ STATIC const mp_rom_map_elem_t onewireio_onewire_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(onewireio_onewire_locals_dict, onewireio_onewire_locals_dict_table); -const mp_obj_type_t onewireio_onewire_type = { - { &mp_type_type }, - .name = MP_QSTR_OneWire, - .make_new = onewireio_onewire_make_new, - .locals_dict = (mp_obj_dict_t *)&onewireio_onewire_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + onewireio_onewire_type, + MP_QSTR_OneWire, + MP_TYPE_FLAG_NONE, + make_new, onewireio_onewire_make_new, + locals_dict, &onewireio_onewire_locals_dict + ); diff --git a/shared-bindings/os/__init__.c b/shared-bindings/os/__init__.c index c839064969..85b54aaa18 100644 --- a/shared-bindings/os/__init__.c +++ b/shared-bindings/os/__init__.c @@ -36,7 +36,6 @@ #include "py/objstr.h" #include "py/runtime.h" #include "shared-bindings/os/__init__.h" -#include "supervisor/shared/translate/translate.h" //| """functions that an OS normally provides //| diff --git a/shared-bindings/paralleldisplay/ParallelBus.c b/shared-bindings/paralleldisplay/ParallelBus.c index f8ab6470e4..890c06c60a 100644 --- a/shared-bindings/paralleldisplay/ParallelBus.c +++ b/shared-bindings/paralleldisplay/ParallelBus.c @@ -35,7 +35,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/util.h" #include "shared-module/displayio/__init__.h" -#include "supervisor/shared/translate/translate.h" //| class ParallelBus: //| """Manage updating a display over 8-bit parallel bus in the background while Python code runs. This @@ -158,9 +157,10 @@ STATIC const mp_rom_map_elem_t paralleldisplay_parallelbus_locals_dict_table[] = }; STATIC MP_DEFINE_CONST_DICT(paralleldisplay_parallelbus_locals_dict, paralleldisplay_parallelbus_locals_dict_table); -const mp_obj_type_t paralleldisplay_parallelbus_type = { - { &mp_type_type }, - .name = MP_QSTR_ParallelBus, - .make_new = paralleldisplay_parallelbus_make_new, - .locals_dict = (mp_obj_dict_t *)¶lleldisplay_parallelbus_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + paralleldisplay_parallelbus_type, + MP_QSTR_ParallelBus, + MP_TYPE_FLAG_NONE, + make_new, paralleldisplay_parallelbus_make_new, + locals_dict, ¶lleldisplay_parallelbus_locals_dict + ); diff --git a/shared-bindings/ps2io/Ps2.c b/shared-bindings/ps2io/Ps2.c index 789e1173c8..076cb4ca73 100644 --- a/shared-bindings/ps2io/Ps2.c +++ b/shared-bindings/ps2io/Ps2.c @@ -34,7 +34,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/ps2io/Ps2.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class Ps2: //| """Communicate with a PS/2 keyboard or mouse @@ -226,13 +225,11 @@ STATIC const mp_rom_map_elem_t ps2io_ps2_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(ps2io_ps2_locals_dict, ps2io_ps2_locals_dict_table); -const mp_obj_type_t ps2io_ps2_type = { - { &mp_type_type }, - .name = MP_QSTR_Ps2, - .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = ps2io_ps2_make_new, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = ps2_unary_op, - ), - .locals_dict = (mp_obj_dict_t *)&ps2io_ps2_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + ps2io_ps2_type, + MP_QSTR_Ps2, + MP_TYPE_FLAG_NONE, + make_new, ps2io_ps2_make_new, + unary_op, ps2_unary_op, + locals_dict, &ps2io_ps2_locals_dict + ); diff --git a/shared-bindings/pulseio/PulseIn.c b/shared-bindings/pulseio/PulseIn.c index d738726f1c..f26edfea2c 100644 --- a/shared-bindings/pulseio/PulseIn.c +++ b/shared-bindings/pulseio/PulseIn.c @@ -33,7 +33,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/pulseio/PulseIn.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class PulseIn: //| """Measure a series of active and idle pulses. This is commonly used in infrared receivers @@ -290,14 +289,12 @@ STATIC const mp_rom_map_elem_t pulseio_pulsein_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pulseio_pulsein_locals_dict, pulseio_pulsein_locals_dict_table); -const mp_obj_type_t pulseio_pulsein_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_PulseIn, - .make_new = pulseio_pulsein_make_new, - .locals_dict = (mp_obj_dict_t *)&pulseio_pulsein_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .subscr = pulsein_subscr, - .unary_op = pulsein_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + pulseio_pulsein_type, + MP_QSTR_PulseIn, + MP_TYPE_FLAG_NONE, + make_new, pulseio_pulsein_make_new, + locals_dict, &pulseio_pulsein_locals_dict, + subscr, pulsein_subscr, + unary_op, pulsein_unary_op + ); diff --git a/shared-bindings/pulseio/PulseOut.c b/shared-bindings/pulseio/PulseOut.c index 16777d9843..8d130d2a70 100644 --- a/shared-bindings/pulseio/PulseOut.c +++ b/shared-bindings/pulseio/PulseOut.c @@ -34,7 +34,6 @@ #include "shared-bindings/pulseio/PulseOut.h" #include "shared-bindings/pwmio/PWMOut.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class PulseOut: //| """Pulse PWM "carrier" output on and off. This is commonly used in infrared remotes. The @@ -148,9 +147,10 @@ STATIC const mp_rom_map_elem_t pulseio_pulseout_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pulseio_pulseout_locals_dict, pulseio_pulseout_locals_dict_table); -const mp_obj_type_t pulseio_pulseout_type = { - { &mp_type_type }, - .name = MP_QSTR_PulseOut, - .make_new = pulseio_pulseout_make_new, - .locals_dict = (mp_obj_dict_t *)&pulseio_pulseout_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pulseio_pulseout_type, + MP_QSTR_PulseOut, + MP_TYPE_FLAG_NONE, + make_new, pulseio_pulseout_make_new, + locals_dict, &pulseio_pulseout_locals_dict + ); diff --git a/shared-bindings/pwmio/PWMOut.c b/shared-bindings/pwmio/PWMOut.c index 0c99e26a7d..5ec03d1c28 100644 --- a/shared-bindings/pwmio/PWMOut.c +++ b/shared-bindings/pwmio/PWMOut.c @@ -33,7 +33,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/pwmio/PWMOut.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" void common_hal_pwmio_pwmout_raise_error(pwmout_result_t result) { @@ -299,9 +298,10 @@ STATIC const mp_rom_map_elem_t pwmio_pwmout_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pwmio_pwmout_locals_dict, pwmio_pwmout_locals_dict_table); -const mp_obj_type_t pwmio_pwmout_type = { - { &mp_type_type }, - .name = MP_QSTR_PWMOut, - .make_new = pwmio_pwmout_make_new, - .locals_dict = (mp_obj_dict_t *)&pwmio_pwmout_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pwmio_pwmout_type, + MP_QSTR_PWMOut, + MP_TYPE_FLAG_NONE, + make_new, pwmio_pwmout_make_new, + locals_dict, &pwmio_pwmout_locals_dict + ); diff --git a/shared-bindings/qrio/QRDecoder.c b/shared-bindings/qrio/QRDecoder.c index e8cabade33..a2c8ea7ee8 100644 --- a/shared-bindings/qrio/QRDecoder.c +++ b/shared-bindings/qrio/QRDecoder.c @@ -139,9 +139,10 @@ STATIC const mp_rom_map_elem_t qrio_qrdecoder_locals_table[] = { STATIC MP_DEFINE_CONST_DICT(qrio_qrdecoder_locals, qrio_qrdecoder_locals_table); -const mp_obj_type_t qrio_qrdecoder_type_obj = { - { &mp_type_type }, - .name = MP_QSTR_QRDecoder, - .make_new = qrio_qrdecoder_make_new, - .locals_dict = (mp_obj_dict_t *)&qrio_qrdecoder_locals, -}; +MP_DEFINE_CONST_OBJ_TYPE( + qrio_qrdecoder_type_obj, + MP_QSTR_QRDecoder, + MP_TYPE_FLAG_NONE, + make_new, qrio_qrdecoder_make_new, + locals_dict, &qrio_qrdecoder_locals + ); diff --git a/shared-bindings/qrio/QRInfo.c b/shared-bindings/qrio/QRInfo.c index d53e638f81..dafbc19b99 100644 --- a/shared-bindings/qrio/QRInfo.c +++ b/shared-bindings/qrio/QRInfo.c @@ -40,23 +40,7 @@ //| const mp_obj_namedtuple_type_t qrio_qrinfo_type_obj = { - .base = { - .base = { - .type = &mp_type_type - }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_QRInfo, - .print = namedtuple_print, - .parent = &mp_type_tuple, - .make_new = namedtuple_make_new, - .attr = namedtuple_attr, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - ), - }, + NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_QRInfo), .n_fields = 2, .fields = { MP_QSTR_payload, diff --git a/shared-bindings/random/__init__.c b/shared-bindings/random/__init__.c index 6fa9629f8c..16bdf95df4 100644 --- a/shared-bindings/random/__init__.c +++ b/shared-bindings/random/__init__.c @@ -31,7 +31,6 @@ #include "py/obj.h" #include "py/runtime.h" #include "shared-bindings/random/__init__.h" -#include "supervisor/shared/translate/translate.h" //| """pseudo-random numbers and choices //| diff --git a/shared-bindings/rgbmatrix/RGBMatrix.c b/shared-bindings/rgbmatrix/RGBMatrix.c index c68798e352..c333e8c1d1 100644 --- a/shared-bindings/rgbmatrix/RGBMatrix.c +++ b/shared-bindings/rgbmatrix/RGBMatrix.c @@ -435,14 +435,12 @@ STATIC mp_int_t rgbmatrix_rgbmatrix_get_buffer(mp_obj_t self_in, mp_buffer_info_ return 0; } -const mp_obj_type_t rgbmatrix_RGBMatrix_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_RGBMatrix, - .locals_dict = (mp_obj_dict_t *)&rgbmatrix_rgbmatrix_locals_dict, - .make_new = rgbmatrix_rgbmatrix_make_new, - MP_TYPE_EXTENDED_FIELDS( - .buffer_p = { .get_buffer = rgbmatrix_rgbmatrix_get_buffer, }, - .protocol = &rgbmatrix_rgbmatrix_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + rgbmatrix_RGBMatrix_type, + MP_QSTR_RGBMatrix, + MP_TYPE_FLAG_NONE, + locals_dict, &rgbmatrix_rgbmatrix_locals_dict, + make_new, rgbmatrix_rgbmatrix_make_new, + buffer, rgbmatrix_rgbmatrix_get_buffer, + protocol, &rgbmatrix_rgbmatrix_proto + ); diff --git a/shared-bindings/rotaryio/IncrementalEncoder.c b/shared-bindings/rotaryio/IncrementalEncoder.c index d2031432e6..6a4e8098bc 100644 --- a/shared-bindings/rotaryio/IncrementalEncoder.c +++ b/shared-bindings/rotaryio/IncrementalEncoder.c @@ -180,9 +180,10 @@ STATIC const mp_rom_map_elem_t rotaryio_incrementalencoder_locals_dict_table[] = }; STATIC MP_DEFINE_CONST_DICT(rotaryio_incrementalencoder_locals_dict, rotaryio_incrementalencoder_locals_dict_table); -const mp_obj_type_t rotaryio_incrementalencoder_type = { - { &mp_type_type }, - .name = MP_QSTR_IncrementalEncoder, - .make_new = rotaryio_incrementalencoder_make_new, - .locals_dict = (mp_obj_dict_t *)&rotaryio_incrementalencoder_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + rotaryio_incrementalencoder_type, + MP_QSTR_IncrementalEncoder, + MP_TYPE_FLAG_NONE, + make_new, rotaryio_incrementalencoder_make_new, + locals_dict, &rotaryio_incrementalencoder_locals_dict + ); diff --git a/shared-bindings/rtc/RTC.c b/shared-bindings/rtc/RTC.c index bf2b0915c4..114055833d 100644 --- a/shared-bindings/rtc/RTC.c +++ b/shared-bindings/rtc/RTC.c @@ -34,7 +34,6 @@ #include "shared-bindings/rtc/__init__.h" #include "shared-bindings/rtc/RTC.h" #include "shared-bindings/time/__init__.h" -#include "supervisor/shared/translate/translate.h" const rtc_rtc_obj_t rtc_rtc_obj = {{&rtc_rtc_type}}; @@ -126,9 +125,10 @@ STATIC const mp_rom_map_elem_t rtc_rtc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(rtc_rtc_locals_dict, rtc_rtc_locals_dict_table); -const mp_obj_type_t rtc_rtc_type = { - { &mp_type_type }, - .name = MP_QSTR_RTC, - .make_new = rtc_rtc_make_new, - .locals_dict = (mp_obj_dict_t *)&rtc_rtc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + rtc_rtc_type, + MP_QSTR_RTC, + MP_TYPE_FLAG_NONE, + make_new, rtc_rtc_make_new, + locals_dict, &rtc_rtc_locals_dict + ); diff --git a/shared-bindings/rtc/__init__.c b/shared-bindings/rtc/__init__.c index e1220841eb..908b324071 100644 --- a/shared-bindings/rtc/__init__.c +++ b/shared-bindings/rtc/__init__.c @@ -87,4 +87,6 @@ const mp_obj_module_t rtc_module = { .globals = (mp_obj_dict_t *)&rtc_module_globals, }; +MP_REGISTER_ROOT_POINTER(mp_obj_t rtc_time_source); + MP_REGISTER_MODULE(MP_QSTR_rtc, rtc_module); diff --git a/shared-bindings/sdcardio/SDCard.c b/shared-bindings/sdcardio/SDCard.c index 4bceefba45..94ea3ab321 100644 --- a/shared-bindings/sdcardio/SDCard.c +++ b/shared-bindings/sdcardio/SDCard.c @@ -194,9 +194,10 @@ STATIC const mp_rom_map_elem_t sdcardio_sdcard_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(sdcardio_sdcard_locals_dict, sdcardio_sdcard_locals_dict_table); -const mp_obj_type_t sdcardio_SDCard_type = { - { &mp_type_type }, - .name = MP_QSTR_SDCard, - .make_new = sdcardio_sdcard_make_new, - .locals_dict = (mp_obj_dict_t *)&sdcardio_sdcard_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + sdcardio_SDCard_type, + MP_QSTR_SDCard, + MP_TYPE_FLAG_NONE, + make_new, sdcardio_sdcard_make_new, + locals_dict, &sdcardio_sdcard_locals_dict + ); diff --git a/shared-bindings/sdioio/SDCard.c b/shared-bindings/sdioio/SDCard.c index 7ff4fb750a..7c0d391957 100644 --- a/shared-bindings/sdioio/SDCard.c +++ b/shared-bindings/sdioio/SDCard.c @@ -38,7 +38,6 @@ #include "py/mperrno.h" #include "py/objproperty.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class SDCard: //| """SD Card Block Interface with SDIO @@ -268,9 +267,10 @@ STATIC const mp_rom_map_elem_t sdioio_sdcard_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(sdioio_sdcard_locals_dict, sdioio_sdcard_locals_dict_table); -const mp_obj_type_t sdioio_SDCard_type = { - { &mp_type_type }, - .name = MP_QSTR_SDCard, - .make_new = sdioio_sdcard_make_new, - .locals_dict = (mp_obj_dict_t *)&sdioio_sdcard_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + sdioio_SDCard_type, + MP_QSTR_SDCard, + MP_TYPE_FLAG_NONE, + make_new, sdioio_sdcard_make_new, + locals_dict, &sdioio_sdcard_locals_dict + ); diff --git a/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c index d9643495ba..58a4113693 100644 --- a/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c +++ b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c @@ -116,14 +116,12 @@ STATIC const mp_rom_map_elem_t sharpdisplay_framebuffer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(sharpdisplay_framebuffer_locals_dict, sharpdisplay_framebuffer_locals_dict_table); -const mp_obj_type_t sharpdisplay_framebuffer_type = { - { &mp_type_type }, - .name = MP_QSTR_SharpMemoryFramebuffer, - .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = sharpdisplay_framebuffer_make_new, - .locals_dict = (mp_obj_dict_t *)&sharpdisplay_framebuffer_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .buffer_p = { .get_buffer = sharpdisplay_framebuffer_get_buffer, }, - .protocol = &sharpdisplay_framebuffer_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + sharpdisplay_framebuffer_type, + MP_QSTR_SharpMemoryFramebuffer, + MP_TYPE_FLAG_NONE, + make_new, sharpdisplay_framebuffer_make_new, + locals_dict, &sharpdisplay_framebuffer_locals_dict, + buffer, sharpdisplay_framebuffer_get_buffer, + protocol, &sharpdisplay_framebuffer_proto + ); diff --git a/shared-bindings/socketpool/Socket.c b/shared-bindings/socketpool/Socket.c index 9d439b5bd4..f4a811913a 100644 --- a/shared-bindings/socketpool/Socket.c +++ b/shared-bindings/socketpool/Socket.c @@ -447,13 +447,11 @@ STATIC const mp_stream_p_t socket_stream_p = { .is_text = false, }; -const mp_obj_type_t socketpool_socket_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Socket, - .locals_dict = (mp_obj_dict_t *)&socketpool_socket_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_generic_unary_op, - .protocol = &socket_stream_p, - ) -}; +MP_DEFINE_CONST_OBJ_TYPE( + socketpool_socket_type, + MP_QSTR_Socket, + MP_TYPE_FLAG_NONE, + locals_dict, &socketpool_socket_locals_dict, + unary_op, mp_generic_unary_op, + protocol, &socket_stream_p + ); diff --git a/shared-bindings/socketpool/SocketPool.c b/shared-bindings/socketpool/SocketPool.c index 381291fbaf..3db72a86c1 100644 --- a/shared-bindings/socketpool/SocketPool.c +++ b/shared-bindings/socketpool/SocketPool.c @@ -194,12 +194,13 @@ STATIC const mp_rom_map_elem_t socketpool_socketpool_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(socketpool_socketpool_locals_dict, socketpool_socketpool_locals_dict_table); -const mp_obj_type_t socketpool_socketpool_type = { - { &mp_type_type }, - .name = MP_QSTR_SocketPool, - .make_new = socketpool_socketpool_make_new, - .locals_dict = (mp_obj_dict_t *)&socketpool_socketpool_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + socketpool_socketpool_type, + MP_QSTR_SocketPool, + MP_TYPE_FLAG_NONE, + make_new, socketpool_socketpool_make_new, + locals_dict, &socketpool_socketpool_locals_dict + ); MP_WEAK mp_obj_t common_hal_socketpool_socketpool_gethostbyname_raise(socketpool_socketpool_obj_t *self, const char *host) { @@ -219,7 +220,7 @@ void common_hal_socketpool_socketpool_raise_gaierror_noname(void) { mp_obj_t exc_args[] = { MP_OBJ_NEW_SMALL_INT(SOCKETPOOL_EAI_NONAME), - mp_obj_new_str_from_vstr(&mp_type_str, &vstr), + mp_obj_new_str_from_vstr(&vstr), }; nlr_raise(mp_obj_new_exception_args(&mp_type_gaierror, MP_ARRAY_SIZE(exc_args), exc_args)); } diff --git a/shared-bindings/ssl/SSLContext.c b/shared-bindings/ssl/SSLContext.c index a132476614..4b1c0c7403 100644 --- a/shared-bindings/ssl/SSLContext.c +++ b/shared-bindings/ssl/SSLContext.c @@ -198,9 +198,10 @@ STATIC const mp_rom_map_elem_t ssl_sslcontext_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ssl_sslcontext_locals_dict, ssl_sslcontext_locals_dict_table); -const mp_obj_type_t ssl_sslcontext_type = { - { &mp_type_type }, - .name = MP_QSTR_SSLContext, - .make_new = ssl_sslcontext_make_new, - .locals_dict = (mp_obj_dict_t *)&ssl_sslcontext_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + ssl_sslcontext_type, + MP_QSTR_SSLContext, + MP_TYPE_FLAG_NONE, + make_new, ssl_sslcontext_make_new, + locals_dict, &ssl_sslcontext_locals_dict + ); diff --git a/shared-bindings/ssl/SSLSocket.c b/shared-bindings/ssl/SSLSocket.c index e0e7911715..f2a8d8ade6 100644 --- a/shared-bindings/ssl/SSLSocket.c +++ b/shared-bindings/ssl/SSLSocket.c @@ -297,12 +297,11 @@ STATIC const mp_rom_map_elem_t ssl_sslsocket_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ssl_sslsocket_locals_dict, ssl_sslsocket_locals_dict_table); -const mp_obj_type_t ssl_sslsocket_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_SSLSocket, - .locals_dict = (mp_obj_dict_t *)&ssl_sslsocket_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_generic_unary_op, - ) -}; +MP_DEFINE_CONST_OBJ_TYPE( + ssl_sslsocket_type, + MP_QSTR_SSLSocket, + MP_TYPE_FLAG_NONE, + locals_dict, &ssl_sslsocket_locals_dict, + unary_op, mp_generic_unary_op + + ); diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index b774c5550e..8eaf19cf0f 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -33,7 +33,6 @@ #include "py/objnamedtuple.h" #include "py/runtime.h" #include "shared-bindings/storage/__init__.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/flash.h" //| """Storage management diff --git a/shared-bindings/struct/__init__.c b/shared-bindings/struct/__init__.c index 09bc663b47..964d690a38 100644 --- a/shared-bindings/struct/__init__.c +++ b/shared-bindings/struct/__init__.c @@ -36,7 +36,6 @@ #include "py/parsenum.h" #include "shared-bindings/struct/__init__.h" #include "shared-module/struct/__init__.h" -#include "supervisor/shared/translate/translate.h" //| """Manipulation of c-style data //| @@ -74,7 +73,7 @@ STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) { memset(p, 0, size); byte *end_p = &p[size]; shared_modules_struct_pack_into(args[0], p, end_p, n_args - 1, &args[1]); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, MP_OBJ_FUN_ARGS_MAX, struct_pack); @@ -133,8 +132,8 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_unpack_obj, 2, 3, struct_unpack); STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_format, ARG_buffer, ARG_offset }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_format, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_format, MP_ARG_REQUIRED | MP_ARG_OBJ, {} }, + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {} }, { MP_QSTR_offset, MP_ARG_INT, {.u_int = 0} }, }; diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c index 792f18637a..672b59f076 100644 --- a/shared-bindings/supervisor/Runtime.c +++ b/shared-bindings/supervisor/Runtime.c @@ -251,8 +251,9 @@ STATIC const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(supervisor_runtime_locals_dict, supervisor_runtime_locals_dict_table); -const mp_obj_type_t supervisor_runtime_type = { - .base = { &mp_type_type }, - .name = MP_QSTR_Runtime, - .locals_dict = (mp_obj_dict_t *)&supervisor_runtime_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + supervisor_runtime_type, + MP_QSTR_Runtime, + MP_TYPE_FLAG_NONE, + locals_dict, &supervisor_runtime_locals_dict + ); diff --git a/shared-bindings/supervisor/StatusBar.c b/shared-bindings/supervisor/StatusBar.c index 8db1906f5e..4438c5fa4d 100644 --- a/shared-bindings/supervisor/StatusBar.c +++ b/shared-bindings/supervisor/StatusBar.c @@ -118,8 +118,9 @@ STATIC const mp_rom_map_elem_t supervisor_status_bar_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(supervisor_status_bar_locals_dict, supervisor_status_bar_locals_dict_table); -const mp_obj_type_t supervisor_status_bar_type = { - .base = { &mp_type_type }, - .name = MP_QSTR_Status_Bar, - .locals_dict = (mp_obj_dict_t *)&supervisor_status_bar_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + supervisor_status_bar_type, + MP_QSTR_Status_Bar, + MP_TYPE_FLAG_NONE, + locals_dict, &supervisor_status_bar_locals_dict + ); diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index a1820e215e..8b93866655 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -33,7 +33,6 @@ #include "supervisor/shared/display.h" #include "supervisor/shared/reload.h" #include "supervisor/shared/traceback.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/workflow.h" #if CIRCUITPY_USB_IDENTIFICATION diff --git a/shared-bindings/synthio/Biquad.c b/shared-bindings/synthio/Biquad.c index 6fd2856e02..b8dc735154 100644 --- a/shared-bindings/synthio/Biquad.c +++ b/shared-bindings/synthio/Biquad.c @@ -82,23 +82,7 @@ STATIC mp_obj_t synthio_biquad_make_new(const mp_obj_type_t *type_in, size_t n_a } const mp_obj_namedtuple_type_t synthio_biquad_type_obj = { - .base = { - .base = { - .type = &mp_type_type - }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Biquad, - .print = namedtuple_print, - .parent = &mp_type_tuple, - .make_new = synthio_biquad_make_new, - .attr = namedtuple_attr, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - ), - }, + NAMEDTUPLE_TYPE_BASE_AND_SLOTS_MAKE_NEW(MP_QSTR_Biquad, synthio_biquad_make_new), .n_fields = 5, .fields = { MP_QSTR_a1, diff --git a/shared-bindings/synthio/LFO.c b/shared-bindings/synthio/LFO.c index 86e32999cf..6d56da910a 100644 --- a/shared-bindings/synthio/LFO.c +++ b/shared-bindings/synthio/LFO.c @@ -291,14 +291,12 @@ STATIC const synthio_block_proto_t lfo_proto = { .tick = common_hal_synthio_lfo_tick, }; -const mp_obj_type_t synthio_lfo_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_LFO, - .make_new = synthio_lfo_make_new, - .locals_dict = (mp_obj_dict_t *)&synthio_lfo_locals_dict, - .print = lfo_print, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &lfo_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + synthio_lfo_type, + MP_QSTR_LFO, + MP_TYPE_FLAG_NONE, + make_new, synthio_lfo_make_new, + locals_dict, &synthio_lfo_locals_dict, + print, lfo_print, + protocol, &lfo_proto + ); diff --git a/shared-bindings/synthio/Math.c b/shared-bindings/synthio/Math.c index ea75b7c4bf..44073e9a10 100644 --- a/shared-bindings/synthio/Math.c +++ b/shared-bindings/synthio/Math.c @@ -126,10 +126,8 @@ STATIC mp_obj_t mathop_call(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_o STATIC MP_DEFINE_CONST_DICT(synthio_math_operation_locals_dict, synthio_math_operation_locals_table); MAKE_PRINTER(synthio, synthio_math_operation); MAKE_ENUM_TYPE(synthio, MathOperation, synthio_math_operation, - .flags = MP_TYPE_FLAG_EXTENDED, - MP_TYPE_EXTENDED_FIELDS( - .call = mathop_call, - )); + call, mathop_call + ); //| class Math: //| """An arithmetic block @@ -293,14 +291,12 @@ STATIC const synthio_block_proto_t math_proto = { .tick = common_hal_synthio_math_tick, }; -const mp_obj_type_t synthio_math_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Math, - .make_new = synthio_math_make_new, - .locals_dict = (mp_obj_dict_t *)&synthio_math_locals_dict, - .print = math_print, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &math_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + synthio_math_type, + MP_QSTR_Math, + MP_TYPE_FLAG_NONE, + make_new, synthio_math_make_new, + locals_dict, &synthio_math_locals_dict, + print, math_print, + protocol, &math_proto + ); diff --git a/shared-bindings/synthio/MidiTrack.c b/shared-bindings/synthio/MidiTrack.c index 79af9e9744..253ae62b85 100644 --- a/shared-bindings/synthio/MidiTrack.c +++ b/shared-bindings/synthio/MidiTrack.c @@ -33,7 +33,6 @@ #include "shared-bindings/util.h" #include "shared-bindings/synthio/MidiTrack.h" #include "shared-bindings/synthio/__init__.h" -#include "supervisor/shared/translate/translate.h" //| class MidiTrack: //| """Simple MIDI synth""" @@ -76,8 +75,8 @@ STATIC mp_obj_t synthio_miditrack_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_buffer, ARG_tempo, ARG_sample_rate, ARG_waveform, ARG_envelope }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED }, - { MP_QSTR_tempo, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, + { MP_QSTR_tempo, MP_ARG_INT | MP_ARG_REQUIRED, {} }, { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 11025} }, { MP_QSTR_waveform, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } }, { MP_QSTR_envelope, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } }, @@ -186,13 +185,11 @@ STATIC const audiosample_p_t synthio_miditrack_proto = { .get_buffer_structure = (audiosample_get_buffer_structure_fun)synthio_miditrack_get_buffer_structure, }; -const mp_obj_type_t synthio_miditrack_type = { - { &mp_type_type }, - .name = MP_QSTR_MidiTrack, - .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = synthio_miditrack_make_new, - .locals_dict = (mp_obj_dict_t *)&synthio_miditrack_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &synthio_miditrack_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + synthio_miditrack_type, + MP_QSTR_MidiTrack, + MP_TYPE_FLAG_NONE, + make_new, synthio_miditrack_make_new, + locals_dict, &synthio_miditrack_locals_dict, + protocol, &synthio_miditrack_proto + ); diff --git a/shared-bindings/synthio/MidiTrack.h b/shared-bindings/synthio/MidiTrack.h index 5c6bce46cd..cafe913430 100644 --- a/shared-bindings/synthio/MidiTrack.h +++ b/shared-bindings/synthio/MidiTrack.h @@ -1,5 +1,5 @@ /* - * This file is part of the Micro Python project, http://micropython.org/ + * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * diff --git a/shared-bindings/synthio/Note.c b/shared-bindings/synthio/Note.c index a1d0effbed..a1aee54c54 100644 --- a/shared-bindings/synthio/Note.c +++ b/shared-bindings/synthio/Note.c @@ -317,10 +317,11 @@ STATIC const mp_rom_map_elem_t synthio_note_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(synthio_note_locals_dict, synthio_note_locals_dict_table); -const mp_obj_type_t synthio_note_type = { - { &mp_type_type }, - .name = MP_QSTR_Note, - .make_new = synthio_note_make_new, - .locals_dict = (mp_obj_dict_t *)&synthio_note_locals_dict, - .print = note_print, -}; +MP_DEFINE_CONST_OBJ_TYPE( + synthio_note_type, + MP_QSTR_Note, + MP_TYPE_FLAG_NONE, + make_new, synthio_note_make_new, + locals_dict, &synthio_note_locals_dict, + print, note_print + ); diff --git a/shared-bindings/synthio/Synthesizer.c b/shared-bindings/synthio/Synthesizer.c index aa3d74e015..ef7eb1f1bc 100644 --- a/shared-bindings/synthio/Synthesizer.c +++ b/shared-bindings/synthio/Synthesizer.c @@ -37,7 +37,6 @@ #include "shared-bindings/synthio/Synthesizer.h" #include "shared-bindings/synthio/LFO.h" #include "shared-bindings/synthio/__init__.h" -#include "supervisor/shared/translate/translate.h" //| NoteSequence = Sequence[Union[int, Note]] //| """A sequence of notes, which can each be integer MIDI note numbers or `Note` objects""" @@ -451,13 +450,11 @@ STATIC const audiosample_p_t synthio_synthesizer_proto = { .get_buffer_structure = (audiosample_get_buffer_structure_fun)synthio_synthesizer_get_buffer_structure, }; -const mp_obj_type_t synthio_synthesizer_type = { - { &mp_type_type }, - .name = MP_QSTR_Synthesizer, - .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = synthio_synthesizer_make_new, - .locals_dict = (mp_obj_dict_t *)&synthio_synthesizer_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &synthio_synthesizer_proto, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + synthio_synthesizer_type, + MP_QSTR_Synthesizer, + MP_TYPE_FLAG_NONE, + make_new, synthio_synthesizer_make_new, + locals_dict, &synthio_synthesizer_locals_dict, + protocol, &synthio_synthesizer_proto + ); diff --git a/shared-bindings/synthio/__init__.c b/shared-bindings/synthio/__init__.c index 6f0fbd2782..67c65fc62e 100644 --- a/shared-bindings/synthio/__init__.c +++ b/shared-bindings/synthio/__init__.c @@ -171,23 +171,7 @@ STATIC mp_obj_t synthio_envelope_make_new(const mp_obj_type_t *type_in, size_t n }; const mp_obj_namedtuple_type_t synthio_envelope_type_obj = { - .base = { - .base = { - .type = &mp_type_type - }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Envelope, - .print = namedtuple_print, - .parent = &mp_type_tuple, - .make_new = synthio_envelope_make_new, - .attr = namedtuple_attr, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - ), - }, + NAMEDTUPLE_TYPE_BASE_AND_SLOTS_MAKE_NEW(MP_QSTR_Envelope, synthio_envelope_make_new), .n_fields = 5, .fields = { MP_QSTR_attack_time, @@ -233,14 +217,14 @@ const mp_obj_namedtuple_type_t synthio_envelope_type_obj = { STATIC mp_obj_t synthio_from_file(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_file, ARG_sample_rate, ARG_waveform, ARG_envelope }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 11025} }, { MP_QSTR_waveform, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } }, { MP_QSTR_envelope, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - if (!mp_obj_is_type(args[ARG_file].u_obj, &mp_type_fileio)) { + if (!mp_obj_is_type(args[ARG_file].u_obj, &mp_type_vfs_fat_fileio)) { mp_raise_TypeError(translate("file must be a file opened in byte mode")); } pyb_file_obj_t *file = MP_OBJ_TO_PTR(args[ARG_file].u_obj); diff --git a/shared-bindings/terminalio/Terminal.c b/shared-bindings/terminalio/Terminal.c index 05c10f2887..27544059eb 100644 --- a/shared-bindings/terminalio/Terminal.c +++ b/shared-bindings/terminalio/Terminal.c @@ -35,7 +35,6 @@ #include "py/runtime.h" #include "py/stream.h" #include "shared-bindings/fontio/BuiltinFont.h" -#include "supervisor/shared/translate/translate.h" //| class Terminal: //| """Display a character stream with a TileGrid @@ -140,15 +139,12 @@ STATIC const mp_stream_p_t terminalio_terminal_stream_p = { .is_text = true, }; -const mp_obj_type_t terminalio_terminal_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Terminal, - .make_new = terminalio_terminal_make_new, - .locals_dict = (mp_obj_dict_t *)&terminalio_terminal_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &terminalio_terminal_stream_p, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + terminalio_terminal_type, + MP_QSTR_Terminal, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + make_new, terminalio_terminal_make_new, + locals_dict, (mp_obj_dict_t *)&terminalio_terminal_locals_dict, + iter, mp_stream_unbuffered_iter, + protocol, &terminalio_terminal_stream_p + ); diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index a4e5033def..4bd501667a 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -34,7 +34,6 @@ #include "shared/timeutils/timeutils.h" #include "shared-bindings/rtc/__init__.h" #include "shared-bindings/time/__init__.h" -#include "supervisor/shared/translate/translate.h" //| """time and timing related functions //| @@ -119,23 +118,7 @@ STATIC mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, s //| ... //| const mp_obj_namedtuple_type_t struct_time_type_obj = { - .base = { - .base = { - .type = &mp_type_type - }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_struct_time, - .print = namedtuple_print, - .parent = &mp_type_tuple, - .make_new = struct_time_make_new, - .attr = namedtuple_attr, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - ), - }, + NAMEDTUPLE_TYPE_BASE_AND_SLOTS_MAKE_NEW(MP_QSTR_struct_time, struct_time_make_new), .n_fields = 9, .fields = { MP_QSTR_tm_year, @@ -177,7 +160,7 @@ void struct_time_to_tm(mp_obj_t t, timeutils_struct_time_t *tm) { mp_obj_t *elems; size_t len; - if (!mp_obj_is_type(t, &mp_type_tuple) && !mp_obj_is_type(t, &struct_time_type_obj.base)) { + if (!mp_obj_is_type(t, &mp_type_tuple) && !mp_obj_is_type(t, (mp_obj_type_t *)&struct_time_type_obj.base)) { mp_raise_TypeError(translate("Tuple or struct_time argument required")); } @@ -291,7 +274,7 @@ STATIC mp_obj_t time_mktime(mp_obj_t t) { mp_obj_t *elem; size_t len; - if (!mp_obj_is_type(t, &mp_type_tuple) && !mp_obj_is_type(t, &struct_time_type_obj.base)) { + if (!mp_obj_is_type(t, &mp_type_tuple) && !mp_obj_is_type(t, (mp_obj_type_t *)&struct_time_type_obj.base)) { mp_raise_TypeError(translate("Tuple or struct_time argument required")); } diff --git a/shared-bindings/touchio/TouchIn.c b/shared-bindings/touchio/TouchIn.c index 64de6e18b0..a5a2593630 100644 --- a/shared-bindings/touchio/TouchIn.c +++ b/shared-bindings/touchio/TouchIn.c @@ -36,7 +36,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/touchio/TouchIn.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" //| class TouchIn: //| """Read the state of a capacitive touch sensor @@ -182,9 +181,10 @@ STATIC const mp_rom_map_elem_t touchio_touchin_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(touchio_touchin_locals_dict, touchio_touchin_locals_dict_table); -const mp_obj_type_t touchio_touchin_type = { - { &mp_type_type }, - .name = MP_QSTR_TouchIn, - .make_new = touchio_touchin_make_new, - .locals_dict = (mp_obj_t)&touchio_touchin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + touchio_touchin_type, + MP_QSTR_TouchIn, + MP_TYPE_FLAG_NONE, + make_new, touchio_touchin_make_new, + locals_dict, &touchio_touchin_locals_dict + ); diff --git a/shared-bindings/traceback/__init__.c b/shared-bindings/traceback/__init__.c index ca34161842..773a41904d 100644 --- a/shared-bindings/traceback/__init__.c +++ b/shared-bindings/traceback/__init__.c @@ -158,7 +158,7 @@ STATIC mp_obj_t traceback_format_exception(size_t n_args, const mp_obj_t *pos_ar vstr_t vstr; vstr_init_print(&vstr, 0, &print); traceback_exception_common(false, &print, n_args, pos_args, kw_args); - mp_obj_t output = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + mp_obj_t output = mp_obj_new_str_from_vstr(&vstr); return mp_obj_new_list(1, &output); } diff --git a/shared-bindings/usb/core/Device.c b/shared-bindings/usb/core/Device.c index d700ccef86..120bbefd45 100644 --- a/shared-bindings/usb/core/Device.c +++ b/shared-bindings/usb/core/Device.c @@ -331,8 +331,9 @@ STATIC const mp_rom_map_elem_t usb_core_device_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(usb_core_device_locals_dict, usb_core_device_locals_dict_table); -const mp_obj_type_t usb_core_device_type = { - { &mp_type_type }, - .name = MP_QSTR_Device, - .locals_dict = (mp_obj_t)&usb_core_device_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + usb_core_device_type, + MP_QSTR_Device, + MP_TYPE_FLAG_NONE, + locals_dict, &usb_core_device_locals_dict + ); diff --git a/shared-bindings/usb/core/__init__.c b/shared-bindings/usb/core/__init__.c index ab7e0a2020..0212ae8f30 100644 --- a/shared-bindings/usb/core/__init__.c +++ b/shared-bindings/usb/core/__init__.c @@ -126,15 +126,12 @@ STATIC mp_obj_t usb_core_devices_iternext(mp_obj_t self_in) { return MP_OBJ_STOP_ITERATION; } -const mp_obj_type_t usb_core_devices_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_USBDevices, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = usb_core_devices_iternext, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + usb_core_devices_type, + MP_QSTR_USBDevices, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + iter, usb_core_devices_iternext + ); STATIC mp_obj_t usb_core_find(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_find_all, ARG_idVendor, ARG_idProduct }; diff --git a/shared-bindings/usb/core/__init__.h b/shared-bindings/usb/core/__init__.h index 2067c4cd18..86b944dfb2 100644 --- a/shared-bindings/usb/core/__init__.h +++ b/shared-bindings/usb/core/__init__.h @@ -35,14 +35,12 @@ extern const mp_obj_module_t usb_core_module; void usb_core_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind); #define MP_DEFINE_USB_CORE_EXCEPTION(exc_name, base_name) \ - const mp_obj_type_t mp_type_usb_core_##exc_name = { \ - { &mp_type_type }, \ - .name = MP_QSTR_##exc_name, \ - .print = usb_core_exception_print, \ - .make_new = mp_obj_exception_make_new, \ - .attr = mp_obj_exception_attr, \ - .parent = &mp_type_##base_name, \ - }; + MP_DEFINE_CONST_OBJ_TYPE(mp_type_usb_core_##exc_name, MP_QSTR_##exc_name, MP_TYPE_FLAG_NONE, \ + make_new, mp_obj_exception_make_new, \ + print, usb_core_exception_print, \ + attr, mp_obj_exception_attr, \ + parent, &mp_type_##base_name \ + ); extern const mp_obj_type_t mp_type_usb_core_USBError; extern const mp_obj_type_t mp_type_usb_core_USBTimeoutError; diff --git a/shared-bindings/usb_cdc/Serial.c b/shared-bindings/usb_cdc/Serial.c index 9fe6cafd5f..52bc3d7295 100644 --- a/shared-bindings/usb_cdc/Serial.c +++ b/shared-bindings/usb_cdc/Serial.c @@ -33,7 +33,6 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" //| class Serial: //| """Receives cdc commands over USB""" @@ -278,14 +277,11 @@ STATIC const mp_stream_p_t usb_cdc_serial_stream_p = { .pyserial_dont_return_none_compatibility = true, }; -const mp_obj_type_t usb_cdc_serial_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_Serial, - .locals_dict = (mp_obj_dict_t *)&usb_cdc_serial_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &usb_cdc_serial_stream_p, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + usb_cdc_serial_type, + MP_QSTR_Serial, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + locals_dict, &usb_cdc_serial_locals_dict, + iter, mp_stream_unbuffered_iter, + protocol, &usb_cdc_serial_stream_p + ); diff --git a/shared-bindings/usb_cdc/__init__.c b/shared-bindings/usb_cdc/__init__.c index e7a13a768a..8b3ca345bc 100644 --- a/shared-bindings/usb_cdc/__init__.c +++ b/shared-bindings/usb_cdc/__init__.c @@ -31,9 +31,6 @@ #include "shared-bindings/usb_cdc/__init__.h" #include "shared-bindings/usb_cdc/Serial.h" -#include "supervisor/shared/translate/translate.h" - -#include "py/runtime.h" //| """USB CDC Serial streams //| diff --git a/shared-bindings/usb_hid/Device.c b/shared-bindings/usb_hid/Device.c index 34b496a90e..efd0d15a6e 100644 --- a/shared-bindings/usb_hid/Device.c +++ b/shared-bindings/usb_hid/Device.c @@ -27,7 +27,6 @@ #include "py/objproperty.h" #include "shared-bindings/usb_hid/Device.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class Device: //| """HID Device specification""" @@ -264,9 +263,10 @@ STATIC const mp_rom_map_elem_t usb_hid_device_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(usb_hid_device_locals_dict, usb_hid_device_locals_dict_table); -const mp_obj_type_t usb_hid_device_type = { - { &mp_type_type }, - .name = MP_QSTR_Device, - .make_new = usb_hid_device_make_new, - .locals_dict = (mp_obj_t)&usb_hid_device_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + usb_hid_device_type, + MP_QSTR_Device, + MP_TYPE_FLAG_NONE, + make_new, usb_hid_device_make_new, + locals_dict, &usb_hid_device_locals_dict + ); diff --git a/shared-bindings/usb_hid/__init__.c b/shared-bindings/usb_hid/__init__.c index 2f374084bb..412e0918e9 100644 --- a/shared-bindings/usb_hid/__init__.c +++ b/shared-bindings/usb_hid/__init__.c @@ -31,8 +31,6 @@ #include "shared-bindings/usb_hid/__init__.h" #include "shared-bindings/usb_hid/Device.h" -#include "supervisor/shared/translate/translate.h" - //| """USB Human Interface Device //| //| The `usb_hid` module allows you to output data as a HID device.""" diff --git a/shared-bindings/usb_host/Port.c b/shared-bindings/usb_host/Port.c index 9be6da9df3..64f08869b7 100644 --- a/shared-bindings/usb_host/Port.c +++ b/shared-bindings/usb_host/Port.c @@ -69,9 +69,10 @@ STATIC const mp_rom_map_elem_t usb_host_port_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(usb_host_port_locals_dict, usb_host_port_locals_dict_table); -const mp_obj_type_t usb_host_port_type = { - { &mp_type_type }, - .name = MP_QSTR_Port, - .make_new = usb_host_port_make_new, - .locals_dict = (mp_obj_t)&usb_host_port_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + usb_host_port_type, + MP_QSTR_Port, + MP_TYPE_FLAG_NONE, + make_new, usb_host_port_make_new, + locals_dict, &usb_host_port_locals_dict + ); diff --git a/shared-bindings/usb_midi/PortIn.c b/shared-bindings/usb_midi/PortIn.c index ca07c8695a..8bc238a43e 100644 --- a/shared-bindings/usb_midi/PortIn.c +++ b/shared-bindings/usb_midi/PortIn.c @@ -33,7 +33,6 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" //| class PortIn: //| """Receives midi commands over USB""" @@ -109,14 +108,11 @@ STATIC const mp_stream_p_t usb_midi_portin_stream_p = { .is_text = false, }; -const mp_obj_type_t usb_midi_portin_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_PortIn, - .locals_dict = (mp_obj_dict_t *)&usb_midi_portin_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &usb_midi_portin_stream_p, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + usb_midi_portin_type, + MP_QSTR_PortIn, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + locals_dict, &usb_midi_portin_locals_dict, + iter, mp_stream_unbuffered_iter, + protocol, &usb_midi_portin_stream_p + ); diff --git a/shared-bindings/usb_midi/PortOut.c b/shared-bindings/usb_midi/PortOut.c index f1f61f948a..2f35a5baa5 100644 --- a/shared-bindings/usb_midi/PortOut.c +++ b/shared-bindings/usb_midi/PortOut.c @@ -33,7 +33,6 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" //| class PortOut: //| """Sends midi messages to a computer over USB""" @@ -91,14 +90,11 @@ STATIC const mp_stream_p_t usb_midi_portout_stream_p = { .is_text = false, }; -const mp_obj_type_t usb_midi_portout_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_PortOut, - .locals_dict = (mp_obj_dict_t *)&usb_midi_portout_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &usb_midi_portout_stream_p, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + usb_midi_portout_type, + MP_QSTR_PortOut, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + locals_dict, &usb_midi_portout_locals_dict, + iter, mp_stream_unbuffered_iter, + protocol, &usb_midi_portout_stream_p + ); diff --git a/shared-bindings/usb_midi/__init__.c b/shared-bindings/usb_midi/__init__.c index 651f4a51d1..3790ea501e 100644 --- a/shared-bindings/usb_midi/__init__.c +++ b/shared-bindings/usb_midi/__init__.c @@ -32,7 +32,6 @@ #include "shared-bindings/usb_midi/__init__.h" #include "shared-bindings/usb_midi/PortIn.h" #include "shared-bindings/usb_midi/PortOut.h" -#include "supervisor/shared/translate/translate.h" #include "py/runtime.h" diff --git a/shared-bindings/util.c b/shared-bindings/util.c index 7cb0d51176..4b882375d1 100644 --- a/shared-bindings/util.c +++ b/shared-bindings/util.c @@ -27,7 +27,6 @@ #include "py/runtime.h" #include "shared-bindings/util.h" -#include "supervisor/shared/translate/translate.h" // If so, deinit() has already been called on the object, so complain. void raise_deinited_error(void) { diff --git a/shared-bindings/vectorio/Circle.c b/shared-bindings/vectorio/Circle.c index 308e828a02..4dc3058e74 100644 --- a/shared-bindings/vectorio/Circle.c +++ b/shared-bindings/vectorio/Circle.c @@ -8,7 +8,6 @@ #include "py/objproperty.h" #include "py/objtype.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class Circle: //| def __init__( @@ -133,13 +132,11 @@ STATIC const mp_rom_map_elem_t vectorio_circle_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(vectorio_circle_locals_dict, vectorio_circle_locals_dict_table); -const mp_obj_type_t vectorio_circle_type = { - { &mp_type_type }, - .name = MP_QSTR_Circle, - .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = vectorio_circle_make_new, - .locals_dict = (mp_obj_dict_t *)&vectorio_circle_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &circle_draw_protocol, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + vectorio_circle_type, + MP_QSTR_Circle, + MP_TYPE_FLAG_NONE, + make_new, vectorio_circle_make_new, + locals_dict, &vectorio_circle_locals_dict, + protocol, &circle_draw_protocol + ); diff --git a/shared-bindings/vectorio/Polygon.c b/shared-bindings/vectorio/Polygon.c index 452631eddc..251e113d9f 100644 --- a/shared-bindings/vectorio/Polygon.c +++ b/shared-bindings/vectorio/Polygon.c @@ -9,7 +9,6 @@ #include "py/objproperty.h" #include "py/objtype.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" #define VECTORIO_POLYGON_DEBUG(...) (void)0 @@ -142,13 +141,11 @@ STATIC const mp_rom_map_elem_t vectorio_polygon_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(vectorio_polygon_locals_dict, vectorio_polygon_locals_dict_table); -const mp_obj_type_t vectorio_polygon_type = { - { &mp_type_type }, - .name = MP_QSTR_Polygon, - .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = vectorio_polygon_make_new, - .locals_dict = (mp_obj_dict_t *)&vectorio_polygon_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &polygon_draw_protocol, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + vectorio_polygon_type, + MP_QSTR_Polygon, + MP_TYPE_FLAG_NONE, + make_new, vectorio_polygon_make_new, + locals_dict, &vectorio_polygon_locals_dict, + protocol, &polygon_draw_protocol + ); diff --git a/shared-bindings/vectorio/Rectangle.c b/shared-bindings/vectorio/Rectangle.c index 01453693f8..35e207559f 100644 --- a/shared-bindings/vectorio/Rectangle.c +++ b/shared-bindings/vectorio/Rectangle.c @@ -7,7 +7,6 @@ #include "py/objtype.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" //| class Rectangle: //| def __init__( @@ -164,13 +163,11 @@ STATIC const mp_rom_map_elem_t vectorio_rectangle_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(vectorio_rectangle_locals_dict, vectorio_rectangle_locals_dict_table); -const mp_obj_type_t vectorio_rectangle_type = { - { &mp_type_type }, - .name = MP_QSTR_Rectangle, - .flags = MP_TYPE_FLAG_EXTENDED, - .make_new = vectorio_rectangle_make_new, - .locals_dict = (mp_obj_dict_t *)&vectorio_rectangle_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .protocol = &rectangle_draw_protocol, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + vectorio_rectangle_type, + MP_QSTR_Rectangle, + MP_TYPE_FLAG_NONE, + make_new, vectorio_rectangle_make_new, + locals_dict, &vectorio_rectangle_locals_dict, + protocol, &rectangle_draw_protocol + ); diff --git a/shared-bindings/vectorio/VectorShape.c b/shared-bindings/vectorio/VectorShape.c index 578749eb92..c2bce53f09 100644 --- a/shared-bindings/vectorio/VectorShape.c +++ b/shared-bindings/vectorio/VectorShape.c @@ -1,4 +1,3 @@ - #include "shared-module/vectorio/__init__.h" #include "shared-bindings/vectorio/VectorShape.h" #include "shared-bindings/vectorio/Circle.h" @@ -16,7 +15,6 @@ #include "py/objproperty.h" #include "py/objtype.h" #include "py/runtime.h" -#include "supervisor/shared/translate/translate.h" // shape: The shape implementation to draw. @@ -243,8 +241,9 @@ STATIC const mp_rom_map_elem_t vectorio_vector_shape_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(vectorio_vector_shape_locals_dict, vectorio_vector_shape_locals_dict_table); -const mp_obj_type_t vectorio_vector_shape_type = { - { &mp_type_type }, - .name = MP_QSTR_VectorShape, - .locals_dict = (mp_obj_dict_t *)&vectorio_vector_shape_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + vectorio_vector_shape_type, + MP_QSTR_VectorShape, + MP_TYPE_FLAG_NONE, + locals_dict, &vectorio_vector_shape_locals_dict + ); diff --git a/shared-bindings/watchdog/WatchDogTimer.c b/shared-bindings/watchdog/WatchDogTimer.c index 49cfdaecb4..fca860fe92 100644 --- a/shared-bindings/watchdog/WatchDogTimer.c +++ b/shared-bindings/watchdog/WatchDogTimer.c @@ -148,9 +148,9 @@ STATIC const mp_rom_map_elem_t watchdog_watchdogtimer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(watchdog_watchdogtimer_locals_dict, watchdog_watchdogtimer_locals_dict_table); -const mp_obj_type_t watchdog_watchdogtimer_type = { - { &mp_type_type }, - .name = MP_QSTR_WatchDogTimer, - // .make_new = watchdog_watchdogtimer_make_new, - .locals_dict = (mp_obj_dict_t *)&watchdog_watchdogtimer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + watchdog_watchdogtimer_type, + MP_QSTR_WatchDogTimer, + MP_TYPE_FLAG_NONE, + locals_dict, &watchdog_watchdogtimer_locals_dict + ); diff --git a/shared-bindings/watchdog/__init__.c b/shared-bindings/watchdog/__init__.c index 70aaddc8a5..da7fb23868 100644 --- a/shared-bindings/watchdog/__init__.c +++ b/shared-bindings/watchdog/__init__.c @@ -79,13 +79,14 @@ //| """ //| -const mp_obj_type_t mp_type_WatchDogTimeout = { - { &mp_type_type }, - .name = MP_QSTR_WatchDogTimeout, - .make_new = mp_obj_exception_make_new, - .attr = mp_obj_exception_attr, - .parent = &mp_type_Exception, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_WatchDogTimeout, + MP_QSTR_WatchDogTimeout, + MP_TYPE_FLAG_NONE, + make_new, mp_obj_exception_make_new, + attr, mp_obj_exception_attr, + parent, &mp_type_Exception + ); mp_obj_exception_t mp_watchdog_timeout_exception = { .base.type = &mp_type_WatchDogTimeout, diff --git a/shared-bindings/wifi/Monitor.c b/shared-bindings/wifi/Monitor.c index acbc63ec89..bde6caa59f 100644 --- a/shared-bindings/wifi/Monitor.c +++ b/shared-bindings/wifi/Monitor.c @@ -151,9 +151,12 @@ STATIC const mp_rom_map_elem_t wifi_monitor_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(wifi_monitor_locals_dict, wifi_monitor_locals_dict_table); -const mp_obj_type_t wifi_monitor_type = { - .base = { &mp_type_type }, - .name = MP_QSTR_Monitor, - .make_new = wifi_monitor_make_new, - .locals_dict = (mp_obj_t)&wifi_monitor_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + wifi_monitor_type, + MP_QSTR_Monitor, + MP_TYPE_FLAG_NONE, + make_new, wifi_monitor_make_new, + locals_dict, &wifi_monitor_locals_dict + ); + +MP_REGISTER_ROOT_POINTER(mp_obj_t wifi_monitor_singleton); diff --git a/shared-bindings/wifi/Network.c b/shared-bindings/wifi/Network.c index 387b1f587d..d262b392eb 100644 --- a/shared-bindings/wifi/Network.c +++ b/shared-bindings/wifi/Network.c @@ -119,8 +119,9 @@ STATIC const mp_rom_map_elem_t wifi_network_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(wifi_network_locals_dict, wifi_network_locals_dict_table); -const mp_obj_type_t wifi_network_type = { - .base = { &mp_type_type }, - .name = MP_QSTR_Network, - .locals_dict = (mp_obj_t)&wifi_network_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + wifi_network_type, + MP_QSTR_Network, + MP_TYPE_FLAG_NONE, + locals_dict, &wifi_network_locals_dict + ); diff --git a/shared-bindings/wifi/Packet.c b/shared-bindings/wifi/Packet.c index d21c8b0639..1a5056aaf6 100644 --- a/shared-bindings/wifi/Packet.c +++ b/shared-bindings/wifi/Packet.c @@ -58,13 +58,11 @@ STATIC MP_DEFINE_CONST_DICT(wifi_packet_locals_dict, wifi_packet_locals_table); MAKE_PRINTER(wifi, wifi_packet); -const mp_obj_type_t wifi_packet_type = { - { &mp_type_type }, - .name = MP_QSTR_Packet, - .print = wifi_packet_print, - .locals_dict = (mp_obj_t)&wifi_packet_locals_dict, - .flags = MP_TYPE_FLAG_EXTENDED, - MP_TYPE_EXTENDED_FIELDS( - .unary_op = mp_generic_unary_op, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + wifi_packet_type, + MP_QSTR_Packet, + MP_TYPE_FLAG_NONE, + print, wifi_packet_print, + locals_dict, &wifi_packet_locals_dict, + unary_op, mp_generic_unary_op + ); diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index 798c7c6d2e..dd56408561 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -777,8 +777,9 @@ STATIC const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(wifi_radio_locals_dict, wifi_radio_locals_dict_table); -const mp_obj_type_t wifi_radio_type = { - .base = { &mp_type_type }, - .name = MP_QSTR_Radio, - .locals_dict = (mp_obj_t)&wifi_radio_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + wifi_radio_type, + MP_QSTR_Radio, + MP_TYPE_FLAG_NONE, + locals_dict, &wifi_radio_locals_dict + ); diff --git a/shared-bindings/wifi/ScannedNetworks.c b/shared-bindings/wifi/ScannedNetworks.c index a893213719..82e8a53b22 100644 --- a/shared-bindings/wifi/ScannedNetworks.c +++ b/shared-bindings/wifi/ScannedNetworks.c @@ -59,12 +59,9 @@ STATIC mp_obj_t scannednetworks_iternext(mp_obj_t self_in) { //| ... //| -const mp_obj_type_t wifi_scannednetworks_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_ScannedNetworks, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = scannednetworks_iternext, - ) -}; +MP_DEFINE_CONST_OBJ_TYPE( + wifi_scannednetworks_type, + MP_QSTR_ScannedNetworks, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, + iter, scannednetworks_iternext + ); diff --git a/shared-bindings/zlib/__init__.c b/shared-bindings/zlib/__init__.c index 1b38d59ff4..7a218f9a5b 100644 --- a/shared-bindings/zlib/__init__.c +++ b/shared-bindings/zlib/__init__.c @@ -39,8 +39,6 @@ #include "shared-bindings/zlib/__init__.h" -#include "supervisor/shared/translate/translate.h" - //| """zlib decompression functionality //| //| The `zlib` module allows limited functionality similar to the CPython zlib library. diff --git a/shared-module/audiocore/WaveFile.c b/shared-module/audiocore/WaveFile.c index 590148f5c3..021bb63449 100644 --- a/shared-module/audiocore/WaveFile.c +++ b/shared-module/audiocore/WaveFile.c @@ -33,7 +33,6 @@ #include "py/runtime.h" #include "shared-module/audiocore/WaveFile.h" -#include "supervisor/shared/translate/translate.h" struct wave_format_chunk { uint16_t audio_format; diff --git a/shared-module/audiomp3/MP3Decoder.c b/shared-module/audiomp3/MP3Decoder.c index 21385670a2..2049c6aa1d 100644 --- a/shared-module/audiomp3/MP3Decoder.c +++ b/shared-module/audiomp3/MP3Decoder.c @@ -35,7 +35,6 @@ #include "py/runtime.h" #include "shared-module/audiomp3/MP3Decoder.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/background_callback.h" #include "lib/mp3/src/mp3common.h" diff --git a/shared-module/bitbangio/I2C.c b/shared-module/bitbangio/I2C.c index 65926b8c07..4ee33fd8f5 100644 --- a/shared-module/bitbangio/I2C.c +++ b/shared-module/bitbangio/I2C.c @@ -32,7 +32,6 @@ #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/digitalio/DigitalInOut.h" -#include "supervisor/shared/translate/translate.h" STATIC void delay(bitbangio_i2c_obj_t *self) { // We need to use an accurate delay to get acceptable I2C diff --git a/shared-module/bitbangio/SPI.c b/shared-module/bitbangio/SPI.c index c82cecff62..60d216f619 100644 --- a/shared-module/bitbangio/SPI.c +++ b/shared-module/bitbangio/SPI.c @@ -32,7 +32,6 @@ #include "shared-bindings/bitbangio/SPI.h" #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/microcontroller/__init__.h" -#include "supervisor/shared/translate/translate.h" #define MAX_BAUDRATE (common_hal_mcu_get_clock_frequency() / 48) diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index 2d5a8a07e4..4c096a25a6 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -27,7 +27,6 @@ #include "shared-bindings/board/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-module/board/__init__.h" -#include "supervisor/shared/translate/translate.h" #include "mpconfigboard.h" #include "py/runtime.h" @@ -140,6 +139,9 @@ mp_obj_t common_hal_board_create_spi(const mp_int_t instance) { #if CIRCUITPY_BOARD_UART + +MP_REGISTER_ROOT_POINTER(mp_obj_t board_uart_bus); + typedef struct { const mcu_pin_obj_t *tx; const mcu_pin_obj_t *rx; diff --git a/shared-module/getpass/__init__.c b/shared-module/getpass/__init__.c index 8f16d75b53..72469a686f 100644 --- a/shared-module/getpass/__init__.c +++ b/shared-module/getpass/__init__.c @@ -57,5 +57,5 @@ mp_obj_t shared_module_getpass_getpass(const char *prompt, mp_print_t *print) { } } - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_vstr(&vstr); } diff --git a/shared-module/keypad/__init__.c b/shared-module/keypad/__init__.c index 68cde559fb..5d0905e420 100644 --- a/shared-module/keypad/__init__.c +++ b/shared-module/keypad/__init__.c @@ -154,3 +154,5 @@ mp_obj_t common_hal_keypad_generic_get_events(void *self_in) { keypad_scanner_obj_t *self = self_in; return self->events; } + +MP_REGISTER_ROOT_POINTER(mp_obj_t keypad_scanners_linked_list); diff --git a/shared-module/memorymonitor/AllocationSize.c b/shared-module/memorymonitor/AllocationSize.c index 42fae3b065..76b1590682 100644 --- a/shared-module/memorymonitor/AllocationSize.c +++ b/shared-module/memorymonitor/AllocationSize.c @@ -89,3 +89,6 @@ void memorymonitor_allocationsizes_track_allocation(size_t block_count) { void memorymonitor_allocationsizes_reset(void) { MP_STATE_VM(active_allocationsizes) = NULL; } + +MP_REGISTER_ROOT_POINTER(mp_obj_t active_allocationsizes); +MP_REGISTER_ROOT_POINTER(mp_obj_t active_allocationalarms); diff --git a/shared-module/msgpack/__init__.c b/shared-module/msgpack/__init__.c index 27416a29fd..aac38607cb 100644 --- a/shared-module/msgpack/__init__.c +++ b/shared-module/msgpack/__init__.c @@ -36,7 +36,6 @@ #include "py/runtime.h" #include "py/stream.h" -#include "supervisor/shared/translate/translate.h" #include "shared-bindings/msgpack/ExtType.h" #include "shared-bindings/msgpack/__init__.h" #include "shared-module/msgpack/__init__.h" @@ -376,7 +375,7 @@ STATIC mp_obj_t unpack_bytes(msgpack_stream_t *s, size_t size) { size -= n; p += n; } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC mp_obj_t unpack_ext(msgpack_stream_t *s, size_t size, mp_obj_t ext_hook) { @@ -475,7 +474,7 @@ STATIC mp_obj_t unpack(msgpack_stream_t *s, mp_obj_t ext_hook, bool use_list) { vstr_init_len(&vstr, size); byte *p = (byte *)vstr.buf; read(s, p, size); - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_vstr(&vstr); } case 0xde: case 0xdf: { diff --git a/shared-module/os/getenv.c b/shared-module/os/getenv.c index 7b102fd3e5..7fba522256 100644 --- a/shared-module/os/getenv.c +++ b/shared-module/os/getenv.c @@ -392,7 +392,7 @@ mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t d handle_getenv_error(result, mp_raise_msg_varg); if (quoted) { - return mp_obj_new_str_from_vstr(&mp_type_str, &buf); + return mp_obj_new_str_from_vstr(&buf); } else { return mp_parse_num_integer(buf.buf, buf.len, 0, NULL); } diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 060972d0c3..e961f83e31 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -38,7 +38,6 @@ #include "shared-bindings/storage/__init__.h" #include "supervisor/filesystem.h" #include "supervisor/flash.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/usb.h" #if CIRCUITPY_USB_MSC diff --git a/shared-module/struct/__init__.c b/shared-module/struct/__init__.c index 5fc3d30f25..3cd9d37e03 100644 --- a/shared-module/struct/__init__.c +++ b/shared-module/struct/__init__.c @@ -31,7 +31,6 @@ #include "py/runtime.h" #include "py/binary.h" #include "py/parsenum.h" -#include "supervisor/shared/translate/translate.h" #include "shared-bindings/struct/__init__.h" STATIC void struct_validate_format(char fmt) { diff --git a/shared-module/synthio/__init__.c b/shared-module/synthio/__init__.c index c4f5b2f9b8..daf41191f1 100644 --- a/shared-module/synthio/__init__.c +++ b/shared-module/synthio/__init__.c @@ -511,7 +511,7 @@ mp_float_t synthio_block_slot_get(synthio_block_slot_t *slot) { block->last_tick = synthio_global_tick; // previously verified by call to mp_proto_get in synthio_block_assign_slot - const synthio_block_proto_t *p = mp_type_get_protocol_slot(mp_obj_get_type(slot->obj)); + const synthio_block_proto_t *p = MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(slot->obj), protocol); mp_float_t value = p->tick(slot->obj); block->value = value; return value; diff --git a/shared-module/usb/utf16le.c b/shared-module/usb/utf16le.c index 2b55dc6bab..10152a2a7d 100644 --- a/shared-module/usb/utf16le.c +++ b/shared-module/usb/utf16le.c @@ -70,5 +70,5 @@ mp_obj_t utf16le_to_string(const uint16_t *buf, size_t utf16_len) { vstr_init(&vstr, utf16_len); utf16_str utf = {buf, utf16_len}; _convert_utf16le_to_utf8(&vstr, &utf); - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_vstr(&vstr); } diff --git a/shared-module/usb_hid/Device.c b/shared-module/usb_hid/Device.c index 8691794955..00736906c4 100644 --- a/shared-module/usb_hid/Device.c +++ b/shared-module/usb_hid/Device.c @@ -32,7 +32,6 @@ #include "shared-bindings/usb_hid/Device.h" #include "shared-module/usb_hid/__init__.h" #include "shared-module/usb_hid/Device.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/tick.h" #include "tusb.h" diff --git a/shared-module/usb_hid/__init__.c b/shared-module/usb_hid/__init__.c index 11b87a78f1..d962ff855a 100644 --- a/shared-module/usb_hid/__init__.c +++ b/shared-module/usb_hid/__init__.c @@ -33,7 +33,6 @@ #include "shared-bindings/usb_hid/__init__.h" #include "shared-bindings/usb_hid/Device.h" #include "supervisor/memory.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/usb.h" static const uint8_t usb_hid_descriptor_template[] = { diff --git a/shared-module/usb_midi/__init__.c b/shared-module/usb_midi/__init__.c index ed1b8a0518..8cac2ba8af 100644 --- a/shared-module/usb_midi/__init__.c +++ b/shared-module/usb_midi/__init__.c @@ -34,7 +34,6 @@ #include "shared-bindings/usb_midi/PortIn.h" #include "shared-bindings/usb_midi/PortOut.h" #include "supervisor/memory.h" -#include "supervisor/shared/translate/translate.h" #include "supervisor/usb.h" #include "tusb.h" diff --git a/shared/libc/abort_.c b/shared/libc/abort_.c index 0c1d860aef..3051eae81e 100644 --- a/shared/libc/abort_.c +++ b/shared/libc/abort_.c @@ -1,7 +1,5 @@ #include -#include "supervisor/shared/translate/translate.h" - NORETURN void abort_(void); NORETURN void abort_(void) { diff --git a/shared/libc/printf.c b/shared/libc/printf.c index dbf0c26744..e52ed523ef 100644 --- a/shared/libc/printf.c +++ b/shared/libc/printf.c @@ -60,13 +60,13 @@ int snprintf(char *str, size_t size, const char *fmt, ...); int printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - int ret = mp_vprintf(&mp_plat_print, fmt, ap); + int ret = mp_vprintf(MICROPY_INTERNAL_PRINTF_PRINTER, fmt, ap); va_end(ap); return ret; } int vprintf(const char *fmt, va_list ap) { - return mp_vprintf(&mp_plat_print, fmt, ap); + return mp_vprintf(MICROPY_INTERNAL_PRINTF_PRINTER, fmt, ap); } // need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a') diff --git a/shared/netutils/dhcpserver.c b/shared/netutils/dhcpserver.c index 3f90a06e46..0a84da60d6 100644 --- a/shared/netutils/dhcpserver.c +++ b/shared/netutils/dhcpserver.c @@ -32,6 +32,7 @@ #include #include "py/mperrno.h" #include "py/mphal.h" +#include "lwip/opt.h" #if LWIP_UDP @@ -65,7 +66,7 @@ #define PORT_DHCP_SERVER (67) #define PORT_DHCP_CLIENT (68) -#define DEFAULT_DNS MAKE_IP4(8, 8, 8, 8) +#define DEFAULT_DNS MAKE_IP4(192, 168, 4, 1) #define DEFAULT_LEASE_TIME_S (24 * 60 * 60) // in seconds #define MAC_LEN (6) diff --git a/shared/netutils/netutils.c b/shared/netutils/netutils.c index 030b1535cd..ab2b592427 100644 --- a/shared/netutils/netutils.c +++ b/shared/netutils/netutils.c @@ -31,7 +31,6 @@ #include "py/runtime.h" #include "shared/netutils/netutils.h" -#include "supervisor/shared/translate/translate.h" // Takes an array with a raw IPv4 address and returns something like '192.168.0.1'. mp_obj_t netutils_format_ipv4_addr(uint8_t *ip, netutils_endian_t endian) { diff --git a/shared/netutils/netutils.h b/shared/netutils/netutils.h index 3bb9212800..dfc554bf8a 100644 --- a/shared/netutils/netutils.h +++ b/shared/netutils/netutils.h @@ -27,6 +27,8 @@ #ifndef MICROPY_INCLUDED_LIB_NETUTILS_NETUTILS_H #define MICROPY_INCLUDED_LIB_NETUTILS_NETUTILS_H +#include "py/obj.h" + #define NETUTILS_IPV4ADDR_BUFSIZE 4 #define NETUTILS_TRACE_IS_TX (0x0001) diff --git a/shared/readline/readline.c b/shared/readline/readline.c index 9e1e904417..db4653b82b 100644 --- a/shared/readline/readline.c +++ b/shared/readline/readline.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -419,11 +419,6 @@ right_arrow_key: // right arrow if (rl.cursor_pos < rl.line->len) { redraw_step_forward = 1; - // Check if we have moved into a UTF-8 continuation byte - while (UTF8_IS_CONT(rl.line->buf[rl.cursor_pos+redraw_step_forward]) && - rl.cursor_pos+redraw_step_forward < rl.line->len) { - redraw_step_forward++; - } } } else if (c == 'D') { #if MICROPY_REPL_EMACS_KEYS @@ -432,11 +427,6 @@ left_arrow_key: // left arrow if (rl.cursor_pos > rl.orig_line_len) { redraw_step_back = 1; - // Check if we have moved into a UTF-8 continuation byte - while (UTF8_IS_CONT(rl.line->buf[rl.cursor_pos-redraw_step_back])) { - redraw_step_back++; - cont_chars++; - } } } else if (c == 'H') { // home @@ -637,10 +627,12 @@ void readline_push_history(const char *line) { // so update the history char *most_recent_hist = str_dup_maybe(line); if (most_recent_hist != NULL) { - for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) { + for (int i = MICROPY_READLINE_HISTORY_SIZE - 1; i > 0; i--) { MP_STATE_PORT(readline_hist)[i] = MP_STATE_PORT(readline_hist)[i - 1]; } MP_STATE_PORT(readline_hist)[0] = most_recent_hist; } } } + +MP_REGISTER_ROOT_POINTER(const char *readline_hist[MICROPY_READLINE_HISTORY_SIZE]); diff --git a/shared/runtime/gchelper_generic.c b/shared/runtime/gchelper_generic.c index dcd35f9c7e..272e37056a 100644 --- a/shared/runtime/gchelper_generic.c +++ b/shared/runtime/gchelper_generic.c @@ -98,7 +98,7 @@ STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { #elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__) -// Fallback implementation, prefer gchelper_m0.s or gchelper_m3.s +// Fallback implementation, prefer gchelper_thumb1.s or gchelper_thumb2.s STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { register long r4 asm ("r4"); diff --git a/shared/runtime/gchelper_native.c b/shared/runtime/gchelper_native.c index 1e4af9c844..dbab8d6017 100644 --- a/shared/runtime/gchelper_native.c +++ b/shared/runtime/gchelper_native.c @@ -41,7 +41,7 @@ MP_NOINLINE void gc_helper_collect_regs_and_stack(void) { uintptr_t sp = gc_helper_get_regs_and_sp(regs); // trace the stack, including the registers (since they live on the stack in this function) - gc_collect_root((void **)sp, ((uint32_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); + gc_collect_root((void **)sp, ((uintptr_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uintptr_t)); } #endif diff --git a/shared/runtime/gchelper_m0.s b/shared/runtime/gchelper_thumb1.s similarity index 94% rename from shared/runtime/gchelper_m0.s rename to shared/runtime/gchelper_thumb1.s index db0d9738d1..a316c4fb36 100644 --- a/shared/runtime/gchelper_m0.s +++ b/shared/runtime/gchelper_thumb1.s @@ -25,7 +25,6 @@ */ .syntax unified - .cpu cortex-m0 .thumb .section .text @@ -34,6 +33,9 @@ .global gc_helper_get_regs_and_sp .type gc_helper_get_regs_and_sp, %function +@ This function will compile on processors like Cortex M0 that don't support +@ newer Thumb-2 instructions. + @ uint gc_helper_get_regs_and_sp(r0=uint regs[10]) gc_helper_get_regs_and_sp: @ store registers into given array diff --git a/shared/runtime/gchelper_m3.s b/shared/runtime/gchelper_thumb2.s similarity index 96% rename from shared/runtime/gchelper_m3.s rename to shared/runtime/gchelper_thumb2.s index 5220fa0883..bbc98459ec 100644 --- a/shared/runtime/gchelper_m3.s +++ b/shared/runtime/gchelper_thumb2.s @@ -25,7 +25,6 @@ */ .syntax unified - .cpu cortex-m3 .thumb .section .text @@ -34,6 +33,8 @@ .global gc_helper_get_regs_and_sp .type gc_helper_get_regs_and_sp, %function +@ This function requires Thumb-2 instruction support, e.g. Cortex M3/M4. + @ uint gc_helper_get_regs_and_sp(r0=uint regs[10]) gc_helper_get_regs_and_sp: @ store registers into given array diff --git a/shared/runtime/mpirq.c b/shared/runtime/mpirq.c index 8e474bf5a2..acd727403b 100644 --- a/shared/runtime/mpirq.c +++ b/shared/runtime/mpirq.c @@ -81,8 +81,8 @@ void mp_irq_handler(mp_irq_obj_t *self) { // Uncaught exception; disable the callback so that it doesn't run again self->methods->trigger(self->parent, 0); self->handler = mp_const_none; - printf("Uncaught exception in IRQ callback handler\n"); - mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + mp_printf(MICROPY_ERROR_PRINTER, "Uncaught exception in IRQ callback handler\n"); + mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val)); } gc_unlock(); mp_sched_unlock(); @@ -125,11 +125,12 @@ STATIC const mp_rom_map_elem_t mp_irq_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table); -const mp_obj_type_t mp_irq_type = { - { &mp_type_type }, - .name = MP_QSTR_irq, - .call = mp_irq_call, - .locals_dict = (mp_obj_dict_t *)&mp_irq_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_irq_type, + MP_QSTR_irq, + MP_TYPE_FLAG_NONE, + call, mp_irq_call, + locals_dict, &mp_irq_locals_dict + ); #endif // MICROPY_ENABLE_SCHEDULER diff --git a/shared/runtime/pyexec.c b/shared/runtime/pyexec.c index 0717bfc6a8..7b71fe4dea 100644 --- a/shared/runtime/pyexec.c +++ b/shared/runtime/pyexec.c @@ -639,7 +639,7 @@ friendly_repl_reset: // If the user gets to here and interrupts are disabled then // they'll never see the prompt, traceback etc. The USB REPL needs // interrupts to be enabled or no transfers occur. So we try to - // do the user a favor and re-enable interrupts. + // do the user a favor and reenable interrupts. if (query_irq() == IRQ_STATE_DISABLED) { enable_irq(IRQ_STATE_ENABLED); mp_hal_stdout_tx_str("MPY: enabling IRQs\r\n"); @@ -796,3 +796,5 @@ mp_obj_t pyb_set_repl_info(mp_obj_t o_value) { } MP_DEFINE_CONST_FUN_OBJ_1(pyb_set_repl_info_obj, pyb_set_repl_info); #endif + +MP_REGISTER_ROOT_POINTER(vstr_t * repl_line); diff --git a/shared/runtime/pyexec.h b/shared/runtime/pyexec.h index d0c012fe46..0e1a354036 100644 --- a/shared/runtime/pyexec.h +++ b/shared/runtime/pyexec.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/shared/runtime/sys_stdio_mphal.c b/shared/runtime/sys_stdio_mphal.c index 580d97f614..236c6f3eb3 100644 --- a/shared/runtime/sys_stdio_mphal.c +++ b/shared/runtime/sys_stdio_mphal.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013-2019 Damien P. George + * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -120,26 +120,20 @@ STATIC const mp_rom_map_elem_t stdio_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(stdio_locals_dict, stdio_locals_dict_table); STATIC const mp_stream_p_t stdio_obj_stream_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stdio_read, .write = stdio_write, .ioctl = stdio_ioctl, .is_text = true, }; -STATIC const mp_obj_type_t stdio_obj_type = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, - .name = MP_QSTR_FileIO, - // TODO .make_new? - .print = stdio_obj_print, - .locals_dict = (mp_obj_dict_t *)&stdio_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &stdio_obj_stream_p, - ), -}; +MP_DEFINE_CONST_OBJ_TYPE( + stdio_obj_type, + MP_QSTR_FileIO, + MP_TYPE_FLAG_ITER_IS_STREAM, + print, stdio_obj_print, + protocol, &stdio_obj_stream_p, + locals_dict, &stdio_locals_dict + ); const sys_stdio_obj_t mp_sys_stdin_obj = {{&stdio_obj_type}, .fd = STDIO_FD_IN}; const sys_stdio_obj_t mp_sys_stdout_obj = {{&stdio_obj_type}, .fd = STDIO_FD_OUT}; @@ -159,25 +153,20 @@ STATIC mp_uint_t stdio_buffer_write(mp_obj_t self_in, const void *buf, mp_uint_t } STATIC const mp_stream_p_t stdio_buffer_obj_stream_p = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stdio_buffer_read, .write = stdio_buffer_write, .ioctl = stdio_ioctl, .is_text = false, }; -STATIC const mp_obj_type_t stdio_buffer_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_FileIO, - .flags = MP_TYPE_FLAG_EXTENDED, - .print = stdio_obj_print, - .locals_dict = (mp_obj_dict_t *)&stdio_locals_dict, - MP_TYPE_EXTENDED_FIELDS( - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &stdio_buffer_obj_stream_p, - ), -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + stdio_buffer_obj_type, + MP_QSTR_FileIO, + MP_TYPE_FLAG_ITER_IS_STREAM, + print, stdio_obj_print, + protocol, &stdio_buffer_obj_stream_p, + locals_dict, &stdio_locals_dict + ); STATIC const sys_stdio_obj_t stdio_buffer_obj = {{&stdio_buffer_obj_type}, .fd = 0}; // fd unused #endif diff --git a/supervisor/flash_root_pointers.h b/shared/tinyusb/mp_cdc_common.c similarity index 57% rename from supervisor/flash_root_pointers.h rename to shared/tinyusb/mp_cdc_common.c index a426b9c4eb..cd4f5d1013 100644 --- a/supervisor/flash_root_pointers.h +++ b/shared/tinyusb/mp_cdc_common.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * Copyright (c) 2022 Ibrahim Abdelkader * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,13 +23,32 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SUPERVISOR_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_SUPERVISOR_FLASH_ROOT_POINTERS_H -#ifdef EXTERNAL_FLASH_DEVICES -#include "supervisor/shared/external_flash/external_flash_root_pointers.h" -#else -#include "supervisor/internal_flash_root_pointers.h" +#include "py/runtime.h" +#include "py/mphal.h" +#include "modmachine.h" + +#if MICROPY_HW_USB_CDC_1200BPS_TOUCH && MICROPY_HW_ENABLE_USBDEV + +#include "tusb.h" + +static mp_sched_node_t mp_bootloader_sched_node; + +STATIC void usbd_cdc_run_bootloader_task(mp_sched_node_t *node) { + mp_hal_delay_ms(250); + machine_bootloader(0, NULL); +} + +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { + if (dtr == false && rts == false) { + // Device is disconnected. + cdc_line_coding_t line_coding; + tud_cdc_n_get_line_coding(itf, &line_coding); + if (line_coding.bit_rate == 1200) { + // Delay bootloader jump to allow the USB stack to service endpoints. + mp_sched_schedule_node(&mp_bootloader_sched_node, usbd_cdc_run_bootloader_task); + } + } +} + #endif - -#endif // MICROPY_INCLUDED_SUPERVISOR_FLASH_ROOT_POINTERS_H diff --git a/shared/tinyusb/mp_usbd_descriptor.c b/shared/tinyusb/mp_usbd_descriptor.c new file mode 100644 index 0000000000..8fab599b67 --- /dev/null +++ b/shared/tinyusb/mp_usbd_descriptor.c @@ -0,0 +1,133 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * Copyright (c) 2022 Blake W. Felt & Angus Gratton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mpconfig.h" + +#if MICROPY_HW_ENABLE_USBDEV + +#include "tusb.h" +#include "mp_usbd.h" +#include "mp_usbd_internal.h" + +#define USBD_CDC_CMD_MAX_SIZE (8) +#define USBD_CDC_IN_OUT_MAX_SIZE (64) + +const tusb_desc_device_t mp_usbd_desc_device_static = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .idVendor = MICROPY_HW_USB_VID, + .idProduct = MICROPY_HW_USB_PID, + .bcdDevice = 0x0100, + .iManufacturer = USBD_STR_MANUF, + .iProduct = USBD_STR_PRODUCT, + .iSerialNumber = USBD_STR_SERIAL, + .bNumConfigurations = 1, +}; + +const uint8_t mp_usbd_desc_cfg_static[USBD_STATIC_DESC_LEN] = { + TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_STATIC_MAX, USBD_STR_0, USBD_STATIC_DESC_LEN, + 0, USBD_MAX_POWER_MA), + + #if CFG_TUD_CDC + TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, + USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE), + #endif + #if CFG_TUD_MSC + TUD_MSC_DESCRIPTOR(USBD_ITF_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), + #endif +}; + +const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + char serial_buf[MICROPY_HW_USB_DESC_STR_MAX + 1]; // Includes terminating NUL byte + static uint16_t desc_wstr[MICROPY_HW_USB_DESC_STR_MAX + 1]; // Includes prefix uint16_t + const char *desc_str; + uint16_t desc_len; + + switch (index) { + case 0: + desc_wstr[1] = 0x0409; // supported language is English + desc_len = 4; + break; + case USBD_STR_SERIAL: + // TODO: make a port-specific serial number callback + mp_usbd_port_get_serial_number(serial_buf); + desc_str = serial_buf; + break; + case USBD_STR_MANUF: + desc_str = MICROPY_HW_USB_MANUFACTURER_STRING; + break; + case USBD_STR_PRODUCT: + desc_str = MICROPY_HW_USB_PRODUCT_FS_STRING; + break; + #if CFG_TUD_CDC + case USBD_STR_CDC: + desc_str = MICROPY_HW_USB_CDC_INTERFACE_STRING; + break; + #endif + #if CFG_TUD_MSC + case USBD_STR_MSC: + desc_str = MICROPY_HW_USB_MSC_INTERFACE_STRING; + break; + #endif + default: + desc_str = NULL; + } + + if (index != 0) { + if (desc_str == NULL) { + return NULL; // Will STALL the endpoint + } + + // Convert from narrow string to wide string + desc_len = 2; + for (int i = 0; i < MICROPY_HW_USB_DESC_STR_MAX && desc_str[i] != 0; i++) { + desc_wstr[1 + i] = desc_str[i]; + desc_len += 2; + } + } + // first byte is length (including header), second byte is string type + desc_wstr[0] = (TUSB_DESC_STRING << 8) | desc_len; + + return desc_wstr; +} + + +const uint8_t *tud_descriptor_device_cb(void) { + return (const void *)&mp_usbd_desc_device_static; +} + +const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { + (void)index; + return mp_usbd_desc_cfg_static; +} + +#endif diff --git a/ports/broadcom/supervisor/internal_flash_root_pointers.h b/shared/tinyusb/mp_usbd_internal.h similarity index 74% rename from ports/broadcom/supervisor/internal_flash_root_pointers.h rename to shared/tinyusb/mp_usbd_internal.h index 5efe3ac813..8b8f50bae8 100644 --- a/ports/broadcom/supervisor/internal_flash_root_pointers.h +++ b/shared/tinyusb/mp_usbd_internal.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2022 Angus Gratton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,9 +23,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_BROADCOM_INTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_BROADCOM_INTERNAL_FLASH_ROOT_POINTERS_H +#ifndef MICROPY_INCLUDED_SHARED_TINYUSB_MP_USBD_INTERNAL_H +#define MICROPY_INCLUDED_SHARED_TINYUSB_MP_USBD_INTERNAL_H +#include "tusb.h" -#define FLASH_ROOT_POINTERS +// Static USB device descriptor values +extern const tusb_desc_device_t mp_usbd_desc_device_static; +extern const uint8_t mp_usbd_desc_cfg_static[USBD_STATIC_DESC_LEN]; -#endif // MICROPY_INCLUDED_BROADCOM_INTERNAL_FLASH_ROOT_POINTERS_H +#endif // MICROPY_INCLUDED_SHARED_TINYUSB_MP_USBD_INTERNAL_H diff --git a/shared/tinyusb/tusb_config.h b/shared/tinyusb/tusb_config.h new file mode 100644 index 0000000000..28bee09a59 --- /dev/null +++ b/shared/tinyusb/tusb_config.h @@ -0,0 +1,132 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 Damien P. George + * Copyright (c) 2022 Angus Gratton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef MICROPY_INCLUDED_SHARED_TINYUSB_TUSB_CONFIG_H +#define MICROPY_INCLUDED_SHARED_TINYUSB_TUSB_CONFIG_H + +#include "py/mpconfig.h" + +#if MICROPY_HW_ENABLE_USBDEV + +#ifndef MICROPY_HW_USB_MANUFACTURER_STRING +#define MICROPY_HW_USB_MANUFACTURER_STRING "MicroPython" +#endif + +#ifndef MICROPY_HW_USB_PRODUCT_FS_STRING +#define MICROPY_HW_USB_PRODUCT_FS_STRING "Board in FS mode" +#endif + +#ifndef MICROPY_HW_USB_CDC_INTERFACE_STRING +#define MICROPY_HW_USB_CDC_INTERFACE_STRING "Board CDC" +#endif + +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE) + +#if MICROPY_HW_USB_CDC +#define CFG_TUD_CDC (1) +#else +#define CFG_TUD_CDC (0) +#endif + +#if MICROPY_HW_USB_MSC +#define CFG_TUD_MSC (1) +#else +#define CFG_TUD_MSC (0) +#endif + +// CDC Configuration +#if CFG_TUD_CDC +#define CFG_TUD_CDC_RX_BUFSIZE (256) +#define CFG_TUD_CDC_TX_BUFSIZE (256) +#endif + +// MSC Configuration +#if CFG_TUD_MSC +#ifndef MICROPY_HW_USB_MSC_INTERFACE_STRING +#define MICROPY_HW_USB_MSC_INTERFACE_STRING "Board MSC" +#endif +// Set MSC EP buffer size to FatFS block size to avoid partial read/writes (offset arg). +#define CFG_TUD_MSC_BUFSIZE (MICROPY_FATFS_MAX_SS) +#endif + +// Define static descriptor size and interface count based on the above config + +#define USBD_STATIC_DESC_LEN (TUD_CONFIG_DESC_LEN + \ + (CFG_TUD_CDC ? (TUD_CDC_DESC_LEN) : 0) + \ + (CFG_TUD_MSC ? (TUD_MSC_DESC_LEN) : 0) \ + ) + +#define USBD_STR_0 (0x00) +#define USBD_STR_MANUF (0x01) +#define USBD_STR_PRODUCT (0x02) +#define USBD_STR_SERIAL (0x03) +#define USBD_STR_CDC (0x04) +#define USBD_STR_MSC (0x05) + +#define USBD_MAX_POWER_MA (250) + +#ifndef MICROPY_HW_USB_DESC_STR_MAX +#define MICROPY_HW_USB_DESC_STR_MAX (20) +#endif + +#if CFG_TUD_CDC +#define USBD_ITF_CDC (0) // needs 2 interfaces +#define USBD_CDC_EP_CMD (0x81) +#define USBD_CDC_EP_OUT (0x02) +#define USBD_CDC_EP_IN (0x82) +#endif // CFG_TUD_CDC + +#if CFG_TUD_MSC +// Interface & Endpoint numbers for MSC come after CDC, if it is enabled +#if CFG_TUD_CDC +#define USBD_ITF_MSC (2) +#define EPNUM_MSC_OUT (0x03) +#define EPNUM_MSC_IN (0x83) +#else +#define USBD_ITF_MSC (0) +#define EPNUM_MSC_OUT (0x01) +#define EPNUM_MSC_IN (0x81) +#endif // CFG_TUD_CDC +#endif // CFG_TUD_MSC + +/* Limits of statically defined USB interfaces, endpoints, strings */ +#if CFG_TUD_MSC +#define USBD_ITF_STATIC_MAX (USBD_ITF_MSC + 1) +#define USBD_STR_STATIC_MAX (USBD_STR_MSC + 1) +#define USBD_EP_STATIC_MAX (EPNUM_MSC_OUT + 1) +#elif CFG_TUD_CDC +#define USBD_ITF_STATIC_MAX (USBD_ITF_CDC + 2) +#define USBD_STR_STATIC_MAX (USBD_STR_CDC + 1) +#define USBD_EP_STATIC_MAX (((EPNUM_CDC_EP_IN)&~TUSB_DIR_IN_MASK) + 1) +#else // !CFG_TUD_MSC && !CFG_TUD_CDC +#define USBD_ITF_STATIC_MAX (0) +#define USBD_STR_STATIC_MAX (0) +#define USBD_EP_STATIC_MAX (0) +#endif + +#endif // MICROPY_HW_ENABLE_USBDEV + +#endif // MICROPY_INCLUDED_SHARED_TINYUSB_TUSB_CONFIG_H diff --git a/supervisor/shared/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c index 8d6938713d..1619409bb4 100644 --- a/supervisor/shared/external_flash/external_flash.c +++ b/supervisor/shared/external_flash/external_flash.c @@ -33,6 +33,7 @@ #include "supervisor/shared/external_flash/common_commands.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" +#include "py/gc.h" #include "py/misc.h" #include "py/obj.h" #include "py/runtime.h" @@ -367,7 +368,8 @@ static bool allocate_ram_cache(void) { return true; } - if (MP_STATE_MEM(gc_pool_start) == 0) { + // Couldn't allocate outside the heap. Is the heap available? + if (!gc_alloc_possible()) { return false; } @@ -414,7 +416,7 @@ static void release_ram_cache(void) { if (supervisor_cache != NULL) { free_memory(supervisor_cache); supervisor_cache = NULL; - } else if (MP_STATE_MEM(gc_pool_start)) { + } else if (gc_alloc_possible()) { m_free(MP_STATE_VM(flash_ram_cache)); } MP_STATE_VM(flash_ram_cache) = NULL; @@ -462,7 +464,7 @@ static bool flush_ram_cache(bool keep_cache) { write_flash(current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], SPI_FLASH_PAGE_SIZE); - if (!keep_cache && supervisor_cache == NULL && MP_STATE_MEM(gc_pool_start)) { + if (!keep_cache && supervisor_cache == NULL && gc_alloc_possible()) { m_free(MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j]); } } @@ -605,3 +607,5 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, void MP_WEAK external_flash_setup(void) { } + +MP_REGISTER_ROOT_POINTER(uint8_t * *flash_ram_cache); diff --git a/supervisor/shared/external_flash/external_flash_root_pointers.h b/supervisor/shared/external_flash/external_flash_root_pointers.h deleted file mode 100644 index 0613c9a57d..0000000000 --- a/supervisor/shared/external_flash/external_flash_root_pointers.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_ROOT_POINTERS_H - -#include - -// We use this when we can allocate the whole cache in RAM. -#define FLASH_ROOT_POINTERS \ - uint8_t **flash_ram_cache; \ - -#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_ROOT_POINTERS_H diff --git a/supervisor/shared/flash.c b/supervisor/shared/flash.c index 53815c9836..3baca1d0e6 100644 --- a/supervisor/shared/flash.c +++ b/supervisor/shared/flash.c @@ -203,12 +203,13 @@ STATIC const mp_rom_map_elem_t supervisor_flash_obj_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(supervisor_flash_obj_locals_dict, supervisor_flash_obj_locals_dict_table); -const mp_obj_type_t supervisor_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_Flash, - .make_new = supervisor_flash_obj_make_new, - .locals_dict = (struct _mp_obj_dict_t *)&supervisor_flash_obj_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + supervisor_flash_type, + MP_QSTR_Flash, + MP_TYPE_FLAG_NONE, + make_new, supervisor_flash_obj_make_new, + locals_dict, &supervisor_flash_obj_locals_dict + ); void supervisor_flash_init_vfs(fs_user_mount_t *vfs) { vfs->base.type = &mp_fat_vfs_type; diff --git a/supervisor/shared/memory.c b/supervisor/shared/memory.c index 7420b2b0b8..badc35b55e 100644 --- a/supervisor/shared/memory.c +++ b/supervisor/shared/memory.c @@ -346,3 +346,5 @@ void supervisor_move_memory(void) { // Add calls to further clients here. old_allocations = NULL; } + +MP_REGISTER_ROOT_POINTER(struct _supervisor_allocation_node *first_embedded_allocation); diff --git a/supervisor/shared/tick.c b/supervisor/shared/tick.c index b91257c8c8..7c35bc2f9b 100644 --- a/supervisor/shared/tick.c +++ b/supervisor/shared/tick.c @@ -30,7 +30,6 @@ #include "py/mphal.h" #include "py/mpstate.h" #include "py/runtime.h" -#include "supervisor/linker.h" #include "supervisor/filesystem.h" #include "supervisor/background_callback.h" #include "supervisor/port.h" diff --git a/supervisor/shared/usb/host_keyboard.c b/supervisor/shared/usb/host_keyboard.c index 0fd64d2662..fc74bfd33f 100644 --- a/supervisor/shared/usb/host_keyboard.c +++ b/supervisor/shared/usb/host_keyboard.c @@ -318,7 +318,7 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons } void usb_keyboard_init(void) { - ringbuf_init(&_incoming_ringbuf, _buf, sizeof(_buf) - 1); + ringbuf_init(&_incoming_ringbuf, _buf, sizeof(_buf)); } bool usb_keyboard_chars_available(void) { diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index ecf83b8bcb..af7398a920 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -339,7 +339,7 @@ bool supervisor_start_web_workflow(bool reload) { initialized = pool.base.type == &socketpool_socketpool_type; - if (initialized){ + if (initialized) { if (!common_hal_socketpool_socket_get_closed(&active)) { common_hal_socketpool_socket_close(&active); } @@ -368,10 +368,10 @@ bool supervisor_start_web_workflow(bool reload) { } // Wake polling thread (maybe) socketpool_socket_poll_resume(); - #endif - return true; - } - return false; + #endif + return true; +} +return false; } void web_workflow_send_raw(socketpool_socket_obj_t *socket, const uint8_t *buf, int len) { diff --git a/supervisor/shared/web_workflow/websocket.c b/supervisor/shared/web_workflow/websocket.c index 0b829bb6f8..afedf3d434 100644 --- a/supervisor/shared/web_workflow/websocket.c +++ b/supervisor/shared/web_workflow/websocket.c @@ -59,7 +59,7 @@ static _websocket cp_serial; void websocket_init(void) { socketpool_socket_reset(&cp_serial.socket); - ringbuf_init(&_incoming_ringbuf, _buf, sizeof(_buf) - 1); + ringbuf_init(&_incoming_ringbuf, _buf, sizeof(_buf)); } void websocket_handoff(socketpool_socket_obj_t *socket) { diff --git a/tests/README b/tests/README deleted file mode 100644 index 8794202e15..0000000000 --- a/tests/README +++ /dev/null @@ -1,27 +0,0 @@ -This directory contains tests for various functionality areas of MicroPython. -To run all stable tests, run "run-tests.py" script in this directory. - -Tests of capabilities not supported on all platforms should be written -to check for the capability being present. If it is not, the test -should merely output 'SKIP' followed by the line terminator, and call -sys.exit() to raise SystemExit, instead of attempting to test the -missing capability. The testing framework (run-tests.py in this -directory, test_main.c in qemu_arm) recognizes this as a skipped test. - -There are a few features for which this mechanism cannot be used to -condition a test. The run-tests.py script uses small scripts in the -feature_check directory to check whether each such feature is present, -and skips the relevant tests if not. - -Tests are generally verified by running the test both in MicroPython and -in CPython and comparing the outputs. If the output differs the test fails -and the outputs are saved in a .out and a .exp file respectively. -For tests that cannot be run in CPython, for example because they use -the machine module, a .exp file can be provided next to the test's .py -file. A convenient way to generate that is to run the test, let it fail -(because CPython cannot run it) and then copy the .out file (but not -before checking it manually!) - -When creating new tests, anything that relies on float support should go in the -float/ subdirectory. Anything that relies on import x, where x is not a built-in -module, should go in the import/ subdirectory. diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000000..b0bff4872e --- /dev/null +++ b/tests/README.md @@ -0,0 +1,149 @@ +# MicroPython Test Suite + +This directory contains tests for various functionality areas of MicroPython. +To run all stable tests, run "run-tests.py" script in this directory. + +Tests of capabilities not supported on all platforms should be written +to check for the capability being present. If it is not, the test +should merely output 'SKIP' followed by the line terminator, and call +sys.exit() to raise SystemExit, instead of attempting to test the +missing capability. The testing framework (run-tests.py in this +directory, test_main.c in qemu_arm) recognizes this as a skipped test. + +There are a few features for which this mechanism cannot be used to +condition a test. The run-tests.py script uses small scripts in the +feature_check directory to check whether each such feature is present, +and skips the relevant tests if not. + +Tests are generally verified by running the test both in MicroPython and +in CPython and comparing the outputs. If the output differs the test fails +and the outputs are saved in a .out and a .exp file respectively. +For tests that cannot be run in CPython, for example because they use +the machine module, a .exp file can be provided next to the test's .py +file. A convenient way to generate that is to run the test, let it fail +(because CPython cannot run it) and then copy the .out file (but not +before checking it manually!) + +When creating new tests, anything that relies on float support should go in the +float/ subdirectory. Anything that relies on import x, where x is not a built-in +module, should go in the import/ subdirectory. + +## perf_bench + +The `perf_bench` directory contains some performance benchmarks that can be used +to benchmark different MicroPython firmwares or host ports. + +The runner utility is `run-perfbench,py`. Execute `./run-perfbench.py --help` +for a full list of command line options. + +### Benchmarking a target + +To run tests on a firmware target using `pyboard.py`, run the command line like +this: + +``` +./run-perfbench.py -p -d /dev/ttyACM0 168 100 +``` + +* `-p` indicates running on a remote target via pyboard.py, not the host. +* `-d PORTNAME` is the serial port, `/dev/ttyACM0` is the default if not + provided. +* `168` is value `N`, the approximate CPU frequency in MHz (in this case Pyboard + V1.1 is 168MHz). It's possible to choose other values as well: lower values + like `10` will run much the tests much quicker, higher values like `1000` will + run much longer. +* `100` is value `M`, the approximate heap size in kilobytes (can get this from + `import micropython; micropython.mem_info()` or estimate it). It's possible to + choose other values here too: lower values like `10` will run shorter/smaller + tests, and higher values will run bigger tests. The maximum value of `M` is + limited by available heap, and the tests are written so the "recommended" + value is approximately the upper limit. + +### Benchmarking the host + +To benchmark the host build (unix/Windows), run like this: + +``` +./run-perfbench.py 2000 10000 +``` + +The output of perfbench is a list of tests and times/scores, like this: + +``` +N=2000 M=10000 n_average=8 +perf_bench/bm_chaos.py: SKIP +perf_bench/bm_fannkuch.py: 94550.38 2.9145 84.68 2.8499 +perf_bench/bm_fft.py: 79920.38 10.0771 129269.74 8.8205 +perf_bench/bm_float.py: 43844.62 17.8229 353219.64 17.7693 +perf_bench/bm_hexiom.py: 32959.12 15.0243 775.77 14.8893 +perf_bench/bm_nqueens.py: 40855.00 10.7297 247776.15 11.3647 +perf_bench/bm_pidigits.py: 64547.75 2.5609 7751.36 2.5996 +perf_bench/core_import_mpy_multi.py: 15433.38 14.2733 33065.45 14.2368 +perf_bench/core_import_mpy_single.py: 263.00 11.3910 3858.35 12.9021 +perf_bench/core_qstr.py: 4929.12 1.8434 8117.71 1.7921 +perf_bench/core_yield_from.py: 16274.25 6.2584 12334.13 5.8125 +perf_bench/misc_aes.py: 57425.25 5.5226 17888.60 5.7482 +perf_bench/misc_mandel.py: 40809.25 8.2007 158107.00 9.8864 +perf_bench/misc_pystone.py: 39821.75 6.4145 100867.62 6.5043 +perf_bench/misc_raytrace.py: 36293.75 6.8501 26906.93 6.8402 +perf_bench/viper_call0.py: 15573.00 14.9931 19644.99 13.1550 +perf_bench/viper_call1a.py: 16725.75 9.8205 18099.96 9.2752 +perf_bench/viper_call1b.py: 20752.62 8.3372 14565.60 9.0663 +perf_bench/viper_call1c.py: 20849.88 5.8783 14444.80 6.6295 +perf_bench/viper_call2a.py: 16156.25 11.2956 18818.59 11.7959 +perf_bench/viper_call2b.py: 22047.38 8.9484 13725.73 9.6800 +``` + +The numbers across each line are times and scores for the test: + +* Runtime average (microseconds, lower is better) +* Runtime standard deviation as a percentage +* Score average (units depend on the benchmark, higher is better) +* Score standard deviation as a percentage + +### Comparing performance + +Usually you want to know if something is faster or slower than a reference. To +do this, copy the output of each `run-perfbench.py` run to a text file. + +This can be done multiple ways, but one way on Linux/macOS is with the `tee` +utility: `./run-perfbench.py -p 168 100 | tee pyb-run1.txt` + +Once you have two files with output from two different runs (maybe with +different code or configuration), compare the runtimes with `./run-perfbench.py +-t pybv-run1.txt pybv-run2.txt` or compare scores with `./run-perfbench.py -s +pybv-run1.txt pybv-run2.txt`: + +``` +> ./run-perfbench.py -s pyb-run1.txt pyb-run2.txt +diff of scores (higher is better) +N=168 M=100 pyb-run1.txt -> pyb-run2.txt diff diff% (error%) +bm_chaos.py 352.90 -> 352.63 : -0.27 = -0.077% (+/-0.00%) +bm_fannkuch.py 77.52 -> 77.45 : -0.07 = -0.090% (+/-0.01%) +bm_fft.py 2516.80 -> 2519.74 : +2.94 = +0.117% (+/-0.00%) +bm_float.py 5749.27 -> 5749.65 : +0.38 = +0.007% (+/-0.00%) +bm_hexiom.py 42.22 -> 42.30 : +0.08 = +0.189% (+/-0.00%) +bm_nqueens.py 4407.55 -> 4414.44 : +6.89 = +0.156% (+/-0.00%) +bm_pidigits.py 638.09 -> 632.14 : -5.95 = -0.932% (+/-0.25%) +core_import_mpy_multi.py 477.74 -> 477.57 : -0.17 = -0.036% (+/-0.00%) +core_import_mpy_single.py 58.74 -> 58.72 : -0.02 = -0.034% (+/-0.00%) +core_qstr.py 63.11 -> 63.11 : +0.00 = +0.000% (+/-0.01%) +core_yield_from.py 357.57 -> 357.57 : +0.00 = +0.000% (+/-0.00%) +misc_aes.py 397.27 -> 396.47 : -0.80 = -0.201% (+/-0.00%) +misc_mandel.py 3375.70 -> 3375.84 : +0.14 = +0.004% (+/-0.00%) +misc_pystone.py 2265.36 -> 2265.97 : +0.61 = +0.027% (+/-0.01%) +misc_raytrace.py 367.61 -> 368.15 : +0.54 = +0.147% (+/-0.01%) +viper_call0.py 605.92 -> 605.92 : +0.00 = +0.000% (+/-0.00%) +viper_call1a.py 576.78 -> 576.78 : +0.00 = +0.000% (+/-0.00%) +viper_call1b.py 452.45 -> 452.46 : +0.01 = +0.002% (+/-0.01%) +viper_call1c.py 457.39 -> 457.39 : +0.00 = +0.000% (+/-0.00%) +viper_call2a.py 561.37 -> 561.37 : +0.00 = +0.000% (+/-0.00%) +viper_call2b.py 389.49 -> 389.50 : +0.01 = +0.003% (+/-0.01%) +``` + +Note in particular the error percentages at the end of each line. If these are +high relative to the percentage difference then it indicates high variability in +the test runs, and the absolute difference value is unreliable. High error +percentages are particularly common on PC builds, where the host OS may +influence test run times. Increasing the `N` value may help average this out by +running each test longer. diff --git a/tests/basics/assign_expr.py b/tests/basics/assign_expr.py index f243905dc2..2cf604193b 100644 --- a/tests/basics/assign_expr.py +++ b/tests/basics/assign_expr.py @@ -12,6 +12,17 @@ x = 1 print(x, x := 5, x) print(x) +# Test "while" with assignment expression as conditional, assigning to a new local. +# The while conditional is compiled after the while body, so this tests how the +# compiler handles the case of an unbound local being compiled before it is assigned. +def f(): + l = [0, 1] + while local := len(l): + print(local, l.pop()) + + +f() + def foo(): print("any", any((hit := i) % 5 == 3 and (hit % 2) == 0 for i in range(10))) diff --git a/tests/basics/assign_expr.py.exp b/tests/basics/assign_expr.py.exp index e38e1ae7a6..47da56b80d 100644 --- a/tests/basics/assign_expr.py.exp +++ b/tests/basics/assign_expr.py.exp @@ -5,6 +5,8 @@ True 5 1 5 5 5 +2 1 +1 0 any True 8 123 diff --git a/tests/basics/assign_expr_scope.py b/tests/basics/assign_expr_scope.py new file mode 100644 index 0000000000..69dc9f0d17 --- /dev/null +++ b/tests/basics/assign_expr_scope.py @@ -0,0 +1,81 @@ +# Test scoping rules for assignment expression :=. + +# Test that var is closed over (assigned to in the scope of scope0). +def scope0(): + any((var0 := i) for i in range(2)) + return var0 + + +print("scope0") +print(scope0()) +print(globals().get("var0", None)) + +# Test that var1 gets closed over correctly in the list comprehension. +def scope1(): + var1 = 0 + dummy1 = 1 + dummy2 = 1 + print([var1 := i for i in [0, 1] if i > var1]) + print(var1) + + +print("scope1") +scope1() +print(globals().get("var1", None)) + +# Test that var2 in the comprehension honours the global declaration. +def scope2(): + global var2 + print([var2 := i for i in range(2)]) + print(globals().get("var2", None)) + + +print("scope2") +scope2() +print(globals().get("var2", None)) + +# Test that var1 in the comprehension remains local to inner1. +def scope3(): + global var3 + + def inner3(): + print([var3 := i for i in range(2)]) + + inner3() + print(globals().get("var3", None)) + + +print("scope3") +scope3() +print(globals().get("var3", None)) + +# Test that var4 in the comprehension honours the global declarations. +def scope4(): + global var4 + + def inner4(): + global var4 + print([var4 := i for i in range(2)]) + + inner4() + print(var4) + + +print("scope4") +scope4() +print(globals().get("var4", None)) + +# Test that var5 in the comprehension honours the nonlocal declaration. +def scope5(): + def inner5(): + nonlocal var5 + print([var5 := i for i in range(2)]) + + inner5() + print(var5) + var5 = 0 # force var5 to be a local to scope5 + + +print("scope5") +scope5() +print(globals().get("var5", None)) diff --git a/tests/basics/assign_expr_scope.py.exp b/tests/basics/assign_expr_scope.py.exp new file mode 100644 index 0000000000..5c780b3822 --- /dev/null +++ b/tests/basics/assign_expr_scope.py.exp @@ -0,0 +1,23 @@ +scope0 +1 +None +scope1 +[1] +1 +None +scope2 +[0, 1] +1 +1 +scope3 +[0, 1] +None +None +scope4 +[0, 1] +1 +1 +scope5 +[0, 1] +1 +None diff --git a/tests/basics/assign_expr_syntaxerror.py b/tests/basics/assign_expr_syntaxerror.py index 11b3501292..0c334d075a 100644 --- a/tests/basics/assign_expr_syntaxerror.py +++ b/tests/basics/assign_expr_syntaxerror.py @@ -8,9 +8,9 @@ def test(code): test("x := 1") test("((x, y) := 1)") - -# these are currently all allowed in MicroPython, but not in CPython test("([i := i + 1 for i in range(4)])") test("([i := -1 for i, j in [(1, 2)]])") test("([[(i := j) for i in range(2)] for j in range(2)])") + +# this is currently allowed in MicroPython, but not in CPython test("([[(j := i) for i in range(2)] for j in range(2)])") diff --git a/tests/basics/assign_expr_syntaxerror.py.exp b/tests/basics/assign_expr_syntaxerror.py.exp index 2ba7d7df86..8b386b2a95 100644 --- a/tests/basics/assign_expr_syntaxerror.py.exp +++ b/tests/basics/assign_expr_syntaxerror.py.exp @@ -1,6 +1,6 @@ SyntaxError SyntaxError -[1, 2, 3, 4] -[-1] -[[0, 0], [1, 1]] +SyntaxError +SyntaxError +SyntaxError [[0, 1], [0, 1]] diff --git a/tests/basics/builtin_str_hex.py b/tests/basics/builtin_str_hex.py new file mode 100644 index 0000000000..7390c8eaee --- /dev/null +++ b/tests/basics/builtin_str_hex.py @@ -0,0 +1,24 @@ +if not hasattr(bytes, "fromhex"): + print("SKIP") + raise SystemExit + +for x in ( + b"\x00\x01\x02\x03\x04\x05\x06\x07", + b"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + b"\x7f\x80\xff", + b"1234ABCDabcd", +): + print(x.hex()) + print(bytearray(x).hex()) + print(memoryview(x).hex()) + print(x.hex(":")) + print(bytearray(x).hex(":")) + print(memoryview(x).hex(":")) + +for x in ( + "0001020304050607", + "08090a0b0c0d0e0f", + "7f80ff", + "313233344142434461626364", +): + print(bytes.fromhex(x)) diff --git a/tests/basics/builtin_str_hex.py.exp b/tests/basics/builtin_str_hex.py.exp new file mode 100644 index 0000000000..990dd85707 --- /dev/null +++ b/tests/basics/builtin_str_hex.py.exp @@ -0,0 +1,28 @@ +0001020304050607 +0001020304050607 +0001020304050607 +00:01:02:03:04:05:06:07 +00:01:02:03:04:05:06:07 +00:01:02:03:04:05:06:07 +08090a0b0c0d0e0f +08090a0b0c0d0e0f +08090a0b0c0d0e0f +08:09:0a:0b:0c:0d:0e:0f +08:09:0a:0b:0c:0d:0e:0f +08:09:0a:0b:0c:0d:0e:0f +7f80ff +7f80ff +7f80ff +7f:80:ff +7f:80:ff +7f:80:ff +313233344142434461626364 +313233344142434461626364 +313233344142434461626364 +31:32:33:34:41:42:43:44:61:62:63:64 +31:32:33:34:41:42:43:44:61:62:63:64 +31:32:33:34:41:42:43:44:61:62:63:64 +b'\x00\x01\x02\x03\x04\x05\x06\x07' +b'\x08\t\n\x0b\x0c\r\x0e\x0f' +b'\x7f\x80\xff' +b'1234ABCDabcd' diff --git a/tests/basics/bytearray_byte_operations.py b/tests/basics/bytearray_byte_operations.py new file mode 100644 index 0000000000..7ce53cac53 --- /dev/null +++ b/tests/basics/bytearray_byte_operations.py @@ -0,0 +1,35 @@ +# test bytearray with its re-use of byte functions + +print(bytearray(b"hello world").find(b"ll")) +print(bytearray(b"hello\x00world").rfind(b"l")) + +print(bytearray(b"abc efg ").strip(b"g a")) +print(bytearray(b" spacious ").lstrip()) +print(bytearray(b"www.example.com").lstrip(b"cmowz.")) +print(bytearray(b" spacious ").rstrip()) +print(bytearray(b"mississippi").rstrip(b"ipz")) + +print(bytearray(b"abc").split(b"a")) +print(bytearray(b"abcabc").rsplit(b"bc")) + +print(bytearray(b"asdfasdf").replace(b"a", b"b")) + +print("00\x0000".index("0", 0)) +print("00\x0000".index("0", 3)) +print("00\x0000".rindex("0", 0)) +print("00\x0000".rindex("0", 3)) + +print(bytearray(b"foobar").endswith(b"bar")) +print(bytearray(b"1foo").startswith(b"foo", 1)) + +print(bytearray(b" T E \x00 S T").lower()) +print(bytearray(b" te \x00 st").upper()) + +print(bytearray(b" \t\n\r\v\f").isspace()) +print(bytearray(b"this ").isalpha()) +print(bytearray(b"0123456789").isdigit()) +print(bytearray(b"AB").isupper()) +print(bytearray(b"cheese-cake").islower()) + +print(bytearray(b",").join((bytearray(b"abc"), bytearray(b"def")))) +print(type(bytearray(b",").join((b"a", b"b", b"c")))) diff --git a/tests/basics/bytearray_center.py b/tests/basics/bytearray_center.py new file mode 100644 index 0000000000..c262a8c209 --- /dev/null +++ b/tests/basics/bytearray_center.py @@ -0,0 +1,8 @@ +try: + bytearray.center +except AttributeError: + print("SKIP") + raise SystemExit + +print(bytearray(b"foo").center(6)) +print(type(bytearray(b"foo").center(6))) diff --git a/tests/basics/bytearray_construct.py b/tests/basics/bytearray_construct.py index 75fdc41178..eb4d4e641f 100644 --- a/tests/basics/bytearray_construct.py +++ b/tests/basics/bytearray_construct.py @@ -5,3 +5,8 @@ print(bytearray('1234', 'utf-8')) print(bytearray('12345', 'utf-8', 'strict')) print(bytearray((1, 2))) print(bytearray([1, 2])) + +try: + print(bytearray('1234')) +except TypeError: + print("TypeError") diff --git a/tests/basics/bytearray_count.py b/tests/basics/bytearray_count.py new file mode 100644 index 0000000000..a151c1e818 --- /dev/null +++ b/tests/basics/bytearray_count.py @@ -0,0 +1,7 @@ +try: + bytearray.count +except AttributeError: + print("SKIP") + raise SystemExit + +print(bytearray(b"aaaa").count(b"a")) diff --git a/tests/basics/bytearray_partition.py b/tests/basics/bytearray_partition.py new file mode 100644 index 0000000000..b48ec4ed9b --- /dev/null +++ b/tests/basics/bytearray_partition.py @@ -0,0 +1,8 @@ +try: + bytearray.partition +except AttributeError: + print("SKIP") + raise SystemExit + +print(bytearray(b"asdsf").partition(b"s")) +print(bytearray(b"asdsf").rpartition(b"s")) diff --git a/tests/basics/bytes_center.py b/tests/basics/bytes_center.py new file mode 100644 index 0000000000..5d8b41d92f --- /dev/null +++ b/tests/basics/bytes_center.py @@ -0,0 +1,13 @@ +try: + bytes.center +except: + print("SKIP") + raise SystemExit + +print(b"foo".center(0)) +print(b"foo".center(1)) +print(b"foo".center(3)) +print(b"foo".center(4)) +print(b"foo".center(5)) +print(b"foo".center(6)) +print(b"foo".center(20)) diff --git a/tests/basics/bytes_count.py b/tests/basics/bytes_count.py index 5fa0730f5c..e71f09db00 100644 --- a/tests/basics/bytes_count.py +++ b/tests/basics/bytes_count.py @@ -48,6 +48,13 @@ print(b"aaaa".count(b'a', 1, 5)) print(b"aaaa".count(b'a', -1, 5)) print(b"abbabba".count(b"abba")) +print(b'\xaa \xaa'.count(b'\xaa')) +print(b'\xaa \xaa \xaa \xaa'.count(b'\xaa')) +print(b'\xaa \xaa \xaa \xaa'.count(b'\xaa'), 1) +print(b'\xaa \xaa \xaa \xaa'.count(b'\xaa'), 2) +print(b'\xaa \xaa \xaa \xaa'.count(b'\xaa'), 1, 3) +print(b'\xaa \xaa \xaa \xaa'.count(b'\xaa'), 2, 3) + def t(): return True diff --git a/tests/basics/dict_union.py b/tests/basics/dict_union.py new file mode 100644 index 0000000000..606b1c4c52 --- /dev/null +++ b/tests/basics/dict_union.py @@ -0,0 +1,36 @@ +# Test dictionary union. +# +# The tests sort the resulting dictionaries for now, since map insertion +# order is not implemented in MicroPython. + +try: + {} | {} +except TypeError: + print("SKIP") + raise SystemExit + + +def print_sorted_dict(d): + print(sorted(d.items())) + + +def test_union(a, b): + print_sorted_dict(a | b) + print_sorted_dict(b | a) + a |= a + print_sorted_dict(a) + a |= b + print_sorted_dict(a) + + +d = {} +e = {} +test_union(d, e) + +d = {1: "apple"} +e = {1: "cheese"} +test_union(d, e) + +d = {"spam": 1, "eggs": 2, "cheese": 3} +e = {"cheese": "cheddar", "aardvark": "Ethel"} +test_union(d, e) diff --git a/tests/basics/dict_union.py.exp b/tests/basics/dict_union.py.exp new file mode 100644 index 0000000000..7a8f83bd54 --- /dev/null +++ b/tests/basics/dict_union.py.exp @@ -0,0 +1,12 @@ +[] +[] +[] +[] +[(1, 'cheese')] +[(1, 'apple')] +[(1, 'apple')] +[(1, 'cheese')] +[('aardvark', 'Ethel'), ('cheese', 'cheddar'), ('eggs', 2), ('spam', 1)] +[('aardvark', 'Ethel'), ('cheese', 3), ('eggs', 2), ('spam', 1)] +[('cheese', 3), ('eggs', 2), ('spam', 1)] +[('aardvark', 'Ethel'), ('cheese', 'cheddar'), ('eggs', 2), ('spam', 1)] diff --git a/tests/basics/fun_calldblstar.py b/tests/basics/fun_calldblstar.py index d4816c5cd3..0308f42bdb 100644 --- a/tests/basics/fun_calldblstar.py +++ b/tests/basics/fun_calldblstar.py @@ -21,9 +21,12 @@ a = A() a.f(1, **{'b':2}) a.f(1, **{'b':val for val in range(1)}) +# test for duplicate keys in **kwargs not allowed + +def f1(**kwargs): + print(kwargs) + try: - f(1, **{len: 1}) + f1(**{'a': 1, 'b': 2}, **{'b': 3, 'c': 4}) except TypeError: - print(True) -else: - print(False) + print('TypeError') diff --git a/tests/basics/fun_callstardblstar.py b/tests/basics/fun_callstardblstar.py index f395df3333..c08e46f668 100644 --- a/tests/basics/fun_callstardblstar.py +++ b/tests/basics/fun_callstardblstar.py @@ -37,3 +37,7 @@ f2(*iter(range(4)), **{'a': 1}) # case where *args is not a tuple/list and takes up most of the memory allocated for **kwargs f2(*iter(range(100)), **{str(i): i for i in range(100)}) + +# regression test - iterable with unknown len() was exactly using preallocated +# memory causing args 4 and 5 to overflow the allocated arg array +print(1, *iter((1, 2, 3)), *iter((1, 2, 3)), 4, 5, sep=",") diff --git a/tests/basics/fun_globals.py b/tests/basics/fun_globals.py index 3f32e8bdb0..69f8638e8d 100644 --- a/tests/basics/fun_globals.py +++ b/tests/basics/fun_globals.py @@ -19,3 +19,18 @@ try: foo.__globals__ = None except AttributeError: print("AttributeError") + +# test closures have the __globals__ attribute + + +def outer(): + x = 1 + + def inner(): + return x + + return inner + + +print(outer.__globals__ is globals()) +print(outer().__globals__ is globals()) diff --git a/tests/basics/fun_name.py b/tests/basics/fun_name.py index bb1f14992f..b2642280a2 100644 --- a/tests/basics/fun_name.py +++ b/tests/basics/fun_name.py @@ -24,9 +24,11 @@ except AttributeError: pass # name of a function that has closed over variables +# and also the name of the inner closure def outer(): x = 1 def inner(): return x return inner print(outer.__name__) +print(outer().__name__) diff --git a/tests/basics/int_big_error.py b/tests/basics/int_big_error.py index 79809aef11..1793cf3253 100644 --- a/tests/basics/int_big_error.py +++ b/tests/basics/int_big_error.py @@ -7,6 +7,16 @@ try: except ValueError: print("ValueError") +try: + i @ 0 +except TypeError: + print("TypeError") + +try: + i @= 0 +except TypeError: + print("TypeError") + try: len(i) except TypeError: diff --git a/tests/basics/io_stringio_base.py b/tests/basics/io_stringio_base.py new file mode 100644 index 0000000000..dffc879074 --- /dev/null +++ b/tests/basics/io_stringio_base.py @@ -0,0 +1,24 @@ +# Checks that an instance type inheriting from a native base that uses +# MP_TYPE_FLAG_ITER_IS_STREAM will still have a getiter. + +try: + import uio as io +except ImportError: + import io + +a = io.StringIO() +a.write("hello\nworld\nmicro\npython\n") +a.seek(0) + +for line in a: + print(line) + +class X(io.StringIO): + pass + +b = X() +b.write("hello\nworld\nmicro\npython\n") +b.seek(0) + +for line in b: + print(line) diff --git a/tests/basics/memoryview_slice_size.py b/tests/basics/memoryview_slice_size.py new file mode 100644 index 0000000000..c56514d21f --- /dev/null +++ b/tests/basics/memoryview_slice_size.py @@ -0,0 +1,27 @@ +# test memoryview slicing beyond the limit of what memoryview can internally index + +try: + from sys import maxsize + from uctypes import bytearray_at + + memoryview +except: + print("SKIP") + raise SystemExit + +if maxsize <= 0xFFFF_FFFF: + slice_max = 0xFF_FFFF +else: + slice_max = 0xFF_FFFF_FFFF_FFFF + +buf = bytearray_at(0, slice_max + 2) +mv = memoryview(buf) + +# this should work +print(mv[slice_max : slice_max + 1]) + +# this should overflow the internal index for memoryview slicing +try: + print(mv[slice_max + 1 : slice_max + 2]) +except OverflowError: + print("OverflowError") diff --git a/tests/basics/memoryview_slice_size.py.exp b/tests/basics/memoryview_slice_size.py.exp new file mode 100644 index 0000000000..34baadd35e --- /dev/null +++ b/tests/basics/memoryview_slice_size.py.exp @@ -0,0 +1,2 @@ + +OverflowError diff --git a/tests/basics/module_dict.py b/tests/basics/module_dict.py new file mode 100644 index 0000000000..c847294f08 --- /dev/null +++ b/tests/basics/module_dict.py @@ -0,0 +1,13 @@ +# test __dict__ attribute of a built-in module +# see import/module_dict.py for the equivalent test on user modules + +import sys + +if not hasattr(sys, "__dict__"): + print("SKIP") + raise SystemExit + + +# dict of a built-in module (read-only) +print(type(sys.__dict__)) +print(sys.__dict__["__name__"]) diff --git a/tests/basics/namedtuple1.py b/tests/basics/namedtuple1.py index f55a95625e..eee8a3909c 100644 --- a/tests/basics/namedtuple1.py +++ b/tests/basics/namedtuple1.py @@ -77,3 +77,8 @@ print(t.foo, t.bar) # Not implemented so far #T2 = namedtuple("TupComma", "foo,bar") #t = T2(1, 2) + +# Creating an empty namedtuple should not segfault +T5 = namedtuple("TupEmpty", []) +t = T5() +print(t) diff --git a/tests/basics/nanbox_smallint.py b/tests/basics/nanbox_smallint.py index 167b196010..b3a502e447 100644 --- a/tests/basics/nanbox_smallint.py +++ b/tests/basics/nanbox_smallint.py @@ -1,6 +1,10 @@ # Test creating small integers without heap allocation in nan-boxing mode. -import micropython +try: + import micropython +except ImportError: + print("SKIP") + raise SystemExit try: # Test for nan-box build by allocating a float while heap is locked. diff --git a/tests/basics/string_fstring.py b/tests/basics/string_fstring.py index 7e8a97fd30..8907a5c478 100644 --- a/tests/basics/string_fstring.py +++ b/tests/basics/string_fstring.py @@ -56,3 +56,8 @@ try: except (ValueError, SyntaxError): # MicroPython incorrectly raises ValueError here. print('SyntaxError') + +# Allow literal tuples +print(f"a {1,} b") +print(f"a {x,y,} b") +print(f"a {x,1} b") diff --git a/tests/basics/string_fstring_debug.py b/tests/basics/string_fstring_debug.py index 76a448ca06..95abd4d6d0 100644 --- a/tests/basics/string_fstring_debug.py +++ b/tests/basics/string_fstring_debug.py @@ -21,3 +21,7 @@ print(f"a {x=:08x} b {y} c") print(f'a {f() + g("foo") + h()=} b') print(f'a {f() + g("foo") + h()=:08x} b') + +print(f"a {1,=} b") +print(f"a {x,y,=} b") +print(f"a {x,1=} b") diff --git a/tests/basics/string_fstring_debug.py.exp b/tests/basics/string_fstring_debug.py.exp index 563030f400..f0309e1c98 100644 --- a/tests/basics/string_fstring_debug.py.exp +++ b/tests/basics/string_fstring_debug.py.exp @@ -4,3 +4,6 @@ a x=1 b 2 c a x=00000001 b 2 c a f() + g("foo") + h()=15 b a f() + g("foo") + h()=0000000f b +a 1,=(1,) b +a x,y,=(1, 2) b +a x,1=(1, 1) b diff --git a/tests/cmdline/cmd_showbc.py b/tests/cmdline/cmd_showbc.py index e5874f990a..4a2e6500aa 100644 --- a/tests/cmdline/cmd_showbc.py +++ b/tests/cmdline/cmd_showbc.py @@ -119,12 +119,12 @@ def f(): #from sys import * # tested at module scope # raise - raise - raise 1 + if a: raise + if a: raise 1 # return - return - return 1 + if a: return + if a: return 1 # function with lots of locals def f(): diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 45a1d169b6..db06de9237 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -47,13 +47,13 @@ arg names: 42 IMPORT_STAR 43 LOAD_CONST_NONE 44 RETURN_VALUE -File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 45\[46\] bytes) -Raw bytecode (code_info_size=8\[46\], bytecode_size=370): +File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 46\[68\] bytes) +Raw bytecode (code_info_size=8\[46\], bytecode_size=382): a8 12 9\[bf\] 03 05 60 60 26 22 24 64 22 24 25 25 24 26 23 63 22 22 25 23 23 2f 6c 25 65 25 25 69 68 26 65 27 6a 62 20 23 62 2a 29 69 24 25 28 67 26 ######## -\.\+81 63 +\.\+51 63 arg names: (N_STATE 22) (N_EXC_STACK 2) @@ -126,19 +126,18 @@ arg names: bc=313 line=100 bc=315 line=101 ######## - bc=321 line=103 - bc=327 line=106 - bc=331 line=107 - bc=337 line=110 - bc=340 line=111 - bc=346 line=114 - bc=346 line=117 - bc=351 line=118 - bc=363 line=121 - bc=363 line=122 - bc=364 line=123 - bc=366 line=126 - bc=368 line=127 + bc=325 line=106 + bc=329 line=107 + bc=335 line=110 + bc=338 line=111 + bc=344 line=114 + bc=344 line=117 + bc=349 line=118 + bc=361 line=121 + bc=361 line=122 + bc=365 line=123 + bc=370 line=126 + bc=375 line=127 00 LOAD_CONST_NONE 01 LOAD_CONST_FALSE 02 BINARY_OP 27 __add__ @@ -363,46 +362,55 @@ arg names: 308 LOAD_FAST 1 309 POP_TOP 310 END_FINALLY -311 JUMP 324 -313 SETUP_EXCEPT 320 -315 UNWIND_JUMP 327 1 -318 POP_EXCEPT_JUMP 324 -320 POP_TOP -321 POP_EXCEPT_JUMP 324 -323 END_FINALLY -324 LOAD_FAST 0 -325 POP_JUMP_IF_TRUE 313 -327 LOAD_FAST 0 -328 SETUP_WITH 335 -330 POP_TOP -331 LOAD_DEREF 14 -333 POP_TOP -334 LOAD_CONST_NONE -335 WITH_CLEANUP -336 END_FINALLY -337 LOAD_CONST_SMALL_INT 1 -338 STORE_DEREF 16 -340 LOAD_FAST_N 16 -342 MAKE_CLOSURE \.\+ 1 -345 STORE_FAST 13 -346 LOAD_CONST_SMALL_INT 0 -347 LOAD_CONST_NONE -348 IMPORT_NAME 'a' -350 STORE_FAST 0 -351 LOAD_CONST_SMALL_INT 0 -352 LOAD_CONST_STRING 'b' -354 BUILD_TUPLE 1 -356 IMPORT_NAME 'a' -358 IMPORT_FROM 'b' -360 STORE_DEREF 14 -362 POP_TOP -363 RAISE_LAST -364 LOAD_CONST_SMALL_INT 1 -365 RAISE_OBJ -366 LOAD_CONST_NONE -367 RETURN_VALUE +311 JUMP 322 +313 SETUP_EXCEPT 318 +315 UNWIND_JUMP 325 1 +318 POP_TOP +319 POP_EXCEPT_JUMP 322 +321 END_FINALLY +322 LOAD_FAST 0 +323 POP_JUMP_IF_TRUE 313 +325 LOAD_FAST 0 +326 SETUP_WITH 333 +328 POP_TOP +329 LOAD_DEREF 14 +331 POP_TOP +332 LOAD_CONST_NONE +333 WITH_CLEANUP +334 END_FINALLY +335 LOAD_CONST_SMALL_INT 1 +336 STORE_DEREF 16 +338 LOAD_FAST_N 16 +340 MAKE_CLOSURE \.\+ 1 +343 STORE_FAST 13 +344 LOAD_CONST_SMALL_INT 0 +345 LOAD_CONST_NONE +346 IMPORT_NAME 'a' +348 STORE_FAST 0 +349 LOAD_CONST_SMALL_INT 0 +350 LOAD_CONST_STRING 'b' +352 BUILD_TUPLE 1 +354 IMPORT_NAME 'a' +356 IMPORT_FROM 'b' +358 STORE_DEREF 14 +360 POP_TOP +361 LOAD_FAST 0 +362 POP_JUMP_IF_FALSE 365 +364 RAISE_LAST +365 LOAD_FAST 0 +366 POP_JUMP_IF_FALSE 370 368 LOAD_CONST_SMALL_INT 1 -369 RETURN_VALUE +369 RAISE_OBJ +370 LOAD_FAST 0 +371 POP_JUMP_IF_FALSE 375 +373 LOAD_CONST_NONE +374 RETURN_VALUE +375 LOAD_FAST 0 +376 POP_JUMP_IF_FALSE 380 +378 LOAD_CONST_SMALL_INT 1 +379 RETURN_VALUE +380 LOAD_CONST_NONE +381 RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 59 bytes) Raw bytecode (code_info_size=8, bytecode_size=51): a8 10 0a 05 80 82 34 38 81 57 c0 57 c1 57 c2 57 diff --git a/tests/cmdline/cmd_showbc_const.py b/tests/cmdline/cmd_showbc_const.py new file mode 100644 index 0000000000..54f9ec23cd --- /dev/null +++ b/tests/cmdline/cmd_showbc_const.py @@ -0,0 +1,69 @@ +# cmdline: -v -v +# Test constant-related bytecode optimisations +# (constant folding, compile-time if/while evaluation, etc.) +from micropython import const +import sys + +try: + sys.settrace + # if MICROPY_PY_SYS_SETTRACE is enabled, compile-time const optimizations + # are disabled so the bytecode output is very different + print("SKIP") + raise SystemExit +except AttributeError: + pass + +_STR = const("foo") +_EMPTY_TUPLE = const(()) +_TRUE = const(True) +_FALSE = const(False) +_SMALLINT = const(33) +_ZERO = const(0) + +# Bytecode generated for these if/while statements should contain no JUMP_IF +# and no instances of string 'Eliminated' + +if _STR or _EMPTY_TUPLE: + print("Kept") +if _STR and _EMPTY_TUPLE: + print("Eliminated") +if _TRUE: + print("Kept") +if _SMALLINT: + print("Kept") +if _ZERO and _SMALLINT: + print("Eliminated") +if _FALSE: + print("Eliminated") + +while _SMALLINT: + print("Kept") + break +while _ZERO: + print("Eliminated") +while _FALSE: + print("Eliminated") + +# These values are stored in variables, and therefore bytecode will contain JUMP_IF + +a = _EMPTY_TUPLE or _STR +if a == _STR: + print("Kept") + +b = _SMALLINT and _STR +if b == _STR: + print("Kept") + +# The compiler is also unable to optimise these expressions, even though the arguments are const, +# so these also contain JUMP_IF + +if (_EMPTY_TUPLE or _STR) == _STR: + print("Kept") + +if (_EMPTY_TUPLE and _STR) == _STR: + print("Not Eliminated") + +if (not _STR) == _FALSE: + print("Kept") + +assert True diff --git a/tests/cmdline/cmd_showbc_const.py.exp b/tests/cmdline/cmd_showbc_const.py.exp new file mode 100644 index 0000000000..6cdc3e9c96 --- /dev/null +++ b/tests/cmdline/cmd_showbc_const.py.exp @@ -0,0 +1,160 @@ +File cmdline/cmd_showbc_const.py, code block '' (descriptor: \.\+, bytecode @\.\+ 198 bytes) +Raw bytecode (code_info_size=40, bytecode_size=158): + 2c 4c 01 60 2c 46 22 65 27 4a 83 0c 20 27 40 20 + 27 20 27 40 60 20 27 24 40 60 40 24 27 47 24 27 + 67 40 27 47 27 47 26 47 80 10 02 2a 01 1b 03 1c + 02 16 02 59 80 51 1b 04 16 04 48 0f 11 04 13 05 + 59 11 09 10 06 34 01 59 11 0a 65 57 11 0b df 44 + 43 59 4a 01 5d 11 09 10 07 34 01 59 11 09 10 07 + 34 01 59 11 09 10 07 34 01 59 11 09 10 07 34 01 + 59 42 42 42 35 23 00 16 0c 11 0c 23 00 d9 44 47 + 11 09 10 07 34 01 59 23 00 16 0d 11 0d 23 00 d9 + 44 47 11 09 10 07 34 01 59 23 00 23 00 d9 44 47 + 11 09 10 07 34 01 59 23 01 23 00 d9 44 47 11 09 + 23 02 34 01 59 50 23 03 d9 44 47 11 09 10 07 34 + 01 59 42 40 51 63 +arg names: +(N_STATE 6) +(N_EXC_STACK 1) + bc=0 line=1 + bc=0 line=4 + bc=12 line=5 + bc=18 line=7 + bc=20 line=8 + bc=25 line=11 + bc=32 line=12 + bc=42 line=14 + bc=45 line=26 + bc=45 line=27 + bc=52 line=28 + bc=52 line=30 + bc=52 line=31 + bc=59 line=32 + bc=59 line=33 + bc=66 line=34 + bc=66 line=36 + bc=66 line=39 + bc=66 line=40 + bc=73 line=41 + bc=77 line=42 + bc=77 line=44 + bc=77 line=47 + bc=77 line=49 + bc=81 line=50 + bc=88 line=51 + bc=95 line=53 + bc=99 line=54 + bc=106 line=55 + bc=113 line=58 + bc=113 line=60 + bc=120 line=61 + bc=127 line=63 + bc=134 line=64 + bc=141 line=66 + bc=147 line=67 + bc=154 line=69 +00 LOAD_CONST_SMALL_INT 0 +01 LOAD_CONST_STRING 'const' +03 BUILD_TUPLE 1 +05 IMPORT_NAME 'micropython' +07 IMPORT_FROM 'const' +09 STORE_NAME const +11 POP_TOP +12 LOAD_CONST_SMALL_INT 0 +13 LOAD_CONST_NONE +14 IMPORT_NAME 'sys' +16 STORE_NAME sys +18 SETUP_EXCEPT 35 +20 LOAD_NAME sys +22 LOAD_ATTR settrace +24 POP_TOP +25 LOAD_NAME print +27 LOAD_CONST_STRING 'SKIP' +29 CALL_FUNCTION n=1 nkw=0 +31 POP_TOP +32 LOAD_NAME SystemExit +34 RAISE_OBJ +35 DUP_TOP +36 LOAD_NAME AttributeError +38 BINARY_OP 8 +39 POP_JUMP_IF_FALSE 44 +41 POP_TOP +42 POP_EXCEPT_JUMP 45 +44 END_FINALLY +45 LOAD_NAME print +47 LOAD_CONST_STRING 'Kept' +49 CALL_FUNCTION n=1 nkw=0 +51 POP_TOP +52 LOAD_NAME print +54 LOAD_CONST_STRING 'Kept' +56 CALL_FUNCTION n=1 nkw=0 +58 POP_TOP +59 LOAD_NAME print +61 LOAD_CONST_STRING 'Kept' +63 CALL_FUNCTION n=1 nkw=0 +65 POP_TOP +66 LOAD_NAME print +68 LOAD_CONST_STRING 'Kept' +70 CALL_FUNCTION n=1 nkw=0 +72 POP_TOP +73 JUMP 77 +75 JUMP 66 +77 LOAD_CONST_OBJ \.\+='foo' +79 STORE_NAME a +81 LOAD_NAME a +83 LOAD_CONST_OBJ \.\+='foo' +85 BINARY_OP 2 __eq__ +86 POP_JUMP_IF_FALSE 95 +88 LOAD_NAME print +90 LOAD_CONST_STRING 'Kept' +92 CALL_FUNCTION n=1 nkw=0 +94 POP_TOP +95 LOAD_CONST_OBJ \.\+='foo' +97 STORE_NAME b +99 LOAD_NAME b +101 LOAD_CONST_OBJ \.\+='foo' +103 BINARY_OP 2 __eq__ +104 POP_JUMP_IF_FALSE 113 +106 LOAD_NAME print +108 LOAD_CONST_STRING 'Kept' +110 CALL_FUNCTION n=1 nkw=0 +112 POP_TOP +113 LOAD_CONST_OBJ \.\+='foo' +115 LOAD_CONST_OBJ \.\+='foo' +117 BINARY_OP 2 __eq__ +118 POP_JUMP_IF_FALSE 127 +120 LOAD_NAME print +122 LOAD_CONST_STRING 'Kept' +124 CALL_FUNCTION n=1 nkw=0 +126 POP_TOP +127 LOAD_CONST_OBJ \.\+=() +129 LOAD_CONST_OBJ \.\+='foo' +131 BINARY_OP 2 __eq__ +132 POP_JUMP_IF_FALSE 141 +134 LOAD_NAME print +136 LOAD_CONST_OBJ \.\+='Not Eliminated' +138 CALL_FUNCTION n=1 nkw=0 +140 POP_TOP +141 LOAD_CONST_FALSE +142 LOAD_CONST_OBJ \.\+=False +144 BINARY_OP 2 __eq__ +145 POP_JUMP_IF_FALSE 154 +147 LOAD_NAME print +149 LOAD_CONST_STRING 'Kept' +151 CALL_FUNCTION n=1 nkw=0 +153 POP_TOP +154 JUMP 156 +156 LOAD_CONST_NONE +157 RETURN_VALUE +Kept +Kept +Kept +Kept +Kept +Kept +Kept +Kept +mem: total=\\d\+, current=\\d\+, peak=\\d\+ +stack: \\d\+ out of \\d\+ +GC: total: \\d\+, used: \\d\+, free: \\d\+ + No. of 1-blocks: \\d\+, 2-blocks: \\d\+, max blk sz: \\d\+, max free sz: \\d\+ diff --git a/tests/cmdline/cmd_showbc_opt.py b/tests/cmdline/cmd_showbc_opt.py new file mode 100644 index 0000000000..02785860d9 --- /dev/null +++ b/tests/cmdline/cmd_showbc_opt.py @@ -0,0 +1,33 @@ +# cmdline: -v -v +# test printing of bytecode when it's optimised away + + +def f0(): + return 0 + print(1) + + +def f1(x): + if x: + return + print(1) + print(2) + + +def f2(x): + raise Exception + print(1) + + +def f3(x): + while x: + break + print(1) + print(2) + + +def f4(x): + while x: + continue + print(1) + print(2) diff --git a/tests/cmdline/cmd_showbc_opt.py.exp b/tests/cmdline/cmd_showbc_opt.py.exp new file mode 100644 index 0000000000..9e4e4fae10 --- /dev/null +++ b/tests/cmdline/cmd_showbc_opt.py.exp @@ -0,0 +1,122 @@ +File cmdline/cmd_showbc_opt.py, code block '' (descriptor: \.\+, bytecode @\.\+ 35 bytes) +Raw bytecode (code_info_size=13, bytecode_size=22): + 00 16 01 60 20 64 40 84 07 64 40 84 07 32 00 16 + 02 32 01 16 03 32 02 16 04 32 03 16 05 32 04 16 + 06 51 63 +arg names: +(N_STATE 1) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=4 + bc=0 line=5 + bc=4 line=8 + bc=4 line=10 + bc=8 line=17 + bc=12 line=20 + bc=12 line=22 + bc=16 line=29 +00 MAKE_FUNCTION \.\+ +02 STORE_NAME f0 +04 MAKE_FUNCTION \.\+ +06 STORE_NAME f1 +08 MAKE_FUNCTION \.\+ +10 STORE_NAME f2 +12 MAKE_FUNCTION \.\+ +14 STORE_NAME f3 +16 MAKE_FUNCTION \.\+ +18 STORE_NAME f4 +20 LOAD_CONST_NONE +21 RETURN_VALUE +File cmdline/cmd_showbc_opt.py, code block 'f0' (descriptor: \.\+, bytecode @\.\+ 8 bytes) +Raw bytecode (code_info_size=6, bytecode_size=2): + 08 08 02 60 40 22 80 63 +arg names: +(N_STATE 2) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=4 + bc=0 line=6 + bc=2 line=7 +00 LOAD_CONST_SMALL_INT 0 +01 RETURN_VALUE +File cmdline/cmd_showbc_opt.py, code block 'f1' (descriptor: \.\+, bytecode @\.\+ 22 bytes) +Raw bytecode (code_info_size=9, bytecode_size=13): + 11 0e 03 08 80 0a 23 22 20 b0 44 42 51 63 12 07 + 82 34 01 59 51 63 +arg names: x +(N_STATE 3) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=11 + bc=3 line=12 + bc=5 line=13 + bc=5 line=14 +00 LOAD_FAST 0 +01 POP_JUMP_IF_FALSE 5 +03 LOAD_CONST_NONE +04 RETURN_VALUE +05 LOAD_GLOBAL print +07 LOAD_CONST_SMALL_INT 2 +08 CALL_FUNCTION n=1 nkw=0 +10 POP_TOP +11 LOAD_CONST_NONE +12 RETURN_VALUE +File cmdline/cmd_showbc_opt.py, code block 'f2' (descriptor: \.\+, bytecode @\.\+ 10 bytes) +Raw bytecode (code_info_size=7, bytecode_size=3): + 11 0a 04 08 80 11 23 12 09 65 +arg names: x +(N_STATE 3) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=18 + bc=3 line=19 +00 LOAD_GLOBAL Exception +02 RAISE_OBJ +File cmdline/cmd_showbc_opt.py, code block 'f3' (descriptor: \.\+, bytecode @\.\+ 24 bytes) +Raw bytecode (code_info_size=9, bytecode_size=15): + 11 0e 05 08 80 16 22 22 23 42 42 42 43 b0 43 3b + 12 07 82 34 01 59 51 63 +arg names: x +(N_STATE 3) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=23 + bc=2 line=24 + bc=4 line=25 + bc=7 line=26 +00 JUMP 4 +02 JUMP 7 +04 LOAD_FAST 0 +05 POP_JUMP_IF_TRUE 2 +07 LOAD_GLOBAL print +09 LOAD_CONST_SMALL_INT 2 +10 CALL_FUNCTION n=1 nkw=0 +12 POP_TOP +13 LOAD_CONST_NONE +14 RETURN_VALUE +File cmdline/cmd_showbc_opt.py, code block 'f4' (descriptor: \.\+, bytecode @\.\+ 24 bytes) +Raw bytecode (code_info_size=9, bytecode_size=15): + 11 0e 06 08 80 1d 22 22 23 42 42 42 40 b0 43 3b + 12 07 82 34 01 59 51 63 +arg names: x +(N_STATE 3) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=30 + bc=2 line=31 + bc=4 line=32 + bc=7 line=33 +00 JUMP 4 +02 JUMP 4 +04 LOAD_FAST 0 +05 POP_JUMP_IF_TRUE 2 +07 LOAD_GLOBAL print +09 LOAD_CONST_SMALL_INT 2 +10 CALL_FUNCTION n=1 nkw=0 +12 POP_TOP +13 LOAD_CONST_NONE +14 RETURN_VALUE +mem: total=\\d\+, current=\\d\+, peak=\\d\+ +stack: \\d\+ out of \\d\+ +GC: total: \\d\+, used: \\d\+, free: \\d\+ + No. of 1-blocks: \\d\+, 2-blocks: \\d\+, max blk sz: \\d\+, max free sz: \\d\+ diff --git a/tests/cpydiff/modules_os_getenv_argcount.py b/tests/cpydiff/modules_os_getenv_argcount.py deleted file mode 100644 index d7838a92cc..0000000000 --- a/tests/cpydiff/modules_os_getenv_argcount.py +++ /dev/null @@ -1,14 +0,0 @@ -""" -categories: Modules,os -description: ``getenv`` only allows one argument -cause: Unknown -workaround: Test that the return value is ``None`` -""" -import os - -try: - print(os.getenv("NEW_VARIABLE", "DEFAULT")) -except TypeError: - print("should not get here") - # this assumes NEW_VARIABLE is never an empty variable - print(os.getenv("NEW_VARIABLE") or "DEFAULT") diff --git a/tests/cpydiff/types_float_implicit_conversion.py b/tests/cpydiff/types_float_implicit_conversion.py new file mode 100644 index 0000000000..3726839fac --- /dev/null +++ b/tests/cpydiff/types_float_implicit_conversion.py @@ -0,0 +1,14 @@ +""" +categories: Types,float +description: uPy allows implicit conversion of objects in maths operations while CPython does not. +cause: Unknown +workaround: Objects should be wrapped in ``float(obj)`` for compatibility with CPython. +""" + + +class Test: + def __float__(self): + return 0.5 + + +print(2.0 * Test()) diff --git a/tests/extmod/framebuf_ellipse.py b/tests/extmod/framebuf_ellipse.py new file mode 100644 index 0000000000..a4c784aff8 --- /dev/null +++ b/tests/extmod/framebuf_ellipse.py @@ -0,0 +1,65 @@ +try: + import framebuf +except ImportError: + print("SKIP") + raise SystemExit + + +def printbuf(): + print("--8<--") + for y in range(h): + for x in range(w): + print("%02x" % buf[(x + y * w)], end="") + print() + print("-->8--") + + +w = 30 +h = 30 +buf = bytearray(w * h) +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS8) + +# Outline +fbuf.fill(0) +fbuf.ellipse(15, 15, 12, 6, 0xFF, False) +printbuf() + +# Fill +fbuf.fill(0) +fbuf.ellipse(15, 15, 6, 12, 0xAA, True) +printbuf() + +# Outline and fill some different quadrant combos. +for m in (0, 0b0001, 0b0010, 0b0100, 0b1000, 0b1010): + fbuf.fill(0) + fbuf.ellipse(15, 15, 6, 12, 0xAA, False, m) + printbuf() + fbuf.fill(0) + fbuf.ellipse(15, 15, 6, 12, 0xAA, True, m) + printbuf() + +# Draw ellipses that will go out of bounds at each of the edges. +for x, y in ( + ( + 4, + 4, + ), + ( + 26, + 4, + ), + ( + 26, + 26, + ), + ( + 4, + 26, + ), +): + fbuf.fill(0) + fbuf.ellipse(x, y, 6, 12, 0xAA, False) + printbuf() + fbuf.fill(0) + fbuf.ellipse(x, y, 6, 12, 0xAA, True) + printbuf() diff --git a/tests/extmod/framebuf_ellipse.py.exp b/tests/extmod/framebuf_ellipse.py.exp new file mode 100644 index 0000000000..ae6ad1ee7e --- /dev/null +++ b/tests/extmod/framebuf_ellipse.py.exp @@ -0,0 +1,704 @@ +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000ffffffffffffffffff00000000000000000000 +0000000000000000ffffff000000000000000000ffffff00000000000000 +000000000000ffff000000000000000000000000000000ffff0000000000 +0000000000ff00000000000000000000000000000000000000ff00000000 +00000000ff000000000000000000000000000000000000000000ff000000 +000000ff0000000000000000000000000000000000000000000000ff0000 +000000ff0000000000000000000000000000000000000000000000ff0000 +000000ff0000000000000000000000000000000000000000000000ff0000 +00000000ff000000000000000000000000000000000000000000ff000000 +0000000000ff00000000000000000000000000000000000000ff00000000 +000000000000ffff000000000000000000000000000000ffff0000000000 +0000000000000000ffffff000000000000000000ffffff00000000000000 +0000000000000000000000ffffffffffffffffff00000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000aaaaaa00000000000000000000000000 +00000000000000000000000000aaaaaaaaaa000000000000000000000000 +000000000000000000000000aaaaaaaaaaaaaa0000000000000000000000 +0000000000000000000000aaaaaaaaaaaaaaaaaa00000000000000000000 +0000000000000000000000aaaaaaaaaaaaaaaaaa00000000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +0000000000000000000000aaaaaaaaaaaaaaaaaa00000000000000000000 +0000000000000000000000aaaaaaaaaaaaaaaaaa00000000000000000000 +000000000000000000000000aaaaaaaaaaaaaa0000000000000000000000 +00000000000000000000000000aaaaaaaaaa000000000000000000000000 +0000000000000000000000000000aaaaaa00000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +0000000000000000000000000000000000aa000000000000000000000000 +000000000000000000000000000000000000aa0000000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +000000000000000000000000000000aaaaaa000000000000000000000000 +000000000000000000000000000000aaaaaaaa0000000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +00000000000000000000000000aa00000000000000000000000000000000 +000000000000000000000000aa0000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +00000000000000000000000000aaaaaa0000000000000000000000000000 +000000000000000000000000aaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +000000000000000000000000aa0000000000000000000000000000000000 +00000000000000000000000000aa00000000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +000000000000000000000000aaaaaaaa0000000000000000000000000000 +00000000000000000000000000aaaaaa0000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +000000000000000000000000000000000000aa0000000000000000000000 +0000000000000000000000000000000000aa000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaa0000000000000000000000 +000000000000000000000000000000aaaaaa000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +00000000000000000000000000aa00000000000000000000000000000000 +000000000000000000000000aa0000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +000000000000000000000000000000000000aa0000000000000000000000 +0000000000000000000000000000000000aa000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +00000000000000000000000000aaaaaa0000000000000000000000000000 +000000000000000000000000aaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaa0000000000000000000000 +000000000000000000000000000000aaaaaa000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +aa00000000000000aa000000000000000000000000000000000000000000 +aa00000000000000aa000000000000000000000000000000000000000000 +00aa0000000000aa00000000000000000000000000000000000000000000 +0000aa000000aa0000000000000000000000000000000000000000000000 +000000aaaaaa000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaa000000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaa000000000000000000000000000000000000000000 +00aaaaaaaaaaaaaa00000000000000000000000000000000000000000000 +0000aaaaaaaaaa0000000000000000000000000000000000000000000000 +000000aaaaaa000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +00000000000000000000000000000000000000000000aa00000000000000 +00000000000000000000000000000000000000000000aa00000000000000 +0000000000000000000000000000000000000000000000aa0000000000aa +000000000000000000000000000000000000000000000000aa000000aa00 +00000000000000000000000000000000000000000000000000aaaaaa0000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +00000000000000000000000000000000000000000000aaaaaaaaaaaaaaaa +00000000000000000000000000000000000000000000aaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000000000aaaaaaaaaaaaaa +000000000000000000000000000000000000000000000000aaaaaaaaaa00 +00000000000000000000000000000000000000000000000000aaaaaa0000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000aaaaaa0000 +000000000000000000000000000000000000000000000000aa000000aa00 +0000000000000000000000000000000000000000000000aa0000000000aa +00000000000000000000000000000000000000000000aa00000000000000 +00000000000000000000000000000000000000000000aa00000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000aaaaaa0000 +000000000000000000000000000000000000000000000000aaaaaaaaaa00 +0000000000000000000000000000000000000000000000aaaaaaaaaaaaaa +00000000000000000000000000000000000000000000aaaaaaaaaaaaaaaa +00000000000000000000000000000000000000000000aaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000aaaaaa000000000000000000000000000000000000000000000000 +0000aa000000aa0000000000000000000000000000000000000000000000 +00aa0000000000aa00000000000000000000000000000000000000000000 +aa00000000000000aa000000000000000000000000000000000000000000 +aa00000000000000aa000000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000aaaaaa000000000000000000000000000000000000000000000000 +0000aaaaaaaaaa0000000000000000000000000000000000000000000000 +00aaaaaaaaaaaaaa00000000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaa000000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaa000000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +-->8-- diff --git a/tests/extmod/framebuf_polygon.py b/tests/extmod/framebuf_polygon.py new file mode 100644 index 0000000000..03130b3bf0 --- /dev/null +++ b/tests/extmod/framebuf_polygon.py @@ -0,0 +1,222 @@ +import sys + +try: + import framebuf + from array import array +except ImportError: + print("SKIP") + raise SystemExit + + +# TODO: poly needs functions that aren't in dynruntime.h yet. +if not hasattr(framebuf.FrameBuffer, "poly"): + print("SKIP") + raise SystemExit + + +def print_buffer(buffer, width, height): + for row in range(height): + for col in range(width): + val = buffer[(row * width) + col] + sys.stdout.write(" {:02x}".format(val) if val else " ··") + sys.stdout.write("\n") + + +buf = bytearray(70 * 70) + +w = 30 +h = 25 +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS8) +col = 0xFF +col_fill = 0x99 + +# This describes a arbitrary polygon (this happens to be a concave polygon in +# the shape of an upper-case letter 'M'). +poly = array( + "h", + ( + 0, + 20, + 3, + 20, + 3, + 10, + 6, + 17, + 9, + 10, + 9, + 20, + 12, + 20, + 12, + 3, + 9, + 3, + 6, + 10, + 3, + 3, + 0, + 3, + ), +) +# This describes the same polygon, but the points are in reverse order +# (it shouldn't matter if the polygon has clockwise or anti-clockwise +# winding). Also defined as a bytes instead of array. +poly_reversed = bytes( + ( + 0, + 3, + 3, + 3, + 6, + 10, + 9, + 3, + 12, + 3, + 12, + 20, + 9, + 20, + 9, + 10, + 6, + 17, + 3, + 10, + 3, + 20, + 0, + 20, + ) +) + +# Draw the line polygon (at the origin) and the reversed-order polygon (offset). +fbuf.fill(0) +fbuf.poly(0, 0, poly, col) +fbuf.poly(15, -2, poly_reversed, col) +print_buffer(buf, w, h) +print() + +# Same but filled. +fbuf.fill(0) +fbuf.poly(0, 0, poly, col_fill, True) +fbuf.poly(15, -2, poly_reversed, col_fill, True) +print_buffer(buf, w, h) +print() + +# Draw the fill then the outline to ensure that no fill goes outside the outline. +fbuf.fill(0) +fbuf.poly(0, 0, poly, col_fill, True) +fbuf.poly(0, 0, poly, col) +fbuf.poly(15, -2, poly, col_fill, True) +fbuf.poly(15, -2, poly, col) +print_buffer(buf, w, h) +print() + +# Draw the outline then the fill to ensure the fill completely covers the outline. +fbuf.fill(0) +fbuf.poly(0, 0, poly, col) +fbuf.poly(0, 0, poly, col_fill, True) +fbuf.poly(15, -2, poly, col) +fbuf.poly(15, -2, poly, col_fill, True) +print_buffer(buf, w, h) +print() + +# Draw polygons that will go out of bounds at each of the edges. +for x, y in ( + ( + -8, + -8, + ), + ( + 24, + -6, + ), + ( + 20, + 12, + ), + ( + -2, + 10, + ), +): + fbuf.fill(0) + fbuf.poly(x, y, poly, col) + print_buffer(buf, w, h) + print() + fbuf.fill(0) + fbuf.poly(x, y, poly_reversed, col, True) + print_buffer(buf, w, h) + print() + +# Edge cases: These two lists describe self-intersecting polygons +poly_hourglass = array("h", (0, 0, 9, 0, 0, 19, 9, 19)) +poly_star = array("h", (7, 0, 3, 18, 14, 5, 0, 5, 11, 18)) + +# As before, fill then outline. +fbuf.fill(0) +fbuf.poly(0, 2, poly_hourglass, col_fill, True) +fbuf.poly(0, 2, poly_hourglass, col) +fbuf.poly(12, 2, poly_star, col_fill, True) +fbuf.poly(12, 2, poly_star, col) +print_buffer(buf, w, h) +print() + +# Outline then fill. +fbuf.fill(0) +fbuf.poly(0, 2, poly_hourglass, col) +fbuf.poly(0, 2, poly_hourglass, col_fill, True) +fbuf.poly(12, 2, poly_star, col) +fbuf.poly(12, 2, poly_star, col_fill, True) +print_buffer(buf, w, h) +print() + +# Edge cases: These are "degenerate" polygons. +poly_empty = array("h") # Will draw nothing at all. +poly_one = array("h", (20, 20)) # Will draw a single point. +poly_two = array("h", (10, 10, 5, 5)) # Will draw a single line. +poly_wrong_length = array("h", (2, 2, 4)) # Will round down to one point. + +fbuf.fill(0) +fbuf.poly(0, 0, poly_empty, col) +fbuf.poly(0, 0, poly_one, col) +fbuf.poly(0, 0, poly_two, col) +fbuf.poly(0, 0, poly_wrong_length, col) +print_buffer(buf, w, h) +print() + +# A shape with a horizontal overhang. +poly_overhang = array("h", (0, 0, 0, 5, 5, 5, 5, 10, 10, 10, 10, 0)) + +fbuf.fill(0) +fbuf.poly(0, 0, poly_overhang, col) +fbuf.poly(0, 0, poly_overhang, col_fill, True) +print_buffer(buf, w, h) +print() + +fbuf.fill(0) +fbuf.poly(0, 0, poly_overhang, col_fill, True) +fbuf.poly(0, 0, poly_overhang, col) +print_buffer(buf, w, h) +print() + +# Triangles +w = 70 +h = 70 +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS8) +t1 = array("h", [40, 0, 20, 68, 62, 40]) +t2 = array("h", [40, 0, 0, 16, 20, 68]) + +fbuf.fill(0) +fbuf.poly(0, 0, t1, 0xFF, False) +fbuf.poly(0, 0, t2, 0xFF, False) +print_buffer(buf, w, h) + +fbuf.fill(0) +fbuf.poly(0, 0, t1, 0xFF, True) +fbuf.poly(0, 0, t2, 0xFF, True) +print_buffer(buf, w, h) diff --git a/tests/extmod/framebuf_polygon.py.exp b/tests/extmod/framebuf_polygon.py.exp new file mode 100644 index 0000000000..9b4801c788 --- /dev/null +++ b/tests/extmod/framebuf_polygon.py.exp @@ -0,0 +1,582 @@ + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· + ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· + ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· + ff ·· ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· + ff ·· ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· + ff ·· ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ff ·· ff ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ff ·· ff ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ff ·· ff ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ff ·· ff ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· + 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· + ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ff 99 99 99 ff ·· ·· ·· ff 99 99 99 ff ·· ·· + ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· ff 99 99 99 ff ·· ·· ·· ff 99 99 99 ff ·· ·· + ff 99 99 99 ff ·· ·· ·· ff 99 99 99 ff ·· ·· ff 99 99 99 99 ff ·· ff 99 99 99 99 ff ·· ·· + ff 99 99 99 ff ·· ·· ·· ff 99 99 99 ff ·· ·· ff 99 99 99 99 ff ·· ff 99 99 99 99 ff ·· ·· + ff 99 99 99 99 ff ·· ff 99 99 99 99 ff ·· ·· ff 99 99 99 99 99 ff 99 99 99 99 99 ff ·· ·· + ff 99 99 99 99 ff ·· ff 99 99 99 99 ff ·· ·· ff 99 99 ff 99 99 ff 99 99 ff 99 99 ff ·· ·· + ff 99 99 99 99 99 ff 99 99 99 99 99 ff ·· ·· ff 99 99 ff 99 99 99 99 99 ff 99 99 ff ·· ·· + ff 99 99 ff 99 99 ff 99 99 ff 99 99 ff ·· ·· ff 99 99 ff ff 99 99 99 ff ff 99 99 ff ·· ·· + ff 99 99 ff 99 99 99 99 99 ff 99 99 ff ·· ·· ff 99 99 ff ff 99 99 99 ff ff 99 99 ff ·· ·· + ff 99 99 ff ff 99 99 99 ff ff 99 99 ff ·· ·· ff 99 99 ff ·· ff 99 ff ·· ff 99 99 ff ·· ·· + ff 99 99 ff ff 99 99 99 ff ff 99 99 ff ·· ·· ff 99 99 ff ·· ff 99 ff ·· ff 99 99 ff ·· ·· + ff 99 99 ff ·· ff 99 ff ·· ff 99 99 ff ·· ·· ff 99 99 ff ·· ·· ff ·· ·· ff 99 99 ff ·· ·· + ff 99 99 ff ·· ff 99 ff ·· ff 99 99 ff ·· ·· ff 99 99 ff ·· ·· ff ·· ·· ff 99 99 ff ·· ·· + ff 99 99 ff ·· ·· ff ·· ·· ff 99 99 ff ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· + ff 99 99 ff ·· ·· ff ·· ·· ff 99 99 ff ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· + ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· + 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ff ·· ·· ·· ff ff + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ·· ·· ·· ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ·· ·· ·· ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ·· ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ·· ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ff ·· ff ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ·· ·· ·· ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ·· ·· ·· ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ·· ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ·· ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ff ff ff ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· + ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ·· ff 99 99 99 99 ff ·· ff 99 99 99 99 ff ·· ·· ·· ·· + ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ·· ·· ff 99 ff ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ·· ·· ff 99 ff ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ff 99 ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 99 ff 99 99 ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ff 99 ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ff 99 ff ·· ·· ·· ·· ·· ·· ·· + ·· ff 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ff 99 ff ·· ·· ·· ff 99 ff ·· ·· ·· ·· ·· ·· + ·· ff 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· + ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· ·· ·· + ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· + ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· ·· ·· 99 99 99 ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· ·· ·· 99 99 99 ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· 99 99 99 ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· + ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· 99 99 99 ·· ·· ·· ·· ·· ·· ·· + ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· 99 99 99 ·· ·· ·· ·· ·· ·· ·· + ·· 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· 99 99 99 ·· ·· ·· 99 99 99 ·· ·· ·· ·· ·· ·· + ·· 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ff ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ff ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ff ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· diff --git a/tests/extmod/framebuf_scroll.py b/tests/extmod/framebuf_scroll.py new file mode 100644 index 0000000000..db9b6ea1e9 --- /dev/null +++ b/tests/extmod/framebuf_scroll.py @@ -0,0 +1,45 @@ +try: + import framebuf +except ImportError: + print("SKIP") + raise SystemExit + + +def printbuf(): + print("--8<--") + bytes_per_row = w // 2 + for y in range(h): + for x in range(bytes_per_row): + print("%02x" % buf[(x + y * bytes_per_row)], end="") + print() + print("-->8--") + + +w = 10 +h = 10 +buf = bytearray(w * h // 2) +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS4_HMSB) + + +def prepare_buffer(): + fbuf.fill(0) + fbuf.rect(2, 0, 6, 10, 0x07, True) + fbuf.rect(0, 2, 10, 6, 0x01, True) + + +prepare_buffer() +printbuf() + +fbuf.scroll(5, -1) +printbuf() + +prepare_buffer() +fbuf.scroll(-5, 5) +printbuf() + +prepare_buffer() +# Scrolling by at least the size of buffer, no change to buffer. +fbuf.scroll(15, 7) +fbuf.scroll(10, -1) +fbuf.scroll(1, -10) +printbuf() diff --git a/tests/extmod/framebuf_scroll.py.exp b/tests/extmod/framebuf_scroll.py.exp new file mode 100644 index 0000000000..7e99b275da --- /dev/null +++ b/tests/extmod/framebuf_scroll.py.exp @@ -0,0 +1,48 @@ +--8<-- +0077777700 +0077777700 +1111111111 +1111111111 +1111111111 +1111111111 +1111111111 +1111111111 +0077777700 +0077777700 +-->8-- +--8<-- +0077700777 +0077711111 +1111111111 +1111111111 +1111111111 +1111111111 +1111111111 +1111100777 +0077700777 +0077777700 +-->8-- +--8<-- +0077777700 +0077777700 +1111111111 +1111111111 +1111111111 +7770011111 +7770011111 +1111111111 +1111177700 +1111177700 +-->8-- +--8<-- +0077777700 +0077777700 +1111111111 +1111111111 +1111111111 +1111111111 +1111111111 +1111111111 +0077777700 +0077777700 +-->8-- diff --git a/tests/extmod/ticks_add.py b/tests/extmod/ticks_add.py new file mode 100644 index 0000000000..2f1ba6c810 --- /dev/null +++ b/tests/extmod/ticks_add.py @@ -0,0 +1,42 @@ +try: + from utime import ticks_diff, ticks_add +except ImportError: + print("SKIP") + raise SystemExit + +# Maximum value returned from ticks_add, ticks_ms, etc. +TICKS_MAX = ticks_add(0, -1) +# Maximum value returned from ticks_diff. +TICKS_INTERVAL_MAX = TICKS_MAX // 2 + +# Invariants: +# - ticks_diff(ticks_add(T, delta), T) == delta +# - ticks_diff(T, ticks_add(T, delta)) == -delta + +# Check actual values of ticks_add. +print(ticks_add(20, 12)) +print(ticks_add(20, -12)) + +# Check invariant. +print(ticks_diff(ticks_add(100, 123), 100)) +print(ticks_diff(ticks_add(100, -123), 100)) +print(ticks_diff(100, ticks_add(100, 123))) +print(ticks_diff(100, ticks_add(100, -123))) + +# Check limits. +for T in (0, 10, TICKS_MAX): + for delta in ( + -TICKS_INTERVAL_MAX - 1, + -TICKS_INTERVAL_MAX, + 0, + TICKS_INTERVAL_MAX, + TICKS_INTERVAL_MAX + 1, + ): + try: + print(ticks_diff(ticks_add(T, delta), T) == delta) + except OverflowError: + print("OverflowError") + try: + print(ticks_diff(T, ticks_add(T, delta)) == -delta) + except OverflowError: + print("OverflowError") diff --git a/tests/extmod/ticks_add.py.exp b/tests/extmod/ticks_add.py.exp new file mode 100644 index 0000000000..60dc6f5afd --- /dev/null +++ b/tests/extmod/ticks_add.py.exp @@ -0,0 +1,36 @@ +32 +8 +123 +-123 +-123 +123 +OverflowError +OverflowError +True +True +True +True +True +True +OverflowError +OverflowError +OverflowError +OverflowError +True +True +True +True +True +True +OverflowError +OverflowError +OverflowError +OverflowError +True +True +True +True +True +True +OverflowError +OverflowError diff --git a/tests/extmod/uasyncio_gather.py b/tests/extmod/uasyncio_gather.py index c666ff6b17..5e5bb62d7c 100644 --- a/tests/extmod/uasyncio_gather.py +++ b/tests/extmod/uasyncio_gather.py @@ -61,6 +61,11 @@ async def main(): print("====") + # Gather with no awaitables + print(await asyncio.gather()) + + print("====") + # Test return_exceptions, where one task is cancelled and the other finishes normally tasks = [asyncio.create_task(task(1)), asyncio.create_task(task(2))] tasks[0].cancel() diff --git a/tests/extmod/uasyncio_gather.py.exp b/tests/extmod/uasyncio_gather.py.exp index a5ea47ab50..371d1ae60d 100644 --- a/tests/extmod/uasyncio_gather.py.exp +++ b/tests/extmod/uasyncio_gather.py.exp @@ -9,6 +9,8 @@ Task C: Compute factorial(4)... Task C: factorial(4) = 24 [2, 6, 24] ==== +[] +==== start 2 end 2 [CancelledError(), 2] diff --git a/tests/extmod/uasyncio_heaplock.py b/tests/extmod/uasyncio_heaplock.py index 482e7319ff..6ea9270c7a 100644 --- a/tests/extmod/uasyncio_heaplock.py +++ b/tests/extmod/uasyncio_heaplock.py @@ -1,14 +1,26 @@ -# test that basic scheduling of tasks, and asyncio.sleep_ms, does not use the heap +# test that the following do not use the heap: +# - basic scheduling of tasks +# - uasyncio.sleep_ms +# - StreamWriter.write, stream is blocked and data to write is a bytes object +# - StreamWriter.write, when stream is not blocked import micropython # strict stackless builds can't call functions without allocating a frame on the heap try: - f = lambda: 0 + # force bytecode (in case we're running with emit=native) and verify + # that bytecode-calling-bytecode doesn't allocate + @micropython.bytecode + def f(x): + x and f(x - 1) + micropython.heap_lock() - f() + f(1) micropython.heap_unlock() except RuntimeError: + # RuntimeError (max recursion depth) not MemoryError because effectively + # the recursion depth is at the limit while the heap is locked with + # stackless print("SKIP") raise SystemExit @@ -19,6 +31,17 @@ except ImportError: raise SystemExit +class TestStream: + def __init__(self, blocked): + self.blocked = blocked + + def write(self, data): + print("TestStream.write", data) + if self.blocked: + return None + return len(data) + + async def task(id, n, t): for i in range(n): print(id, i) @@ -29,14 +52,27 @@ async def main(): t1 = asyncio.create_task(task(1, 4, 100)) t2 = asyncio.create_task(task(2, 2, 250)) + # test scheduling tasks, and calling sleep_ms micropython.heap_lock() - print("start") await asyncio.sleep_ms(5) print("sleep") await asyncio.sleep_ms(350) print("finish") + micropython.heap_unlock() + # test writing to a stream, when the underlying stream is blocked + s = asyncio.StreamWriter(TestStream(True), None) + micropython.heap_lock() + s.write(b"12") + micropython.heap_unlock() + + # test writing to a stream, when the underlying stream is not blocked + buf = bytearray(b"56") + s = asyncio.StreamWriter(TestStream(False), None) + micropython.heap_lock() + s.write(b"34") + s.write(buf) micropython.heap_unlock() diff --git a/tests/extmod/uasyncio_heaplock.py.exp b/tests/extmod/uasyncio_heaplock.py.exp index 68c6366c6f..5c7b4e3dba 100644 --- a/tests/extmod/uasyncio_heaplock.py.exp +++ b/tests/extmod/uasyncio_heaplock.py.exp @@ -7,3 +7,6 @@ sleep 2 1 1 3 finish +TestStream.write b'12' +TestStream.write b'34' +TestStream.write bytearray(b'56') diff --git a/tests/extmod/uasyncio_threadsafeflag.py b/tests/extmod/uasyncio_threadsafeflag.py index 32eafae8bc..a70015f8b6 100644 --- a/tests/extmod/uasyncio_threadsafeflag.py +++ b/tests/extmod/uasyncio_threadsafeflag.py @@ -76,5 +76,25 @@ async def main(): print("wait task") await t + # Flag set, cleared, and set again. + print("----") + print("set event") + flag.set() + print("yield") + await asyncio.sleep(0) + print("clear event") + flag.clear() + print("yield") + await asyncio.sleep(0) + t = asyncio.create_task(task(4, flag)) + print("yield") + await asyncio.sleep(0) + print("set event") + flag.set() + print("yield") + await asyncio.sleep(0) + print("wait task") + await t + asyncio.run(main()) diff --git a/tests/extmod/uasyncio_threadsafeflag.py.exp b/tests/extmod/uasyncio_threadsafeflag.py.exp index aef4e479ba..757115ac4b 100644 --- a/tests/extmod/uasyncio_threadsafeflag.py.exp +++ b/tests/extmod/uasyncio_threadsafeflag.py.exp @@ -19,3 +19,14 @@ yield task 3 task 3 done wait task +---- +set event +yield +clear event +yield +yield +task 4 +set event +yield +wait task +task 4 done diff --git a/tests/extmod/ubinascii_hexlify.py b/tests/extmod/ubinascii_hexlify.py index 260010237c..d06029aaba 100644 --- a/tests/extmod/ubinascii_hexlify.py +++ b/tests/extmod/ubinascii_hexlify.py @@ -4,11 +4,16 @@ except ImportError: print("SKIP") raise SystemExit -print(binascii.hexlify(b"\x00\x01\x02\x03\x04\x05\x06\x07")) -print(binascii.hexlify(b"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f")) -print(binascii.hexlify(b"\x7f\x80\xff")) -print(binascii.hexlify(b"1234ABCDabcd")) -try: - binascii.hexlify("") -except TypeError: - print("TypeError") +for x in ( + b"\x00\x01\x02\x03\x04\x05\x06\x07", + b"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + b"\x7f\x80\xff", + b"1234ABCDabcd", +): + print(binascii.hexlify(x)) + +# Two-argument version (now supported in CPython) +print(binascii.hexlify(b"123", ":")) + +# zero length buffer +print(binascii.hexlify(b"", b":")) diff --git a/tests/extmod/ubinascii_micropython.py b/tests/extmod/ubinascii_micropython.py index 87c69b5838..e69de29bb2 100644 --- a/tests/extmod/ubinascii_micropython.py +++ b/tests/extmod/ubinascii_micropython.py @@ -1,12 +0,0 @@ -try: - import binascii -except ImportError: - print("SKIP") - raise SystemExit - -# two arguments supported in uPy but not CPython -a = binascii.hexlify(b"123", ":") -print(a) - -# zero length buffer -print(binascii.hexlify(b"", b":")) diff --git a/tests/extmod/ubinascii_micropython.py.exp b/tests/extmod/ubinascii_micropython.py.exp deleted file mode 100644 index a195d2602c..0000000000 --- a/tests/extmod/ubinascii_micropython.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -b'31:32:33' -b'' diff --git a/tests/extmod/ubinascii_unhexlify.py b/tests/extmod/ubinascii_unhexlify.py index 63994c11f1..866fca7345 100644 --- a/tests/extmod/ubinascii_unhexlify.py +++ b/tests/extmod/ubinascii_unhexlify.py @@ -4,10 +4,13 @@ except ImportError: print("SKIP") raise SystemExit -print(binascii.unhexlify(b"0001020304050607")) -print(binascii.unhexlify(b"08090a0b0c0d0e0f")) -print(binascii.unhexlify(b"7f80ff")) -print(binascii.unhexlify(b"313233344142434461626364")) +for x in ( + b"0001020304050607", + b"08090a0b0c0d0e0f", + b"7f80ff", + b"313233344142434461626364", +): + print(binascii.unhexlify(x)) # Unicode strings can be decoded print(binascii.unhexlify("313233344142434461626364")) diff --git a/tests/extmod/ure_namedclass.py b/tests/extmod/ure_namedclass.py index d2df7f23af..442172f4ab 100644 --- a/tests/extmod/ure_namedclass.py +++ b/tests/extmod/ure_namedclass.py @@ -12,7 +12,7 @@ def print_groups(match): try: i = 0 while True: - print(m.group(i)) + print(match.group(i)) i += 1 except IndexError: pass @@ -29,3 +29,8 @@ print_groups(m) m = re.match(r"(([0-9]*)([a-z]*)\d*)", "1234hello567") print_groups(m) + +# named class within a class set +print_groups(re.match("([^\s]+)\s*([^\s]+)", "1 23")) +print_groups(re.match("([\s\d]+)([\W]+)", "1 2-+=")) +print_groups(re.match("([\W]+)([^\W]+)([^\S]+)([^\D]+)", " a_1 23")) diff --git a/tests/extmod/ussl_poll.py b/tests/extmod/ussl_poll.py new file mode 100644 index 0000000000..8080ec5112 --- /dev/null +++ b/tests/extmod/ussl_poll.py @@ -0,0 +1,196 @@ +try: + import uselect + import ussl + import io + import ubinascii as binascii +except ImportError: + print("SKIP") + raise SystemExit + +from micropython import const + +_MP_STREAM_POLL_RD = const(0x0001) +_MP_STREAM_POLL_WR = const(0x0004) +_MP_STREAM_POLL_NVAL = const(0x0020) +_MP_STREAM_POLL = const(3) +_MP_STREAM_CLOSE = const(4) + + +# This self-signed key/cert pair is randomly generated and to be used for +# testing/demonstration only. You should always generate your own key/cert. +key = binascii.unhexlify( + b"3082013b020100024100cc20643fd3d9c21a0acba4f48f61aadd675f52175a9dcf07fbef" + b"610a6a6ba14abb891745cd18a1d4c056580d8ff1a639460f867013c8391cdc9f2e573b0f" + b"872d0203010001024100bb17a54aeb3dd7ae4edec05e775ca9632cf02d29c2a089b563b0" + b"d05cdf95aeca507de674553f28b4eadaca82d5549a86058f9996b07768686a5b02cb240d" + b"d9f1022100f4a63f5549e817547dca97b5c658038e8593cb78c5aba3c4642cc4cd031d86" + b"8f022100d598d870ffe4a34df8de57047a50b97b71f4d23e323f527837c9edae88c79483" + b"02210098560c89a70385c36eb07fd7083235c4c1184e525d838aedf7128958bedfdbb102" + b"2051c0dab7057a8176ca966f3feb81123d4974a733df0f958525f547dfd1c271f9022044" + b"6c2cafad455a671a8cf398e642e1be3b18a3d3aec2e67a9478f83c964c4f1f" +) +cert = binascii.unhexlify( + b"308201d53082017f020203e8300d06092a864886f70d01010505003075310b3009060355" + b"0406130258583114301206035504080c0b54686550726f76696e63653110300e06035504" + b"070c075468654369747931133011060355040a0c0a436f6d70616e7958595a3113301106" + b"0355040b0c0a436f6d70616e7958595a3114301206035504030c0b546865486f73744e61" + b"6d65301e170d3139313231383033333935355a170d3239313231353033333935355a3075" + b"310b30090603550406130258583114301206035504080c0b54686550726f76696e636531" + b"10300e06035504070c075468654369747931133011060355040a0c0a436f6d70616e7958" + b"595a31133011060355040b0c0a436f6d70616e7958595a3114301206035504030c0b5468" + b"65486f73744e616d65305c300d06092a864886f70d0101010500034b003048024100cc20" + b"643fd3d9c21a0acba4f48f61aadd675f52175a9dcf07fbef610a6a6ba14abb891745cd18" + b"a1d4c056580d8ff1a639460f867013c8391cdc9f2e573b0f872d0203010001300d06092a" + b"864886f70d0101050500034100b0513fe2829e9ecbe55b6dd14c0ede7502bde5d46153c8" + b"e960ae3ebc247371b525caeb41bbcf34686015a44c50d226e66aef0a97a63874ca5944ef" + b"979b57f0b3" +) + + +class _Pipe(io.IOBase): + def __init__(self): + self._other = None + self.block_reads = False + self.block_writes = False + + self.write_buffers = [] + self.last_poll_arg = None + + def readinto(self, buf): + if self.block_reads or len(self._other.write_buffers) == 0: + return None + + read_buf = self._other.write_buffers[0] + l = min(len(buf), len(read_buf)) + buf[:l] = read_buf[:l] + if l == len(read_buf): + self._other.write_buffers.pop(0) + else: + self._other.write_buffers[0] = read_buf[l:] + return l + + def write(self, buf): + if self.block_writes: + return None + + self.write_buffers.append(memoryview(bytes(buf))) + return len(buf) + + def ioctl(self, request, arg): + if request == _MP_STREAM_POLL: + self.last_poll_arg = arg + ret = 0 + if arg & _MP_STREAM_POLL_RD: + if not self.block_reads and self._other.write_buffers: + ret |= _MP_STREAM_POLL_RD + if arg & _MP_STREAM_POLL_WR: + if not self.block_writes: + ret |= _MP_STREAM_POLL_WR + return ret + + elif request == _MP_STREAM_CLOSE: + return 0 + + raise NotImplementedError() + + @classmethod + def new_pair(cls): + p1 = cls() + p2 = cls() + p1._other = p2 + p2._other = p1 + return p1, p2 + + +def assert_poll(s, i, arg, expected_arg, expected_ret): + ret = s.ioctl(_MP_STREAM_POLL, arg) + assert i.last_poll_arg == expected_arg + i.last_poll_arg = None + assert ret == expected_ret + + +def assert_raises(cb, *args, **kwargs): + try: + cb(*args, **kwargs) + raise AssertionError("should have raised") + except Exception as exc: + pass + + +client_io, server_io = _Pipe.new_pair() + +client_io.block_reads = True +client_io.block_writes = True +client_sock = ussl.wrap_socket(client_io, do_handshake=False) + +server_sock = ussl.wrap_socket(server_io, key=key, cert=cert, server_side=True, do_handshake=False) + +# Do a test read, at this point the TLS handshake wants to write, +# so it returns None: +assert client_sock.read(128) is None + +# Polling for either read or write actually check if the underlying socket can write: +assert_poll(client_sock, client_io, _MP_STREAM_POLL_RD, _MP_STREAM_POLL_WR, 0) +assert_poll(client_sock, client_io, _MP_STREAM_POLL_WR, _MP_STREAM_POLL_WR, 0) + +# Mark the socket as writable, and do another test read: +client_io.block_writes = False +assert client_sock.read(128) is None + +# The client wrote the CLIENT_HELLO message +assert len(client_io.write_buffers) == 1 + +# At this point the TLS handshake wants to read, but we don't know that yet: +assert_poll(client_sock, client_io, _MP_STREAM_POLL_RD, _MP_STREAM_POLL_RD, 0) +assert_poll(client_sock, client_io, _MP_STREAM_POLL_WR, _MP_STREAM_POLL_WR, _MP_STREAM_POLL_WR) + +# Do a test write +client_sock.write(b"foo") + +# Now we know that we want to read: +assert_poll(client_sock, client_io, _MP_STREAM_POLL_RD, _MP_STREAM_POLL_RD, 0) +assert_poll(client_sock, client_io, _MP_STREAM_POLL_WR, _MP_STREAM_POLL_RD, 0) + +# Unblock reads and nudge the two sockets: +client_io.block_reads = False +while server_io.write_buffers or client_io.write_buffers: + if server_io.write_buffers: + assert client_sock.read(128) is None + if client_io.write_buffers: + assert server_sock.read(128) is None + +# At this point, the handshake is done, try writing data: +client_sock.write(b"foo") +assert server_sock.read(3) == b"foo" + +# Test reading partial data: +client_sock.write(b"foobar") +assert server_sock.read(3) == b"foo" +server_io.block_reads = True +assert_poll( + server_sock, server_io, _MP_STREAM_POLL_RD, None, _MP_STREAM_POLL_RD +) # Did not go to the socket, just consumed buffered data +assert server_sock.read(3) == b"bar" + + +# Polling on a closed socket errors out: +client_io, _ = _Pipe.new_pair() +client_sock = ussl.wrap_socket(client_io, do_handshake=False) +client_sock.close() +assert_poll( + client_sock, client_io, _MP_STREAM_POLL_RD, None, _MP_STREAM_POLL_NVAL +) # Did not go to the socket + + +# Errors propagates to poll: +client_io, server_io = _Pipe.new_pair() +client_sock = ussl.wrap_socket(client_io, do_handshake=False) + +# The server returns garbage: +server_io.write(b"fooba") # Needs to be exactly 5 bytes + +assert_poll(client_sock, client_io, _MP_STREAM_POLL_RD, _MP_STREAM_POLL_RD, _MP_STREAM_POLL_RD) +assert_raises(client_sock.read, 128) +assert_poll( + client_sock, client_io, _MP_STREAM_POLL_RD, None, _MP_STREAM_POLL_NVAL +) # Did not go to the socket diff --git a/tests/extmod/ussl_poll.py.exp b/tests/extmod/ussl_poll.py.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/extmod/uzlib_decompio.py b/tests/extmod/uzlib_decompio.py index ce3b7f4a99..a0b9ccaf5e 100644 --- a/tests/extmod/uzlib_decompio.py +++ b/tests/extmod/uzlib_decompio.py @@ -26,13 +26,13 @@ print(inp.read()) print(buf.seek(0, 1)) -# zlib bitstream -inp = zlib.DecompIO(io.BytesIO(b"x\x9c30\xa0=\x00\x00\xb3q\x12\xc1")) +# zlib bitstream (with 256 byte window size) +inp = zlib.DecompIO(io.BytesIO(b"\x08\x9930\xa0=\x00\x00\xb3q\x12\xc1")) print(inp.read(10)) print(inp.read()) # zlib bitstream, wrong checksum -inp = zlib.DecompIO(io.BytesIO(b"x\x9c30\xa0=\x00\x00\xb3q\x12\xc0")) +inp = zlib.DecompIO(io.BytesIO(b"\x08\x9930\xa0=\x00\x00\xb3q\x12\xc0")) try: print(inp.read()) except OSError as e: diff --git a/tests/extmod/vfs_fat_fileio1.py b/tests/extmod/vfs_fat_fileio1.py index 3bc85af9f8..e10c44bb9a 100644 --- a/tests/extmod/vfs_fat_fileio1.py +++ b/tests/extmod/vfs_fat_fileio1.py @@ -39,11 +39,11 @@ class RAMFS: try: bdev = RAMFS(50) + os.VfsFat.mkfs(bdev) except MemoryError: print("SKIP") raise SystemExit -os.VfsFat.mkfs(bdev) vfs = os.VfsFat(bdev) os.mount(vfs, "/ramdisk") os.chdir("/ramdisk") diff --git a/tests/extmod/vfs_fat_fileio2.py b/tests/extmod/vfs_fat_fileio2.py index e243f2839b..7aed7c4ce4 100644 --- a/tests/extmod/vfs_fat_fileio2.py +++ b/tests/extmod/vfs_fat_fileio2.py @@ -40,11 +40,11 @@ class RAMFS: try: bdev = RAMFS(50) + os.VfsFat.mkfs(bdev) except MemoryError: print("SKIP") raise SystemExit -os.VfsFat.mkfs(bdev) vfs = os.VfsFat(bdev) os.mount(vfs, "/ramdisk") os.chdir("/ramdisk") diff --git a/tests/extmod/vfs_fat_ilistdir_del.py b/tests/extmod/vfs_fat_ilistdir_del.py new file mode 100644 index 0000000000..ccdacc57c2 --- /dev/null +++ b/tests/extmod/vfs_fat_ilistdir_del.py @@ -0,0 +1,80 @@ +# Test ilistdir __del__ for VfsFat using a RAM device. +import gc + +try: + import uos + + uos.VfsFat +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 512 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + + def readblocks(self, block, buf, off=0): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block, buf, off=0): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + + +def test(bdev, vfs_class): + vfs_class.mkfs(bdev) + vfs = vfs_class(bdev) + vfs.mkdir("/test_d1") + vfs.mkdir("/test_d2") + vfs.mkdir("/test_d3") + + for i in range(10): + print(i) + + # We want to partially iterate the ilistdir iterator to leave it in an + # open state, which will then test the finaliser when it's garbage collected. + idir = vfs.ilistdir("/") + print(any(idir)) + + # Alternate way of partially iterating the ilistdir object, modifying the + # filesystem while it's open. + for dname, *_ in vfs.ilistdir("/"): + vfs.rmdir(dname) + break + vfs.mkdir(dname) + + # Also create a fully drained iterator and ensure trying to re-use it + # throws the correct exception. + idir_emptied = vfs.ilistdir("/") + l = list(idir_emptied) + print(len(l)) + try: + next(idir_emptied) + except StopIteration: + pass + + gc.collect() + vfs.open("/test", "w").close() + + +try: + bdev = RAMBlockDevice(50) +except MemoryError: + print("SKIP") + raise SystemExit + +test(bdev, uos.VfsFat) diff --git a/tests/extmod/vfs_fat_ilistdir_del.py.exp b/tests/extmod/vfs_fat_ilistdir_del.py.exp new file mode 100644 index 0000000000..0ab2b019f4 --- /dev/null +++ b/tests/extmod/vfs_fat_ilistdir_del.py.exp @@ -0,0 +1,30 @@ +0 +True +3 +1 +True +4 +2 +True +4 +3 +True +4 +4 +True +4 +5 +True +4 +6 +True +4 +7 +True +4 +8 +True +4 +9 +True +4 diff --git a/tests/extmod/vfs_fat_ramdisk.py b/tests/extmod/vfs_fat_ramdisk.py index 9a5c49a6cc..3d66d75766 100644 --- a/tests/extmod/vfs_fat_ramdisk.py +++ b/tests/extmod/vfs_fat_ramdisk.py @@ -40,12 +40,11 @@ class RAMFS: try: bdev = RAMFS(50) + os.VfsFat.mkfs(bdev) except MemoryError: print("SKIP") raise SystemExit -os.VfsFat.mkfs(bdev) - print(b"FOO_FILETXT" not in bdev.data) print(b"hello!" not in bdev.data) diff --git a/tests/extmod/vfs_lfs_ilistdir_del.py b/tests/extmod/vfs_lfs_ilistdir_del.py new file mode 100644 index 0000000000..073576986d --- /dev/null +++ b/tests/extmod/vfs_lfs_ilistdir_del.py @@ -0,0 +1,75 @@ +# Test ilistdir __del__ for VfsLittle using a RAM device. +import gc + +try: + import uos + + uos.VfsLfs2 +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 1024 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + + def readblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + + +def test(bdev, vfs_class): + vfs_class.mkfs(bdev) + vfs = vfs_class(bdev) + vfs.mkdir("/test_d1") + vfs.mkdir("/test_d2") + vfs.mkdir("/test_d3") + + for i in range(10): + print(i) + + # We want to partially iterate the ilistdir iterator to leave it in an + # open state, which will then test the finaliser when it's garbage collected. + idir = vfs.ilistdir("/") + print(any(idir)) + + # Alternate way of partially iterating the ilistdir object, modifying the + # filesystem while it's open. + for dname, *_ in vfs.ilistdir("/"): + vfs.rmdir(dname) + break + vfs.mkdir(dname) + + # Also create a fully drained iterator and ensure trying to re-use it + # throws the correct exception. + idir_emptied = vfs.ilistdir("/") + l = list(idir_emptied) + print(len(l)) + try: + next(idir_emptied) + except StopIteration: + pass + + gc.collect() + vfs.open("/test", "w").close() + + +bdev = RAMBlockDevice(30) +test(bdev, uos.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_ilistdir_del.py.exp b/tests/extmod/vfs_lfs_ilistdir_del.py.exp new file mode 100644 index 0000000000..0ab2b019f4 --- /dev/null +++ b/tests/extmod/vfs_lfs_ilistdir_del.py.exp @@ -0,0 +1,30 @@ +0 +True +3 +1 +True +4 +2 +True +4 +3 +True +4 +4 +True +4 +5 +True +4 +6 +True +4 +7 +True +4 +8 +True +4 +9 +True +4 diff --git a/tests/extmod/vfs_lfs_mtime.py b/tests/extmod/vfs_lfs_mtime.py index bd8ae7b2a2..0a330b3e94 100644 --- a/tests/extmod/vfs_lfs_mtime.py +++ b/tests/extmod/vfs_lfs_mtime.py @@ -101,5 +101,10 @@ def test(bdev, vfs_class): vfs.umount() -bdev = RAMBlockDevice(30) -test(bdev, os.VfsLfs2) +try: + bdev = RAMBlockDevice(30) +except MemoryError: + print("SKIP") + raise SystemExit + +test(bdev, uos.VfsLfs2) diff --git a/tests/extmod/vfs_posix.py b/tests/extmod/vfs_posix.py index 61c948cf5b..3723339c1e 100644 --- a/tests/extmod/vfs_posix.py +++ b/tests/extmod/vfs_posix.py @@ -1,6 +1,7 @@ # Test for VfsPosix try: + import gc import os os.VfsPosix @@ -42,8 +43,8 @@ f.close() # close on a closed file should succeed f.close() -# construct a file object using the type constructor, with a raw fileno -f = type(f)(2) +# construct a file object with a raw fileno +f = open(2) print(f) # file read @@ -51,6 +52,34 @@ f = open(temp_dir + "/test", "r") print(f.read()) f.close() +# file finaliser, also see vfs_fat_finaliser.py +names = [temp_dir + "/x%d" % i for i in range(4)] +basefd = temp_dir + "/nextfd1" +nextfd = temp_dir + "/nextfd2" + +with open(basefd, "w") as f: + base_file_no = f.fileno() + +for i in range(1024): # move GC head forwards by allocating a lot of single blocks + [] + + +def write_files_without_closing(): + for n in names: + open(n, "w").write(n) + sorted(list(range(128)), key=lambda x: x) # use up Python and C stack so f is really gone + + +write_files_without_closing() +gc.collect() + +with open(nextfd, "w") as f: + next_file_no = f.fileno() + print("next_file_no <= base_file_no", next_file_no <= base_file_no) + +for n in names + [basefd, nextfd]: + os.remove(n) + # rename os.rename(temp_dir + "/test", temp_dir + "/test2") print(os.listdir(temp_dir)) diff --git a/tests/extmod/vfs_posix.py.exp b/tests/extmod/vfs_posix.py.exp index eb9ab43106..99922e621d 100644 --- a/tests/extmod/vfs_posix.py.exp +++ b/tests/extmod/vfs_posix.py.exp @@ -4,6 +4,7 @@ True hello +next_file_no <= base_file_no True ['test2'] ['test2'] diff --git a/tests/extmod/vfs_posix_ilistdir_del.py b/tests/extmod/vfs_posix_ilistdir_del.py new file mode 100644 index 0000000000..edb50dfd62 --- /dev/null +++ b/tests/extmod/vfs_posix_ilistdir_del.py @@ -0,0 +1,70 @@ +# Test ilistdir __del__ for VfsPosix. +import gc + +try: + import os + + os.VfsPosix +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + + +def test(testdir): + vfs = os.VfsPosix(testdir) + vfs.mkdir("/test_d1") + vfs.mkdir("/test_d2") + vfs.mkdir("/test_d3") + + for i in range(10): + print(i) + + # We want to partially iterate the ilistdir iterator to leave it in an + # open state, which will then test the finaliser when it's garbage collected. + idir = vfs.ilistdir("/") + print(any(idir)) + + # Alternate way of partially iterating the ilistdir object, modifying the + # filesystem while it's open. + for dname, *_ in vfs.ilistdir("/"): + vfs.rmdir(dname) + break + vfs.mkdir(dname) + + # Also create a fully drained iterator and ensure trying to re-use it + # throws the correct exception. + idir_emptied = vfs.ilistdir("/") + l = list(idir_emptied) + print(len(l)) + try: + next(idir_emptied) + except StopIteration: + pass + + gc.collect() + + # Create and delete a file, try to flush out any filesystem + # corruption that may be caused over the loops. + vfs.open("/test", "w").close() + vfs.remove("/test") + + +# We need an empty directory for testing. +# Skip the test if it already exists. +temp_dir = "vfs_posix_ilistdir_del_test_dir" +try: + os.stat(temp_dir) + print("SKIP") + raise SystemExit +except OSError: + pass + +os.mkdir(temp_dir) + +test(temp_dir) + +# Remove tempdir. +for td in os.listdir(temp_dir): + os.rmdir("/".join((temp_dir, td))) + +os.rmdir(temp_dir) diff --git a/tests/extmod/vfs_posix_ilistdir_del.py.exp b/tests/extmod/vfs_posix_ilistdir_del.py.exp new file mode 100644 index 0000000000..c30ba41326 --- /dev/null +++ b/tests/extmod/vfs_posix_ilistdir_del.py.exp @@ -0,0 +1,30 @@ +0 +True +3 +1 +True +3 +2 +True +3 +3 +True +3 +4 +True +3 +5 +True +3 +6 +True +3 +7 +True +3 +8 +True +3 +9 +True +3 diff --git a/tests/extmod/vfs_posix_ilistdir_filter.py b/tests/extmod/vfs_posix_ilistdir_filter.py new file mode 100644 index 0000000000..c32d124971 --- /dev/null +++ b/tests/extmod/vfs_posix_ilistdir_filter.py @@ -0,0 +1,47 @@ +# Test ilistdir filter of . and .. for VfsPosix. + +try: + import os + + os.VfsPosix +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + + +def test(testdir): + vfs = os.VfsPosix(testdir) + + dirs = [".a", "..a", "...a", "a.b", "a..b"] + + for dir in dirs: + vfs.mkdir(dir) + + dirs = [] + for entry in vfs.ilistdir("/"): + dirs.append(entry[0]) + dirs.sort() + + print(dirs) + + +# We need an empty directory for testing. +# Skip the test if it already exists. +temp_dir = "vfs_posix_ilistdir_filter_test_dir" +try: + os.stat(temp_dir) + print("SKIP") + raise SystemExit +except OSError: + pass + +os.mkdir(temp_dir) + +try: + test(temp_dir) +finally: + # Remove tempdir. + for td in os.listdir(temp_dir): + os.rmdir("/".join((temp_dir, td))) + + os.rmdir(temp_dir) diff --git a/tests/extmod/vfs_posix_ilistdir_filter.py.exp b/tests/extmod/vfs_posix_ilistdir_filter.py.exp new file mode 100644 index 0000000000..2f51073836 --- /dev/null +++ b/tests/extmod/vfs_posix_ilistdir_filter.py.exp @@ -0,0 +1 @@ +['...a', '..a', '.a', 'a..b', 'a.b'] diff --git a/tests/float/cmath_dunder.py b/tests/float/cmath_dunder.py new file mode 100644 index 0000000000..909894d9f8 --- /dev/null +++ b/tests/float/cmath_dunder.py @@ -0,0 +1,21 @@ +# test that cmath functions support user classes with __float__ and __complex__ + +try: + import cmath +except ImportError: + print("SKIP") + raise SystemExit + + +class TestFloat: + def __float__(self): + return 1.0 + + +class TestComplex: + def __complex__(self): + return complex(10, 1) + + +for clas in TestFloat, TestComplex: + print("%.5g" % cmath.phase(clas())) diff --git a/tests/float/complex1.py b/tests/float/complex1.py index 139bb0c509..f4107a1390 100644 --- a/tests/float/complex1.py +++ b/tests/float/complex1.py @@ -4,9 +4,19 @@ print(complex(1)) print(complex(1.2)) print(complex(1.2j)) +print(complex("j")) +print(complex("J")) print(complex("1")) print(complex("1.2")) print(complex("1.2j")) +print(complex("1+j")) +print(complex("1+2j")) +print(complex("-1-2j")) +print(complex("+1-2j")) +print(complex(" -1-2j ")) +print(complex(" +1-2j ")) +print(complex("nanj")) +print(complex("nan-infj")) print(complex(1, 2)) print(complex(1j, 2j)) @@ -72,6 +82,13 @@ print(float("-nan") * 1j) print(float("inf") * (1 + 1j)) print(float("-inf") * (1 + 1j)) +# malformed complex strings +for test in ("1+2", "1j+2", "1+2j+3", "1+2+3j", "1 + 2j"): + try: + complex(test) + except ValueError: + print("ValueError", test) + # can't assign to attributes try: (1j).imag = 0 diff --git a/tests/float/complex_dunder.py b/tests/float/complex_dunder.py new file mode 100644 index 0000000000..975d829b47 --- /dev/null +++ b/tests/float/complex_dunder.py @@ -0,0 +1,46 @@ +# test __complex__ function support + + +class TestFloat: + def __float__(self): + return 1.0 + + +class TestComplex: + def __complex__(self): + return 1j + 10 + + +class TestStrComplex: + def __complex__(self): + return "a" + + +class TestNonComplex: + def __complex__(self): + return 6 + + +class Test: + pass + + +print(complex(TestFloat())) +print(complex(TestComplex())) + +try: + print(complex(TestStrComplex())) +except TypeError: + print("TypeError") + + +try: + print(complex(TestNonComplex())) +except TypeError: + print("TypeError") + + +try: + print(complex(Test())) +except TypeError: + print("TypeError") diff --git a/tests/float/float_dunder.py b/tests/float/float_dunder.py new file mode 100644 index 0000000000..1cd03db524 --- /dev/null +++ b/tests/float/float_dunder.py @@ -0,0 +1,42 @@ +# test __float__ function support + + +class TestFloat: + def __float__(self): + return 10.0 + + +class TestStrFloat: + def __float__(self): + return "a" + + +class TestNonFloat: + def __float__(self): + return 6 + + +class Test: + pass + + +print("%.1f" % float(TestFloat())) +print("%.1f" % TestFloat()) + + +try: + print(float(TestStrFloat())) +except TypeError: + print("TypeError") + + +try: + print(float(TestNonFloat())) +except TypeError: + print("TypeError") + + +try: + print(float(Test())) +except TypeError: + print("TypeError") diff --git a/tests/float/float_format.py b/tests/float/float_format.py index 4c8a217567..98ed0eb096 100644 --- a/tests/float/float_format.py +++ b/tests/float/float_format.py @@ -17,3 +17,11 @@ print("%.2e" % float("9" * 40 + "e-21")) # check a case that would render negative digit values, eg ")" characters # the string is converted back to a float to check for no illegal characters float("%.23e" % 1e-80) + +# Check a problem with malformed "e" format numbers on the edge of 1.0e-X. +for r in range(38): + s = "%.12e" % float("1e-" + str(r)) + # It may format as 1e-r, or 9.999...e-(r+1), both are OK. + # But formatting as 0.999...e-r is NOT ok. + if s[0] == "0": + print("FAIL:", s) diff --git a/tests/float/float_format_ints_doubleprec.py b/tests/float/float_format_ints_doubleprec.py index 57899d6d65..67101d3e45 100644 --- a/tests/float/float_format_ints_doubleprec.py +++ b/tests/float/float_format_ints_doubleprec.py @@ -13,3 +13,6 @@ v1 = 0x54B249AD2594C37D # 1e100 v2 = 0x6974E718D7D7625A # 1e200 print("{:.12e}".format(array.array("d", v1.to_bytes(8, sys.byteorder))[0])) print("{:.12e}".format(array.array("d", v2.to_bytes(8, sys.byteorder))[0])) + +for i in range(300): + print(float("1e" + str(i))) diff --git a/tests/float/math_domain.py b/tests/float/math_domain.py index 0c25dc08b6..606a655284 100644 --- a/tests/float/math_domain.py +++ b/tests/float/math_domain.py @@ -17,6 +17,7 @@ for name, f, args in ( ("trunc", math.trunc, ()), ("sqrt", math.sqrt, (-1, 0)), ("exp", math.exp, ()), + ("log", math.log, ()), ("sin", math.sin, ()), ("cos", math.cos, ()), ("tan", math.tan, ()), @@ -27,25 +28,45 @@ for name, f, args in ( ("radians", math.radians, ()), ("degrees", math.degrees, ()), ): - for x in args + (inf, nan): + for x in args + (inf, -inf, nan): try: - ans = f(x) - print("%.4f" % ans) + ans = "%.4f" % f(x) except ValueError: - print(name, "ValueError") + ans = "ValueError" except OverflowError: - print(name, "OverflowError") + ans = "OverflowError" + print("%s(%.4f) = %s" % (name, x, ans)) # double argument functions for name, f, args in ( - ("pow", math.pow, ((0, 2), (-1, 2), (0, -1), (-1, 2.3), (nan, 0), (1, nan))), + ( + "pow", + math.pow, + ( + (0, 2), + (-1, 2), + (0, -1), + (-1, 2.3), + (0.5, inf), + (-0.5, inf), + (0.5, -inf), + (-0.5, -inf), + (1.5, inf), + (-1.5, inf), + (1.5, -inf), + (-1.5, -inf), + (nan, 0), + (1, nan), + ), + ), + ("log", math.log, ()), ("fmod", math.fmod, ((1.2, inf), (1.2, -inf), (1.2, 0), (inf, 1.2))), ("atan2", math.atan2, ((0, 0), (-inf, inf), (-inf, -inf), (inf, -inf))), ("copysign", math.copysign, ()), ): for x in args + ((0, inf), (inf, 0), (inf, inf), (inf, nan), (nan, inf), (nan, nan)): try: - ans = f(*x) - print("%.4f" % ans) + ans = "%.4f" % f(*x) except ValueError: - print(name, "ValueError") + ans = "ValueError" + print("%s(%.4f, %.4f) = %s" % (name, x[0], x[1], ans)) diff --git a/tests/float/math_domain_special.py b/tests/float/math_domain_special.py index 880594dce2..ddabf178a3 100644 --- a/tests/float/math_domain_special.py +++ b/tests/float/math_domain_special.py @@ -29,9 +29,9 @@ for name, f, args in ( ): for x in args + (inf, -inf, nan): try: - ans = f(x) - print("%.4f" % ans) + ans = "%.4f" % f(x) except ValueError: - print(name, "ValueError") + ans = "ValueError" except OverflowError: - print(name, "OverflowError") + ans = "OverflowError" + print("%s(%.4f) = %s" % (name, x, ans)) diff --git a/tests/float/math_dunder.py b/tests/float/math_dunder.py new file mode 100644 index 0000000000..33ea7f7c1c --- /dev/null +++ b/tests/float/math_dunder.py @@ -0,0 +1,15 @@ +# test that math functions support user classes with __float__ + +try: + import math +except ImportError: + print("SKIP") + raise SystemExit + + +class TestFloat: + def __float__(self): + return 1.0 + + +print("%.5g" % math.exp(TestFloat())) diff --git a/tests/float/math_fun.py b/tests/float/math_fun.py index f43216c6fb..9920caf32b 100644 --- a/tests/float/math_fun.py +++ b/tests/float/math_fun.py @@ -38,12 +38,12 @@ functions = [ ] for function_name, function, test_vals in functions: - print(function_name) for value in test_vals: try: - print("{:.5g}".format(function(value))) + ans = "{:.5g}".format(function(value)) except ValueError as e: - print(str(e)) + ans = str(e) + print("{}({:.5g}) = {}".format(function_name, value, ans)) tuple_functions = [ ("frexp", frexp, test_values), @@ -51,10 +51,9 @@ tuple_functions = [ ] for function_name, function, test_vals in tuple_functions: - print(function_name) for value in test_vals: x, y = function(value) - print("{:.5g} {:.5g}".format(x, y)) + print("{}({:.5g}) = ({:.5g}, {:.5g})".format(function_name, value, x, y)) binary_functions = [ ( @@ -123,9 +122,9 @@ binary_functions = [ ] for function_name, function, test_vals in binary_functions: - print(function_name) for value1, value2 in test_vals: try: - print("{:.5g}".format(function(value1, value2))) + ans = "{:.5g}".format(function(value1, value2)) except (ValueError, ZeroDivisionError) as e: - print(type(e)) + ans = type(e) + print("{}({:.5g}, {:.5g}) = {}".format(function_name, value1, value2, ans)) diff --git a/tests/float/math_fun_special.py b/tests/float/math_fun_special.py index 8f51b29acb..9c0fe3555f 100644 --- a/tests/float/math_fun_special.py +++ b/tests/float/math_fun_special.py @@ -52,9 +52,9 @@ functions = [ ] for function_name, function, test_vals in functions: - print(function_name) for value in test_vals: try: - print("{:.4g}".format(function(value))) + ans = "{:.4g}".format(function(value)) except ValueError as e: - print(str(e)) + ans = str(e) + print("{}({:.4g}) = {}".format(function_name, value, ans)) diff --git a/tests/float/string_format_modulo.py b/tests/float/string_format_modulo.py index 0944615381..3c206b7393 100644 --- a/tests/float/string_format_modulo.py +++ b/tests/float/string_format_modulo.py @@ -41,7 +41,10 @@ print(("%.40f" % 1e-300)[:2]) print(("%.40g" % 1e-1)[:2]) print(("%.40g" % 1e-2)[:2]) print(("%.40g" % 1e-3)[:2]) -print(("%.40g" % 1e-4)[:2]) +# Under Appveyor Release builds, 1e-4 was being formatted as 9.99999...e-5 +# instead of 0.0001. (Interestingly, it formatted correctly for the Debug +# build). Avoid the edge case. +print(("%.40g" % 1.1e-4)[:2]) print("%.0g" % 1) # 0 precision 'g' diff --git a/tests/frozen/README.md b/tests/frozen/README.md new file mode 100644 index 0000000000..bd786d5a3c --- /dev/null +++ b/tests/frozen/README.md @@ -0,0 +1,2 @@ +This is a .mpy built against the current .mpy version that can be used to test +freezing without a dependency on mpy-cross. diff --git a/tests/frozen/frozentest.mpy b/tests/frozen/frozentest.mpy new file mode 100644 index 0000000000..7f1163956b Binary files /dev/null and b/tests/frozen/frozentest.mpy differ diff --git a/tests/frozen/frozentest.py b/tests/frozen/frozentest.py new file mode 100644 index 0000000000..78cdd60bf0 --- /dev/null +++ b/tests/frozen/frozentest.py @@ -0,0 +1,7 @@ +print("uPy") +print("a long string that is not interned") +print("a string that has unicode αβγ chars") +print(b"bytes 1234\x01") +print(123456789) +for i in range(4): + print(i) diff --git a/tests/import/module_dict.py b/tests/import/module_dict.py new file mode 100644 index 0000000000..431d80b3b4 --- /dev/null +++ b/tests/import/module_dict.py @@ -0,0 +1,17 @@ +# test __dict__ attribute of a user module + +import sys + +if not hasattr(sys, "__dict__"): + print("SKIP") + raise SystemExit + + +import import1b + +# dict of a user module (read/write) +print(import1b.var) +print(import1b.__dict__["var"]) +import1b.__dict__["var"] = "hello" +print(import1b.var) +print(import1b.__dict__["var"]) diff --git a/tests/inlineasm/asmdata.py b/tests/inlineasm/asmdata.py new file mode 100644 index 0000000000..bbd20c9186 --- /dev/null +++ b/tests/inlineasm/asmdata.py @@ -0,0 +1,16 @@ +# test the "data" directive + + +@micropython.asm_thumb +def ret_num(r0) -> uint: + lsl(r0, r0, 2) + mov(r1, pc) + add(r0, r0, r1) + ldr(r0, [r0, 4]) + b(HERE) + data(4, 0x12345678, 0x20000000, 0x40000000, 0x7FFFFFFF + 1, (1 << 32) - 2) + label(HERE) + + +for i in range(5): + print(hex(ret_num(i))) diff --git a/tests/inlineasm/asmdata.py.exp b/tests/inlineasm/asmdata.py.exp new file mode 100644 index 0000000000..502c04f993 --- /dev/null +++ b/tests/inlineasm/asmdata.py.exp @@ -0,0 +1,5 @@ +0x12345678 +0x20000000 +0x40000000 +0x80000000 +0xfffffffe diff --git a/tests/micropython/builtin_execfile.py b/tests/micropython/builtin_execfile.py new file mode 100644 index 0000000000..8a8ce79f78 --- /dev/null +++ b/tests/micropython/builtin_execfile.py @@ -0,0 +1,70 @@ +# Test builtin execfile function using VFS. + +try: + import uio, uos + + execfile + uio.IOBase + uos.mount +except (ImportError, NameError, AttributeError): + print("SKIP") + raise SystemExit + + +class File(uio.IOBase): + def __init__(self, data): + self.data = data + self.off = 0 + + def ioctl(self, request, arg): + return 0 + + def readinto(self, buf): + buf[:] = memoryview(self.data)[self.off : self.off + len(buf)] + self.off += len(buf) + return len(buf) + + +class Filesystem: + def __init__(self, files): + self.files = files + + def mount(self, readonly, mkfs): + print("mount", readonly, mkfs) + + def umount(self): + print("umount") + + def open(self, file, mode): + print("open", file, mode) + if file not in self.files: + raise OSError(2) # ENOENT + return File(self.files[file]) + + +# First umount any existing mount points the target may have. +try: + uos.umount("/") +except OSError: + pass +for path in uos.listdir("/"): + uos.umount("/" + path) + +# Create and mount the VFS object. +files = { + "/test.py": "print(123)", +} +fs = Filesystem(files) +uos.mount(fs, "/test_mnt") + +# Test execfile with a file that doesn't exist. +try: + execfile("/test_mnt/noexist.py") +except OSError: + print("OSError") + +# Test execfile with a file that does exist. +execfile("/test_mnt/test.py") + +# Unmount the VFS object. +uos.umount(fs) diff --git a/tests/micropython/builtin_execfile.py.exp b/tests/micropython/builtin_execfile.py.exp new file mode 100644 index 0000000000..1d5d8ee571 --- /dev/null +++ b/tests/micropython/builtin_execfile.py.exp @@ -0,0 +1,6 @@ +mount False False +open /noexist.py rb +OSError +open /test.py rb +123 +umount diff --git a/tests/micropython/import_mpy_native.py b/tests/micropython/import_mpy_native.py index 2829de47aa..4945a98166 100644 --- a/tests/micropython/import_mpy_native.py +++ b/tests/micropython/import_mpy_native.py @@ -1,8 +1,9 @@ -# test importing of .mpy files with native code (x64 only) +# test importing of .mpy files with native code try: import sys, io, os + sys.implementation._mpy io.IOBase os.mount except (ImportError, AttributeError): @@ -10,7 +11,8 @@ except (ImportError, AttributeError): raise SystemExit mpy_arch = sys.implementation._mpy >> 8 -if mpy_arch == 0: +if mpy_arch >> 2 == 0: + # This system does not support .mpy files containing native code print("SKIP") raise SystemExit @@ -53,8 +55,8 @@ class UserFS: valid_header = bytes([ord("C"), 6, mpy_arch, 31]) # fmt: off user_files = { - # bad architecture - '/mod0.mpy': b'C\x06\xfc\x1f', + # bad architecture (mpy_arch needed for sub-version) + '/mod0.mpy': bytes([ord('C'), 6, 0xfc | mpy_arch, 31]), # test loading of viper and asm '/mod1.mpy': valid_header + ( @@ -99,7 +101,7 @@ user_files = { b'\x22' # 4 bytes, no children, viper code b'\x00\x00\x00\x00' # dummy machine code - b'\xe0' # scope_flags: VIPERBSS | VIPERRODATA | VIPERRELOC + b'\x70' # scope_flags: VIPERBSS | VIPERRODATA | VIPERRELOC b'\x06\x04' # rodata=6 bytes, bss=4 bytes b'rodata' # rodata content b'\x03\x01\x00' # dummy relocation of rodata diff --git a/tests/micropython/import_mpy_native_gc.py b/tests/micropython/import_mpy_native_gc.py index 39d7740216..0e489c74e2 100644 --- a/tests/micropython/import_mpy_native_gc.py +++ b/tests/micropython/import_mpy_native_gc.py @@ -46,24 +46,26 @@ class UserFS: # Pre-compiled examples/natmod/features0 example for various architectures, keyed -# by the required value of sys.implementation._mpy. +# by the required value of sys.implementation._mpy (without sub-version). features0_file_contents = { # -march=x64 - 0x806: b'C\x06\x08\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x8a\x02\xe9/\x00\x00\x00SH\x8b\x1d\x83\x00\x00\x00\xbe\x02\x00\x00\x00\xffS\x18\xbf\x01\x00\x00\x00H\x85\xc0u\x0cH\x8bC \xbe\x02\x00\x00\x00[\xff\xe0H\x0f\xaf\xf8H\xff\xc8\xeb\xe6ATUSH\x8b\x1dQ\x00\x00\x00H\x8bG\x08L\x8bc(H\x8bx\x08A\xff\xd4H\x8d5+\x00\x00\x00H\x89\xc5H\x8b\x059\x00\x00\x00\x0f\xb7x\x02\xffShH\x89\xefA\xff\xd4H\x8b\x03[]A\\\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x11$\r&\xa5 \x01"\xff', + 0x806: b'C\x06\t\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x8a\x02\xe9/\x00\x00\x00SH\x8b\x1d\x83\x00\x00\x00\xbe\x02\x00\x00\x00\xffS\x18\xbf\x01\x00\x00\x00H\x85\xc0u\x0cH\x8bC \xbe\x02\x00\x00\x00[\xff\xe0H\x0f\xaf\xf8H\xff\xc8\xeb\xe6ATUSH\x8b\x1dQ\x00\x00\x00H\x8bG\x08L\x8bc(H\x8bx\x08A\xff\xd4H\x8d5+\x00\x00\x00H\x89\xc5H\x8b\x059\x00\x00\x00\x0f\xb7x\x02\xffShH\x89\xefA\xff\xd4H\x8b\x03[]A\\\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x11$\r&\xa5 \x01"\xff', # -march=armv6m - 0x1006: b'C\x06\x14\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x88"\x1a\xe0\x00\x00\x13\xb5\nK\nJ{D\x9cX\x02!\xe3h\x98G\x03F\x01 3\xb9\x02!#i\x01\x93\x02\xb0\xbd\xe8\x10@\x18GXC\x01;\xf4\xe7\x00\xbfn\x00\x00\x00\x00\x00\x00\x00\xf8\xb5\nN\nK~D\xf4XChgiXh\xb8G\x05F\x07K\x08I\xf2XyDP\x88ck\x98G(F\xb8G h\xf8\xbd\x00\xbf:\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x11>\r@\xa5:\x01<\xff', + 0x1006: b'C\x06\x11\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x88"\x1a\xe0\x00\x00\x13\xb5\nK\nJ{D\x9cX\x02!\xe3h\x01\x93\x98G\x03\x00\x01 \x00+\x02\xd0XC\x01;\xfa\xe7#i\x02!\x01\x93\x98G\x16\xbd\xc0Fn\x00\x00\x00\x00\x00\x00\x00\xf7\xb5\nN\nK~D\xf4XChgiXh\xb8G\x05\x00\x07K\x08I\xf3XyDX\x88\x01\x93ck\x98G(\x00\xb8G h\xfe\xbd:\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x11>\r@\xa5:\x01<\xff', } # Populate armv7m-derived archs based on armv6m. for arch in (0x1406, 0x1806, 0x1C06, 0x2006): features0_file_contents[arch] = features0_file_contents[0x1006] -if sys.implementation._mpy not in features0_file_contents: +# Check that a .mpy exists for the target (ignore sub-version in lookup). +sys_implementation_mpy = sys.implementation._mpy & ~(3 << 8) +if sys_implementation_mpy not in features0_file_contents: print("SKIP") raise SystemExit # These are the test .mpy files. -user_files = {"/features0.mpy": features0_file_contents[sys.implementation._mpy]} +user_files = {"/features0.mpy": features0_file_contents[sys_implementation_mpy]} # Create and mount a user filesystem. os.mount(UserFS(user_files), "/userfs") diff --git a/tests/micropython/native_fun_attrs.py b/tests/micropython/native_fun_attrs.py new file mode 100644 index 0000000000..e61c869755 --- /dev/null +++ b/tests/micropython/native_fun_attrs.py @@ -0,0 +1,25 @@ +# test native function attributes + + +def f(): + pass + + +if not hasattr(f, "__name__"): + print("SKIP") + raise SystemExit + + +@micropython.native +def native_f(): + pass + + +print(type(native_f.__name__)) +print(type(native_f.__globals__)) +print(native_f.__globals__ is globals()) + +try: + native_f.__name__ = None +except AttributeError: + print("AttributeError") diff --git a/tests/micropython/native_fun_attrs.py.exp b/tests/micropython/native_fun_attrs.py.exp new file mode 100644 index 0000000000..8be35e2f69 --- /dev/null +++ b/tests/micropython/native_fun_attrs.py.exp @@ -0,0 +1,4 @@ + + +True +AttributeError diff --git a/tests/micropython/viper_addr.py b/tests/micropython/viper_addr.py index 84bc6c002e..8e79fadb2a 100644 --- a/tests/micropython/viper_addr.py +++ b/tests/micropython/viper_addr.py @@ -21,7 +21,7 @@ def memsum(src: ptr8, n: int) -> int: # create array and get its address -ar = bytearray("0000") +ar = bytearray(b"0000") addr = get_addr(ar) print(type(ar)) print(type(addr)) diff --git a/tests/micropython/viper_misc.py b/tests/micropython/viper_misc.py index f9267f65ca..2659032df6 100644 --- a/tests/micropython/viper_misc.py +++ b/tests/micropython/viper_misc.py @@ -1,3 +1,5 @@ +# Miscellaneous viper tests. + import micropython @@ -52,8 +54,7 @@ def viper_4args(a: int, b: int, c: int, d: int) -> int: return a + b + c + d -# viper call with 4 args not yet supported -# print(viper_4args(1, 2, 3, 4)) +print(viper_4args(1, 2, 3, 4)) # a local (should have automatic type int) @@ -73,96 +74,3 @@ def viper_no_annotation(x, y): print(viper_no_annotation(4, 5)) - - -# a for loop -@micropython.viper -def viper_for(a: int, b: int) -> int: - total = 0 - for x in range(a, b): - total += x - return total - - -print(viper_for(10, 10000)) - - -# accessing a global -@micropython.viper -def viper_access_global(): - global gl - gl = 1 - return gl - - -print(viper_access_global(), gl) - - -# calling print with object and int types -@micropython.viper -def viper_print(x, y: int): - print(x, y + 1) - - -viper_print(1, 2) - - -# convert constants to objects in tuple -@micropython.viper -def viper_tuple_consts(x): - return (x, 1, False, True) - - -print(viper_tuple_consts(0)) - - -# making a tuple from an object and an int -@micropython.viper -def viper_tuple(x, y: int): - return (x, y + 1) - - -print(viper_tuple(1, 2)) - - -# making a list from an object and an int -@micropython.viper -def viper_list(x, y: int): - return [x, y + 1] - - -print(viper_list(1, 2)) - - -# making a set from an object and an int -@micropython.viper -def viper_set(x, y: int): - return {x, y + 1} - - -print(sorted(list(viper_set(1, 2)))) - - -# raising an exception -@micropython.viper -def viper_raise(x: int): - raise OSError(x) - - -try: - viper_raise(1) -except OSError as e: - print(repr(e)) - - -# calling GC after defining the function -@micropython.viper -def viper_gc() -> int: - return 1 - - -print(viper_gc()) -import gc - -gc.collect() -print(viper_gc()) diff --git a/tests/micropython/viper_misc.py.exp b/tests/micropython/viper_misc.py.exp index e4462771b4..922ceb9fef 100644 --- a/tests/micropython/viper_misc.py.exp +++ b/tests/micropython/viper_misc.py.exp @@ -3,15 +3,6 @@ 0 Ellipsis 6 +10 7 20 -49994955 -1 1 -1 3 -(0, 1, False, True) -(1, 3) -[1, 3] -[1, 3] -OSError(1,) -1 -1 diff --git a/tests/micropython/viper_misc3.py b/tests/micropython/viper_misc3.py new file mode 100644 index 0000000000..7b211e5dd8 --- /dev/null +++ b/tests/micropython/viper_misc3.py @@ -0,0 +1,96 @@ +# Miscellaneous viper tests. + +import micropython + + +# a for loop +@micropython.viper +def viper_for(a: int, b: int) -> int: + total = 0 + for x in range(a, b): + total += x + return total + + +print(viper_for(10, 10000)) + + +# accessing a global +@micropython.viper +def viper_access_global(): + global gl + gl = 1 + return gl + + +print(viper_access_global(), gl) + + +# calling print with object and int types +@micropython.viper +def viper_print(x, y: int): + print(x, y + 1) + + +viper_print(1, 2) + + +# convert constants to objects in tuple +@micropython.viper +def viper_tuple_consts(x): + return (x, 1, False, True) + + +print(viper_tuple_consts(0)) + + +# making a tuple from an object and an int +@micropython.viper +def viper_tuple(x, y: int): + return (x, y + 1) + + +print(viper_tuple(1, 2)) + + +# making a list from an object and an int +@micropython.viper +def viper_list(x, y: int): + return [x, y + 1] + + +print(viper_list(1, 2)) + + +# making a set from an object and an int +@micropython.viper +def viper_set(x, y: int): + return {x, y + 1} + + +print(sorted(list(viper_set(1, 2)))) + + +# raising an exception +@micropython.viper +def viper_raise(x: int): + raise OSError(x) + + +try: + viper_raise(1) +except OSError as e: + print(repr(e)) + + +# calling GC after defining the function +@micropython.viper +def viper_gc() -> int: + return 1 + + +print(viper_gc()) +import gc + +gc.collect() +print(viper_gc()) diff --git a/tests/micropython/viper_misc3.py.exp b/tests/micropython/viper_misc3.py.exp new file mode 100644 index 0000000000..b12807b2f3 --- /dev/null +++ b/tests/micropython/viper_misc3.py.exp @@ -0,0 +1,10 @@ +49994955 +1 1 +1 3 +(0, 1, False, True) +(1, 3) +[1, 3] +[1, 3] +OSError(1,) +1 +1 diff --git a/tests/micropython/viper_storeattr.py b/tests/micropython/viper_storeattr.py new file mode 100644 index 0000000000..65f68b6e22 --- /dev/null +++ b/tests/micropython/viper_storeattr.py @@ -0,0 +1,25 @@ +# test storing an attribute with a value of different viper types + + +class X: + def __str__(self): + return "X" + + +x = X() + + +@micropython.viper +def a(): + x.i0 = 0 + x.i7 = 7 + x.s = "hello" + x.o = x + + +a() + +print(x.i0) +print(x.i7) +print(x.s) +print(x.o) diff --git a/tests/micropython/viper_storeattr.py.exp b/tests/micropython/viper_storeattr.py.exp new file mode 100644 index 0000000000..8e6a6cfda9 --- /dev/null +++ b/tests/micropython/viper_storeattr.py.exp @@ -0,0 +1,4 @@ +0 +7 +hello +X diff --git a/tests/micropython/viper_subscr_multi.py b/tests/micropython/viper_subscr_multi.py index 1561e5534d..a2baba2411 100644 --- a/tests/micropython/viper_subscr_multi.py +++ b/tests/micropython/viper_subscr_multi.py @@ -6,15 +6,24 @@ def f1(b: ptr8): b[0] += b[1] +b = bytearray(b"\x01\x02") +f1(b) +print(b) + + @micropython.viper def f2(b: ptr8, i: int): b[0] += b[i] -b = bytearray(b"\x01\x02") -f1(b) -print(b) - b = bytearray(b"\x01\x02") f2(b, 1) print(b) + + +@micropython.viper +def f3(b: ptr8) -> int: + return b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3] + + +print(hex(f3(b"\x01\x02\x03\x04"))) diff --git a/tests/micropython/viper_subscr_multi.py.exp b/tests/micropython/viper_subscr_multi.py.exp index a2c298bb16..ea644c046d 100644 --- a/tests/micropython/viper_subscr_multi.py.exp +++ b/tests/micropython/viper_subscr_multi.py.exp @@ -1,2 +1,3 @@ bytearray(b'\x03\x02') bytearray(b'\x03\x02') +0x1020304 diff --git a/tests/misc/cexample_class.py b/tests/misc/cexample_class.py new file mode 100644 index 0000000000..6b8718ad8c --- /dev/null +++ b/tests/misc/cexample_class.py @@ -0,0 +1,24 @@ +# test custom native class + +try: + import cexample + import time +except ImportError: + print("SKIP") + raise SystemExit + + +SLEEP_MS = 100 +TOLERANCE_MS = 20 + +timer = cexample.Timer() + +t_start = timer.time() + +time.sleep_ms(100) + +t_end = timer.time() + +print(timer) +print(0 <= t_start <= TOLERANCE_MS) +print(SLEEP_MS - TOLERANCE_MS <= t_end <= SLEEP_MS + TOLERANCE_MS) diff --git a/tests/misc/cexample_class.py.exp b/tests/misc/cexample_class.py.exp new file mode 100644 index 0000000000..b9a06602a3 --- /dev/null +++ b/tests/misc/cexample_class.py.exp @@ -0,0 +1,3 @@ + +True +True diff --git a/tests/misc/cexample_module.py b/tests/misc/cexample_module.py new file mode 100644 index 0000000000..c1da2ecf7a --- /dev/null +++ b/tests/misc/cexample_module.py @@ -0,0 +1,16 @@ +# test custom builtin module + +try: + import cexample +except ImportError: + print("SKIP") + raise SystemExit + +print(cexample) +print(cexample.__name__) + +d = dir(cexample) +d.index("add_ints") +d.index("Timer") + +print(cexample.add_ints(1, 3)) diff --git a/tests/misc/cexample_module.py.exp b/tests/misc/cexample_module.py.exp new file mode 100644 index 0000000000..bb305060e9 --- /dev/null +++ b/tests/misc/cexample_module.py.exp @@ -0,0 +1,3 @@ + +cexample +4 diff --git a/tests/misc/non_compliant.py b/tests/misc/non_compliant.py index ecd4f10391..4c06977d11 100644 --- a/tests/misc/non_compliant.py +++ b/tests/misc/non_compliant.py @@ -54,7 +54,7 @@ except NotImplementedError: # str(...) with keywords not implemented try: str(b"abc", encoding="utf8") -except TypeError: +except NotImplementedError: print("TypeError") # str.rsplit(None, n) not implemented diff --git a/tests/misc/sys_settrace_generator.py.exp b/tests/misc/sys_settrace_generator.py.exp index a83450afe3..c1d13aac86 100644 --- a/tests/misc/sys_settrace_generator.py.exp +++ b/tests/misc/sys_settrace_generator.py.exp @@ -1,195 +1,195 @@ ### trace_handler::main event: call 0: @__main__:test_generator => sys_settrace_generator.py:41 - 1: @__main__: => sys_settrace_generator.py:69 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:test_generator => sys_settrace_generator.py:42 - 1: @__main__: => sys_settrace_generator.py:69 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:test_generator => sys_settrace_generator.py:48 - 1: @__main__: => sys_settrace_generator.py:69 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:test_generator => sys_settrace_generator.py:49 - 1: @__main__: => sys_settrace_generator.py:69 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:test_generator => sys_settrace_generator.py:50 - 1: @__main__: => sys_settrace_generator.py:69 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:52 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:51 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: call 0: @__main__:make_gen => sys_settrace_generator.py:42 - 1: @__main__:test_generator => sys_settrace_generator.py:52 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:51 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:43 - 1: @__main__:test_generator => sys_settrace_generator.py:52 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:51 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: return 0: @__main__:make_gen => sys_settrace_generator.py:43 - 1: @__main__:test_generator => sys_settrace_generator.py:52 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:51 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:56 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:54 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: call 0: @__main__:make_gen => sys_settrace_generator.py:43 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:43 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:44 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: return 0: @__main__:make_gen => sys_settrace_generator.py:44 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: call 0: @__main__:make_gen => sys_settrace_generator.py:44 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:44 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:45 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: return 0: @__main__:make_gen => sys_settrace_generator.py:45 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: call 0: @__main__:make_gen => sys_settrace_generator.py:45 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:45 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:46 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: return 0: @__main__:make_gen => sys_settrace_generator.py:46 - 1: @__main__:test_generator => sys_settrace_generator.py:56 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:54 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: exception + 0: @__main__:test_generator => sys_settrace_generator.py:54 + 1: @__main__: => sys_settrace_generator.py:67 +### trace_handler::main event: line 0: @__main__:test_generator => sys_settrace_generator.py:56 - 1: @__main__: => sys_settrace_generator.py:69 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:58 - 1: @__main__: => sys_settrace_generator.py:69 -### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:59 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:57 + 1: @__main__: => sys_settrace_generator.py:67 test_generator 7 8 +### trace_handler::main event: line + 0: @__main__:test_generator => sys_settrace_generator.py:59 + 1: @__main__: => sys_settrace_generator.py:67 +### trace_handler::main event: line + 0: @__main__:test_generator => sys_settrace_generator.py:60 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:test_generator => sys_settrace_generator.py:61 - 1: @__main__: => sys_settrace_generator.py:69 -### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:62 - 1: @__main__: => sys_settrace_generator.py:69 -### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:63 - 1: @__main__: => sys_settrace_generator.py:69 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: call 0: @__main__:make_gen => sys_settrace_generator.py:42 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:43 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: return 0: @__main__:make_gen => sys_settrace_generator.py:43 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:63 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:61 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:64 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:62 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:63 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:61 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: call 0: @__main__:make_gen => sys_settrace_generator.py:43 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:43 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:44 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: return 0: @__main__:make_gen => sys_settrace_generator.py:44 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:63 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:61 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:64 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:62 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:63 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:61 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: call 0: @__main__:make_gen => sys_settrace_generator.py:44 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:44 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:45 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: return 0: @__main__:make_gen => sys_settrace_generator.py:45 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:63 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:61 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:64 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:62 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:63 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:61 + 1: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: call 0: @__main__:make_gen => sys_settrace_generator.py:45 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:45 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line 0: @__main__:make_gen => sys_settrace_generator.py:46 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: return 0: @__main__:make_gen => sys_settrace_generator.py:46 - 1: @__main__:test_generator => sys_settrace_generator.py:63 - 2: @__main__: => sys_settrace_generator.py:69 + 1: @__main__:test_generator => sys_settrace_generator.py:61 + 2: @__main__: => sys_settrace_generator.py:67 ### trace_handler::main event: line - 0: @__main__:test_generator => sys_settrace_generator.py:65 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:63 + 1: @__main__: => sys_settrace_generator.py:67 7 ### trace_handler::main event: return - 0: @__main__:test_generator => sys_settrace_generator.py:65 - 1: @__main__: => sys_settrace_generator.py:69 + 0: @__main__:test_generator => sys_settrace_generator.py:63 + 1: @__main__: => sys_settrace_generator.py:67 Total traces executed: 54 diff --git a/tests/perf_bench/benchrun.py b/tests/perf_bench/benchrun.py index 87b6489d07..6e6135fd98 100644 --- a/tests/perf_bench/benchrun.py +++ b/tests/perf_bench/benchrun.py @@ -15,7 +15,7 @@ def bm_run(N, M): cur_nm = nm param = p if param is None: - print(-1, -1, "no matching params") + print(-1, -1, "SKIP: no matching params") return # Run and time benchmark diff --git a/tests/perf_bench/bm_fannkuch.py b/tests/perf_bench/bm_fannkuch.py index 9f7ae797f0..49ab05d1e9 100644 --- a/tests/perf_bench/bm_fannkuch.py +++ b/tests/perf_bench/bm_fannkuch.py @@ -51,6 +51,7 @@ def fannkuch(n): # Benchmark interface bm_params = { + (32, 10): (3,), (50, 10): (5,), (100, 10): (6,), (500, 10): (7,), diff --git a/tests/perf_bench/bm_nqueens.py b/tests/perf_bench/bm_nqueens.py index 160f1178aa..7c6ddd59e1 100644 --- a/tests/perf_bench/bm_nqueens.py +++ b/tests/perf_bench/bm_nqueens.py @@ -47,7 +47,7 @@ def n_queens(queen_count): # Benchmark interface bm_params = { - (50, 25): (1, 5), + (32, 10): (1, 5), (100, 25): (1, 6), (1000, 100): (1, 7), (5000, 100): (1, 8), diff --git a/tests/perf_bench/bm_pidigits.py b/tests/perf_bench/bm_pidigits.py index 5949b93063..bdaa73cec7 100644 --- a/tests/perf_bench/bm_pidigits.py +++ b/tests/perf_bench/bm_pidigits.py @@ -36,6 +36,7 @@ def gen_pi_digits(n): # Benchmark interface bm_params = { + (32, 10): (1, 20), (50, 25): (1, 35), (100, 100): (1, 65), (1000, 1000): (2, 250), diff --git a/tests/perf_bench/core_import_mpy_multi.py b/tests/perf_bench/core_import_mpy_multi.py index 4e098eef81..0f37aedf03 100644 --- a/tests/perf_bench/core_import_mpy_multi.py +++ b/tests/perf_bench/core_import_mpy_multi.py @@ -73,7 +73,7 @@ def test(r): # Benchmark interface bm_params = { - (100, 10): (50,), + (32, 10): (50,), (1000, 10): (500,), (5000, 10): (5000,), } diff --git a/tests/perf_bench/core_qstr.py b/tests/perf_bench/core_qstr.py index b87e2c0658..64d6c59e92 100644 --- a/tests/perf_bench/core_qstr.py +++ b/tests/perf_bench/core_qstr.py @@ -10,7 +10,7 @@ def test(r): # Benchmark interface bm_params = { - (100, 10): (400,), + (32, 10): (400,), (1000, 10): (4000,), (5000, 10): (40000,), } diff --git a/tests/run-internalbench.py b/tests/run-internalbench.py index 24f6d5a771..2cf7f3443b 100755 --- a/tests/run-internalbench.py +++ b/tests/run-internalbench.py @@ -13,10 +13,12 @@ from collections import defaultdict # to the correct executable. if os.name == "nt": CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3.exe") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/windows/micropython.exe") + MICROPYTHON = os.getenv( + "MICROPY_MICROPYTHON", "../ports/windows/build-standard/micropython.exe" + ) else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/micropython") + MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-standard/micropython") def run_tests(pyb, test_dict): diff --git a/tests/run-multitests.py b/tests/run-multitests.py index d8a4a48fa7..81db31ea94 100755 --- a/tests/run-multitests.py +++ b/tests/run-multitests.py @@ -3,6 +3,11 @@ # This file is part of the MicroPython project, http://micropython.org/ # The MIT License (MIT) # Copyright (c) 2020 Damien P. George +# +# run-multitests.py +# Runs a test suite that relies on two micropython instances/devices +# interacting in some way. Typically used to test networking / bluetooth etc. + import sys, os, time, re, select import argparse @@ -10,15 +15,26 @@ import itertools import subprocess import tempfile -sys.path.append("../tools") +test_dir = os.path.abspath(os.path.dirname(__file__)) + +if os.path.abspath(sys.path[0]) == test_dir: + # remove the micropython/tests dir from path to avoid + # accidentally importing tests like micropython/const.py + sys.path.pop(0) + +sys.path.insert(0, test_dir + "/../tools") import pyboard if os.name == "nt": CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3.exe") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/windows/micropython.exe") + MICROPYTHON = os.getenv( + "MICROPY_MICROPYTHON", test_dir + "/../ports/windows/build-standard/micropython.exe" + ) else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/micropython") + MICROPYTHON = os.getenv( + "MICROPY_MICROPYTHON", test_dir + "/../ports/unix/build-standard/micropython" + ) # For diff'ing test output DIFF = os.getenv("MICROPY_DIFF", "diff -u") @@ -74,6 +90,12 @@ class multitest: except: ip = HOST_IP return ip + @staticmethod + def expect_reboot(resume, delay_ms=0): + print("WAIT_FOR_REBOOT", resume, delay_ms) + @staticmethod + def output_metric(data): + print("OUTPUT_METRIC", data) {} @@ -293,6 +315,7 @@ def run_test_on_instances(test_file, num_instances, instances): skip = False injected_globals = "" output = [[] for _ in range(num_instances)] + output_metrics = [] # If the test calls get_network_ip() then inject HOST_IP so that devices can know # the IP address of the host. Do this lazily to not require a TCP/IP connection @@ -362,10 +385,27 @@ def run_test_on_instances(test_file, num_instances, instances): last_read_time[idx] = time.time() if out is not None and not any(m in out for m in IGNORE_OUTPUT_MATCHES): trace_instance_output(idx, out) + if out.startswith("WAIT_FOR_REBOOT"): + _, resume, delay_ms = out.split(" ") + + if wait_for_reboot(instance, delay_ms): + # Restart the test code, resuming from requested instance block + if not resume.startswith("instance{}".format(idx)): + raise SystemExit( + 'ERROR: resume function must start with "instance{}"'.format( + idx + ) + ) + append_code = APPEND_CODE_TEMPLATE.format(injected_globals, resume[8:]) + instance.start_file(test_file, append=append_code) + last_read_time[idx] = time.time() + if out.startswith("BROADCAST "): for instance2 in instances: if instance2 is not instance: instance2.write(bytes(out, "ascii") + b"\r\n") + elif out.startswith("OUTPUT_METRIC "): + output_metrics.append(out.split(" ", 1)[1]) else: output[idx].append(out) if err is not None: @@ -387,7 +427,39 @@ def run_test_on_instances(test_file, num_instances, instances): output_str += "--- instance{} ---\n".format(idx) output_str += "\n".join(lines) + "\n" - return error, skip, output_str + return error, skip, output_str, output_metrics + + +def wait_for_reboot(instance, extra_timeout_ms=0): + # Monitor device responses for reboot banner, waiting for idle. + extra_timeout = float(extra_timeout_ms) * 1000 + INITIAL_TIMEOUT = 1 + extra_timeout + FULL_TIMEOUT = 5 + extra_timeout + t_start = t_last_activity = time.monotonic() + while True: + t = time.monotonic() + out, err = instance.readline() + if err is not None: + print("Reboot: communication error", err) + return False + if out: + t_last_activity = t + # Check for reboot banner, see py/pyexec.c "reset friendly REPL" + if re.match(r"^MicroPython v\d+\.\d+\.\d+.* on .*; .* with .*$", out): + time.sleep(0.1) + break + + if t_last_activity == t_start: + if t - t_start > INITIAL_TIMEOUT: + print("Reboot: missed initial Timeout") + return False + else: + if t - t_start > FULL_TIMEOUT: + print("Reboot: Timeout") + return False + + instance.pyb.enter_raw_repl() + return True def print_diff(a, b): @@ -415,7 +487,9 @@ def run_tests(test_files, instances_truth, instances_test): sys.stdout.flush() # Run test on test instances - error, skip, output_test = run_test_on_instances(test_file, num_instances, instances_test) + error, skip, output_test, output_metrics = run_test_on_instances( + test_file, num_instances, instances_test + ) if not skip: # Check if truth exists in a file, and read it in @@ -425,7 +499,7 @@ def run_tests(test_files, instances_truth, instances_test): output_truth = f.read() else: # Run test on truth instances to get expected output - _, _, output_truth = run_test_on_instances( + _, _, output_truth, _ = run_test_on_instances( test_file, num_instances, instances_truth ) @@ -454,6 +528,11 @@ def run_tests(test_files, instances_truth, instances_test): print("### DIFF ###") print_diff(output_truth, output_test) + # Print test output metrics, if there are any. + if output_metrics: + for metric in output_metrics: + print(test_file, ": ", metric, sep="") + if cmd_args.show_output: print() @@ -471,7 +550,10 @@ def run_tests(test_files, instances_truth, instances_test): def main(): global cmd_args - cmd_parser = argparse.ArgumentParser(description="Run network tests for MicroPython") + cmd_parser = argparse.ArgumentParser( + description="Run network tests for MicroPython", + formatter_class=argparse.RawTextHelpFormatter, + ) cmd_parser.add_argument( "-s", "--show-output", action="store_true", help="show test output after running" ) @@ -488,11 +570,19 @@ def main(): default=1, help="repeat the test with this many permutations of the instance order", ) + cmd_parser.epilog = ( + "Supported instance types:\r\n" + " -i pyb: physical device (eg. pyboard) on provided repl port.\n" + " -i micropython unix micropython instance, path customised with MICROPY_MICROPYTHON env.\n" + " -i cpython desktop python3 instance, path customised with MICROPY_CPYTHON3 env.\n" + " -i exec: custom program run on provided path.\n" + "Each instance arg can optionally have custom env provided, eg. ,ENV=VAR,ENV=VAR...\n" + ) cmd_parser.add_argument("files", nargs="+", help="input test files") cmd_args = cmd_parser.parse_args() # clear search path to make sure tests use only builtin modules and those in extmod - os.environ["MICROPYPATH"] = os.pathsep + "../extmod" + os.environ["MICROPYPATH"] = os.pathsep.join(("", ".frozen", "../extmod")) test_files = prepare_test_file_list(cmd_args.files) max_instances = max(t[1] for t in test_files) diff --git a/tests/run-natmodtests.py b/tests/run-natmodtests.py index 0942918d90..db093bc5c5 100755 --- a/tests/run-natmodtests.py +++ b/tests/run-natmodtests.py @@ -11,7 +11,7 @@ import argparse # Paths for host executables CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") -MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/micropython-coverage") +MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-coverage/micropython") NATMOD_EXAMPLE_DIR = "../examples/natmod/" diff --git a/tests/run-perfbench.py b/tests/run-perfbench.py index a2e9e8079a..578f975bb8 100755 --- a/tests/run-perfbench.py +++ b/tests/run-perfbench.py @@ -18,10 +18,12 @@ prepare_script_for_target = __import__("run-tests").prepare_script_for_target # Paths for host executables if os.name == "nt": CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3.exe") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/windows/micropython.exe") + MICROPYTHON = os.getenv( + "MICROPY_MICROPYTHON", "../ports/windows/build-standard/micropython.exe" + ) else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/micropython") + MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-standard/micropython") PYTHON_TRUTH = CPYTHON3 @@ -187,7 +189,7 @@ def parse_output(filename): m = int(m.split("=")[1]) data = [] for l in f: - if l.find(": ") != -1 and l.find(": SKIP") == -1 and l.find("CRASH: ") == -1: + if ": " in l and ": SKIP" not in l and "CRASH: " not in l: name, values = l.strip().split(": ") values = tuple(float(v) for v in values.split()) data.append((name,) + values) @@ -258,9 +260,12 @@ def main(): cmd_parser.add_argument( "--emit", default="bytecode", help="MicroPython emitter to use (bytecode or native)" ) + cmd_parser.add_argument("--heapsize", help="heapsize to use (use default if not specified)") cmd_parser.add_argument("--via-mpy", action="store_true", help="compile code to .mpy first") cmd_parser.add_argument("--mpy-cross-flags", default="", help="flags to pass to mpy-cross") - cmd_parser.add_argument("N", nargs=1, help="N parameter (approximate target CPU frequency)") + cmd_parser.add_argument( + "N", nargs=1, help="N parameter (approximate target CPU frequency in MHz)" + ) cmd_parser.add_argument("M", nargs=1, help="M parameter (approximate target heap in kbytes)") cmd_parser.add_argument("files", nargs="*", help="input test files") args = cmd_parser.parse_args() @@ -283,6 +288,8 @@ def main(): target.enter_raw_repl() else: target = [MICROPYTHON, "-X", "emit=" + args.emit] + if args.heapsize is not None: + target.extend(["-X", "heapsize=" + args.heapsize]) if len(args.files) == 0: tests_skip = ("benchrun.py",) diff --git a/tests/run-tests.py b/tests/run-tests.py index 9f55f0ebab..e2968d2d54 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -13,6 +13,9 @@ from multiprocessing.pool import ThreadPool import threading import tempfile +# Maximum time to run a PC-based test, in seconds. +TEST_TIMEOUT = 30 + # See stackoverflow.com/questions/2632199: __file__ nor sys.argv[0] # are guaranteed to always work, this one should though. BASEPATH = os.path.dirname(os.path.abspath(inspect.getsourcefile(lambda: None))) @@ -27,17 +30,23 @@ def base_path(*p): # to the correct executable. if os.name == "nt": CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", base_path("../ports/windows/micropython.exe")) + MICROPYTHON = os.getenv( + "MICROPY_MICROPYTHON", base_path("../ports/windows/build-standard/micropython.exe") + ) + # mpy-cross is only needed if --via-mpy command-line arg is passed + MPYCROSS = os.getenv("MICROPY_MPYCROSS", base_path("../mpy-cross/build/mpy-cross.exe")) else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", base_path("../ports/unix/micropython")) + MICROPYTHON = os.getenv( + "MICROPY_MICROPYTHON", base_path("../ports/unix/build-standard/micropython") + ) + # mpy-cross is only needed if --via-mpy command-line arg is passed + MPYCROSS = os.getenv("MICROPY_MPYCROSS", base_path("../mpy-cross/build/mpy-cross")) # Use CPython options to not save .pyc files, to only access the core standard library # (not site packages which may clash with u-module names), and improve start up time. -CPYTHON3_CMD = [CPYTHON3, "-Wignore", "-BS"] +CPYTHON3_CMD = [CPYTHON3, "-BS"] -# mpy-cross is only needed if --via-mpy command-line arg is passed -MPYCROSS = os.getenv("MICROPY_MPYCROSS", base_path("../mpy-cross/mpy-cross")) # For diff'ing test output DIFF = os.getenv("MICROPY_DIFF", "diff -u") @@ -45,6 +54,37 @@ DIFF = os.getenv("MICROPY_DIFF", "diff -u") # Set PYTHONIOENCODING so that CPython will use utf-8 on systems which set another encoding in the locale os.environ["PYTHONIOENCODING"] = "utf-8" +# Code to allow a target MicroPython to import an .mpy from RAM +injected_import_hook_code = """\ +import usys, uos, uio +class __File(uio.IOBase): + def __init__(self): + self.off = 0 + def ioctl(self, request, arg): + return 0 + def readinto(self, buf): + buf[:] = memoryview(__buf)[self.off:self.off + len(buf)] + self.off += len(buf) + return len(buf) +class __FS: + def mount(self, readonly, mkfs): + pass + def umount(self): + pass + def chdir(self, path): + pass + def stat(self, path): + if path == '__injected_test.mpy': + return tuple(0 for _ in range(10)) + else: + raise OSError(-2) # ENOENT + def open(self, path, mode): + return __File() +uos.mount(__FS(), '/__vfstest') +uos.chdir('/__vfstest') +__import__('__injected_test') +""" + def rm_f(fname): if os.path.exists(fname): @@ -71,6 +111,68 @@ def convert_regex_escapes(line): return bytes("".join(cs), "utf8") +def prepare_script_for_target(args, *, script_filename=None, script_text=None, force_plain=False): + if force_plain or (not args.via_mpy and args.emit == "bytecode"): + if script_filename is not None: + with open(script_filename, "rb") as f: + script_text = f.read() + elif args.via_mpy: + tempname = tempfile.mktemp(dir="") + mpy_filename = tempname + ".mpy" + + if script_filename is None: + script_filename = tempname + ".py" + cleanup_script_filename = True + with open(script_filename, "wb") as f: + f.write(script_text) + else: + cleanup_script_filename = False + + try: + subprocess.check_output( + [MPYCROSS] + + args.mpy_cross_flags.split() + + ["-o", mpy_filename, "-X", "emit=" + args.emit, script_filename], + stderr=subprocess.STDOUT, + ) + except subprocess.CalledProcessError as er: + return True, b"mpy-cross crash\n" + er.output + + with open(mpy_filename, "rb") as f: + script_text = b"__buf=" + bytes(repr(f.read()), "ascii") + b"\n" + + rm_f(mpy_filename) + if cleanup_script_filename: + rm_f(script_filename) + + script_text += bytes(injected_import_hook_code, "ascii") + else: + print("error: using emit={} must go via .mpy".format(args.emit)) + sys.exit(1) + + return False, script_text + + +def run_script_on_remote_target(pyb, args, test_file, is_special): + had_crash, script = prepare_script_for_target( + args, script_filename=test_file, force_plain=is_special + ) + if had_crash: + return True, script + + try: + had_crash = False + pyb.enter_raw_repl() + output_mupy = pyb.exec_(script) + except pyboard.PyboardError as e: + had_crash = True + if not is_special and e.args[0] == "exception": + output_mupy = e.args[1] + e.args[2] + b"CRASH" + else: + output_mupy = bytes(e.args[0], "ascii") + b"\nCRASH" + return had_crash, output_mupy + + def run_micropython(pyb, args, test_file, is_special=False): special_tests = ( "micropython/meminfo.py", @@ -109,33 +211,29 @@ def run_micropython(pyb, args, test_file, is_special=False): return b"SKIP\n" import select + # Even though these might have the pty module, it's unlikely to function. + if sys.platform in ["win32", "msys", "cygwin"]: + return b"SKIP\n" + def get(required=False): rv = b"" while True: - ready = select.select([emulator], [], [emulator], 0.02) - if ready[0] == [emulator]: - rv += os.read(emulator, 1024) + ready = select.select([master], [], [], 0.02) + if ready[0] == [master]: + rv += os.read(master, 1024) else: if not required or rv: return rv def send_get(what): - os.write(emulator, what) + os.write(master, what) return get() with open(test_file, "rb") as f: # instead of: output_mupy = subprocess.check_output(args, stdin=f) - # openpty returns two read/write file descriptors. The first one is - # used by the program which provides the virtual - # terminal service, and the second one is used by the - # subprogram which requires a tty to work. - emulator, subterminal = pty.openpty() + master, slave = pty.openpty() p = subprocess.Popen( - args, - stdin=subterminal, - stdout=subterminal, - stderr=subprocess.STDOUT, - bufsize=0, + args, stdin=slave, stdout=slave, stderr=subprocess.STDOUT, bufsize=0 ) banner = get(True) output_mupy = banner + b"".join(send_get(line) for line in f) @@ -150,15 +248,14 @@ def run_micropython(pyb, args, test_file, is_special=False): p.kill() except ProcessLookupError: pass - os.close(subterminal) - os.close(emulator) + os.close(master) + os.close(slave) else: output_mupy = subprocess.check_output( args + [test_file], stderr=subprocess.STDOUT ) - - except subprocess.CalledProcessError as error: - return error.output + b"CRASH" + except subprocess.CalledProcessError: + return b"CRASH" else: # a standard test run on PC @@ -167,6 +264,8 @@ def run_micropython(pyb, args, test_file, is_special=False): cmdlist = [MICROPYTHON, "-X", "emit=" + args.emit] if args.heapsize is not None: cmdlist.extend(["-X", "heapsize=" + args.heapsize]) + if sys.platform == "darwin": + cmdlist.extend(["-X", "realtime"]) # if running via .mpy, first compile the .py file if args.via_mpy: @@ -183,20 +282,15 @@ def run_micropython(pyb, args, test_file, is_special=False): # run the actual test try: - result = subprocess.run( - cmdlist, - stderr=subprocess.STDOUT, - stdout=subprocess.PIPE, - check=True, - timeout=10, + output_mupy = subprocess.check_output( + cmdlist, stderr=subprocess.STDOUT, timeout=TEST_TIMEOUT ) - output_mupy = result.stdout - except subprocess.TimeoutExpired as er: - had_crash = True - output_mupy = (er.output or b"") + b"TIMEOUT" except subprocess.CalledProcessError as er: had_crash = True output_mupy = er.output + b"CRASH" + except subprocess.TimeoutExpired as er: + had_crash = True + output_mupy = (er.output or b"") + b"TIMEOUT" # clean up if we had an intermediate .mpy file if args.via_mpy: @@ -213,6 +307,10 @@ def run_micropython(pyb, args, test_file, is_special=False): if had_crash or output_mupy in (b"SKIP\n", b"CRASH"): return output_mupy + # skipped special tests will output "SKIP" surrounded by other interpreter debug output + if is_special and not had_crash and b"\nSKIP\n" in output_mupy: + return b"SKIP\n" + if is_special or test_file in special_tests: # convert parts of the output that are not stable across runs with open(test_file + ".exp", "rb") as f: @@ -428,18 +526,23 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): if upy_float_precision < 64: skip_tests.add("float/float_divmod.py") # tested by float/float_divmod_relaxed.py instead skip_tests.add("float/float2int_doubleprec_intbig.py") + skip_tests.add("float/float_format_ints_doubleprec.py") skip_tests.add("float/float_parse_doubleprec.py") if not has_complex: skip_tests.add("float/complex1.py") skip_tests.add("float/complex1_intbig.py") + skip_tests.add("float/complex_reverse_op.py") skip_tests.add("float/complex_special_methods.py") skip_tests.add("float/int_big_float.py") skip_tests.add("float/true_value.py") skip_tests.add("float/types.py") + skip_tests.add("float/complex_dunder.py") if not has_coverage: skip_tests.add("cmdline/cmd_parsetree.py") + skip_tests.add("cmdline/repl_sys_ps1_ps2.py") + skip_tests.add("extmod/ussl_poll.py") # Some tests shouldn't be run on a PC if args.target == "unix": @@ -514,6 +617,7 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): skip_tests.add("basics/del_deref.py") # requires checking for unbound local skip_tests.add("basics/del_local.py") # requires checking for unbound local skip_tests.add("basics/exception_chain.py") # raise from is not supported + skip_tests.add("basics/fun_name.py") # requires proper names for native functions skip_tests.add("basics/scope_implicit.py") # requires checking for unbound local skip_tests.add("basics/sys_tracebacklimit.py") # requires traceback info skip_tests.add("basics/try_finally_return2.py") # requires raise_varargs @@ -608,17 +712,16 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): with open(test_file_expected, "rb") as f: output_expected = f.read() else: - e = {"PYTHONPATH": os.getcwd(), "PATH": os.environ["PATH"], "LANG": "en_US.UTF-8"} + # CIRCUITPY: set language & make sure testlib is available for `skip_ok`. + e = {"PYTHONPATH": "testlib", "PATH": os.environ["PATH"], "LANG": "en_US.UTF-8"} # run CPython to work out expected output try: - output_expected = subprocess.check_output( - CPYTHON3_CMD + [test_file], env=e, stderr=subprocess.STDOUT - ) + output_expected = subprocess.check_output(CPYTHON3_CMD + [test_file], env=e) if args.write_exp: with open(test_file_expected, "wb") as f: f.write(output_expected) - except subprocess.CalledProcessError as error: - output_expected = error.output + b"CPYTHON3 CRASH" + except subprocess.CalledProcessError: + output_expected = b"CPYTHON3 CRASH" # canonical form for all host platforms is to use \n for end-of-line output_expected = output_expected.replace(b"\r\n", b"\n") @@ -828,8 +931,15 @@ the last matching regex is used: "renesas-ra", "rp2", ) - if args.target in LOCAL_TARGETS or args.list_tests: + if args.list_tests: pyb = None + elif args.target in LOCAL_TARGETS: + pyb = None + if not args.mpy_cross_flags: + if args.target == "unix": + args.mpy_cross_flags = "-march=host" + elif args.target == "qemu-arm": + args.mpy_cross_flags = "-march=armv7m" elif args.target in EXTERNAL_TARGETS: global pyboard sys.path.append(base_path("../tools")) @@ -856,7 +966,6 @@ the last matching regex is used: if args.test_dirs is None: test_dirs = ( "basics", - "circuitpython", "micropython", "misc", "extmod", @@ -883,7 +992,6 @@ the last matching regex is used: "unicode", "unix", "cmdline", - "../extmod/ulab/tests", ) elif args.target == "qemu-arm": if not args.write_exp: diff --git a/tests/skip_if.py b/tests/testlib/skip_if.py similarity index 100% rename from tests/skip_if.py rename to tests/testlib/skip_if.py diff --git a/tests/unicode/data/utf-8_invalid.txt b/tests/unicode/data/utf-8_invalid.txt new file mode 100644 index 0000000000..50020482bf --- /dev/null +++ b/tests/unicode/data/utf-8_invalid.txt @@ -0,0 +1 @@ +aaÿbb diff --git a/tests/unicode/file_invalid.py b/tests/unicode/file_invalid.py new file mode 100644 index 0000000000..3f7f184062 --- /dev/null +++ b/tests/unicode/file_invalid.py @@ -0,0 +1,5 @@ +try: + f = open("unicode/data/utf-8_invalid.txt", encoding="utf-8") + f.read() +except UnicodeError: + print("UnicodeError") diff --git a/tests/unicode/unicode_ure.py b/tests/unicode/unicode_ure.py new file mode 100644 index 0000000000..5a5dc60054 --- /dev/null +++ b/tests/unicode/unicode_ure.py @@ -0,0 +1,32 @@ +# test match.span() for unicode strings + +try: + import ure as re +except ImportError: + try: + import re + except ImportError: + print("SKIP") + raise SystemExit + +try: + m = re.match(".", "a") + m.span +except AttributeError: + print("SKIP") + raise SystemExit + + +def print_spans(match): + print("----") + try: + i = 0 + while True: + print(match.span(i), match.start(i), match.end(i)) + i += 1 + except IndexError: + pass + + +m = re.match(r"([0-9]*)(([a-z]*)([0-9]*))", "1234\u2764567") +print_spans(m) diff --git a/tests/unix/extra_coverage.py b/tests/unix/extra_coverage.py index 32b8d90892..9d9ccb75c1 100644 --- a/tests/unix/extra_coverage.py +++ b/tests/unix/extra_coverage.py @@ -49,11 +49,6 @@ print(buf.write(bytearray(16))) # function defined in C++ code print("cpp", extra_cpp_coverage()) -# test user C module -import cexample - -print(cexample.add_ints(3, 2)) - # test user C module mixed with C++ code import cppexample @@ -96,3 +91,8 @@ import frzmpy3 from frzqstr import returns_NULL print(returns_NULL()) + +# test for freeze_mpy +import frozentest + +print(frozentest.__file__) diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index f91b64db3e..bbea65fa1f 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -17,6 +17,8 @@ abc # GC 0x0 0x0 +# GC part 2 +pass # tracked allocation m_tracked_head = 0x0 0 1 @@ -54,23 +56,20 @@ audiomixer binascii bitmaptools cexample cmath collections cppexample displayio errno gc hashlib heapq io json math os -qrio rainbowio random re -select struct synthio sys -termios time traceback uctypes -ulab ulab.numpy ulab.numpy.fft -ulab.numpy.linalg ulab.scipy -ulab.scipy.linalg ulab.scipy.optimize -ulab.scipy.signal ulab.scipy.special -ulab.utils zlib +platform qrio rainbowio random +re select struct synthio +sys time traceback uctypes +ulab zlib me rainbowio random argv atexit byteorder exc_info -exit getsizeof implementation maxsize -modules path platform print_exception -ps1 ps2 stderr stdin -stdout tracebacklimit version version_info +executable exit getsizeof implementation +maxsize modules path platform +print_exception ps1 ps2 +stderr stdin stdout tracebacklimit +version version_info ementation # attrtuple (start=1, stop=2, step=3) @@ -183,7 +182,6 @@ OSError None None cpp None -5 (3, 'hellocpp') frzstr1 frzstr1.py @@ -204,3 +202,13 @@ X '\x1b' b'\x00\xff' NULL +uPy +a long string that is not interned +a string that has unicode αβγ chars +b'bytes 1234\x01' +123456789 +0 +1 +2 +3 +frozentest.py diff --git a/tests/unix/mod_os.py b/tests/unix/mod_os.py new file mode 100644 index 0000000000..17554d9375 --- /dev/null +++ b/tests/unix/mod_os.py @@ -0,0 +1,21 @@ +# This module is not entirely compatible with CPython +import os + + +os.putenv("TEST_VARIABLE", "TEST_VALUE") + +print(os.getenv("TEST_VARIABLE")) +print(os.getenv("TEST_VARIABLE", "TEST_DEFAULT_VALUE")) + +os.unsetenv("TEST_VARIABLE") + +print(os.getenv("TEST_VARIABLE")) +print(os.getenv("TEST_VARIABLE", "TEST_DEFAULT_VALUE")) + +print(os.system("true")) + +rand = os.urandom(4) +print(type(rand) is bytes, len(rand)) + +os.errno(2) +print(os.errno()) diff --git a/tests/unix/mod_os.py.exp b/tests/unix/mod_os.py.exp new file mode 100644 index 0000000000..465163085b --- /dev/null +++ b/tests/unix/mod_os.py.exp @@ -0,0 +1,7 @@ +TEST_VALUE +TEST_VALUE +None +TEST_DEFAULT_VALUE +0 +True 4 +2 diff --git a/tools/autobuild/build-boards.sh b/tools/autobuild/build-boards.sh index 9caadc1b07..0a0e127f2e 100755 --- a/tools/autobuild/build-boards.sh +++ b/tools/autobuild/build-boards.sh @@ -83,12 +83,7 @@ function build_esp32_boards { if idf.py --version | grep -q v4.2; then if [ $mcu = esp32 ]; then # build standard esp32-based boards with IDF v4.2 - if echo $board_json | grep -q GENERIC; then - # traditionally, GENERIC and GENERIC_SPIRAM boards used manifest_release.py - MICROPY_AUTOBUILD_MAKE="$MICROPY_AUTOBUILD_MAKE FROZEN_MANIFEST=$(pwd)/boards/manifest_release.py" build_board $board_json $fw_tag $dest_dir bin elf map - else - build_board $board_json $fw_tag $dest_dir bin elf map - fi + build_board $board_json $fw_tag $dest_dir bin elf map fi else if [ $mcu != esp32 ]; then @@ -103,6 +98,10 @@ function build_mimxrt_boards { build_boards modmimxrt.c $1 $2 bin hex } +function build_nrf_boards { + build_boards nrfx_glue.h $1 $2 bin hex uf2 +} + function build_renesas_ra_boards { build_boards ra_it.c $1 $2 hex } diff --git a/tools/ci.sh b/tools/ci.sh index 72e779c499..8127a5134c 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -18,7 +18,6 @@ function ci_gcc_arm_setup { # code formatting function ci_code_formatting_setup { - sudo apt-add-repository --yes --update ppa:pybricks/ppa sudo apt-get install uncrustify pip3 install black uncrustify --version @@ -50,6 +49,10 @@ function ci_code_size_setup { } function ci_code_size_build { + # check the following ports for the change in their code size + PORTS_TO_CHECK=bmusp + SUBMODULES="lib/berkeley-db-1.xx lib/mbedtls lib/micropython-lib lib/pico-sdk lib/stm32lib lib/tinyusb" + # starts off at either the ref/pull/N/merge FETCH_HEAD, or the current branch HEAD git checkout -b pull_request # save the current location git remote add upstream https://github.com/micropython/micropython.git @@ -57,14 +60,16 @@ function ci_code_size_build { # build reference, save to size0 # ignore any errors with this build, in case master is failing git checkout `git merge-base --fork-point upstream/master pull_request` + git submodule update --init $SUBMODULES git show -s - tools/metrics.py clean bm - tools/metrics.py build bm | tee ~/size0 || true + tools/metrics.py clean $PORTS_TO_CHECK + tools/metrics.py build $PORTS_TO_CHECK | tee ~/size0 || true # build PR/branch, save to size1 git checkout pull_request + git submodule update --init $SUBMODULES git log upstream/master..HEAD - tools/metrics.py clean bm - tools/metrics.py build bm | tee ~/size1 + tools/metrics.py clean $PORTS_TO_CHECK + tools/metrics.py build $PORTS_TO_CHECK | tee ~/size1 } ######################################################################################## @@ -76,8 +81,8 @@ function ci_mpy_format_setup { function ci_mpy_format_test { # Test mpy-tool.py dump feature on bytecode - python2 ./tools/mpy-tool.py -xd ports/minimal/frozentest.mpy - python3 ./tools/mpy-tool.py -xd ports/minimal/frozentest.mpy + python2 ./tools/mpy-tool.py -xd tests/frozen/frozentest.mpy + python3 ./tools/mpy-tool.py -xd tests/frozen/frozentest.mpy # Test mpy-tool.py dump feature on native code make -C examples/natmod/features1 @@ -173,21 +178,21 @@ function ci_esp8266_build { } ######################################################################################## -# ports/javascript +# ports/webassembly -function ci_javascript_setup { +function ci_webassembly_setup { git clone https://github.com/emscripten-core/emsdk.git (cd emsdk && ./emsdk install latest && ./emsdk activate latest) } -function ci_javascript_build { +function ci_webassembly_build { source emsdk/emsdk_env.sh - make ${MAKEOPTS} -C ports/javascript + make ${MAKEOPTS} -C ports/webassembly } -function ci_javascript_run_tests { +function ci_webassembly_run_tests { # This port is very slow at running, so only run a few of the tests. - (cd tests && MICROPY_MICROPYTHON=../ports/javascript/node_run.sh ./run-tests.py -j1 basics/builtin_*.py) + (cd tests && MICROPY_MICROPYTHON=../ports/webassembly/node_run.sh ./run-tests.py -j1 basics/builtin_*.py) } ######################################################################################## @@ -199,8 +204,9 @@ function ci_mimxrt_setup { function ci_mimxrt_build { make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/mimxrt submodules + make ${MAKEOPTS} -C ports/mimxrt BOARD=MIMXRT1020_EVK submodules make ${MAKEOPTS} -C ports/mimxrt BOARD=MIMXRT1020_EVK + make ${MAKEOPTS} -C ports/mimxrt BOARD=TEENSY40 submodules make ${MAKEOPTS} -C ports/mimxrt BOARD=TEENSY40 } @@ -246,8 +252,10 @@ function ci_qemu_arm_setup { function ci_qemu_arm_build { make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/qemu-arm submodules make ${MAKEOPTS} -C ports/qemu-arm CFLAGS_EXTRA=-DMP_ENDIANNESS_BIG=1 make ${MAKEOPTS} -C ports/qemu-arm clean + make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test submodules make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test test make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test clean make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test BOARD=sabrelite test @@ -282,6 +290,10 @@ function ci_rp2_build { make ${MAKEOPTS} -C ports/rp2 USER_C_MODULES=../../examples/usercmodule/micropython.cmake make ${MAKEOPTS} -C ports/rp2 BOARD=W5100S_EVB_PICO submodules make ${MAKEOPTS} -C ports/rp2 BOARD=W5100S_EVB_PICO + + # Test building ninaw10 driver and NIC interface. + make ${MAKEOPTS} -C ports/rp2 BOARD=ARDUINO_NANO_RP2040_CONNECT submodules + make ${MAKEOPTS} -C ports/rp2 BOARD=ARDUINO_NANO_RP2040_CONNECT } ######################################################################################## @@ -292,6 +304,7 @@ function ci_samd_setup { } function ci_samd_build { + make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/samd submodules make ${MAKEOPTS} -C ports/samd } @@ -307,10 +320,11 @@ function ci_stm32_setup { function ci_stm32_pyb_build { make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/stm32 submodules + make ${MAKEOPTS} -C ports/stm32 MICROPY_PY_NETWORK_WIZNET5K=5200 submodules + make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 submodules git submodule update --init lib/btstack git submodule update --init lib/mynewt-nimble - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_NETWORK_WIZNET5K=5200 MICROPY_PY_CC3K=1 USER_C_MODULES=../../examples/usercmodule + make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_NETWORK_WIZNET5K=5200 USER_C_MODULES=../../examples/usercmodule make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF6 NANBOX=1 MICROPY_BLUETOOTH_NIMBLE=0 MICROPY_BLUETOOTH_BTSTACK=1 make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBV10 CFLAGS_EXTRA='-DMBOOT_FSLOAD=1 -DMBOOT_VFS_LFS2=1' @@ -324,7 +338,7 @@ function ci_stm32_pyb_build { function ci_stm32_nucleo_build { make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/stm32 submodules + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_H743ZI submodules git submodule update --init lib/mynewt-nimble # Test building various MCU families, some with additional options. @@ -355,6 +369,8 @@ function ci_teensy_setup { } function ci_teensy_build { + make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/teensy submodules make ${MAKEOPTS} -C ports/teensy } @@ -406,14 +422,10 @@ function ci_unix_run_tests_helper { function ci_unix_run_tests_full_helper { variant=$1 shift - if [ $variant = standard ]; then - micropython=micropython - else - micropython=micropython-$variant - fi + micropython=../ports/unix/build-$variant/micropython make -C ports/unix VARIANT=$variant "$@" test_full - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/$micropython ./run-multitests.py multi_net/*.py) - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/$micropython ./run-perfbench.py 1000 1000) + (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-multitests.py multi_net/*.py) + (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-perfbench.py 1000 1000) } function ci_native_mpy_modules_build { @@ -442,7 +454,7 @@ function ci_unix_minimal_build { } function ci_unix_minimal_run_tests { - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-minimal ./run-tests.py -e exception_chain -e self_type_check -e subclass_native_init -d basics) + (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/build-minimal/micropython ./run-tests.py -e exception_chain -e self_type_check -e subclass_native_init -d basics) } function ci_unix_standard_build { @@ -454,14 +466,6 @@ function ci_unix_standard_run_tests { ci_unix_run_tests_full_helper standard } -function ci_unix_dev_build { - ci_unix_build_helper VARIANT=dev -} - -function ci_unix_dev_run_tests { - ci_unix_run_tests_helper VARIANT=dev -} - function ci_unix_coverage_setup { sudo pip3 install setuptools sudo pip3 install pyelftools @@ -489,21 +493,21 @@ function ci_unix_coverage_run_mpy_merge_tests { test=$(basename $inpy .py) echo $test outmpy=$outdir/$test.mpy - $mptop/mpy-cross/mpy-cross -o $outmpy $inpy - (cd $outdir && $mptop/ports/unix/micropython-coverage -m $test >> out-individual) + $mptop/mpy-cross/build/mpy-cross -o $outmpy $inpy + (cd $outdir && $mptop/ports/unix/build-coverage/micropython -m $test >> out-individual) allmpy+=($outmpy) done # Merge all the tests into one .mpy file, and then execute it. python3 $mptop/tools/mpy-tool.py --merge -o $outdir/merged.mpy ${allmpy[@]} - (cd $outdir && $mptop/ports/unix/micropython-coverage -m merged > out-merged) + (cd $outdir && $mptop/ports/unix/build-coverage/micropython -m merged > out-merged) # Make sure the outputs match. diff $outdir/out-individual $outdir/out-merged && /bin/rm -rf $outdir } function ci_unix_coverage_run_native_mpy_tests { - MICROPYPATH=examples/natmod/features2 ./ports/unix/micropython-coverage -m features2 + MICROPYPATH=examples/natmod/features2 ./ports/unix/build-coverage/micropython -m features2 (cd tests && ./run-natmodtests.py "$@" extmod/{btree*,framebuf*,uheapq*,urandom*,ure*,uzlib*}.py) } @@ -514,7 +518,6 @@ function ci_unix_32bit_setup { sudo pip3 install setuptools sudo pip3 install pyelftools gcc --version - python2 --version python3 --version } @@ -578,6 +581,7 @@ function ci_unix_float_clang_run_tests { function ci_unix_settrace_build { make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/unix submodules make ${MAKEOPTS} -C ports/unix "${CI_UNIX_OPTS_SYS_SETTRACE[@]}" } @@ -587,6 +591,7 @@ function ci_unix_settrace_run_tests { function ci_unix_settrace_stackless_build { make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/unix submodules make ${MAKEOPTS} -C ports/unix "${CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS[@]}" } @@ -595,13 +600,14 @@ function ci_unix_settrace_stackless_run_tests { } function ci_unix_macos_build { + # Install pkg-config to configure libffi paths. + brew install pkg-config + make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/unix submodules #make ${MAKEOPTS} -C ports/unix deplibs make ${MAKEOPTS} -C ports/unix # check for additional compiler errors/warnings - make ${MAKEOPTS} -C ports/unix VARIANT=dev submodules - make ${MAKEOPTS} -C ports/unix VARIANT=dev make ${MAKEOPTS} -C ports/unix VARIANT=coverage submodules make ${MAKEOPTS} -C ports/unix VARIANT=coverage } @@ -610,7 +616,7 @@ function ci_unix_macos_run_tests { # Issues with macOS tests: # - import_pkg7 has a problem with relative imports # - urandom_basic has a problem with getrandbits(0) - (cd tests && ./run-tests.py --exclude 'import_pkg7.py' --exclude 'urandom_basic.py') + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-standard/micropython ./run-tests.py --exclude 'import_pkg7.py' --exclude 'urandom_basic.py') } function ci_unix_qemu_mips_setup { @@ -629,8 +635,8 @@ function ci_unix_qemu_mips_run_tests { # Issues with MIPS tests: # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) # - ffi tests do not work - file ./ports/unix/micropython-coverage - (cd tests && MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests.py --exclude 'vfs_posix.py' --exclude 'ffi_(callback|float|float2).py') + file ./ports/unix/build-coverage/micropython + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.*\.py' --exclude 'ffi_(callback|float|float2).py') } function ci_unix_qemu_arm_setup { @@ -649,8 +655,8 @@ function ci_unix_qemu_arm_run_tests { # Issues with ARM tests: # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) export QEMU_LD_PREFIX=/usr/arm-linux-gnueabi - file ./ports/unix/micropython-coverage - (cd tests && MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests.py --exclude 'vfs_posix.py') + file ./ports/unix/build-coverage/micropython + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.*\.py') } ######################################################################################## @@ -662,6 +668,7 @@ function ci_windows_setup { function ci_windows_build { make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/windows submodules make ${MAKEOPTS} -C ports/windows CROSS_COMPILE=i686-w64-mingw32- } @@ -670,7 +677,7 @@ function ci_windows_build { ZEPHYR_DOCKER_VERSION=v0.21.0 ZEPHYR_SDK_VERSION=0.13.2 -ZEPHYR_VERSION=v3.0.0 +ZEPHYR_VERSION=v3.1.0 function ci_zephyr_setup { docker pull zephyrprojectrtos/ci:${ZEPHYR_DOCKER_VERSION} @@ -692,7 +699,6 @@ function ci_zephyr_install { function ci_zephyr_build { docker exec zephyr-ci west build -p auto -b qemu_x86 -- -DCONF_FILE=prj_minimal.conf - docker exec zephyr-ci west build -p auto -b qemu_x86 docker exec zephyr-ci west build -p auto -b frdm_k64f docker exec zephyr-ci west build -p auto -b mimxrt1050_evk docker exec zephyr-ci west build -p auto -b nucleo_wb55rg # for bluetooth diff --git a/tools/codestats.sh b/tools/codestats.sh index c0dd747dc6..b0780f64db 100755 --- a/tools/codestats.sh +++ b/tools/codestats.sh @@ -28,7 +28,7 @@ AWK=awk MAKE="make -j2" # these are the binaries that are built; some have 2 or 3 depending on version -bin_unix=ports/unix/micropython +bin_unix=ports/unix/build-standard/micropython bin_stm32=ports/stm32/build-PYBV10/firmware.elf bin_barearm_1=ports/bare-arm/build/flash.elf bin_barearm_2=ports/bare-arm/build/firmware.elf diff --git a/tools/gendoc.py b/tools/gendoc.py deleted file mode 100644 index e7eb011b7c..0000000000 --- a/tools/gendoc.py +++ /dev/null @@ -1,556 +0,0 @@ -# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) -# -# SPDX-License-Identifier: MIT - -""" -Generate documentation for pyboard API from C files. -""" - -import os -import argparse -import re -import markdown - - -# given a list of (name,regex) pairs, find the first one that matches the given line -def re_match_first(regexs, line): - for name, regex in regexs: - match = re.match(regex, line) - if match: - return name, match - return None, None - - -def makedirs(d): - if not os.path.isdir(d): - os.makedirs(d) - - -class Lexer: - class LexerError(Exception): - pass - - class EOF(Exception): - pass - - class Break(Exception): - pass - - def __init__(self, file): - self.filename = file - with open(file, "rt") as f: - line_num = 0 - lines = [] - for line in f: - line_num += 1 - line = line.strip() - if line == "///": - lines.append((line_num, "")) - elif line.startswith("/// "): - lines.append((line_num, line[4:])) - elif len(lines) > 0 and lines[-1][1] is not None: - lines.append((line_num, None)) - if len(lines) > 0 and lines[-1][1] is not None: - lines.append((line_num, None)) - self.cur_line = 0 - self.lines = lines - - def opt_break(self): - if len(self.lines) > 0 and self.lines[0][1] is None: - self.lines.pop(0) - - def next(self): - if len(self.lines) == 0: - raise Lexer.EOF - else: - l = self.lines.pop(0) - self.cur_line = l[0] - if l[1] is None: - raise Lexer.Break - else: - return l[1] - - def error(self, msg): - print("({}:{}) {}".format(self.filename, self.cur_line, msg)) - raise Lexer.LexerError - - -class MarkdownWriter: - def __init__(self): - pass - - def start(self): - self.lines = [] - - def end(self): - return "\n".join(self.lines) - - def heading(self, level, text): - if len(self.lines) > 0: - self.lines.append("") - self.lines.append(level * "#" + " " + text) - self.lines.append("") - - def para(self, text): - if len(self.lines) > 0 and self.lines[-1] != "": - self.lines.append("") - if isinstance(text, list): - self.lines.extend(text) - elif isinstance(text, str): - self.lines.append(text) - else: - assert False - self.lines.append("") - - def single_line(self, text): - self.lines.append(text) - - def module(self, name, short_descr, descr): - self.heading(1, "module {}".format(name)) - self.para(descr) - - def function(self, ctx, name, args, descr): - proto = "{}.{}{}".format(ctx, self.name, self.args) - self.heading(3, "`" + proto + "`") - self.para(descr) - - def method(self, ctx, name, args, descr): - if name == "\\constructor": - proto = "{}{}".format(ctx, args) - elif name == "\\call": - proto = "{}{}".format(ctx, args) - else: - proto = "{}.{}{}".format(ctx, name, args) - self.heading(3, "`" + proto + "`") - self.para(descr) - - def constant(self, ctx, name, descr): - self.single_line("`{}.{}` - {}".format(ctx, name, descr)) - - -class ReStructuredTextWriter: - head_chars = {1: "=", 2: "-", 3: "."} - - def __init__(self): - pass - - def start(self): - self.lines = [] - - def end(self): - return "\n".join(self.lines) - - def _convert(self, text): - return text.replace("`", "``").replace("*", "\\*") - - def heading(self, level, text, convert=True): - if len(self.lines) > 0: - self.lines.append("") - if convert: - text = self._convert(text) - self.lines.append(text) - self.lines.append(len(text) * self.head_chars[level]) - self.lines.append("") - - def para(self, text, indent=""): - if len(self.lines) > 0 and self.lines[-1] != "": - self.lines.append("") - if isinstance(text, list): - for t in text: - self.lines.append(indent + self._convert(t)) - elif isinstance(text, str): - self.lines.append(indent + self._convert(text)) - else: - assert False - self.lines.append("") - - def single_line(self, text): - self.lines.append(self._convert(text)) - - def module(self, name, short_descr, descr): - self.heading(1, ":mod:`{}` --- {}".format(name, self._convert(short_descr)), convert=False) - self.lines.append(".. module:: {}".format(name)) - self.lines.append(" :synopsis: {}".format(short_descr)) - self.para(descr) - - def function(self, ctx, name, args, descr): - args = self._convert(args) - self.lines.append(".. function:: " + name + args) - self.para(descr, indent=" ") - - def method(self, ctx, name, args, descr): - args = self._convert(args) - if name == "\\constructor": - self.lines.append(".. class:: " + ctx + args) - elif name == "\\call": - self.lines.append(".. method:: " + ctx + args) - else: - self.lines.append(".. method:: " + ctx + "." + name + args) - self.para(descr, indent=" ") - - def constant(self, ctx, name, descr): - self.lines.append(".. data:: " + name) - self.para(descr, indent=" ") - - -class DocValidateError(Exception): - pass - - -class DocItem: - def __init__(self): - self.doc = [] - - def add_doc(self, lex): - try: - while True: - line = lex.next() - if len(line) > 0 or len(self.doc) > 0: - self.doc.append(line) - except Lexer.Break: - pass - - def dump(self, writer): - writer.para(self.doc) - - -class DocConstant(DocItem): - def __init__(self, name, descr): - super().__init__() - self.name = name - self.descr = descr - - def dump(self, ctx, writer): - writer.constant(ctx, self.name, self.descr) - - -class DocFunction(DocItem): - def __init__(self, name, args): - super().__init__() - self.name = name - self.args = args - - def dump(self, ctx, writer): - writer.function(ctx, self.name, self.args, self.doc) - - -class DocMethod(DocItem): - def __init__(self, name, args): - super().__init__() - self.name = name - self.args = args - - def dump(self, ctx, writer): - writer.method(ctx, self.name, self.args, self.doc) - - -class DocClass(DocItem): - def __init__(self, name, descr): - super().__init__() - self.name = name - self.descr = descr - self.constructors = {} - self.classmethods = {} - self.methods = {} - self.constants = {} - - def process_classmethod(self, lex, d): - name = d["id"] - if name == "\\constructor": - dict_ = self.constructors - else: - dict_ = self.classmethods - if name in dict_: - lex.error("multiple definition of method '{}'".format(name)) - method = dict_[name] = DocMethod(name, d["args"]) - method.add_doc(lex) - - def process_method(self, lex, d): - name = d["id"] - dict_ = self.methods - if name in dict_: - lex.error("multiple definition of method '{}'".format(name)) - method = dict_[name] = DocMethod(name, d["args"]) - method.add_doc(lex) - - def process_constant(self, lex, d): - name = d["id"] - if name in self.constants: - lex.error("multiple definition of constant '{}'".format(name)) - self.constants[name] = DocConstant(name, d["descr"]) - lex.opt_break() - - def dump(self, writer): - writer.heading(1, "class {}".format(self.name)) - super().dump(writer) - if len(self.constructors) > 0: - writer.heading(2, "Constructors") - for f in sorted(self.constructors.values(), key=lambda x: x.name): - f.dump(self.name, writer) - if len(self.classmethods) > 0: - writer.heading(2, "Class methods") - for f in sorted(self.classmethods.values(), key=lambda x: x.name): - f.dump(self.name, writer) - if len(self.methods) > 0: - writer.heading(2, "Methods") - for f in sorted(self.methods.values(), key=lambda x: x.name): - f.dump(self.name.lower(), writer) - if len(self.constants) > 0: - writer.heading(2, "Constants") - for c in sorted(self.constants.values(), key=lambda x: x.name): - c.dump(self.name, writer) - - -class DocModule(DocItem): - def __init__(self, name, descr): - super().__init__() - self.name = name - self.descr = descr - self.functions = {} - self.constants = {} - self.classes = {} - self.cur_class = None - - def new_file(self): - self.cur_class = None - - def process_function(self, lex, d): - name = d["id"] - if name in self.functions: - lex.error("multiple definition of function '{}'".format(name)) - function = self.functions[name] = DocFunction(name, d["args"]) - function.add_doc(lex) - - # def process_classref(self, lex, d): - # name = d['id'] - # self.classes[name] = name - # lex.opt_break() - - def process_class(self, lex, d): - name = d["id"] - if name in self.classes: - lex.error("multiple definition of class '{}'".format(name)) - self.cur_class = self.classes[name] = DocClass(name, d["descr"]) - self.cur_class.add_doc(lex) - - def process_classmethod(self, lex, d): - self.cur_class.process_classmethod(lex, d) - - def process_method(self, lex, d): - self.cur_class.process_method(lex, d) - - def process_constant(self, lex, d): - if self.cur_class is None: - # a module-level constant - name = d["id"] - if name in self.constants: - lex.error("multiple definition of constant '{}'".format(name)) - self.constants[name] = DocConstant(name, d["descr"]) - lex.opt_break() - else: - # a class-level constant - self.cur_class.process_constant(lex, d) - - def validate(self): - if self.descr is None: - raise DocValidateError("module {} referenced but never defined".format(self.name)) - - def dump(self, writer): - writer.module(self.name, self.descr, self.doc) - if self.functions: - writer.heading(2, "Functions") - for f in sorted(self.functions.values(), key=lambda x: x.name): - f.dump(self.name, writer) - if self.constants: - writer.heading(2, "Constants") - for c in sorted(self.constants.values(), key=lambda x: x.name): - c.dump(self.name, writer) - if self.classes: - writer.heading(2, "Classes") - for c in sorted(self.classes.values(), key=lambda x: x.name): - writer.para("[`{}.{}`]({}) - {}".format(self.name, c.name, c.name, c.descr)) - - def write_html(self, dir): - md_writer = MarkdownWriter() - md_writer.start() - self.dump(md_writer) - with open(os.path.join(dir, "index.html"), "wt") as f: - f.write(markdown.markdown(md_writer.end())) - for c in self.classes.values(): - class_dir = os.path.join(dir, c.name) - makedirs(class_dir) - md_writer.start() - md_writer.para("part of the [{} module](./)".format(self.name)) - c.dump(md_writer) - with open(os.path.join(class_dir, "index.html"), "wt") as f: - f.write(markdown.markdown(md_writer.end())) - - def write_rst(self, dir): - rst_writer = ReStructuredTextWriter() - rst_writer.start() - self.dump(rst_writer) - with open(dir + "/" + self.name + ".rst", "wt") as f: - f.write(rst_writer.end()) - for c in self.classes.values(): - rst_writer.start() - c.dump(rst_writer) - with open(dir + "/" + self.name + "." + c.name + ".rst", "wt") as f: - f.write(rst_writer.end()) - - -class Doc: - def __init__(self): - self.modules = {} - self.cur_module = None - - def new_file(self): - self.cur_module = None - for m in self.modules.values(): - m.new_file() - - def check_module(self, lex): - if self.cur_module is None: - lex.error("module not defined") - - def process_module(self, lex, d): - name = d["id"] - if name not in self.modules: - self.modules[name] = DocModule(name, None) - self.cur_module = self.modules[name] - if self.cur_module.descr is not None: - lex.error("multiple definition of module '{}'".format(name)) - self.cur_module.descr = d["descr"] - self.cur_module.add_doc(lex) - - def process_moduleref(self, lex, d): - name = d["id"] - if name not in self.modules: - self.modules[name] = DocModule(name, None) - self.cur_module = self.modules[name] - lex.opt_break() - - def process_class(self, lex, d): - self.check_module(lex) - self.cur_module.process_class(lex, d) - - def process_function(self, lex, d): - self.check_module(lex) - self.cur_module.process_function(lex, d) - - def process_classmethod(self, lex, d): - self.check_module(lex) - self.cur_module.process_classmethod(lex, d) - - def process_method(self, lex, d): - self.check_module(lex) - self.cur_module.process_method(lex, d) - - def process_constant(self, lex, d): - self.check_module(lex) - self.cur_module.process_constant(lex, d) - - def validate(self): - for m in self.modules.values(): - m.validate() - - def dump(self, writer): - writer.heading(1, "Modules") - writer.para("These are the Python modules that are implemented.") - for m in sorted(self.modules.values(), key=lambda x: x.name): - writer.para("[`{}`]({}/) - {}".format(m.name, m.name, m.descr)) - - def write_html(self, dir): - md_writer = MarkdownWriter() - with open(os.path.join(dir, "module", "index.html"), "wt") as f: - md_writer.start() - self.dump(md_writer) - f.write(markdown.markdown(md_writer.end())) - for m in self.modules.values(): - mod_dir = os.path.join(dir, "module", m.name) - makedirs(mod_dir) - m.write_html(mod_dir) - - def write_rst(self, dir): - # with open(os.path.join(dir, 'module', 'index.html'), 'wt') as f: - # f.write(markdown.markdown(self.dump())) - for m in self.modules.values(): - m.write_rst(dir) - - -regex_descr = r"(?P.*)" - -doc_regexs = ( - (Doc.process_module, re.compile(r"\\module (?P[a-z][a-z0-9]*) - " + regex_descr + r"$")), - (Doc.process_moduleref, re.compile(r"\\moduleref (?P[a-z]+)$")), - (Doc.process_function, re.compile(r"\\function (?P[a-z0-9_]+)(?P\(.*\))$")), - (Doc.process_classmethod, re.compile(r"\\classmethod (?P\\?[a-z0-9_]+)(?P\(.*\))$")), - (Doc.process_method, re.compile(r"\\method (?P\\?[a-z0-9_]+)(?P\(.*\))$")), - ( - Doc.process_constant, - re.compile(r"\\constant (?P[A-Za-z0-9_]+) - " + regex_descr + r"$"), - ), - # (Doc.process_classref, re.compile(r'\\classref (?P[A-Za-z0-9_]+)$')), - (Doc.process_class, re.compile(r"\\class (?P[A-Za-z0-9_]+) - " + regex_descr + r"$")), -) - - -def process_file(file, doc): - lex = Lexer(file) - doc.new_file() - try: - try: - while True: - line = lex.next() - fun, match = re_match_first(doc_regexs, line) - if fun == None: - lex.error("unknown line format: {}".format(line)) - fun(doc, lex, match.groupdict()) - - except Lexer.Break: - lex.error("unexpected break") - - except Lexer.EOF: - pass - - except Lexer.LexerError: - return False - - return True - - -def main(): - cmd_parser = argparse.ArgumentParser( - description="Generate documentation for pyboard API from C files." - ) - cmd_parser.add_argument( - "--outdir", metavar="", default="gendoc-out", help="output directory" - ) - cmd_parser.add_argument("--format", default="html", help="output format: html or rst") - cmd_parser.add_argument("files", nargs="+", help="input files") - args = cmd_parser.parse_args() - - doc = Doc() - for file in args.files: - print("processing", file) - if not process_file(file, doc): - return - try: - doc.validate() - except DocValidateError as e: - print(e) - - makedirs(args.outdir) - - if args.format == "html": - doc.write_html(args.outdir) - elif args.format == "rst": - doc.write_rst(args.outdir) - else: - print("unknown format:", args.format) - return - - print("written to", args.outdir) - - -if __name__ == "__main__": - main() diff --git a/tools/hci_trace_to_pcap.py b/tools/hci_trace_to_pcap.py new file mode 100755 index 0000000000..d55df3fb61 --- /dev/null +++ b/tools/hci_trace_to_pcap.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2023 Jim Mussared +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +# Simple script to take the output printed when HCI_TRACE is enabled in +# unix/mpbthciport.c, extmod/btstack/btstack_hci_uart.c, +# extmod/nimble/hal/hal_uart.c and turn it into a .pcap file suitable for use +# with Wireshark. + +import re +import sys +import struct + +# pcap file header: +# typedef struct pcap_hdr_s { +# guint32 magic_number; /* magic number */ +# guint16 version_major; /* major version number */ +# guint16 version_minor; /* minor version number */ +# gint32 thiszone; /* GMT to local correction */ +# guint32 sigfigs; /* accuracy of timestamps */ +# guint32 snaplen; /* max length of captured packets, in octets */ +# guint32 network; /* data link type */ +# } pcap_hdr_t; + +# pcap record header +# typedef struct pcaprec_hdr_s { +# guint32 ts_sec; /* timestamp seconds */ +# guint32 ts_usec; /* timestamp microseconds */ +# guint32 incl_len; /* number of octets of packet saved in file */ +# guint32 orig_len; /* actual length of packet */ +# } pcaprec_hdr_t; + +_LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR = 201 # "!I" direction, followed by data +sys.stdout.buffer.write( + struct.pack("!IHHiIII", 0xA1B2C3D4, 2, 4, 0, 0, 65535, _LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR) +) + +_DIR_CONTROLLER_TO_HOST = 1 +_DIR_HOST_TO_CONTROLLER = 0 + +reassemble_timestamp = 0 +reassemble_packet = bytearray() + +with open(sys.argv[1], "r") as f: + for line in f: + line = line.strip() + m = re.match("([<>]) \\[ *([0-9]+)\\] ([A-Fa-f0-9:]+)", line) + if not m: + continue + + timestamp = int(m.group(2)) + data = bytes.fromhex(m.group(3).replace(":", "")) + + if m.group(1) == "<": + # Host to controller. + # These are always complete. + sys.stdout.buffer.write( + struct.pack( + "!IIIII", + timestamp // 1000, + timestamp % 1000 * 1000, + len(data) + 4, + len(data) + 4, + _DIR_HOST_TO_CONTROLLER, + ) + ) + sys.stdout.buffer.write(data) + if m.group(1) == ">": + # Controller to host. + # Several of the sources print byte-at-a-time so need to reconstruct packets. + + if not reassemble_packet: + # Use the timestamp of the first fragment. + reassemble_timestamp = timestamp + + reassemble_packet.extend(data) + + if len(reassemble_packet) > 4: + plen = 0 + if reassemble_packet[0] == 1: + # command + plen = 3 + reassemble_packet[3] + elif reassemble_packet[0] == 2: + # acl + plen = 5 + reassemble_packet[3] + (reassemble_packet[4] << 8) + elif reassemble_packet[0] == 4: + # event + plen = 3 + reassemble_packet[2] + + if len(reassemble_packet) >= plen: + # Got a complete packet. + data = reassemble_packet[0:plen] + reassemble_packet = reassemble_packet[plen:] + reassemble_timestamp = timestamp + sys.stdout.buffer.write( + struct.pack( + "!IIIII", + reassemble_timestamp // 1000, + reassemble_timestamp % 1000 * 1000, + len(data) + 4, + len(data) + 4, + _DIR_CONTROLLER_TO_HOST, + ) + ) + sys.stdout.buffer.write(data) + +if reassemble_packet: + print( + "Error: Unknown byte in HCI stream. Remainder:", + reassemble_packet.hex(":"), + file=sys.stderr, + ) diff --git a/tools/makemanifest.py b/tools/makemanifest.py index b2856889b9..a74a6934ae 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -29,127 +29,14 @@ import sys import os import subprocess +# Always use the mpy-cross from this repo. +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../mpy-cross")) +import mpy_cross -########################################################################### -# Public functions to be used in the manifest - - -def include(manifest, **kwargs): - """Include another manifest. - - The manifest argument can be a string (filename) or an iterable of - strings. - - Relative paths are resolved with respect to the current manifest file. - - Optional kwargs can be provided which will be available to the - included script via the `options` variable. - - e.g. include("path.py", extra_features=True) - - in path.py: - options.defaults(standard_features=True) - - # freeze minimal modules. - if options.standard_features: - # freeze standard modules. - if options.extra_features: - # freeze extra modules. - """ - - if not isinstance(manifest, str): - for m in manifest: - include(m) - else: - manifest = convert_path(manifest) - with open(manifest) as f: - # Make paths relative to this manifest file while processing it. - # Applies to includes and input files. - prev_cwd = os.getcwd() - os.chdir(os.path.dirname(manifest)) - exec(f.read(), globals(), {"options": IncludeOptions(**kwargs)}) - os.chdir(prev_cwd) - - -def freeze(path, script=None, opt=0): - """Freeze the input, automatically determining its type. A .py script - will be compiled to a .mpy first then frozen, and a .mpy file will be - frozen directly. - - `path` must be a directory, which is the base directory to search for - files from. When importing the resulting frozen modules, the name of - the module will start after `path`, ie `path` is excluded from the - module name. - - If `path` is relative, it is resolved to the current manifest.py. - Use $(MPY_DIR), $(MPY_LIB_DIR), $(PORT_DIR), $(BOARD_DIR) if you need - to access specific paths. - - If `script` is None all files in `path` will be frozen. - - If `script` is an iterable then freeze() is called on all items of the - iterable (with the same `path` and `opt` passed through). - - If `script` is a string then it specifies the file or directory to - freeze, and can include extra directories before the file or last - directory. The file or directory will be searched for in `path`. If - `script` is a directory then all files in that directory will be frozen. - - `opt` is the optimisation level to pass to mpy-cross when compiling .py - to .mpy. - """ - - freeze_internal(KIND_AUTO, path, script, opt) - - -def freeze_as_str(path): - """Freeze the given `path` and all .py scripts within it as a string, - which will be compiled upon import. - """ - - freeze_internal(KIND_AS_STR, path, None, 0) - - -def freeze_as_mpy(path, script=None, opt=0): - """Freeze the input (see above) by first compiling the .py scripts to - .mpy files, then freezing the resulting .mpy files. - """ - - freeze_internal(KIND_AS_MPY, path, script, opt) - - -def freeze_mpy(path, script=None, opt=0): - """Freeze the input (see above), which must be .mpy files that are - frozen directly. - """ - - freeze_internal(KIND_MPY, path, script, opt) - - -########################################################################### -# Internal implementation - -KIND_AUTO = 0 -KIND_AS_STR = 1 -KIND_AS_MPY = 2 -KIND_MPY = 3 +import manifestfile VARS = {} -manifest_list = [] - - -class IncludeOptions: - def __init__(self, **kwargs): - self._kwargs = kwargs - self._defaults = {} - - def defaults(self, **kwargs): - self._defaults = kwargs - - def __getattr__(self, name): - return self._kwargs.get(name, self._defaults.get(name, None)) - class FreezeError(Exception): pass @@ -163,15 +50,6 @@ def system(cmd): return -1, er.output -def convert_path(path): - # Perform variable substitution. - for name, value in VARS.items(): - path = path.replace("$({})".format(name), value) - # Convert to absolute path (so that future operations don't rely on - # still being chdir'ed). - return os.path.abspath(path) - - def get_timestamp(path, default=None): try: stat = os.stat(path) @@ -182,119 +60,64 @@ def get_timestamp(path, default=None): return default -def get_timestamp_newest(path): - ts_newest = 0 - for dirpath, dirnames, filenames in os.walk(path, followlinks=True): - for f in filenames: - ts_newest = max(ts_newest, get_timestamp(os.path.join(dirpath, f))) - return ts_newest - - def mkdir(filename): path = os.path.dirname(filename) if not os.path.isdir(path): os.makedirs(path) -def freeze_internal(kind, path, script, opt): - path = convert_path(path) - if not os.path.isdir(path): - raise FreezeError("freeze path must be a directory: {}".format(path)) - if script is None and kind == KIND_AS_STR: - manifest_list.append((KIND_AS_STR, path, script, opt)) - elif script is None or isinstance(script, str) and script.find(".") == -1: - # Recursively search `path` for files to freeze, optionally restricted - # to a subdirectory specified by `script` - if script is None: - subdir = "" - else: - subdir = "/" + script - for dirpath, dirnames, filenames in os.walk(path + subdir, followlinks=True): - for f in filenames: - freeze_internal(kind, path, (dirpath + "/" + f)[len(path) + 1 :], opt) - elif not isinstance(script, str): - # `script` is an iterable of items to freeze - for s in script: - freeze_internal(kind, path, s, opt) - else: - # `script` should specify an individual file to be frozen - extension_kind = {KIND_AS_MPY: ".py", KIND_MPY: ".mpy"} - if kind == KIND_AUTO: - for k, ext in extension_kind.items(): - if script.endswith(ext): - kind = k - break - else: - print("warn: unsupported file type, skipped freeze: {}".format(script)) - return - wanted_extension = extension_kind[kind] - if not script.endswith(wanted_extension): - raise FreezeError("expecting a {} file, got {}".format(wanted_extension, script)) - manifest_list.append((kind, path, script, opt)) - - # Formerly make-frozen.py. # This generates: # - MP_FROZEN_STR_NAMES macro # - mp_frozen_str_sizes # - mp_frozen_str_content -def generate_frozen_str_content(paths): - def module_name(f): - return f +def generate_frozen_str_content(modules): + output = [ + b"#include \n", + b"#define MP_FROZEN_STR_NAMES \\\n", + ] - modules = [] - output = [b"#include \n"] - - for path in paths: - root = path.rstrip("/") - root_len = len(root) - - for dirpath, dirnames, filenames in os.walk(root): - for f in filenames: - fullpath = dirpath + "/" + f - st = os.stat(fullpath) - modules.append((path, fullpath[root_len + 1 :], st)) - - output.append(b"#define MP_FROZEN_STR_NAMES \\\n") - for _path, f, st in modules: - m = module_name(f) - output.append(b'"%s\\0" \\\n' % m.encode()) + for _, target_path in modules: + print("STR", target_path) + output.append(b'"%s\\0" \\\n' % target_path.encode()) output.append(b"\n") output.append(b"const uint32_t mp_frozen_str_sizes[] = { ") - for _path, f, st in modules: + for full_path, _ in modules: + st = os.stat(full_path) output.append(b"%d, " % st.st_size) output.append(b"0 };\n") output.append(b"const char mp_frozen_str_content[] = {\n") - for path, f, st in modules: - data = open(path + "/" + f, "rb").read() + for full_path, _ in modules: + with open(full_path, "rb") as f: + data = f.read() - # We need to properly escape the script data to create a C string. - # When C parses hex characters of the form \x00 it keeps parsing the hex - # data until it encounters a non-hex character. Thus one must create - # strings of the form "data\x01" "abc" to properly encode this kind of - # data. We could just encode all characters as hex digits but it's nice - # to be able to read the resulting C code as ASCII when possible. + # We need to properly escape the script data to create a C string. + # When C parses hex characters of the form \x00 it keeps parsing the hex + # data until it encounters a non-hex character. Thus one must create + # strings of the form "data\x01" "abc" to properly encode this kind of + # data. We could just encode all characters as hex digits but it's nice + # to be able to read the resulting C code as ASCII when possible. - data = bytearray(data) # so Python2 extracts each byte as an integer - esc_dict = {ord("\n"): b"\\n", ord("\r"): b"\\r", ord('"'): b'\\"', ord("\\"): b"\\\\"} - output.append(b'"') - break_str = False - for c in data: - try: - output.append(esc_dict[c]) - except KeyError: - if 32 <= c <= 126: - if break_str: - output.append(b'" "') - break_str = False - output.append(chr(c).encode()) - else: - output.append(b"\\x%02x" % c) - break_str = True - output.append(b'\\0"\n') + data = bytearray(data) # so Python2 extracts each byte as an integer + esc_dict = {ord("\n"): b"\\n", ord("\r"): b"\\r", ord('"'): b'\\"', ord("\\"): b"\\\\"} + output.append(b'"') + break_str = False + for c in data: + try: + output.append(esc_dict[c]) + except KeyError: + if 32 <= c <= 126: + if break_str: + output.append(b'" "') + break_str = False + output.append(chr(c).encode()) + else: + output.append(b"\\x%02x" % c) + break_str = True + output.append(b'\\0"\n') output.append(b'"\\0"\n};\n\n') return b"".join(output) @@ -329,7 +152,7 @@ def main(): sys.exit(1) # Get paths to tools - MPY_CROSS = VARS["MPY_DIR"] + "/mpy-cross/mpy-cross" + MPY_CROSS = VARS["MPY_DIR"] + "/mpy-cross/build/mpy-cross" if sys.platform == "win32": MPY_CROSS += ".exe" MPY_CROSS = os.getenv("MICROPY_MPYCROSS", MPY_CROSS) @@ -340,14 +163,13 @@ def main(): print("mpy-cross not found at {}, please build it first".format(MPY_CROSS)) sys.exit(1) + manifest = manifestfile.ManifestFile(manifestfile.MODE_FREEZE, VARS) + # Include top-level inputs, to generate the manifest for input_manifest in args.files: try: - if input_manifest.endswith(".py"): - include(input_manifest) - else: - exec(input_manifest) - except FreezeError as er: + manifest.execute(input_manifest) + except manifestfile.ManifestFileError as er: print('freeze error executing "{}": {}'.format(input_manifest, er.args[0])) sys.exit(1) @@ -355,34 +177,42 @@ def main(): str_paths = [] mpy_files = [] ts_newest = 0 - for kind, path, script, opt in manifest_list: - if kind == KIND_AS_STR: - str_paths.append(path) - ts_outfile = get_timestamp_newest(path) - elif kind == KIND_AS_MPY: - infile = "{}/{}".format(path, script) - outfile = "{}/frozen_mpy/{}.mpy".format(args.build_dir, script[:-3]) - ts_infile = get_timestamp(infile) - ts_outfile = get_timestamp(outfile, 0) - if ts_infile >= ts_outfile: - print("MPY", script) - mkdir(outfile) - res, out = system( - [MPY_CROSS] - + args.mpy_cross_flags.split() - + ["-o", outfile, "-s", script, "-O{}".format(opt), infile] + for result in manifest.files(): + if result.kind == manifestfile.KIND_FREEZE_AS_STR: + str_paths.append( + ( + result.full_path, + result.target_path, ) - if res != 0: - print("error compiling {}:".format(infile)) - sys.stdout.buffer.write(out) - raise SystemExit(1) + ) + ts_outfile = result.timestamp + elif result.kind == manifestfile.KIND_FREEZE_AS_MPY: + outfile = "{}/frozen_mpy/{}.mpy".format(args.build_dir, result.target_path[:-3]) + ts_outfile = get_timestamp(outfile, 0) + if result.timestamp >= ts_outfile: + print("MPY", result.target_path) + mkdir(outfile) + # Add __version__ to the end of the file before compiling. + with manifestfile.tagged_py_file(result.full_path, result.metadata) as tagged_path: + try: + mpy_cross.compile( + tagged_path, + dest=outfile, + src_path=result.target_path, + opt=result.opt, + mpy_cross=MPY_CROSS, + extra_args=args.mpy_cross_flags.split(), + ) + except mpy_cross.CrossCompileError as ex: + print("error compiling {}:".format(result.target_path)) + print(ex.args[0]) + raise SystemExit(1) ts_outfile = get_timestamp(outfile) mpy_files.append(outfile) else: - assert kind == KIND_MPY - infile = "{}/{}".format(path, script) - mpy_files.append(infile) - ts_outfile = get_timestamp(infile) + assert result.kind == manifestfile.KIND_FREEZE_MPY + mpy_files.append(result.full_path) + ts_outfile = result.timestamp ts_newest = max(ts_newest, ts_outfile) # Check if output file needs generating diff --git a/tools/manifestfile.py b/tools/manifestfile.py new file mode 100644 index 0000000000..f9b8a70357 --- /dev/null +++ b/tools/manifestfile.py @@ -0,0 +1,614 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2022 Jim Mussared +# Copyright (c) 2019 Damien P. George +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +from __future__ import print_function +import contextlib +import os +import sys +import glob +import tempfile +from collections import namedtuple + +__all__ = ["ManifestFileError", "ManifestFile"] + +# Allow freeze*() etc. +MODE_FREEZE = 1 +# Only allow include/require/module/package. +MODE_COMPILE = 2 +# Same as compile, but handles require(..., pypi="name") as a requirements.txt entry. +MODE_PYPROJECT = 3 + +# In compile mode, .py -> KIND_COMPILE_AS_MPY +# In freeze mode, .py -> KIND_FREEZE_AS_MPY, .mpy->KIND_FREEZE_MPY +KIND_AUTO = 1 +# Freeze-mode only, .py -> KIND_FREEZE_AS_MPY, .mpy->KIND_FREEZE_MPY +KIND_FREEZE_AUTO = 2 + +# Freeze-mode only, The .py file will be frozen as text. +KIND_FREEZE_AS_STR = 3 +# Freeze-mode only, The .py file will be compiled and frozen as bytecode. +KIND_FREEZE_AS_MPY = 4 +# Freeze-mode only, The .mpy file will be frozen directly. +KIND_FREEZE_MPY = 5 +# Compile mode only, the .py file should be compiled to .mpy. +KIND_COMPILE_AS_MPY = 6 + +# File on the local filesystem. +FILE_TYPE_LOCAL = 1 +# URL to file. (TODO) +FILE_TYPE_HTTP = 2 + + +class ManifestFileError(Exception): + pass + + +class ManifestIgnoreException(Exception): + pass + + +class ManifestUsePyPIException(Exception): + def __init__(self, pypi_name): + self.pypi_name = pypi_name + + +# The set of files that this manifest references. +ManifestOutput = namedtuple( + "ManifestOutput", + [ + "file_type", # FILE_TYPE_*. + "full_path", # The input file full path. + "target_path", # The target path on the device. + "timestamp", # Last modified date of the input file. + "kind", # KIND_*. + "metadata", # Metadata for the containing package. + "opt", # Optimisation level (or None). + ], +) + + +# Represents the metadata for a package. +class ManifestPackageMetadata: + def __init__(self, is_require=False): + self._is_require = is_require + self._initialised = False + + self.version = None + self.description = None + self.license = None + self.author = None + + # Annotate a package as being from the python standard library. + self.stdlib = False + + # Allows a python-ecosys package to be annotated with the + # corresponding name in PyPI. e.g. micropython-lib/urequests is based + # on pypi/requests. + self.pypi = None + # For a micropython package, this is the name that we will publish it + # to PyPI as. e.g. micropython-lib/senml publishes as + # pypi/micropython-senml. + self.pypi_publish = None + + def update( + self, + mode, + description=None, + version=None, + license=None, + author=None, + stdlib=False, + pypi=None, + pypi_publish=None, + ): + if self._initialised: + raise ManifestFileError("Duplicate call to metadata().") + + # In MODE_PYPROJECT, if this manifest is being evaluated as a result + # of a require(), then figure out if it should be replaced by a PyPI + # dependency instead. + if mode == MODE_PYPROJECT and self._is_require: + if stdlib: + # No dependency required at all for CPython. + raise ManifestIgnoreException + if pypi_publish or pypi: + # In the case where a package is both based on a PyPI package and + # provides one, preference depending on the published one. + # (This should be pretty rare). + raise ManifestUsePyPIException(pypi_publish or pypi) + + self.description = description + self.version = version + self.license = version + self.author = author + self.pypi = pypi + self.pypi_publish = pypi_publish + self._initialised = True + + def check_initialised(self, mode): + # Ensure that metadata() is the first thing a manifest.py does. + # This is to ensure that we early-exit if it should be replaced by a pypi dependency. + if mode in (MODE_COMPILE, MODE_PYPROJECT): + if not self._initialised: + raise ManifestFileError("metadata() must be the first command in a manifest file.") + + def __str__(self): + return "version={} description={} license={} author={} pypi={} pypi_publish={}".format( + self.version, self.description, self.license, self.author, self.pypi, self.pypi_publish + ) + + +# Turns a dict of options into a object with attributes used to turn the +# kwargs passed to include() and require into the "options" global in the +# included manifest. +# options = IncludeOptions(foo="bar", blah="stuff") +# options.foo # "bar" +# options.blah # "stuff" +class IncludeOptions: + def __init__(self, **kwargs): + self._kwargs = kwargs + self._defaults = {} + + def defaults(self, **kwargs): + self._defaults = kwargs + + def __getattr__(self, name): + return self._kwargs.get(name, self._defaults.get(name, None)) + + +class ManifestFile: + def __init__(self, mode, path_vars=None): + # See MODE_* constants above. + self._mode = mode + # Path substitution variables. + self._path_vars = path_vars or {} + # List of files (as ManifestFileResult) references by this manifest. + self._manifest_files = [] + # List of PyPI dependencies (when mode=MODE_PYPROJECT). + self._pypi_dependencies = [] + # Don't allow including the same file twice. + self._visited = set() + # Stack of metadata for each level. + self._metadata = [ManifestPackageMetadata()] + + def _resolve_path(self, path): + # Convert path to an absolute path, applying variable substitutions. + for name, value in self._path_vars.items(): + if value is not None: + path = path.replace("$({})".format(name), value) + return os.path.abspath(path) + + def _manifest_globals(self, kwargs): + # This is the "API" available to a manifest file. + g = { + "metadata": self.metadata, + "include": self.include, + "require": self.require, + "package": self.package, + "module": self.module, + "options": IncludeOptions(**kwargs), + } + + # Extra legacy functions only for freeze mode. + if self._mode == MODE_FREEZE: + g.update( + { + "freeze": self.freeze, + "freeze_as_str": self.freeze_as_str, + "freeze_as_mpy": self.freeze_as_mpy, + "freeze_mpy": self.freeze_mpy, + } + ) + + return g + + def files(self): + return self._manifest_files + + def pypi_dependencies(self): + # In MODE_PYPROJECT, this will return a list suitable for requirements.txt. + return self._pypi_dependencies + + def execute(self, manifest_file): + if manifest_file.endswith(".py"): + # Execute file from filesystem. + self.include(manifest_file) + else: + # Execute manifest code snippet. + try: + exec(manifest_file, self._manifest_globals({})) + except Exception as er: + raise ManifestFileError("Error in manifest: {}".format(er)) + + def _add_file(self, full_path, target_path, kind=KIND_AUTO, opt=None): + # Check file exists and get timestamp. + try: + stat = os.stat(full_path) + timestamp = stat.st_mtime + except OSError: + raise ManifestFileError("Cannot stat {}".format(full_path)) + + # Map the AUTO kinds to their actual kind based on mode and extension. + _, ext = os.path.splitext(full_path) + if self._mode == MODE_FREEZE: + if kind in ( + KIND_AUTO, + KIND_FREEZE_AUTO, + ): + if ext.lower() == ".py": + kind = KIND_FREEZE_AS_MPY + elif ext.lower() == ".mpy": + kind = KIND_FREEZE_MPY + else: + if kind != KIND_AUTO: + raise ManifestFileError("Not in freeze mode") + if ext.lower() != ".py": + raise ManifestFileError("Expected .py file") + kind = KIND_COMPILE_AS_MPY + + self._manifest_files.append( + ManifestOutput( + FILE_TYPE_LOCAL, full_path, target_path, timestamp, kind, self._metadata[-1], opt + ) + ) + + def _search(self, base_path, package_path, files, exts, kind, opt=None, strict=False): + base_path = self._resolve_path(base_path) + + if files: + # Use explicit list of files (relative to package_path). + for file in files: + if package_path: + file = os.path.join(package_path, file) + self._add_file(os.path.join(base_path, file), file, kind=kind, opt=opt) + else: + if base_path: + prev_cwd = os.getcwd() + os.chdir(self._resolve_path(base_path)) + + # Find all candidate files. + for dirpath, _, filenames in os.walk(package_path or ".", followlinks=True): + for file in filenames: + file = os.path.relpath(os.path.join(dirpath, file), ".") + _, ext = os.path.splitext(file) + if ext.lower() in exts: + self._add_file( + os.path.join(base_path, file), + file, + kind=kind, + opt=opt, + ) + elif strict: + raise ManifestFileError("Unexpected file type") + + if base_path: + os.chdir(prev_cwd) + + def metadata(self, **kwargs): + """ + From within a manifest file, use this to set the metadata for the + package described by current manifest. + + After executing a manifest file (via execute()), call this + to obtain the metadata for the top-level manifest file. + + See ManifestPackageMetadata.update() for valid kwargs. + """ + if kwargs: + self._metadata[-1].update(self._mode, **kwargs) + return self._metadata[-1] + + def include(self, manifest_path, is_require=False, **kwargs): + """ + Include another manifest. + + The manifest argument can be a string (filename) or an iterable of + strings. + + Relative paths are resolved with respect to the current manifest file. + + If the path is to a directory, then it implicitly includes the + manifest.py file inside that directory. + + Optional kwargs can be provided which will be available to the + included script via the `options` variable. + + e.g. include("path.py", extra_features=True) + + in path.py: + options.defaults(standard_features=True) + + # freeze minimal modules. + if options.standard_features: + # freeze standard modules. + if options.extra_features: + # freeze extra modules. + """ + if is_require: + self._metadata[-1].check_initialised(self._mode) + + if not isinstance(manifest_path, str): + for m in manifest_path: + self.include(m, **kwargs) + else: + manifest_path = self._resolve_path(manifest_path) + # Including a directory grabs the manifest.py inside it. + if os.path.isdir(manifest_path): + manifest_path = os.path.join(manifest_path, "manifest.py") + if manifest_path in self._visited: + return + self._visited.add(manifest_path) + if is_require: + # This include is the result of require("name"), so push a new + # package metadata onto the stack. + self._metadata.append(ManifestPackageMetadata(is_require=True)) + try: + with open(manifest_path) as f: + # Make paths relative to this manifest file while processing it. + # Applies to includes and input files. + prev_cwd = os.getcwd() + os.chdir(os.path.dirname(manifest_path)) + try: + exec(f.read(), self._manifest_globals(kwargs)) + finally: + os.chdir(prev_cwd) + except ManifestIgnoreException: + # e.g. MODE_PYPROJECT and this was a stdlib dependency. No-op. + pass + except ManifestUsePyPIException as e: + # e.g. MODE_PYPROJECT and this was a package from + # python-ecosys. Add PyPI dependency instead. + self._pypi_dependencies.append(e.pypi_name) + except Exception as e: + raise ManifestFileError("Error in manifest file: {}: {}".format(manifest_path, e)) + if is_require: + self._metadata.pop() + + def require(self, name, version=None, unix_ffi=False, pypi=None, **kwargs): + """ + Require a module by name from micropython-lib. + + Optionally specify unix_ffi=True to use a module from the unix-ffi directory. + + Optionally specify pipy="package-name" to indicate that this should + use the named package from PyPI when building for CPython. + """ + self._metadata[-1].check_initialised(self._mode) + + if self._mode == MODE_PYPROJECT and pypi: + # In PYPROJECT mode, allow overriding the PyPI dependency name + # explicitly. Otherwise if the dependent package has metadata + # (pypi_publish) or metadata(pypi) we will use that. + self._pypi_dependencies.append(pypi) + return + + if self._path_vars["MPY_LIB_DIR"]: + lib_dirs = ["micropython", "python-stdlib", "python-ecosys"] + if unix_ffi: + # Search unix-ffi only if unix_ffi=True, and make unix-ffi modules + # take precedence. + lib_dirs = ["unix-ffi"] + lib_dirs + + for lib_dir in lib_dirs: + # Search for {lib_dir}/**/{name}/manifest.py. + for root, dirnames, filenames in os.walk( + os.path.join(self._path_vars["MPY_LIB_DIR"], lib_dir) + ): + if os.path.basename(root) == name and "manifest.py" in filenames: + self.include(root, is_require=True, **kwargs) + return + + raise ValueError("Library not found in local micropython-lib: {}".format(name)) + else: + # TODO: HTTP request to obtain URLs from manifest.json. + raise ValueError("micropython-lib not available for require('{}').", name) + + def package(self, package_path, files=None, base_path=".", opt=None): + """ + Define a package, optionally restricting to a set of files. + + Simple case, a package in the current directory: + package("foo") + will include all .py files in foo, and will be stored as foo/bar/baz.py. + + If the package isn't in the current directory, use base_path: + package("foo", base_path="src") + + To restrict to certain files in the package use files (note: paths should be relative to the package): + package("foo", files=["bar/baz.py"]) + """ + self._metadata[-1].check_initialised(self._mode) + + # Include "base_path/package_path/**/*.py" --> "package_path/**/*.py" + self._search(base_path, package_path, files, exts=(".py",), kind=KIND_AUTO, opt=opt) + + def module(self, module_path, base_path=".", opt=None): + """ + Include a single Python file as a module. + + If the file is in the current directory: + module("foo.py") + + Otherwise use base_path to locate the file: + module("foo.py", "src/drivers") + """ + self._metadata[-1].check_initialised(self._mode) + + # Include "base_path/module_path" --> "module_path" + base_path = self._resolve_path(base_path) + _, ext = os.path.splitext(module_path) + if ext.lower() != ".py": + raise ManifestFileError("module must be .py file") + # TODO: version None + self._add_file(os.path.join(base_path, module_path), module_path, opt=opt) + + def _freeze_internal(self, path, script, exts, kind, opt): + if script is None: + self._search(path, None, None, exts=exts, kind=kind, opt=opt) + elif isinstance(script, str) and os.path.isdir(os.path.join(path, script)): + self._search(path, script, None, exts=exts, kind=kind, opt=opt) + elif not isinstance(script, str): + self._search(path, None, script, exts=exts, kind=kind, opt=opt) + else: + self._search(path, None, (script,), exts=exts, kind=kind, opt=opt) + + def freeze(self, path, script=None, opt=None): + """ + Freeze the input, automatically determining its type. A .py script + will be compiled to a .mpy first then frozen, and a .mpy file will be + frozen directly. + + `path` must be a directory, which is the base directory to _search for + files from. When importing the resulting frozen modules, the name of + the module will start after `path`, ie `path` is excluded from the + module name. + + If `path` is relative, it is resolved to the current manifest.py. + Use $(MPY_DIR), $(MPY_LIB_DIR), $(PORT_DIR), $(BOARD_DIR) if you need + to access specific paths. + + If `script` is None all files in `path` will be frozen. + + If `script` is an iterable then freeze() is called on all items of the + iterable (with the same `path` and `opt` passed through). + + If `script` is a string then it specifies the file or directory to + freeze, and can include extra directories before the file or last + directory. The file or directory will be _searched for in `path`. If + `script` is a directory then all files in that directory will be frozen. + + `opt` is the optimisation level to pass to mpy-cross when compiling .py + to .mpy. + """ + self._freeze_internal( + path, + script, + exts=( + ".py", + ".mpy", + ), + kind=KIND_FREEZE_AUTO, + opt=opt, + ) + + def freeze_as_str(self, path): + """ + Freeze the given `path` and all .py scripts within it as a string, + which will be compiled upon import. + """ + self._search(path, None, None, exts=(".py",), kind=KIND_FREEZE_AS_STR) + + def freeze_as_mpy(self, path, script=None, opt=None): + """ + Freeze the input (see above) by first compiling the .py scripts to + .mpy files, then freezing the resulting .mpy files. + """ + self._freeze_internal(path, script, exts=(".py",), kind=KIND_FREEZE_AS_MPY, opt=opt) + + def freeze_mpy(self, path, script=None, opt=None): + """ + Freeze the input (see above), which must be .mpy files that are + frozen directly. + """ + self._freeze_internal(path, script, exts=(".mpy",), kind=KIND_FREEZE_MPY, opt=opt) + + +# Generate a temporary file with a line appended to the end that adds __version__. +@contextlib.contextmanager +def tagged_py_file(path, metadata): + dest_fd, dest_path = tempfile.mkstemp(suffix=".py", text=True) + try: + with os.fdopen(dest_fd, "w") as dest: + with open(path, "r") as src: + contents = src.read() + dest.write(contents) + + # Don't overwrite a version definition if the file already has one in it. + if metadata.version and "__version__ =" not in contents: + dest.write("\n\n__version__ = {}\n".format(repr(metadata.version))) + yield dest_path + finally: + os.unlink(dest_path) + + +def main(): + import argparse + + cmd_parser = argparse.ArgumentParser(description="List the files referenced by a manifest.") + cmd_parser.add_argument("--freeze", action="store_true", help="freeze mode") + cmd_parser.add_argument("--compile", action="store_true", help="compile mode") + cmd_parser.add_argument("--pyproject", action="store_true", help="pyproject mode") + cmd_parser.add_argument( + "--lib", + default=os.path.join(os.path.dirname(__file__), "../lib/micropython-lib"), + help="path to micropython-lib repo", + ) + cmd_parser.add_argument("--port", default=None, help="path to port dir") + cmd_parser.add_argument("--board", default=None, help="path to board dir") + cmd_parser.add_argument( + "--top", + default=os.path.join(os.path.dirname(__file__), ".."), + help="path to micropython repo", + ) + cmd_parser.add_argument("files", nargs="+", help="input manifest.py") + args = cmd_parser.parse_args() + + path_vars = { + "MPY_DIR": os.path.abspath(args.top) if args.top else None, + "BOARD_DIR": os.path.abspath(args.board) if args.board else None, + "PORT_DIR": os.path.abspath(args.port) if args.port else None, + "MPY_LIB_DIR": os.path.abspath(args.lib) if args.lib else None, + } + + mode = None + if args.freeze: + mode = MODE_FREEZE + elif args.compile: + mode = MODE_COMPILE + elif args.pyproject: + mode = MODE_PYPROJECT + else: + print("Error: No mode specified.", file=sys.stderr) + exit(1) + + m = ManifestFile(mode, path_vars) + for manifest_file in args.files: + try: + m.execute(manifest_file) + except ManifestFileError as er: + print(er, file=sys.stderr) + exit(1) + print(m.metadata()) + for f in m.files(): + print(f) + if mode == MODE_PYPROJECT: + for r in m.pypi_dependencies(): + print("pypi-require:", r) + + +if __name__ == "__main__": + main() diff --git a/tools/merge_micropython.py b/tools/merge_micropython.py index a6d3efcc0d..b596cd59c5 100644 --- a/tools/merge_micropython.py +++ b/tools/merge_micropython.py @@ -2,11 +2,14 @@ This is a helper script for merging in new versions of MicroPython. You *must* evaluate its correctness and adapt it for each MP version. This is committed in the repo more for reference than "fire and forget" use. + +Updated for v1.20.0 merge - dhalbert """ +from io import StringIO + import sh from sh import git -from io import StringIO out_buf = StringIO() @@ -16,17 +19,18 @@ ports_to_delete = [ "embed", "esp32", "esp8266", - "javascript", "mimxrt", "minimal", "pic16bit", "powerpc", "qemu-arm", + "raspberrypi", "renesas-ra", "rp2", "samd", "stm32", "teensy", + "webassembly", "windows", "zephyr", ] @@ -90,25 +94,47 @@ while line: # Delete docs and tests for things we don't need anymore docs_to_delete = [ "conf.py", - "pyboard", - "library/pyb.*", - "library/esp*", - "library/lcd160cr.rst", - "esp8266", - "wipy", - "esp32", - "library/machine.*", - "library/network.*", - "library/ubluetooth.rst", - "library/ucryptolib.rst", - "library/uos.rst", - "library/usocket.rst", - "library/ussl.rst", - "library/ustruct.rst", "develop", - "reference", + "differences", + "esp32", + "esp8266", + "library/bluetooth.rst", + "library/btree.rst", + "library/cryptolib.rst", + "library/esp*.rst", + "library/framebuf.rst", + "library/hashlib.rst", + "library/lcd160cr.rst", + "library/machine*.rst", + "library/math.rst", + "library/network*.rst", + "library/os.rst", + "library/pyb*.rst", + "library/random.rst", + "library/rp2*.rst", + "library/uos.rst", + "library/socket.rst", + "library/ssl.rst", + "library/stm.rst", + "library/struct.rst", + "library/_thread.rst", + "library/time.rst", + "library/uasyncio.rst", + "library/uctypes.rst", + "library/wipy.rst", + "library/wm8960.rst", + "library/zephyr*.rst", + "library/zlib.rst", "make.bat", + "mimxrt", + "pyboard", + "reference", + "renesas-ra", + "rp2", + "samd", "templates/topindex.html", + "wipy", + "zephyr", ] for d in docs_to_delete: try: @@ -117,13 +143,13 @@ for d in docs_to_delete: pass tests_to_delete = [ - "wipy", - "pyb", - "multi_net", - "net_inet", - "multi_bluetooth", "esp32", + "multi_bluetooth", + "multi_net", "net_hosted", + "net_inet", + "pyb", + "wipy", ] for t in tests_to_delete: try: @@ -133,12 +159,19 @@ for t in tests_to_delete: libs_to_delete = [ - "mynewt-nimble", - "nxp_driver", - "mbedtls", - "mbedtls_errors", "asf4", "btstack", + "libhydrogen", + "lwip", + "mbedtls", + "mbedtls_errors", + "micropython-lib", + "mynewt-nimble", + "nrfx", + "nxp_driver", + "pico-sdk", + "stm32lib", + "wiznet5k", ] for l in libs_to_delete: try: @@ -147,30 +180,34 @@ for l in libs_to_delete: pass extmod_to_delete = [ - "machine_*", - "webrepl", - "uzlib", - "ussl*", - "modlwip.c", - "moducryptolib.c", - "modbluetooth*", - "network*", - "nimble", "btstack", - "mpbthci*", + "extmod.cmake", + "machine_*", + "mbedtls", + "modbluetooth.*", + "modbtree.*", + "modframebuf.*", + "modlwip.*", + "modnetwork.*", + "modonewire.*", + "moducryptolib.*", + "modusocket.*", + "modussl_*.*", + "modutimeq.*", + "moduwebsocket.*", + "modwebrepl.*", + "mpbthci.*", + "network_*.*", + "nimble", ] for e in extmod_to_delete: try: git.rm("-rf", "extmod/" + e) except sh.ErrorReturnCode_128 as error: print(error) - pass top_delete = [ "drivers", - ".travis.yml", - ".github/FUNDING.yml", - ".github/workflows/docs.yml", "README.md", "CODEOFCONDUCT.md", "CODECONVENTIONS.md", @@ -181,8 +218,31 @@ for t in top_delete: except sh.ErrorReturnCode_128: pass +dot_github_delete = [ + ".github/dependabot.yml", + ".github/FUNDING.yml", + ".github/ISSUE_TEMPLATE/documentation.md", + ".github/ISSUE_TEMPLATE/security.md", + ".github/workflows/code_formatting.yml", + ".github/workflows/code_size_comment.yml", + ".github/workflows/code_size.yml", + ".github/workflows/commit_formatting.yml", + ".github/workflows/docs.yml", + ".github/workflows/examples.yml", + ".github/workflows/mpremote.yml", + ".github/workflows/mpy_format.yml", + ".github/workflows/mpy_format.yml", + ".github/workflows/ports_*.yml", +] +for t in dot_github_delete: + try: + git.rm("-rf", t) + except sh.ErrorReturnCode_128: + pass + # Always ours: always_ours = [ + ".github", "devices", "supervisor", "shared-bindings", @@ -209,24 +269,24 @@ for ours in always_ours: print(state, path) line = out_buf.readline() -# Check to see if any files changed only in formatting -out_buf = StringIO() -git.status("--porcelain=1", ".", _out=out_buf) -out_buf.seek(0) -line = out_buf.readline() -while line: - state = line.split()[0] - if state in ("D", "R", "DD"): - line = out_buf.readline() - continue - state, path = line.split() - log_buf = StringIO() - git.log("--pretty=tformat:%H", "25ae98f..HEAD", path, _out=log_buf, _tty_out=False) - log_buf.seek(0) - commits = [] - for line in log_buf.readlines(): - commits.append(line.strip()) - if state in ["UU", "M"] and commits == ["a52eb88031620a81521b937f2a0651dbac2bb350"]: - git.checkout("--theirs", path) - git.add(path) - line = out_buf.readline() +# # Check to see if any files changed only in formatting +# out_buf = StringIO() +# git.status("--porcelain=1", ".", _out=out_buf) +# out_buf.seek(0) +# line = out_buf.readline() +# while line: +# state = line.split()[0] +# if state in ("D", "R", "DD"): +# line = out_buf.readline() +# continue +# state, path = line.split() +# log_buf = StringIO() +# git.log("--pretty=tformat:%H", "25ae98f..HEAD", path, _out=log_buf, _tty_out=False) +# log_buf.seek(0) +# commits = [] +# for line in log_buf.readlines(): +# commits.append(line.strip()) +# if state in ["UU", "M"] and commits == ["a52eb88031620a81521b937f2a0651dbac2bb350"]: +# git.checkout("--theirs", path) +# git.add(path) +# line = out_buf.readline() diff --git a/tools/metrics.py b/tools/metrics.py index c857d0733e..da4d188568 100755 --- a/tools/metrics.py +++ b/tools/metrics.py @@ -60,12 +60,14 @@ class PortData: port_data = { "b": PortData("bare-arm", "bare-arm", "build/firmware.elf"), "m": PortData("minimal x86", "minimal", "build/firmware.elf"), - "u": PortData("unix x64", "unix", "micropython"), - "n": PortData("unix nanbox", "unix", "micropython-nanbox", "VARIANT=nanbox"), + "u": PortData("unix x64", "unix", "build-standard/micropython"), + "n": PortData("unix nanbox", "unix", "build-nanbox/micropython", "VARIANT=nanbox"), "s": PortData("stm32", "stm32", "build-PYBV10/firmware.elf", "BOARD=PYBV10"), "c": PortData("cc3200", "cc3200", "build/WIPY/release/application.axf", "BTARGET=application"), "8": PortData("esp8266", "esp8266", "build-GENERIC/firmware.elf"), "3": PortData("esp32", "esp32", "build-GENERIC/micropython.elf"), + "x": PortData("mimxrt", "mimxrt", "build-TEENSY40/firmware.elf"), + "e": PortData("renesas-ra", "renesas-ra", "build-RA6M2_EK/firmware.elf"), "r": PortData("nrf", "nrf", "build-pca10040/firmware.elf"), "p": PortData("rp2", "rp2", "build-PICO/firmware.elf"), "d": PortData("samd", "samd", "build-ADAFRUIT_ITSYBITSY_M4_EXPRESS/firmware.elf"), diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 3a59ac6590..a02104322c 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -88,6 +88,7 @@ class FreezeError(Exception): class Config: MPY_VERSION = 6 + MPY_SUB_VERSION = 1 MICROPY_LONGINT_IMPL_NONE = 0 MICROPY_LONGINT_IMPL_LONGLONG = 1 MICROPY_LONGINT_IMPL_MPZ = 2 @@ -934,6 +935,10 @@ class RawCode(object): " .line_info = fun_data_%s + %u," % (self.escaped_name, self.offset_line_info) ) + print( + " .line_info_top = fun_data_%s + %u," + % (self.escaped_name, self.offset_closure_info) + ) print( " .opcodes = fun_data_%s + %u," % (self.escaped_name, self.offset_opcodes) ) @@ -1334,6 +1339,9 @@ def read_mpy(filename): feature_byte = header[2] mpy_native_arch = feature_byte >> 2 if mpy_native_arch != MP_NATIVE_ARCH_NONE: + mpy_sub_version = feature_byte & 3 + if mpy_sub_version != config.MPY_SUB_VERSION: + raise MPYReadError(filename, "incompatible .mpy sub-version") if config.native_arch == MP_NATIVE_ARCH_NONE: config.native_arch = mpy_native_arch elif config.native_arch != mpy_native_arch: @@ -1657,7 +1665,9 @@ def merge_mpy(compiled_modules, output_file): else: main_cm_idx = None for idx, cm in enumerate(compiled_modules): - if cm.header[2]: + feature_byte = cm.header[2] + mpy_native_arch = feature_byte >> 2 + if mpy_native_arch: # Must use qstr_table and obj_table from this raw_code if main_cm_idx is not None: raise Exception("can't merge files when more than one contains native code") @@ -1669,7 +1679,7 @@ def merge_mpy(compiled_modules, output_file): header = bytearray(4) header[0] = ord("C") header[1] = config.MPY_VERSION - header[2] = config.native_arch << 2 + header[2] = config.native_arch << 2 | config.MPY_SUB_VERSION if config.native_arch else 0 header[3] = config.mp_small_int_bits merged_mpy.extend(header) diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py index 4d01f52df8..69a3ee48cb 100755 --- a/tools/mpy_ld.py +++ b/tools/mpy_ld.py @@ -36,6 +36,7 @@ import makeqstrdata as qstrutil # MicroPython constants MPY_VERSION = 6 +MPY_SUB_VERSION = 1 MP_CODE_BYTECODE = 2 MP_CODE_NATIVE_VIPER = 4 MP_NATIVE_ARCH_X86 = 1 @@ -919,7 +920,11 @@ def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs): out.open(fmpy) # MPY: header - out.write_bytes(bytearray([ord("C"), MPY_VERSION, env.arch.mpy_feature, MP_SMALL_INT_BITS])) + out.write_bytes( + bytearray( + [ord("C"), MPY_VERSION, env.arch.mpy_feature | MPY_SUB_VERSION, MP_SMALL_INT_BITS] + ) + ) # MPY: n_qstr out.write_uint(1 + len(native_qstr_vals)) diff --git a/tools/pyboard.py b/tools/pyboard.py index a521a04a2e..bfec3e1972 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -48,10 +48,13 @@ Or: """ +import ast +import os +import struct import sys import time -import os -import ast + +from collections import namedtuple try: stdout = sys.stdout.buffer @@ -67,7 +70,15 @@ def stdout_write_bytes(b): class PyboardError(Exception): - pass + def convert(self, info): + if len(self.args) >= 3: + if b"OSError" in self.args[2] and b"ENOENT" in self.args[2]: + return OSError(errno.ENOENT, info) + + return self + + +listdir_result = namedtuple("dir_result", ["name", "st_mode", "st_ino", "st_size"]) class TelnetToSerial: @@ -256,7 +267,19 @@ class Pyboard: delayed = False for attempt in range(wait + 1): try: - self.serial = serial.Serial(device, **serial_kwargs) + if os.name == "nt": + self.serial = serial.Serial(**serial_kwargs) + self.serial.port = device + portinfo = list(serial.tools.list_ports.grep(device)) # type: ignore + if portinfo and portinfo[0].manufacturer != "Microsoft": + # ESP8266/ESP32 boards use RTS/CTS for flashing and boot mode selection. + # DTR False: to avoid using the reset button will hang the MCU in bootloader mode + # RTS False: to prevent pulses on rts on serial.close() that would POWERON_RESET an ESPxx + self.serial.dtr = False # DTR False = gpio0 High = Normal boot + self.serial.rts = False # RTS False = EN High = MCU enabled + self.serial.open() + else: + self.serial = serial.Serial(device, **serial_kwargs) break except (OSError, IOError): # Py2 and Py3 have different errors if wait == 0: @@ -360,7 +383,7 @@ class Pyboard: def raw_paste_write(self, command_bytes): # Read initial header, with window size. data = self.serial.read(2) - window_size = data[0] | data[1] << 8 + window_size = struct.unpack(" 1: + print(str(er.args[2], "ascii")) + else: + print(er) pyb.exit_raw_repl() pyb.close() sys.exit(1) @@ -737,7 +854,7 @@ def main(): # do filesystem commands, if given if args.filesystem: - filesystem_command(pyb, args.files) + filesystem_command(pyb, args.files, verbose=True) del args.files[:] # run the command, if given diff --git a/tools/uncrustify.cfg b/tools/uncrustify.cfg index 3812cd3182..bf5e37bf3f 100644 --- a/tools/uncrustify.cfg +++ b/tools/uncrustify.cfg @@ -1,5 +1,8 @@ # Uncrustify-0.71.0_f +# IMPORTANT: Output is different if using Uncrustify 0.73 or newer, and config file format has changed in newer versions. +# Use version 0.71 or 0.72 to get matching code formatting. + # # General options # diff --git a/tools/upip.py b/tools/upip.py deleted file mode 100644 index a62d04f66b..0000000000 --- a/tools/upip.py +++ /dev/null @@ -1,351 +0,0 @@ -# upip - Package manager for MicroPython - -# SPDX-FileCopyrightText: Copyright (c) 2015-2018 Paul Sokolovsky -# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) -# -# SPDX-License-Identifier: MIT - -import sys -import gc -import uos as os -import uerrno as errno -import ujson as json -import uzlib -import upip_utarfile as tarfile - -gc.collect() - - -debug = False -index_urls = ["https://micropython.org/pi", "https://pypi.org/pypi"] -install_path = None -cleanup_files = [] -gzdict_sz = 16 + 15 - -file_buf = bytearray(512) - - -class NotFoundError(Exception): - pass - - -def op_split(path): - if path == "": - return ("", "") - r = path.rsplit("/", 1) - if len(r) == 1: - return ("", path) - head = r[0] - if not head: - head = "/" - return (head, r[1]) - - -# Expects *file* name -def _makedirs(name, mode=0o777): - ret = False - s = "" - comps = name.rstrip("/").split("/")[:-1] - if comps[0] == "": - s = "/" - for c in comps: - if s and s[-1] != "/": - s += "/" - s += c - try: - os.mkdir(s) - ret = True - except OSError as e: - if e.errno != errno.EEXIST and e.errno != errno.EISDIR: - raise e - ret = False - return ret - - -def save_file(fname, subf): - global file_buf - with open(fname, "wb") as outf: - while True: - sz = subf.readinto(file_buf) - if not sz: - break - outf.write(file_buf, sz) - - -def install_tar(f, prefix): - meta = {} - for info in f: - # print(info) - fname = info.name - try: - fname = fname[fname.index("/") + 1 :] - except ValueError: - fname = "" - - save = True - for p in ("setup.", "PKG-INFO", "README"): - # print(fname, p) - if fname.startswith(p) or ".egg-info" in fname: - if fname.endswith("/requires.txt"): - meta["deps"] = f.extractfile(info).read() - save = False - if debug: - print("Skipping", fname) - break - - if save: - outfname = prefix + fname - if info.type != tarfile.DIRTYPE: - if debug: - print("Extracting " + outfname) - _makedirs(outfname) - subf = f.extractfile(info) - save_file(outfname, subf) - return meta - - -def expandhome(s): - if "~/" in s: - h = os.getenv("HOME") - s = s.replace("~/", h + "/") - return s - - -import ussl -import usocket - -warn_ussl = True - - -def url_open(url): - global warn_ussl - - if debug: - print(url) - - proto, _, host, urlpath = url.split("/", 3) - try: - port = 443 - if ":" in host: - host, port = host.split(":") - port = int(port) - ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) - except OSError as e: - fatal("Unable to resolve %s (no Internet?)" % host, e) - # print("Address infos:", ai) - ai = ai[0] - - s = usocket.socket(ai[0], ai[1], ai[2]) - try: - # print("Connect address:", addr) - s.connect(ai[-1]) - - if proto == "https:": - s = ussl.wrap_socket(s, server_hostname=host) - if warn_ussl: - print("Warning: %s SSL certificate is not validated" % host) - warn_ussl = False - - # MicroPython rawsocket module supports file interface directly - s.write("GET /%s HTTP/1.0\r\nHost: %s:%s\r\n\r\n" % (urlpath, host, port)) - l = s.readline() - protover, status, msg = l.split(None, 2) - if status != b"200": - if status == b"404" or status == b"301": - raise NotFoundError("Package not found") - raise ValueError(status) - while 1: - l = s.readline() - if not l: - raise ValueError("Unexpected EOF in HTTP headers") - if l == b"\r\n": - break - except Exception as e: - s.close() - raise e - - return s - - -def get_pkg_metadata(name): - for url in index_urls: - try: - f = url_open("%s/%s/json" % (url, name)) - except NotFoundError: - continue - try: - return json.load(f) - finally: - f.close() - raise NotFoundError("Package not found") - - -def fatal(msg, exc=None): - print("Error:", msg) - if exc and debug: - raise exc - sys.exit(1) - - -def install_pkg(pkg_spec, install_path): - package = pkg_spec.split("==") - data = get_pkg_metadata(package[0]) - - if len(package) == 1: - latest_ver = data["info"]["version"] - else: - latest_ver = package[1] - packages = data["releases"][latest_ver] - del data - gc.collect() - assert len(packages) == 1 - package_url = packages[0]["url"] - print("Installing %s %s from %s" % (pkg_spec, latest_ver, package_url)) - f1 = url_open(package_url) - try: - f2 = uzlib.DecompIO(f1, gzdict_sz) - f3 = tarfile.TarFile(fileobj=f2) - meta = install_tar(f3, install_path) - finally: - f1.close() - del f3 - del f2 - gc.collect() - return meta - - -def install(to_install, install_path=None): - # Calculate gzip dictionary size to use - global gzdict_sz - sz = gc.mem_free() + gc.mem_alloc() - if sz <= 65536: - gzdict_sz = 16 + 12 - - if install_path is None: - install_path = get_install_path() - if install_path[-1] != "/": - install_path += "/" - if not isinstance(to_install, list): - to_install = [to_install] - print("Installing to: " + install_path) - # sets would be perfect here, but don't depend on them - installed = [] - try: - while to_install: - if debug: - print("Queue:", to_install) - pkg_spec = to_install.pop(0) - if pkg_spec in installed: - continue - meta = install_pkg(pkg_spec, install_path) - installed.append(pkg_spec) - if debug: - print(meta) - deps = meta.get("deps", "").rstrip() - if deps: - deps = deps.decode("utf-8").split("\n") - to_install.extend(deps) - except Exception as e: - print( - "Error installing '{}': {}, packages may be partially installed".format(pkg_spec, e), - file=sys.stderr, - ) - - -def get_install_path(): - global install_path - if install_path is None: - # sys.path[0] is current module's path - install_path = sys.path[1] - if install_path == ".frozen": - install_path = sys.path[2] - install_path = expandhome(install_path) - return install_path - - -def cleanup(): - for fname in cleanup_files: - try: - os.unlink(fname) - except OSError: - print("Warning: Cannot delete " + fname) - - -def help(): - print( - """\ -upip - Simple PyPI package manager for MicroPython -Usage: micropython -m upip install [-p ] ... | -r -import upip; upip.install(package_or_list, []) - -If isn't given, packages will be installed to sys.path[1], or -sys.path[2] if the former is .frozen (path can be set from MICROPYPATH -environment variable if supported).""" - ) - print("Default install path:", get_install_path()) - print( - """\ - -Note: only MicroPython packages (usually, named micropython-*) are supported -for installation, upip does not support arbitrary code in setup.py. -""" - ) - - -def main(): - global debug - global index_urls - global install_path - install_path = None - - if len(sys.argv) < 2 or sys.argv[1] == "-h" or sys.argv[1] == "--help": - help() - return - - if sys.argv[1] != "install": - fatal("Only 'install' command supported") - - to_install = [] - - i = 2 - while i < len(sys.argv) and sys.argv[i][0] == "-": - opt = sys.argv[i] - i += 1 - if opt == "-h" or opt == "--help": - help() - return - elif opt == "-p": - install_path = sys.argv[i] - i += 1 - elif opt == "-r": - list_file = sys.argv[i] - i += 1 - with open(list_file) as f: - while True: - l = f.readline() - if not l: - break - if l[0] == "#": - continue - to_install.append(l.rstrip()) - elif opt == "-i": - index_urls = [sys.argv[i]] - i += 1 - elif opt == "--debug": - debug = True - else: - fatal("Unknown/unsupported option: " + opt) - - to_install.extend(sys.argv[i:]) - if not to_install: - help() - return - - install(to_install) - - if not debug: - cleanup() - - -if __name__ == "__main__": - main() diff --git a/tools/upip_utarfile.py b/tools/upip_utarfile.py deleted file mode 100644 index 3e527fad8d..0000000000 --- a/tools/upip_utarfile.py +++ /dev/null @@ -1,99 +0,0 @@ -# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) -# -# SPDX-License-Identifier: MIT - -import uctypes - -# http://www.gnu.org/software/tar/manual/html_node/Standard.html -TAR_HEADER = { - "name": (uctypes.ARRAY | 0, uctypes.UINT8 | 100), - "size": (uctypes.ARRAY | 124, uctypes.UINT8 | 11), -} - -DIRTYPE = "dir" -REGTYPE = "file" - - -def roundup(val, align): - return (val + align - 1) & ~(align - 1) - - -class FileSection: - def __init__(self, f, content_len, aligned_len): - self.f = f - self.content_len = content_len - self.align = aligned_len - content_len - - def read(self, sz=65536): - if self.content_len == 0: - return b"" - if sz > self.content_len: - sz = self.content_len - data = self.f.read(sz) - sz = len(data) - self.content_len -= sz - return data - - def readinto(self, buf): - if self.content_len == 0: - return 0 - if len(buf) > self.content_len: - buf = memoryview(buf)[: self.content_len] - sz = self.f.readinto(buf) - self.content_len -= sz - return sz - - def skip(self): - sz = self.content_len + self.align - if sz: - buf = bytearray(16) - while sz: - s = min(sz, 16) - self.f.readinto(buf, s) - sz -= s - - -class TarInfo: - def __str__(self): - return "TarInfo(%r, %s, %d)" % (self.name, self.type, self.size) - - -class TarFile: - def __init__(self, name=None, fileobj=None): - if fileobj: - self.f = fileobj - else: - self.f = open(name, "rb") - self.subf = None - - def next(self): - if self.subf: - self.subf.skip() - buf = self.f.read(512) - if not buf: - return None - - h = uctypes.struct(uctypes.addressof(buf), TAR_HEADER, uctypes.LITTLE_ENDIAN) - - # Empty block means end of archive - if h.name[0] == 0: - return None - - d = TarInfo() - d.name = str(h.name, "utf-8").rstrip("\0") - d.size = int(bytes(h.size), 8) - d.type = [REGTYPE, DIRTYPE][d.name[-1] == "/"] - self.subf = d.subf = FileSection(self.f, d.size, roundup(d.size, 512)) - return d - - def __iter__(self): - return self - - def __next__(self): - v = self.next() - if v is None: - raise StopIteration - return v - - def extractfile(self, tarinfo): - return tarinfo.subf diff --git a/tools/verifygitlog.py b/tools/verifygitlog.py index 09c10c80d6..ee3e119f37 100755 --- a/tools/verifygitlog.py +++ b/tools/verifygitlog.py @@ -7,6 +7,8 @@ import sys verbosity = 0 # Show what's going on, 0 1 or 2. suggestions = 1 # Set to 0 to not include lengthy suggestions in error messages. +ignore_prefixes = [] + def verbose(*args): if verbosity: @@ -18,6 +20,22 @@ def very_verbose(*args): print(*args) +class ErrorCollection: + # Track errors and warnings as the program runs + def __init__(self): + self.has_errors = False + self.has_warnings = False + self.prefix = "" + + def error(self, text): + print("error: {}{}".format(self.prefix, text)) + self.has_errors = True + + def warning(self, text): + print("warning: {}{}".format(self.prefix, text)) + self.has_warnings = True + + def git_log(pretty_format, *args): # Delete pretty argument from user args so it doesn't interfere with what we do. args = ["git", "log"] + [arg for arg in args if "--pretty" not in args] @@ -28,83 +46,108 @@ def git_log(pretty_format, *args): yield line.decode().rstrip("\r\n") -def verify(sha): +def diagnose_subject_line(subject_line, subject_line_format, err): + err.error("Subject line: " + subject_line) + if not subject_line.endswith("."): + err.error('* should end with "."') + if not re.match(r"^[^!]+: ", subject_line): + err.error('* should start with "path: "') + if re.match(r"^[^!]+: *$", subject_line): + err.error("* should contain a subject after the path.") + m = re.match(r"^[^!]+: ([a-z][^ ]*)", subject_line) + if m: + err.error('* first word of subject ("{}") should be capitalised.'.format(m.group(1))) + if re.match(r"^[^!]+: [^ ]+$", subject_line): + err.error("* subject should contain more than one word.") + err.error("* should match: " + repr(subject_line_format)) + err.error('* Example: "py/runtime: Add support for foo to bar."') + + +def verify(sha, err): verbose("verify", sha) - errors = [] - warnings = [] - - def error_text(err): - return "commit " + sha + ": " + err - - def error(err): - errors.append(error_text(err)) - - def warning(err): - warnings.append(error_text(err)) + err.prefix = "commit " + sha + ": " # Author and committer email. for line in git_log("%ae%n%ce", sha, "-n1"): very_verbose("email", line) if "noreply" in line: - error("Unwanted email address: " + line) + err.error("Unwanted email address: " + line) # Message body. raw_body = list(git_log("%B", sha, "-n1")) + verify_message_body(raw_body, err) + + +def verify_message_body(raw_body, err): if not raw_body: - error("Message is empty") - return errors, warnings + err.error("Message is empty") + return # Subject line. subject_line = raw_body[0] + for prefix in ignore_prefixes: + if subject_line.startswith(prefix): + verbose("Skipping ignored commit message") + return very_verbose("subject_line", subject_line) subject_line_format = r"^[^!]+: [A-Z]+.+ .+\.$" if not re.match(subject_line_format, subject_line): - error("Subject line should match " + repr(subject_line_format) + ": " + subject_line) + diagnose_subject_line(subject_line, subject_line_format, err) if len(subject_line) >= 73: - error("Subject line should be 72 or less characters: " + subject_line) + err.error("Subject line should be 72 or fewer characters: " + subject_line) # Second one divides subject and body. if len(raw_body) > 1 and raw_body[1]: - error("Second message line should be empty: " + raw_body[1]) + err.error("Second message line should be empty: " + raw_body[1]) # Message body lines. for line in raw_body[2:]: # Long lines with URLs are exempt from the line length rule. if len(line) >= 76 and "://" not in line: - error("Message lines should be 75 or less characters: " + line) + err.error("Message lines should be 75 or less characters: " + line) if not raw_body[-1].startswith("Signed-off-by: ") or "@" not in raw_body[-1]: - warning("Message should be signed-off") - - return errors, warnings + err.warning('Message should be signed-off. Use "git commit -s".') def run(args): verbose("run", *args) - has_errors = False - has_warnings = False - for sha in git_log("%h", *args): - errors, warnings = verify(sha) - has_errors |= any(errors) - has_warnings |= any(warnings) - for err in errors: - print("error:", err) - for err in warnings: - print("warning:", err) - if has_errors or has_warnings: + + err = ErrorCollection() + + if "--check-file" in args: + filename = args[-1] + verbose("checking commit message from", filename) + with open(args[-1]) as f: + # Remove comment lines as well as any empty lines at the end. + lines = [line.rstrip("\r\n") for line in f if not line.startswith("#")] + while not lines[-1]: + lines.pop() + verify_message_body(lines, err) + else: # Normal operation, pass arguments to git log + for sha in git_log("%h", *args): + verify(sha, err) + + if err.has_errors or err.has_warnings: if suggestions: print("See https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md") else: print("ok") - if has_errors: + if err.has_errors: sys.exit(1) def show_help(): - print("usage: verifygitlog.py [-v -n -h] ...") + print("usage: verifygitlog.py [-v -n -h --check-file] ...") print("-v : increase verbosity, can be specified multiple times") print("-n : do not print multi-line suggestions") print("-h : print this help message and exit") + print( + "--check-file : Pass a single argument which is a file containing a candidate commit message" + ) + print( + "--ignore-rebase : Skip checking commits with git rebase autosquash prefixes or WIP as a prefix" + ) print("... : arguments passed to git log to retrieve commits to verify") print(" see https://www.git-scm.com/docs/git-log") print(" passing no arguments at all will verify all commits") @@ -117,6 +160,10 @@ if __name__ == "__main__": args = sys.argv[1:] verbosity = args.count("-v") suggestions = args.count("-n") == 0 + if "--ignore-rebase" in args: + args.remove("--ignore-rebase") + ignore_prefixes = ["squash!", "fixup!", "amend!", "WIP"] + if "-h" in args: show_help() else: