diff --git a/MicroPython_BUILD/.cproject b/MicroPython_BUILD/.cproject
index 74a9008..7594b09 100644
--- a/MicroPython_BUILD/.cproject
+++ b/MicroPython_BUILD/.cproject
@@ -49,6 +49,7 @@
+
@@ -117,7 +118,6 @@
${PWD}/BUILD.sh
-
-j8 all
true
false
@@ -125,7 +125,6 @@
${PWD}/BUILD.sh
-
flash
true
false
@@ -133,7 +132,6 @@
${PWD}/BUILD.sh
-
clean
true
false
@@ -141,6 +139,7 @@
${PWD}/BUILD.sh
+
-v all
true
false
@@ -148,6 +147,7 @@
${PWD}/BUILD.sh
+
-f8 flash
true
false
@@ -155,6 +155,7 @@
${PWD}/BUILD.sh
+
-f16 flash
true
false
@@ -176,7 +177,6 @@
${PWD}/BUILD.sh
-
-j8 clean all
true
false
@@ -184,7 +184,6 @@
${PWD}/BUILD.sh
-
-j8 clean all flash
true
false
@@ -193,7 +192,14 @@
mate-terminal
--working-directory="${PWD}" -e "./BUILD.sh menuconfig" &
-
+ true
+ false
+ true
+
+
+ ${PWD}/BUILD.sh
+
+ -j8 -v clean all
true
false
true
diff --git a/MicroPython_BUILD/BUILD.sh b/MicroPython_BUILD/BUILD.sh
index fc92da6..e53747f 100755
--- a/MicroPython_BUILD/BUILD.sh
+++ b/MicroPython_BUILD/BUILD.sh
@@ -20,6 +20,9 @@
# makefatfs - create FatFS image
# flashfatfs - create and flash FatFS image to ESP32
# copyfatfs - flash prebuilt FatFS image to ESP32
+# makelfsfs - create LittleFS image
+# flashlfsfs - create and flash LittleFS image to ESP32
+# copylfsfs - flash prebuilt LittleFS image to ESP32
# size - display static memory footprint of the firmware
# size-components - display detailed memory footprint of the firmware
# size-files - display detailed memory footprint of the firmware
@@ -45,7 +48,7 @@
#=======================
-TOOLS_VER=ver20180321.id
+TOOLS_VER=ver20180404.id
#=======================
# -----------------------------
diff --git a/MicroPython_BUILD/components/micropython/README.md b/MicroPython_BUILD/components/micropython/README.md
new file mode 100644
index 0000000..9bfde4d
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/README.md
@@ -0,0 +1,58 @@
+# MicroPython for ESP32
+
+# with support for 4MB of psRAM
+
+
+**MicroPython core** is synchronized with [main MicroPython repository](https://github.com/micropython/micropython)
+
+**Commit:** bcfff4fc98a73c5ad9b7d3e338649955e861ada4
+
+
+
+Some source files are changed to be compatible with this port.
+All modified files has the copyright notice:
+_Copyright (c) 2018 LoBo (https://github.com/loboris)_
+
+## List of the modified files:
+
+### **py** directory
+
+builtinhelp.c
+modmath.c
+modmicropython.c
+modsys.c
+modthread.c
+mpconfig.h
+mphal.h
+mpstate.h
+mpthread.h
+mpz.c
+mpz.h
+obj.c
+obj.h
+objint_mpz.c
+ringbuf.h
+runtime.h
+scheduler.c
+vm.c
+
+### **extmod** directory
+
+machine_pulse.c
+modbtree.c
+modframebuf.c
+modlwip.c
+moduhashlib.c
+moduselect.c
+modussl_mbedtls.c
+modutimeq.c
+utime_mphal.c
+utime_mphal.h
+vfs.c
+
+### **lib** directory
+
+utils/pyexec.c
+utils/sys_stdio_mphal.c
+mp-readline/readline.c
+
diff --git a/MicroPython_BUILD/components/micropython/docs/library/array.rst b/MicroPython_BUILD/components/micropython/docs/library/array.rst
new file mode 100644
index 0000000..f837b03
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/array.rst
@@ -0,0 +1,29 @@
+:mod:`array` -- arrays of numeric data
+======================================
+
+.. module:: array
+ :synopsis: efficient arrays of numeric data
+
+|see_cpython_module| :mod:`python:array`.
+
+Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``,
+``L``, ``q``, ``Q``, ``f``, ``d`` (the latter 2 depending on the
+floating-point support).
+
+Classes
+-------
+
+.. class:: array.array(typecode, [iterable])
+
+ Create array with elements of given type. Initial contents of the
+ array are given by *iterable*. If it is not provided, an empty
+ array is created.
+
+ .. method:: append(val)
+
+ Append new element *val* to the end of array, growing it.
+
+ .. method:: extend(iterable)
+
+ Append new elements as contained in *iterable* to the end of
+ array, growing it.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/btree.rst b/MicroPython_BUILD/components/micropython/docs/library/btree.rst
new file mode 100644
index 0000000..3578acd
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/btree.rst
@@ -0,0 +1,159 @@
+:mod:`btree` -- simple BTree database
+=====================================
+
+.. module:: btree
+ :synopsis: simple BTree database
+
+The ``btree`` module implements a simple key-value database using external
+storage (disk files, or in general case, a random-access `stream`). Keys are
+stored sorted in the database, and besides efficient retrieval by a key
+value, a database also supports efficient ordered range scans (retrieval
+of values with the keys in a given range). On the application interface
+side, BTree database work as close a possible to a way standard `dict`
+type works, one notable difference is that both keys and values must
+be `bytes` objects (so, if you want to store objects of other types, you
+need to serialize them to `bytes` first).
+
+The module is based on the well-known BerkelyDB library, version 1.xx.
+
+Example::
+
+ import btree
+
+ # First, we need to open a stream which holds a database
+ # This is usually a file, but can be in-memory database
+ # using uio.BytesIO, a raw flash partition, etc.
+ # Oftentimes, you want to create a database file if it doesn't
+ # exist and open if it exists. Idiom below takes care of this.
+ # DO NOT open database with "a+b" access mode.
+ try:
+ f = open("mydb", "r+b")
+ except OSError:
+ f = open("mydb", "w+b")
+
+ # Now open a database itself
+ db = btree.open(f)
+
+ # The keys you add will be sorted internally in the database
+ db[b"3"] = b"three"
+ db[b"1"] = b"one"
+ db[b"2"] = b"two"
+
+ # Assume that any changes are cached in memory unless
+ # explicitly flushed (or database closed). Flush database
+ # at the end of each "transaction".
+ db.flush()
+
+ # Prints b'two'
+ print(db[b"2"])
+
+ # Iterate over sorted keys in the database, starting from b"2"
+ # until the end of the database, returning only values.
+ # Mind that arguments passed to values() method are *key* values.
+ # Prints:
+ # b'two'
+ # b'three'
+ for word in db.values(b"2"):
+ print(word)
+
+ del db[b"2"]
+
+ # No longer true, prints False
+ print(b"2" in db)
+
+ # Prints:
+ # b"1"
+ # b"3"
+ for key in db:
+ print(key)
+
+ db.close()
+
+ # Don't forget to close the underlying stream!
+ f.close()
+
+
+Functions
+---------
+
+.. function:: open(stream, \*, flags=0, pagesize=0, cachesize=0, minkeypage=0)
+
+ Open a database from a random-access `stream` (like an open file). All
+ other parameters are optional and keyword-only, and allow to tweak advanced
+ parameters of the database operation (most users will not need them):
+
+ * *flags* - Currently unused.
+ * *pagesize* - Page size used for the nodes in BTree. Acceptable range
+ is 512-65536. If 0, a port-specific default will be used, optimized for
+ port's memory usage and/or performance.
+ * *cachesize* - Suggested memory cache size in bytes. For a
+ board with enough memory using larger values may improve performance.
+ Cache policy is as follows: entire cache is not allocated at once;
+ instead, accessing a new page in database will allocate a memory buffer
+ for it, until value specified by *cachesize* is reached. Then, these
+ buffers will be managed using LRU (least recently used) policy. More
+ buffers may still be allocated if needed (e.g., if a database contains
+ big keys and/or values). Allocated cache buffers aren't reclaimed.
+ * *minkeypage* - Minimum number of keys to store per page. Default value
+ of 0 equivalent to 2.
+
+ Returns a BTree object, which implements a dictionary protocol (set
+ of methods), and some additional methods described below.
+
+Methods
+-------
+
+.. method:: btree.close()
+
+ Close the database. It's mandatory to close the database at the end of
+ processing, as some unwritten data may be still in the cache. Note that
+ this does not close underlying stream with which the database was opened,
+ it should be closed separately (which is also mandatory to make sure that
+ data flushed from buffer to the underlying storage).
+
+.. method:: btree.flush()
+
+ Flush any data in cache to the underlying stream.
+
+.. method:: btree.__getitem__(key)
+ btree.get(key, default=None)
+ btree.__setitem__(key, val)
+ btree.__detitem__(key)
+ btree.__contains__(key)
+
+ Standard dictionary methods.
+
+.. method:: btree.__iter__()
+
+ A BTree object can be iterated over directly (similar to a dictionary)
+ to get access to all keys in order.
+
+.. method:: btree.keys([start_key, [end_key, [flags]]])
+ btree.values([start_key, [end_key, [flags]]])
+ btree.items([start_key, [end_key, [flags]]])
+
+ These methods are similar to standard dictionary methods, but also can
+ take optional parameters to iterate over a key sub-range, instead of
+ the entire database. Note that for all 3 methods, *start_key* and
+ *end_key* arguments represent key values. For example, `values()`
+ method will iterate over values corresponding to they key range
+ given. None values for *start_key* means "from the first key", no
+ *end_key* or its value of None means "until the end of database".
+ By default, range is inclusive of *start_key* and exclusive of
+ *end_key*, you can include *end_key* in iteration by passing *flags*
+ of `btree.INCL`. You can iterate in descending key direction
+ by passing *flags* of `btree.DESC`. The flags values can be ORed
+ together.
+
+Constants
+---------
+
+.. data:: INCL
+
+ A flag for `keys()`, `values()`, `items()` methods to specify that
+ scanning should be inclusive of the end key.
+
+.. data:: DESC
+
+ A flag for `keys()`, `values()`, `items()` methods to specify that
+ scanning should be in descending direction of keys.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/builtins.rst b/MicroPython_BUILD/components/micropython/docs/library/builtins.rst
new file mode 100644
index 0000000..365248d
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/builtins.rst
@@ -0,0 +1,199 @@
+Builtin functions and exceptions
+================================
+
+All builtin functions and exceptions are described here. They are also
+available via ``builtins`` module.
+
+Functions and types
+-------------------
+
+.. function:: abs()
+
+.. function:: all()
+
+.. function:: any()
+
+.. function:: bin()
+
+.. class:: bool()
+
+.. class:: bytearray()
+
+.. class:: bytes()
+
+ |see_cpython| `python:bytes`.
+
+.. function:: callable()
+
+.. function:: chr()
+
+.. function:: classmethod()
+
+.. function:: compile()
+
+.. class:: complex()
+
+.. function:: delattr(obj, name)
+
+ The argument *name* should be a string, and this function deletes the named
+ attribute from the object given by *obj*.
+
+.. class:: dict()
+
+.. function:: dir()
+
+.. function:: divmod()
+
+.. function:: enumerate()
+
+.. function:: eval()
+
+.. function:: exec()
+
+.. function:: filter()
+
+.. class:: float()
+
+.. class:: frozenset()
+
+.. function:: getattr()
+
+.. function:: globals()
+
+.. function:: hasattr()
+
+.. function:: hash()
+
+.. function:: hex()
+
+.. function:: id()
+
+.. function:: input()
+
+.. class:: int()
+
+ .. classmethod:: from_bytes(bytes, byteorder)
+
+ In MicroPython, `byteorder` parameter must be positional (this is
+ compatible with CPython).
+
+ .. method:: to_bytes(size, byteorder)
+
+ In MicroPython, `byteorder` parameter must be positional (this is
+ compatible with CPython).
+
+.. function:: isinstance()
+
+.. function:: issubclass()
+
+.. function:: iter()
+
+.. function:: len()
+
+.. class:: list()
+
+.. function:: locals()
+
+.. function:: map()
+
+.. function:: max()
+
+.. class:: memoryview()
+
+.. function:: min()
+
+.. function:: next()
+
+.. class:: object()
+
+.. function:: oct()
+
+.. function:: open()
+
+.. function:: ord()
+
+.. function:: pow()
+
+.. function:: print()
+
+.. function:: property()
+
+.. function:: range()
+
+.. function:: repr()
+
+.. function:: reversed()
+
+.. function:: round()
+
+.. class:: set()
+
+.. function:: setattr()
+
+.. class:: slice()
+
+ The *slice* builtin is the type that slice objects have.
+
+.. function:: sorted()
+
+.. function:: staticmethod()
+
+.. class:: str()
+
+.. function:: sum()
+
+.. function:: super()
+
+.. class:: tuple()
+
+.. function:: type()
+
+.. function:: zip()
+
+
+Exceptions
+----------
+
+.. exception:: AssertionError
+
+.. exception:: AttributeError
+
+.. exception:: Exception
+
+.. exception:: ImportError
+
+.. exception:: IndexError
+
+.. exception:: KeyboardInterrupt
+
+.. exception:: KeyError
+
+.. exception:: MemoryError
+
+.. exception:: NameError
+
+.. exception:: NotImplementedError
+
+.. exception:: OSError
+
+ |see_cpython| `python:OSError`. MicroPython doesn't implement ``errno``
+ attribute, instead use the standard way to access exception arguments:
+ ``exc.args[0]``.
+
+.. exception:: RuntimeError
+
+.. exception:: StopIteration
+
+.. exception:: SyntaxError
+
+.. exception:: SystemExit
+
+ |see_cpython| `python:SystemExit`.
+
+.. exception:: TypeError
+
+ |see_cpython| `python:TypeError`.
+
+.. exception:: ValueError
+
+.. exception:: ZeroDivisionError
diff --git a/MicroPython_BUILD/components/micropython/docs/library/cmath.rst b/MicroPython_BUILD/components/micropython/docs/library/cmath.rst
new file mode 100644
index 0000000..59e4ec1
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/cmath.rst
@@ -0,0 +1,63 @@
+:mod:`cmath` -- mathematical functions for complex numbers
+==========================================================
+
+.. module:: cmath
+ :synopsis: mathematical functions for complex numbers
+
+|see_cpython_module| :mod:`python:cmath`.
+
+The ``cmath`` module provides some basic mathematical functions for
+working with complex numbers.
+
+Availability: not available on WiPy and ESP8266. Floating point support
+required for this module.
+
+Functions
+---------
+
+.. function:: cos(z)
+
+ Return the cosine of ``z``.
+
+.. function:: exp(z)
+
+ Return the exponential of ``z``.
+
+.. function:: log(z)
+
+ Return the natural logarithm of ``z``. The branch cut is along the negative real axis.
+
+.. function:: log10(z)
+
+ Return the base-10 logarithm of ``z``. The branch cut is along the negative real axis.
+
+.. function:: phase(z)
+
+ Returns the phase of the number ``z``, in the range (-pi, +pi].
+
+.. function:: polar(z)
+
+ Returns, as a tuple, the polar form of ``z``.
+
+.. function:: rect(r, phi)
+
+ Returns the complex number with modulus ``r`` and phase ``phi``.
+
+.. function:: sin(z)
+
+ Return the sine of ``z``.
+
+.. function:: sqrt(z)
+
+ Return the square-root of ``z``.
+
+Constants
+---------
+
+.. data:: e
+
+ base of the natural logarithm
+
+.. data:: pi
+
+ the ratio of a circle's circumference to its diameter
diff --git a/MicroPython_BUILD/components/micropython/docs/library/framebuf.rst b/MicroPython_BUILD/components/micropython/docs/library/framebuf.rst
new file mode 100644
index 0000000..ed4b78a
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/framebuf.rst
@@ -0,0 +1,161 @@
+:mod:`framebuf` --- Frame buffer manipulation
+=============================================
+
+.. module:: framebuf
+ :synopsis: Frame buffer manipulation
+
+This module provides a general frame buffer which can be used to create
+bitmap images, which can then be sent to a display.
+
+class FrameBuffer
+-----------------
+
+The FrameBuffer class provides a pixel buffer which can be drawn upon with
+pixels, lines, rectangles, text and even other FrameBuffer's. It is useful
+when generating output for displays.
+
+For example::
+
+ import framebuf
+
+ # FrameBuffer needs 2 bytes for every RGB565 pixel
+ fbuf = FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565)
+
+ fbuf.fill(0)
+ fbuf.text('MicroPython!', 0, 0, 0xffff)
+ fbuf.hline(0, 10, 96, 0xffff)
+
+Constructors
+------------
+
+.. class:: FrameBuffer(buffer, width, height, format, stride=width)
+
+ Construct a FrameBuffer object. The parameters are:
+
+ - *buffer* is an object with a buffer protocol which must be large
+ enough to contain every pixel defined by the width, height and
+ format of the FrameBuffer.
+ - *width* is the width of the FrameBuffer in pixels
+ - *height* is the height of the FrameBuffer in pixels
+ - *format* specifies the type of pixel used in the FrameBuffer;
+ permissible values are listed under Constants below. These set the
+ number of bits used to encode a color value and the layout of these
+ bits in *buffer*.
+ Where a color value c is passed to a method, c is a small integer
+ with an encoding that is dependent on the format of the FrameBuffer.
+ - *stride* is the number of pixels between each horizontal line
+ of pixels in the FrameBuffer. This defaults to *width* but may
+ need adjustments when implementing a FrameBuffer within another
+ larger FrameBuffer or screen. The *buffer* size must accommodate
+ an increased step size.
+
+ One must specify valid *buffer*, *width*, *height*, *format* and
+ optionally *stride*. Invalid *buffer* size or dimensions may lead to
+ unexpected errors.
+
+Drawing primitive shapes
+------------------------
+
+The following methods draw shapes onto the FrameBuffer.
+
+.. method:: FrameBuffer.fill(c)
+
+ Fill the entire FrameBuffer with the specified color.
+
+.. method:: FrameBuffer.pixel(x, y[, c])
+
+ If *c* is not given, get the color value of the specified pixel.
+ If *c* is given, set the specified pixel to the given color.
+
+.. method:: FrameBuffer.hline(x, y, w, c)
+.. method:: FrameBuffer.vline(x, y, h, c)
+.. method:: FrameBuffer.line(x1, y1, x2, y2, c)
+
+ Draw a line from a set of coordinates using the given color and
+ a thickness of 1 pixel. The `line` method draws the line up to
+ a second set of coordinates whereas the `hline` and `vline`
+ methods draw horizontal and vertical lines respectively up to
+ a given length.
+
+.. method:: FrameBuffer.rect(x, y, w, h, c)
+.. method:: FrameBuffer.fill_rect(x, y, w, h, c)
+
+ Draw a rectangle at the given location, size and color. The `rect`
+ method draws only a 1 pixel outline whereas the `fill_rect` method
+ draws both the outline and interior.
+
+Drawing text
+------------
+
+.. method:: FrameBuffer.text(s, x, y[, c])
+
+ Write text to the FrameBuffer using the the coordinates as the upper-left
+ corner of the text. The color of the text can be defined by the optional
+ argument but is otherwise a default value of 1. All characters have
+ dimensions of 8x8 pixels and there is currently no way to change the font.
+
+
+Other methods
+-------------
+
+.. method:: FrameBuffer.scroll(xstep, ystep)
+
+ Shift the contents of the FrameBuffer by the given vector. This may
+ leave a footprint of the previous colors in the FrameBuffer.
+
+.. method:: FrameBuffer.blit(fbuf, x, y[, key])
+
+ Draw another FrameBuffer on top of the current one at the given coordinates.
+ If *key* is specified then it should be a color integer and the
+ corresponding color will be considered transparent: all pixels with that
+ color value will not be drawn.
+
+ This method works between FrameBuffer instances utilising different formats,
+ but the resulting colors may be unexpected due to the mismatch in color
+ formats.
+
+Constants
+---------
+
+.. data:: framebuf.MONO_VLSB
+
+ Monochrome (1-bit) color format
+ This defines a mapping where the bits in a byte are vertically mapped with
+ bit 0 being nearest the top of the screen. Consequently each byte occupies
+ 8 vertical pixels. Subsequent bytes appear at successive horizontal
+ locations until the rightmost edge is reached. Further bytes are rendered
+ at locations starting at the leftmost edge, 8 pixels lower.
+
+.. data:: framebuf.MONO_HLSB
+
+ Monochrome (1-bit) color format
+ This defines a mapping where the bits in a byte are horizontally mapped.
+ Each byte occupies 8 horizontal pixels with bit 0 being the leftmost.
+ Subsequent bytes appear at successive horizontal locations until the
+ rightmost edge is reached. Further bytes are rendered on the next row, one
+ pixel lower.
+
+.. data:: framebuf.MONO_HMSB
+
+ Monochrome (1-bit) color format
+ This defines a mapping where the bits in a byte are horizontally mapped.
+ Each byte occupies 8 horizontal pixels with bit 7 being the leftmost.
+ Subsequent bytes appear at successive horizontal locations until the
+ rightmost edge is reached. Further bytes are rendered on the next row, one
+ pixel lower.
+
+.. data:: framebuf.RGB565
+
+ Red Green Blue (16-bit, 5+6+5) color format
+
+.. data:: framebuf.GS2_HMSB
+
+ Grayscale (2-bit) color format
+
+.. data:: framebuf.GS4_HMSB
+
+ Grayscale (4-bit) color format
+
+.. data:: framebuf.GS8
+
+ Grayscale (8-bit) color format
diff --git a/MicroPython_BUILD/components/micropython/docs/library/gc.rst b/MicroPython_BUILD/components/micropython/docs/library/gc.rst
new file mode 100644
index 0000000..c823aed
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/gc.rst
@@ -0,0 +1,66 @@
+:mod:`gc` -- control the garbage collector
+==========================================
+
+.. module:: gc
+ :synopsis: control the garbage collector
+
+|see_cpython_module| :mod:`python:gc`.
+
+Functions
+---------
+
+.. function:: enable()
+
+ Enable automatic garbage collection.
+
+.. function:: disable()
+
+ Disable automatic garbage collection. Heap memory can still be allocated,
+ and garbage collection can still be initiated manually using :meth:`gc.collect`.
+
+.. function:: collect()
+
+ Run a garbage collection.
+
+.. function:: mem_alloc()
+
+ Return the number of bytes of heap RAM that are allocated.
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ This function is MicroPython extension.
+
+.. function:: mem_free()
+
+ Return the number of bytes of available heap RAM, or -1 if this amount
+ is not known.
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ This function is MicroPython extension.
+
+.. function:: threshold([amount])
+
+ Set or query the additional GC allocation threshold. Normally, a collection
+ is triggered only when a new allocation cannot be satisfied, i.e. on an
+ out-of-memory (OOM) condition. If this function is called, in addition to
+ OOM, a collection will be triggered each time after *amount* bytes have been
+ allocated (in total, since the previous time such an amount of bytes
+ have been allocated). *amount* is usually specified as less than the
+ full heap size, with the intention to trigger a collection earlier than when the
+ heap becomes exhausted, and in the hope that an early collection will prevent
+ excessive memory fragmentation. This is a heuristic measure, the effect
+ of which will vary from application to application, as well as
+ the optimal value of the *amount* parameter.
+
+ Calling the function without argument will return the current value of
+ the threshold. A value of -1 means a disabled allocation threshold.
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ This function is a MicroPython extension. CPython has a similar
+ function - ``set_threshold()``, but due to different GC
+ implementations, its signature and semantics are different.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/math.rst b/MicroPython_BUILD/components/micropython/docs/library/math.rst
new file mode 100644
index 0000000..a6f13d4
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/math.rst
@@ -0,0 +1,185 @@
+:mod:`math` -- mathematical functions
+=====================================
+
+.. module:: math
+ :synopsis: mathematical functions
+
+|see_cpython_module| :mod:`python:math`.
+
+The ``math`` module provides some basic mathematical functions for
+working with floating-point numbers.
+
+*Note:* On the pyboard, floating-point numbers have 32-bit precision.
+
+Availability: not available on WiPy. Floating point support required
+for this module.
+
+Functions
+---------
+
+.. function:: acos(x)
+
+ Return the inverse cosine of ``x``.
+
+.. function:: acosh(x)
+
+ Return the inverse hyperbolic cosine of ``x``.
+
+.. function:: asin(x)
+
+ Return the inverse sine of ``x``.
+
+.. function:: asinh(x)
+
+ Return the inverse hyperbolic sine of ``x``.
+
+.. function:: atan(x)
+
+ Return the inverse tangent of ``x``.
+
+.. function:: atan2(y, x)
+
+ Return the principal value of the inverse tangent of ``y/x``.
+
+.. function:: atanh(x)
+
+ Return the inverse hyperbolic tangent of ``x``.
+
+.. function:: ceil(x)
+
+ Return an integer, being ``x`` rounded towards positive infinity.
+
+.. function:: copysign(x, y)
+
+ Return ``x`` with the sign of ``y``.
+
+.. function:: cos(x)
+
+ Return the cosine of ``x``.
+
+.. function:: cosh(x)
+
+ Return the hyperbolic cosine of ``x``.
+
+.. function:: degrees(x)
+
+ Return radians ``x`` converted to degrees.
+
+.. function:: erf(x)
+
+ Return the error function of ``x``.
+
+.. function:: erfc(x)
+
+ Return the complementary error function of ``x``.
+
+.. function:: exp(x)
+
+ Return the exponential of ``x``.
+
+.. function:: expm1(x)
+
+ Return ``exp(x) - 1``.
+
+.. function:: fabs(x)
+
+ Return the absolute value of ``x``.
+
+.. function:: floor(x)
+
+ Return an integer, being ``x`` rounded towards negative infinity.
+
+.. function:: fmod(x, y)
+
+ Return the remainder of ``x/y``.
+
+.. function:: frexp(x)
+
+ Decomposes a floating-point number into its mantissa and exponent.
+ The returned value is the tuple ``(m, e)`` such that ``x == m * 2**e``
+ exactly. If ``x == 0`` then the function returns ``(0.0, 0)``, otherwise
+ the relation ``0.5 <= abs(m) < 1`` holds.
+
+.. function:: gamma(x)
+
+ Return the gamma function of ``x``.
+
+.. function:: isfinite(x)
+
+ Return ``True`` if ``x`` is finite.
+
+.. function:: isinf(x)
+
+ Return ``True`` if ``x`` is infinite.
+
+.. function:: isnan(x)
+
+ Return ``True`` if ``x`` is not-a-number
+
+.. function:: ldexp(x, exp)
+
+ Return ``x * (2**exp)``.
+
+.. function:: lgamma(x)
+
+ Return the natural logarithm of the gamma function of ``x``.
+
+.. function:: log(x)
+
+ Return the natural logarithm of ``x``.
+
+.. function:: log10(x)
+
+ Return the base-10 logarithm of ``x``.
+
+.. function:: log2(x)
+
+ Return the base-2 logarithm of ``x``.
+
+.. function:: modf(x)
+
+ Return a tuple of two floats, being the fractional and integral parts of
+ ``x``. Both return values have the same sign as ``x``.
+
+.. function:: pow(x, y)
+
+ Returns ``x`` to the power of ``y``.
+
+.. function:: radians(x)
+
+ Return degrees ``x`` converted to radians.
+
+.. function:: sin(x)
+
+ Return the sine of ``x``.
+
+.. function:: sinh(x)
+
+ Return the hyperbolic sine of ``x``.
+
+.. function:: sqrt(x)
+
+ Return the square root of ``x``.
+
+.. function:: tan(x)
+
+ Return the tangent of ``x``.
+
+.. function:: tanh(x)
+
+ Return the hyperbolic tangent of ``x``.
+
+.. function:: trunc(x)
+
+ Return an integer, being ``x`` rounded towards 0.
+
+Constants
+---------
+
+.. data:: e
+
+ base of the natural logarithm
+
+.. data:: pi
+
+ the ratio of a circle's circumference to its diameter
diff --git a/MicroPython_BUILD/components/micropython/docs/library/micropython.rst b/MicroPython_BUILD/components/micropython/docs/library/micropython.rst
new file mode 100644
index 0000000..a6ea738
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/micropython.rst
@@ -0,0 +1,137 @@
+:mod:`micropython` -- access and control MicroPython internals
+==============================================================
+
+.. module:: micropython
+ :synopsis: access and control MicroPython internals
+
+Functions
+---------
+
+.. function:: const(expr)
+
+ Used to declare that the expression is a constant so that the compile can
+ optimise it. The use of this function should be as follows::
+
+ from micropython import const
+
+ CONST_X = const(123)
+ CONST_Y = const(2 * CONST_X + 1)
+
+ Constants declared this way are still accessible as global variables from
+ outside the module they are declared in. On the other hand, if a constant
+ begins with an underscore then it is hidden, it is not available as a global
+ variable, and does not take up any memory during execution.
+
+ This `const` function is recognised directly by the MicroPython parser and is
+ provided as part of the :mod:`micropython` module mainly so that scripts can be
+ written which run under both CPython and MicroPython, by following the above
+ pattern.
+
+.. function:: opt_level([level])
+
+ If *level* is given then this function sets the optimisation level for subsequent
+ compilation of scripts, and returns ``None``. Otherwise it returns the current
+ optimisation level.
+
+ The optimisation level controls the following compilation features:
+
+ - Assertions: at level 0 assertion statements are enabled and compiled into the
+ bytecode; at levels 1 and higher assertions are not compiled.
+ - Built-in ``__debug__`` variable: at level 0 this variable expands to ``True``;
+ at levels 1 and higher it expands to ``False``.
+ - Source-code line numbers: at levels 0, 1 and 2 source-code line number are
+ stored along with the bytecode so that exceptions can report the line number
+ they occurred at; at levels 3 and higher line numbers are not stored.
+
+ The default optimisation level is usually level 0.
+
+.. function:: alloc_emergency_exception_buf(size)
+
+ Allocate *size* bytes of RAM for the emergency exception buffer (a good
+ size is around 100 bytes). The buffer is used to create exceptions in cases
+ when normal RAM allocation would fail (eg within an interrupt handler) and
+ therefore give useful traceback information in these situations.
+
+ A good way to use this function is to put it at the start of your main script
+ (eg ``boot.py`` or ``main.py``) and then the emergency exception buffer will be active
+ for all the code following it.
+
+.. function:: mem_info([verbose])
+
+ Print information about currently used memory. If the *verbose* argument
+ is given then extra information is printed.
+
+ The information that is printed is implementation dependent, but currently
+ includes the amount of stack and heap used. In verbose mode it prints out
+ the entire heap indicating which blocks are used and which are free.
+
+.. function:: qstr_info([verbose])
+
+ Print information about currently interned strings. If the *verbose*
+ argument is given then extra information is printed.
+
+ The information that is printed is implementation dependent, but currently
+ includes the number of interned strings and the amount of RAM they use. In
+ verbose mode it prints out the names of all RAM-interned strings.
+
+.. function:: stack_use()
+
+ Return an integer representing the current amount of stack that is being
+ used. The absolute value of this is not particularly useful, rather it
+ should be used to compute differences in stack usage at different points.
+
+.. function:: heap_lock()
+.. function:: heap_unlock()
+
+ Lock or unlock the heap. When locked no memory allocation can occur and a
+ `MemoryError` will be raised if any heap allocation is attempted.
+
+ These functions can be nested, ie `heap_lock()` can be called multiple times
+ in a row and the lock-depth will increase, and then `heap_unlock()` must be
+ called the same number of times to make the heap available again.
+
+.. function:: kbd_intr(chr)
+
+ Set the character that will raise a `KeyboardInterrupt` exception. By
+ default this is set to 3 during script execution, corresponding to Ctrl-C.
+ Passing -1 to this function will disable capture of Ctrl-C, and passing 3
+ will restore it.
+
+ This function can be used to prevent the capturing of Ctrl-C on the
+ incoming stream of characters that is usually used for the REPL, in case
+ that stream is used for other purposes.
+
+.. function:: schedule(func, arg)
+
+ Schedule the function *func* to be executed "very soon". The function
+ is passed the value *arg* as its single argument. "Very soon" means that
+ the MicroPython runtime will do its best to execute the function at the
+ earliest possible time, given that it is also trying to be efficient, and
+ that the following conditions hold:
+
+ - A scheduled function will never preempt another scheduled function.
+ - Scheduled functions are always executed "between opcodes" which means
+ that all fundamental Python operations (such as appending to a list)
+ are guaranteed to be atomic.
+ - A given port may define "critical regions" within which scheduled
+ functions will never be executed. Functions may be scheduled within
+ a critical region but they will not be executed until that region
+ is exited. An example of a critical region is a preempting interrupt
+ handler (an IRQ).
+
+ A use for this function is to schedule a callback from a preempting IRQ.
+ Such an IRQ puts restrictions on the code that runs in the IRQ (for example
+ the heap may be locked) and scheduling a function to call later will lift
+ those restrictions.
+
+ Note: If `schedule()` is called from a preempting IRQ, when memory
+ allocation is not allowed and the callback to be passed to `schedule()` is
+ a bound method, passing this directly will fail. This is because creating a
+ reference to a bound method causes memory allocation. A solution is to
+ create a reference to the method in the class constructor and to pass that
+ reference to `schedule()`. This is discussed in detail here
+ :ref:`reference documentation ` under "Creation of Python
+ objects".
+
+ There is a finite stack to hold the scheduled functions and `schedule()`
+ will raise a `RuntimeError` if the stack is full.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/network.rst b/MicroPython_BUILD/components/micropython/docs/library/network.rst
new file mode 100644
index 0000000..a113209
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/network.rst
@@ -0,0 +1,603 @@
+****************************************
+:mod:`network` --- network configuration
+****************************************
+
+.. module:: network
+ :synopsis: network configuration
+
+This module provides network drivers and routing configuration. To use this
+module, a MicroPython variant/build with network capabilities must be installed.
+Network drivers for specific hardware are available within this module and are
+used to configure hardware network interface(s). Network services provided
+by configured interfaces are then available for use via the :mod:`usocket`
+module.
+
+For example::
+
+ # connect/ show IP config a specific network interface
+ # see below for examples of specific drivers
+ import network
+ import utime
+ nic = network.Driver(...)
+ if not nic.isconnected():
+ nic.connect()
+ print("Waiting for connection...")
+ while not nic.isconnected():
+ utime.sleep(1)
+ print(nic.ifconfig())
+
+ # now use usocket as usual
+ import usocket as socket
+ addr = socket.getaddrinfo('micropython.org', 80)[0][-1]
+ s = socket.socket()
+ s.connect(addr)
+ s.send(b'GET / HTTP/1.1\r\nHost: micropython.org\r\n\r\n')
+ data = s.recv(1000)
+ s.close()
+
+Common network adapter interface
+================================
+
+This section describes an (implied) abstract base class for all network
+interface classes implemented by `MicroPython ports `
+for different hardware. This means that MicroPython does not actually
+provide ``AbstractNIC`` class, but any actual NIC class, as described
+in the following sections, implements methods as described here.
+
+.. class:: AbstractNIC(id=None, ...)
+
+Instantiate a network interface object. Parameters are network interface
+dependent. If there are more than one interface of the same type, the first
+parameter should be `id`.
+
+ .. method:: active([is_active])
+
+ Activate ("up") or deactivate ("down") the network interface, if
+ a boolean argument is passed. Otherwise, query current state if
+ no argument is provided. Most other methods require an active
+ interface (behavior of calling them on inactive interface is
+ undefined).
+
+ .. method:: connect([service_id, key=None, \*, ...])
+
+ Connect the interface to a network. This method is optional, and
+ available only for interfaces which are not "always connected".
+ If no parameters are given, connect to the default (or the only)
+ service. If a single parameter is given, it is the primary identifier
+ of a service to connect to. It may be accompanied by a key
+ (password) required to access said service. There can be further
+ arbitrary keyword-only parameters, depending on the networking medium
+ type and/or particular device. Parameters can be used to: a)
+ specify alternative service identifer types; b) provide additional
+ connection parameters. For various medium types, there are different
+ sets of predefined/recommended parameters, among them:
+
+ * WiFi: *bssid* keyword to connect to a specific BSSID (MAC address)
+
+ .. method:: disconnect()
+
+ Disconnect from network.
+
+ .. method:: isconnected()
+
+ Returns ``True`` if connected to network, otherwise returns ``False``.
+
+ .. method:: scan(\*, ...)
+
+ Scan for the available network services/connections. Returns a
+ list of tuples with discovered service parameters. For various
+ network media, there are different variants of predefined/
+ recommended tuple formats, among them:
+
+ * WiFi: (ssid, bssid, channel, RSSI, authmode, hidden). There
+ may be further fields, specific to a particular device.
+
+ The function may accept additional keyword arguments to filter scan
+ results (e.g. scan for a particular service, on a particular channel,
+ for services of a particular set, etc.), and to affect scan
+ duration and other parameters. Where possible, parameter names
+ should match those in connect().
+
+ .. method:: status([param])
+
+ Query dynamic status information of the interface. When called with no
+ argument the return value describes the network link status. Otherwise
+ *param* should be a string naming the particular status parameter to
+ retrieve.
+
+ The return types and values are dependent on the network
+ medium/technology. Some of the parameters that may be supported are:
+
+ * WiFi STA: use ``'rssi'`` to retrieve the RSSI of the AP signal
+ * WiFi AP: use ``'stations'`` to retrieve a list of all the STAs
+ connected to the AP. The list contains tuples of the form
+ (MAC, RSSI).
+
+ .. method:: ifconfig([(ip, subnet, gateway, dns)])
+
+ Get/set IP-level network interface parameters: IP address, subnet mask,
+ gateway and DNS server. When called with no arguments, this method returns
+ a 4-tuple with the above information. To set the above values, pass a
+ 4-tuple with the required information. For example::
+
+ nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
+
+ .. method:: config('param')
+ config(param=value, ...)
+
+ Get or set general network interface parameters. These methods allow to work
+ with additional parameters beyond standard IP configuration (as dealt with by
+ `ifconfig()`). These include network-specific and hardware-specific
+ parameters. For setting parameters, the keyword argument
+ syntax should be used, and multiple parameters can be set at once. For
+ querying, a parameter name should be quoted as a string, and only one
+ parameter can be queried at a time::
+
+ # Set WiFi access point name (formally known as ESSID) and WiFi channel
+ ap.config(essid='My AP', channel=11)
+ # Query params one by one
+ print(ap.config('essid'))
+ print(ap.config('channel'))
+
+.. only:: port_pyboard
+
+ class CC3K
+ ==========
+
+ This class provides a driver for CC3000 WiFi modules. Example usage::
+
+ import network
+ nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3)
+ nic.connect('your-ssid', 'your-password')
+ while not nic.isconnected():
+ pyb.delay(50)
+ print(nic.ifconfig())
+
+ # now use socket as usual
+ ...
+
+ For this example to work the CC3000 module must have the following connections:
+
+ - MOSI connected to Y8
+ - MISO connected to Y7
+ - CLK connected to Y6
+ - CS connected to Y5
+ - VBEN connected to Y4
+ - IRQ connected to Y3
+
+ It is possible to use other SPI busses and other pins for CS, VBEN and IRQ.
+
+ Constructors
+ ------------
+
+ .. class:: CC3K(spi, pin_cs, pin_en, pin_irq)
+
+ Create a CC3K driver object, initialise the CC3000 module using the given SPI bus
+ and pins, and return the CC3K object.
+
+ Arguments are:
+
+ - *spi* is an :ref:`SPI object ` which is the SPI bus that the CC3000 is
+ connected to (the MOSI, MISO and CLK pins).
+ - *pin_cs* is a :ref:`Pin object ` which is connected to the CC3000 CS pin.
+ - *pin_en* is a :ref:`Pin object ` which is connected to the CC3000 VBEN pin.
+ - *pin_irq* is a :ref:`Pin object ` which is connected to the CC3000 IRQ pin.
+
+ All of these objects will be initialised by the driver, so there is no need to
+ initialise them yourself. For example, you can use::
+
+ nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3)
+
+ Methods
+ -------
+
+ .. method:: cc3k.connect(ssid, key=None, \*, security=WPA2, bssid=None)
+
+ Connect to a WiFi access point using the given SSID, and other security
+ parameters.
+
+ .. method:: cc3k.disconnect()
+
+ Disconnect from the WiFi access point.
+
+ .. method:: cc3k.isconnected()
+
+ Returns True if connected to a WiFi access point and has a valid IP address,
+ False otherwise.
+
+ .. method:: cc3k.ifconfig()
+
+ Returns a 7-tuple with (ip, subnet mask, gateway, DNS server, DHCP server,
+ MAC address, SSID).
+
+ .. method:: cc3k.patch_version()
+
+ Return the version of the patch program (firmware) on the CC3000.
+
+ .. method:: cc3k.patch_program('pgm')
+
+ Upload the current firmware to the CC3000. You must pass 'pgm' as the first
+ argument in order for the upload to proceed.
+
+ Constants
+ ---------
+
+ .. data:: CC3K.WEP
+ .. data:: CC3K.WPA
+ .. data:: CC3K.WPA2
+
+ security type to use
+
+ class WIZNET5K
+ ==============
+
+ This class allows you to control WIZnet5x00 Ethernet adaptors based on
+ the W5200 and W5500 chipsets. The particular chipset that is supported
+ by the firmware is selected at compile-time via the MICROPY_PY_WIZNET5K
+ option.
+
+ Example usage::
+
+ import network
+ nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4)
+ print(nic.ifconfig())
+
+ # now use socket as usual
+ ...
+
+ For this example to work the WIZnet5x00 module must have the following connections:
+
+ - MOSI connected to X8
+ - MISO connected to X7
+ - SCLK connected to X6
+ - nSS connected to X5
+ - nRESET connected to X4
+
+ It is possible to use other SPI busses and other pins for nSS and nRESET.
+
+ Constructors
+ ------------
+
+ .. class:: WIZNET5K(spi, pin_cs, pin_rst)
+
+ Create a WIZNET5K driver object, initialise the WIZnet5x00 module using the given
+ SPI bus and pins, and return the WIZNET5K object.
+
+ Arguments are:
+
+ - *spi* is an :ref:`SPI object ` which is the SPI bus that the WIZnet5x00 is
+ connected to (the MOSI, MISO and SCLK pins).
+ - *pin_cs* is a :ref:`Pin object ` which is connected to the WIZnet5x00 nSS pin.
+ - *pin_rst* is a :ref:`Pin object ` which is connected to the WIZnet5x00 nRESET pin.
+
+ All of these objects will be initialised by the driver, so there is no need to
+ initialise them yourself. For example, you can use::
+
+ nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4)
+
+ Methods
+ -------
+
+ .. method:: wiznet5k.isconnected()
+
+ Returns ``True`` if the physical Ethernet link is connected and up.
+ Returns ``False`` otherwise.
+
+ .. method:: wiznet5k.ifconfig([(ip, subnet, gateway, dns)])
+
+ Get/set IP address, subnet mask, gateway and DNS.
+
+ When called with no arguments, this method returns a 4-tuple with the above information.
+
+ To set the above values, pass a 4-tuple with the required information. For example::
+
+ nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
+
+ .. method:: wiznet5k.regs()
+
+ Dump the WIZnet5x00 registers. Useful for debugging.
+
+.. _network.WLAN:
+
+.. only:: port_esp8266
+
+ Functions
+ =========
+
+ .. function:: phy_mode([mode])
+
+ Get or set the PHY mode.
+
+ If the *mode* parameter is provided, sets the mode to its value. If
+ the function is called without parameters, returns the current mode.
+
+ The possible modes are defined as constants:
+ * ``MODE_11B`` -- IEEE 802.11b,
+ * ``MODE_11G`` -- IEEE 802.11g,
+ * ``MODE_11N`` -- IEEE 802.11n.
+
+ class WLAN
+ ==========
+
+ This class provides a driver for WiFi network processor in the ESP8266. Example usage::
+
+ import network
+ # enable station interface and connect to WiFi access point
+ nic = network.WLAN(network.STA_IF)
+ nic.active(True)
+ nic.connect('your-ssid', 'your-password')
+ # now use sockets as usual
+
+ Constructors
+ ------------
+ .. class:: WLAN(interface_id)
+
+ Create a WLAN network interface object. Supported interfaces are
+ ``network.STA_IF`` (station aka client, connects to upstream WiFi access
+ points) and ``network.AP_IF`` (access point, allows other WiFi clients to
+ connect). Availability of the methods below depends on interface type.
+ For example, only STA interface may `connect()` to an access point.
+
+ Methods
+ -------
+
+ .. method:: wlan.active([is_active])
+
+ Activate ("up") or deactivate ("down") network interface, if boolean
+ argument is passed. Otherwise, query current state if no argument is
+ provided. Most other methods require active interface.
+
+ .. method:: wlan.connect(ssid=None, password=None, \*, bssid=None)
+
+ Connect to the specified wireless network, using the specified password.
+ If *bssid* is given then the connection will be restricted to the
+ access-point with that MAC address (the *ssid* must also be specified
+ in this case).
+
+ .. method:: wlan.disconnect()
+
+ Disconnect from the currently connected wireless network.
+
+ .. method:: wlan.scan()
+
+ Scan for the available wireless networks.
+
+ Scanning is only possible on STA interface. Returns list of tuples with
+ the information about WiFi access points:
+
+ (ssid, bssid, channel, RSSI, authmode, hidden)
+
+ *bssid* is hardware address of an access point, in binary form, returned as
+ bytes object. You can use `ubinascii.hexlify()` to convert it to ASCII form.
+
+ There are five values for authmode:
+
+ * 0 -- open
+ * 1 -- WEP
+ * 2 -- WPA-PSK
+ * 3 -- WPA2-PSK
+ * 4 -- WPA/WPA2-PSK
+
+ and two for hidden:
+
+ * 0 -- visible
+ * 1 -- hidden
+
+ .. method:: wlan.status([param])
+
+ Return the current status of the wireless connection.
+
+ When called with no argument the return value describes the network link status.
+ The possible statuses are defined as constants:
+
+ * ``STAT_IDLE`` -- no connection and no activity,
+ * ``STAT_CONNECTING`` -- connecting in progress,
+ * ``STAT_WRONG_PASSWORD`` -- failed due to incorrect password,
+ * ``STAT_NO_AP_FOUND`` -- failed because no access point replied,
+ * ``STAT_CONNECT_FAIL`` -- failed due to other problems,
+ * ``STAT_GOT_IP`` -- connection successful.
+
+ When called with one argument *param* should be a string naming the status
+ parameter to retrieve. Supported parameters in WiFI STA mode are: ``'rssi'``.
+
+ .. method:: wlan.isconnected()
+
+ In case of STA mode, returns ``True`` if connected to a WiFi access
+ point and has a valid IP address. In AP mode returns ``True`` when a
+ station is connected. Returns ``False`` otherwise.
+
+ .. method:: wlan.ifconfig([(ip, subnet, gateway, dns)])
+
+ Get/set IP-level network interface parameters: IP address, subnet mask,
+ gateway and DNS server. When called with no arguments, this method returns
+ a 4-tuple with the above information. To set the above values, pass a
+ 4-tuple with the required information. For example::
+
+ nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
+
+ .. method:: wlan.config('param')
+ .. method:: wlan.config(param=value, ...)
+
+ Get or set general network interface parameters. These methods allow to work
+ with additional parameters beyond standard IP configuration (as dealt with by
+ `wlan.ifconfig()`). These include network-specific and hardware-specific
+ parameters. For setting parameters, keyword argument syntax should be used,
+ multiple parameters can be set at once. For querying, parameters name should
+ be quoted as a string, and only one parameter can be queries at time::
+
+ # Set WiFi access point name (formally known as ESSID) and WiFi channel
+ ap.config(essid='My AP', channel=11)
+ # Query params one by one
+ print(ap.config('essid'))
+ print(ap.config('channel'))
+
+ Following are commonly supported parameters (availability of a specific parameter
+ depends on network technology type, driver, and `MicroPython port`).
+
+ ============= ===========
+ Parameter Description
+ ============= ===========
+ mac MAC address (bytes)
+ essid WiFi access point name (string)
+ channel WiFi channel (integer)
+ hidden Whether ESSID is hidden (boolean)
+ authmode Authentication mode supported (enumeration, see module constants)
+ password Access password (string)
+ dhcp_hostname The DHCP hostname to use
+ ============= ===========
+
+
+
+.. only:: port_wipy
+
+ class WLAN
+ ==========
+
+ This class provides a driver for the WiFi network processor in the WiPy. Example usage::
+
+ import network
+ import time
+ # setup as a station
+ wlan = network.WLAN(mode=WLAN.STA)
+ wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key'))
+ while not wlan.isconnected():
+ time.sleep_ms(50)
+ print(wlan.ifconfig())
+
+ # now use socket as usual
+ ...
+
+ Constructors
+ ------------
+
+ .. class:: WLAN(id=0, ...)
+
+ Create a WLAN object, and optionally configure it. See `init()` for params of configuration.
+
+ .. note::
+
+ The ``WLAN`` constructor is special in the sense that if no arguments besides the id are given,
+ it will return the already existing ``WLAN`` instance without re-configuring it. This is
+ because ``WLAN`` is a system feature of the WiPy. If the already existing instance is not
+ initialized it will do the same as the other constructors an will initialize it with default
+ values.
+
+ Methods
+ -------
+
+ .. method:: wlan.init(mode, \*, ssid, auth, channel, antenna)
+
+ Set or get the WiFi network processor configuration.
+
+ Arguments are:
+
+ - *mode* can be either ``WLAN.STA`` or ``WLAN.AP``.
+ - *ssid* is a string with the ssid name. Only needed when mode is ``WLAN.AP``.
+ - *auth* is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``,
+ ``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password.
+ If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal
+ values (e.g. 'ABC1DE45BF'). Only needed when mode is ``WLAN.AP``.
+ - *channel* a number in the range 1-11. Only needed when mode is ``WLAN.AP``.
+ - *antenna* selects between the internal and the external antenna. Can be either
+ ``WLAN.INT_ANT`` or ``WLAN.EXT_ANT``.
+
+ For example, you can do::
+
+ # create and configure as an access point
+ wlan.init(mode=WLAN.AP, ssid='wipy-wlan', auth=(WLAN.WPA2,'www.wipy.io'), channel=7, antenna=WLAN.INT_ANT)
+
+ or::
+
+ # configure as an station
+ wlan.init(mode=WLAN.STA)
+
+ .. method:: wlan.connect(ssid, \*, auth=None, bssid=None, timeout=None)
+
+ Connect to a WiFi access point using the given SSID, and other security
+ parameters.
+
+ - *auth* is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``,
+ ``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password.
+ If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal
+ values (e.g. 'ABC1DE45BF').
+ - *bssid* is the MAC address of the AP to connect to. Useful when there are several
+ APs with the same ssid.
+ - *timeout* is the maximum time in milliseconds to wait for the connection to succeed.
+
+ .. method:: wlan.scan()
+
+ Performs a network scan and returns a list of named tuples with (ssid, bssid, sec, channel, rssi).
+ Note that channel is always ``None`` since this info is not provided by the WiPy.
+
+ .. method:: wlan.disconnect()
+
+ Disconnect from the WiFi access point.
+
+ .. method:: wlan.isconnected()
+
+ In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address.
+ In AP mode returns ``True`` when a station is connected, ``False`` otherwise.
+
+ .. method:: wlan.ifconfig(if_id=0, config=['dhcp' or configtuple])
+
+ With no parameters given returns a 4-tuple of *(ip, subnet_mask, gateway, DNS_server)*.
+
+ if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params
+ are negotiated with the AP.
+
+ If the 4-tuple config is given then a static IP is configured. For instance::
+
+ wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
+
+ .. method:: wlan.mode([mode])
+
+ Get or set the WLAN mode.
+
+ .. method:: wlan.ssid([ssid])
+
+ Get or set the SSID when in AP mode.
+
+ .. method:: wlan.auth([auth])
+
+ Get or set the authentication type when in AP mode.
+
+ .. method:: wlan.channel([channel])
+
+ Get or set the channel (only applicable in AP mode).
+
+ .. method:: wlan.antenna([antenna])
+
+ Get or set the antenna type (external or internal).
+
+ .. method:: wlan.mac([mac_addr])
+
+ Get or set a 6-byte long bytes object with the MAC address.
+
+ .. method:: wlan.irq(\*, handler, wake)
+
+ Create a callback to be triggered when a WLAN event occurs during ``machine.SLEEP``
+ mode. Events are triggered by socket activity or by WLAN connection/disconnection.
+
+ - *handler* is the function that gets called when the IRQ is triggered.
+ - *wake* must be ``machine.SLEEP``.
+
+ Returns an IRQ object.
+
+ Constants
+ ---------
+
+ .. data:: WLAN.STA
+ .. data:: WLAN.AP
+
+ selects the WLAN mode
+
+ .. data:: WLAN.WEP
+ .. data:: WLAN.WPA
+ .. data:: WLAN.WPA2
+
+ selects the network security
+
+ .. data:: WLAN.INT_ANT
+ .. data:: WLAN.EXT_ANT
+
+ selects the antenna type
diff --git a/MicroPython_BUILD/components/micropython/docs/library/ubinascii.rst b/MicroPython_BUILD/components/micropython/docs/library/ubinascii.rst
new file mode 100644
index 0000000..192d345
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/ubinascii.rst
@@ -0,0 +1,40 @@
+:mod:`ubinascii` -- binary/ASCII conversions
+============================================
+
+.. module:: ubinascii
+ :synopsis: binary/ASCII conversions
+
+|see_cpython_module| :mod:`python:binascii`.
+
+This module implements conversions between binary data and various
+encodings of it in ASCII form (in both directions).
+
+Functions
+---------
+
+.. function:: hexlify(data, [sep])
+
+ Convert binary data to hexadecimal representation. Returns bytes string.
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ If additional argument, *sep* is supplied, it is used as a separator
+ between hexadecimal values.
+
+.. function:: unhexlify(data)
+
+ Convert hexadecimal data to binary representation. Returns bytes string.
+ (i.e. inverse of hexlify)
+
+.. function:: a2b_base64(data)
+
+ Decode base64-encoded data, ignoring invalid characters in the input.
+ Conforms to `RFC 2045 s.6.8 `_.
+ Returns a bytes object.
+
+.. function:: b2a_base64(data)
+
+ Encode binary data in base64 format, as in `RFC 3548
+ `_. Returns the encoded data
+ followed by a newline character, as a bytes object.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/ucollections.rst b/MicroPython_BUILD/components/micropython/docs/library/ucollections.rst
new file mode 100644
index 0000000..96de67a
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/ucollections.rst
@@ -0,0 +1,55 @@
+:mod:`ucollections` -- collection and container types
+=====================================================
+
+.. module:: ucollections
+ :synopsis: collection and container types
+
+|see_cpython_module| :mod:`python:collections`.
+
+This module implements advanced collection and container types to
+hold/accumulate various objects.
+
+Classes
+-------
+
+.. function:: namedtuple(name, fields)
+
+ This is factory function to create a new namedtuple type with a specific
+ name and set of fields. A namedtuple is a subclass of tuple which allows
+ to access its fields not just by numeric index, but also with an attribute
+ access syntax using symbolic field names. Fields is a sequence of strings
+ specifying field names. For compatibility with CPython it can also be a
+ a string with space-separated field named (but this is less efficient).
+ Example of use::
+
+ from ucollections import namedtuple
+
+ MyTuple = namedtuple("MyTuple", ("id", "name"))
+ t1 = MyTuple(1, "foo")
+ t2 = MyTuple(2, "bar")
+ print(t1.name)
+ assert t2.name == t2[1]
+
+.. function:: OrderedDict(...)
+
+ ``dict`` type subclass which remembers and preserves the order of keys
+ added. When ordered dict is iterated over, keys/items are returned in
+ the order they were added::
+
+ from ucollections import OrderedDict
+
+ # To make benefit of ordered keys, OrderedDict should be initialized
+ # from sequence of (key, value) pairs.
+ d = OrderedDict([("z", 1), ("a", 2)])
+ # More items can be added as usual
+ d["w"] = 5
+ d["b"] = 3
+ for k, v in d.items():
+ print(k, v)
+
+ Output::
+
+ z 1
+ a 2
+ w 5
+ b 3
diff --git a/MicroPython_BUILD/components/micropython/docs/library/uctypes.rst b/MicroPython_BUILD/components/micropython/docs/library/uctypes.rst
new file mode 100644
index 0000000..c938d74
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/uctypes.rst
@@ -0,0 +1,210 @@
+:mod:`uctypes` -- access binary data in a structured way
+========================================================
+
+.. module:: uctypes
+ :synopsis: access binary data in a structured way
+
+This module implements "foreign data interface" for MicroPython. The idea
+behind it is similar to CPython's ``ctypes`` modules, but the actual API is
+different, streamlined and optimized for small size. The basic idea of the
+module is to define data structure layout with about the same power as the
+C language allows, and then access it using familiar dot-syntax to reference
+sub-fields.
+
+.. seealso::
+
+ Module :mod:`ustruct`
+ Standard Python way to access binary data structures (doesn't scale
+ well to large and complex structures).
+
+Defining structure layout
+-------------------------
+
+Structure layout is defined by a "descriptor" - a Python dictionary which
+encodes field names as keys and other properties required to access them as
+associated values. Currently, uctypes requires explicit specification of
+offsets for each field. Offset are given in bytes from a structure start.
+
+Following are encoding examples for various field types:
+
+* Scalar types::
+
+ "field_name": offset | uctypes.UINT32
+
+ in other words, value is scalar type identifier ORed with field offset
+ (in bytes) from the start of the structure.
+
+* Recursive structures::
+
+ "sub": (offset, {
+ "b0": 0 | uctypes.UINT8,
+ "b1": 1 | uctypes.UINT8,
+ })
+
+ i.e. value is a 2-tuple, first element of which is offset, and second is
+ a structure descriptor dictionary (note: offsets in recursive descriptors
+ are relative to the structure it defines).
+
+* Arrays of primitive types::
+
+ "arr": (offset | uctypes.ARRAY, size | uctypes.UINT8),
+
+ i.e. value is a 2-tuple, first element of which is ARRAY flag ORed
+ with offset, and second is scalar element type ORed number of elements
+ in array.
+
+* Arrays of aggregate types::
+
+ "arr2": (offset | uctypes.ARRAY, size, {"b": 0 | uctypes.UINT8}),
+
+ i.e. value is a 3-tuple, first element of which is ARRAY flag ORed
+ with offset, second is a number of elements in array, and third is
+ descriptor of element type.
+
+* Pointer to a primitive type::
+
+ "ptr": (offset | uctypes.PTR, uctypes.UINT8),
+
+ i.e. value is a 2-tuple, first element of which is PTR flag ORed
+ with offset, and second is scalar element type.
+
+* Pointer to an aggregate type::
+
+ "ptr2": (offset | uctypes.PTR, {"b": 0 | uctypes.UINT8}),
+
+ i.e. value is a 2-tuple, first element of which is PTR flag ORed
+ with offset, second is descriptor of type pointed to.
+
+* Bitfields::
+
+ "bitf0": offset | uctypes.BFUINT16 | lsbit << uctypes.BF_POS | bitsize << uctypes.BF_LEN,
+
+ i.e. value is type of scalar value containing given bitfield (typenames are
+ similar to scalar types, but prefixes with "BF"), ORed with offset for
+ scalar value containing the bitfield, and further ORed with values for
+ bit offset and bit length of the bitfield within scalar value, shifted by
+ BF_POS and BF_LEN positions, respectively. Bitfield position is counted
+ from the least significant bit, and is the number of right-most bit of a
+ field (in other words, it's a number of bits a scalar needs to be shifted
+ right to extract the bitfield).
+
+ In the example above, first a UINT16 value will be extracted at offset 0
+ (this detail may be important when accessing hardware registers, where
+ particular access size and alignment are required), and then bitfield
+ whose rightmost bit is *lsbit* bit of this UINT16, and length
+ is *bitsize* bits, will be extracted. For example, if *lsbit* is 0 and
+ *bitsize* is 8, then effectively it will access least-significant byte
+ of UINT16.
+
+ Note that bitfield operations are independent of target byte endianness,
+ in particular, example above will access least-significant byte of UINT16
+ in both little- and big-endian structures. But it depends on the least
+ significant bit being numbered 0. Some targets may use different
+ numbering in their native ABI, but ``uctypes`` always uses the normalized
+ numbering described above.
+
+Module contents
+---------------
+
+.. class:: struct(addr, descriptor, layout_type=NATIVE)
+
+ Instantiate a "foreign data structure" object based on structure address in
+ memory, descriptor (encoded as a dictionary), and layout type (see below).
+
+.. data:: LITTLE_ENDIAN
+
+ Layout type for a little-endian packed structure. (Packed means that every
+ field occupies exactly as many bytes as defined in the descriptor, i.e.
+ the alignment is 1).
+
+.. data:: BIG_ENDIAN
+
+ Layout type for a big-endian packed structure.
+
+.. data:: NATIVE
+
+ Layout type for a native structure - with data endianness and alignment
+ conforming to the ABI of the system on which MicroPython runs.
+
+.. function:: sizeof(struct)
+
+ Return size of data structure in bytes. Argument can be either structure
+ class or specific instantiated structure object (or its aggregate field).
+
+.. function:: addressof(obj)
+
+ Return address of an object. Argument should be bytes, bytearray or
+ other object supporting buffer protocol (and address of this buffer
+ is what actually returned).
+
+.. function:: bytes_at(addr, size)
+
+ Capture memory at the given address and size as bytes object. As bytes
+ object is immutable, memory is actually duplicated and copied into
+ bytes object, so if memory contents change later, created object
+ retains original value.
+
+.. function:: bytearray_at(addr, size)
+
+ Capture memory at the given address and size as bytearray object.
+ Unlike bytes_at() function above, memory is captured by reference,
+ so it can be both written too, and you will access current value
+ at the given memory address.
+
+Structure descriptors and instantiating structure objects
+---------------------------------------------------------
+
+Given a structure descriptor dictionary and its layout type, you can
+instantiate a specific structure instance at a given memory address
+using :class:`uctypes.struct()` constructor. Memory address usually comes from
+following sources:
+
+* Predefined address, when accessing hardware registers on a baremetal
+ system. Lookup these addresses in datasheet for a particular MCU/SoC.
+* As a return value from a call to some FFI (Foreign Function Interface)
+ function.
+* From uctypes.addressof(), when you want to pass arguments to an FFI
+ function, or alternatively, to access some data for I/O (for example,
+ data read from a file or network socket).
+
+Structure objects
+-----------------
+
+Structure objects allow accessing individual fields using standard dot
+notation: ``my_struct.substruct1.field1``. If a field is of scalar type,
+getting it will produce a primitive value (Python integer or float)
+corresponding to the value contained in a field. A scalar field can also
+be assigned to.
+
+If a field is an array, its individual elements can be accessed with
+the standard subscript operator ``[]`` - both read and assigned to.
+
+If a field is a pointer, it can be dereferenced using ``[0]`` syntax
+(corresponding to C ``*`` operator, though ``[0]`` works in C too).
+Subscripting a pointer with other integer values but 0 are supported too,
+with the same semantics as in C.
+
+Summing up, accessing structure fields generally follows C syntax,
+except for pointer dereference, when you need to use ``[0]`` operator
+instead of ``*``.
+
+Limitations
+-----------
+
+Accessing non-scalar fields leads to allocation of intermediate objects
+to represent them. This means that special care should be taken to
+layout a structure which needs to be accessed when memory allocation
+is disabled (e.g. from an interrupt). The recommendations are:
+
+* Avoid nested structures. For example, instead of
+ ``mcu_registers.peripheral_a.register1``, define separate layout
+ descriptors for each peripheral, to be accessed as
+ ``peripheral_a.register1``.
+* Avoid other non-scalar data, like array. For example, instead of
+ ``peripheral_a.register[0]`` use ``peripheral_a.register0``.
+
+Note that these recommendations will lead to decreased readability
+and conciseness of layouts, so they should be used only if the need
+to access structure fields without allocation is anticipated (it's
+even possible to define 2 parallel layouts - one for normal usage,
+and a restricted one to use when memory allocation is prohibited).
diff --git a/MicroPython_BUILD/components/micropython/docs/library/uerrno.rst b/MicroPython_BUILD/components/micropython/docs/library/uerrno.rst
new file mode 100644
index 0000000..e336eb5
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/uerrno.rst
@@ -0,0 +1,34 @@
+:mod:`uerrno` -- system error codes
+===================================
+
+.. module:: uerrno
+ :synopsis: system error codes
+
+|see_cpython_module| :mod:`python:errno`.
+
+This module provides access to symbolic error codes for `OSError` exception.
+A particular inventory of codes depends on `MicroPython port`.
+
+Constants
+---------
+
+.. data:: EEXIST, EAGAIN, etc.
+
+ Error codes, based on ANSI C/POSIX standard. All error codes start with
+ "E". As mentioned above, inventory of the codes depends on
+ `MicroPython port`. Errors are usually accessible as ``exc.args[0]``
+ where ``exc`` is an instance of `OSError`. Usage example::
+
+ try:
+ uos.mkdir("my_dir")
+ except OSError as exc:
+ if exc.args[0] == uerrno.EEXIST:
+ print("Directory already exists")
+
+.. data:: errorcode
+
+ Dictionary mapping numeric error codes to strings with symbolic error
+ code (see above)::
+
+ >>> print(uerrno.errorcode[uerrno.EEXIST])
+ EEXIST
diff --git a/MicroPython_BUILD/components/micropython/docs/library/uhashlib.rst b/MicroPython_BUILD/components/micropython/docs/library/uhashlib.rst
new file mode 100644
index 0000000..50ed658
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/uhashlib.rst
@@ -0,0 +1,57 @@
+:mod:`uhashlib` -- hashing algorithms
+=====================================
+
+.. module:: uhashlib
+ :synopsis: hashing algorithms
+
+|see_cpython_module| :mod:`python:hashlib`.
+
+This module implements binary data hashing algorithms. The exact inventory
+of available algorithms depends on a board. Among the algorithms which may
+be implemented:
+
+* SHA256 - The current generation, modern hashing algorithm (of SHA2 series).
+ It is suitable for cryptographically-secure purposes. Included in the
+ MicroPython core and any board is recommended to provide this, unless
+ it has particular code size constraints.
+
+* SHA1 - A previous generation algorithm. Not recommended for new usages,
+ but SHA1 is a part of number of Internet standards and existing
+ applications, so boards targeting network connectivity and
+ interoperatiability will try to provide this.
+
+* MD5 - A legacy algorithm, not considered cryptographically secure. Only
+ selected boards, targeting interoperatibility with legacy applications,
+ will offer this.
+
+Constructors
+------------
+
+.. class:: uhashlib.sha256([data])
+
+ Create an SHA256 hasher object and optionally feed ``data`` into it.
+
+.. class:: uhashlib.sha1([data])
+
+ Create an SHA1 hasher object and optionally feed ``data`` into it.
+
+.. class:: uhashlib.md5([data])
+
+ Create an MD5 hasher object and optionally feed ``data`` into it.
+
+Methods
+-------
+
+.. method:: hash.update(data)
+
+ Feed more binary data into hash.
+
+.. method:: hash.digest()
+
+ Return hash for all data passed through hash, as a bytes object. After this
+ method is called, more data cannot be fed into the hash any longer.
+
+.. method:: hash.hexdigest()
+
+ This method is NOT implemented. Use ``ubinascii.hexlify(hash.digest())``
+ to achieve a similar effect.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/uheapq.rst b/MicroPython_BUILD/components/micropython/docs/library/uheapq.rst
new file mode 100644
index 0000000..f822f1e
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/uheapq.rst
@@ -0,0 +1,27 @@
+:mod:`uheapq` -- heap queue algorithm
+=====================================
+
+.. module:: uheapq
+ :synopsis: heap queue algorithm
+
+|see_cpython_module| :mod:`python:heapq`.
+
+This module implements the heap queue algorithm.
+
+A heap queue is simply a list that has its elements stored in a certain way.
+
+Functions
+---------
+
+.. function:: heappush(heap, item)
+
+ Push the ``item`` onto the ``heap``.
+
+.. function:: heappop(heap)
+
+ Pop the first item from the ``heap``, and return it. Raises IndexError if
+ heap is empty.
+
+.. function:: heapify(x)
+
+ Convert the list ``x`` into a heap. This is an in-place operation.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/uio.rst b/MicroPython_BUILD/components/micropython/docs/library/uio.rst
new file mode 100644
index 0000000..8142070
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/uio.rst
@@ -0,0 +1,114 @@
+:mod:`uio` -- input/output streams
+==================================
+
+.. module:: uio
+ :synopsis: input/output streams
+
+|see_cpython_module| :mod:`python:io`.
+
+This module contains additional types of `stream` (file-like) objects
+and helper functions.
+
+Conceptual hierarchy
+--------------------
+
+.. admonition:: Difference to CPython
+ :class: attention
+
+ Conceptual hierarchy of stream base classes is simplified in MicroPython,
+ as described in this section.
+
+(Abstract) base stream classes, which serve as a foundation for behavior
+of all the concrete classes, adhere to few dichotomies (pair-wise
+classifications) in CPython. In MicroPython, they are somewhat simplified
+and made implicit to achieve higher efficiencies and save resources.
+
+An important dichotomy in CPython is unbuffered vs buffered streams. In
+MicroPython, all streams are currently unbuffered. This is because all
+modern OSes, and even many RTOSes and filesystem drivers already perform
+buffering on their side. Adding another layer of buffering is counter-
+productive (an issue known as "bufferbloat") and takes precious memory.
+Note that there still cases where buffering may be useful, so we may
+introduce optional buffering support at a later time.
+
+But in CPython, another important dichotomy is tied with "bufferedness" -
+it's whether a stream may incur short read/writes or not. A short read
+is when a user asks e.g. 10 bytes from a stream, but gets less, similarly
+for writes. In CPython, unbuffered streams are automatically short
+operation susceptible, while buffered are guarantee against them. The
+no short read/writes is an important trait, as it allows to develop
+more concise and efficient programs - something which is highly desirable
+for MicroPython. So, while MicroPython doesn't support buffered streams,
+it still provides for no-short-operations streams. Whether there will
+be short operations or not depends on each particular class' needs, but
+developers are strongly advised to favor no-short-operations behavior
+for the reasons stated above. For example, MicroPython sockets are
+guaranteed to avoid short read/writes. Actually, at this time, there is
+no example of a short-operations stream class in the core, and one would
+be a port-specific class, where such a need is governed by hardware
+peculiarities.
+
+The no-short-operations behavior gets tricky in case of non-blocking
+streams, blocking vs non-blocking behavior being another CPython dichotomy,
+fully supported by MicroPython. Non-blocking streams never wait for
+data either to arrive or be written - they read/write whatever possible,
+or signal lack of data (or ability to write data). Clearly, this conflicts
+with "no-short-operations" policy, and indeed, a case of non-blocking
+buffered (and this no-short-ops) streams is convoluted in CPython - in
+some places, such combination is prohibited, in some it's undefined or
+just not documented, in some cases it raises verbose exceptions. The
+matter is much simpler in MicroPython: non-blocking stream are important
+for efficient asynchronous operations, so this property prevails on
+the "no-short-ops" one. So, while blocking streams will avoid short
+reads/writes whenever possible (the only case to get a short read is
+if end of file is reached, or in case of error (but errors don't
+return short data, but raise exceptions)), non-blocking streams may
+produce short data to avoid blocking the operation.
+
+The final dichotomy is binary vs text streams. MicroPython of course
+supports these, but while in CPython text streams are inherently
+buffered, they aren't in MicroPython. (Indeed, that's one of the cases
+for which we may introduce buffering support.)
+
+Note that for efficiency, MicroPython doesn't provide abstract base
+classes corresponding to the hierarchy above, and it's not possible
+to implement, or subclass, a stream class in pure Python.
+
+Functions
+---------
+
+.. function:: open(name, mode='r', **kwargs)
+
+ Open a file. Builtin ``open()`` function is aliased to this function.
+ All ports (which provide access to file system) are required to support
+ *mode* parameter, but support for other arguments vary by port.
+
+Classes
+-------
+
+.. class:: FileIO(...)
+
+ This is type of a file open in binary mode, e.g. using ``open(name, "rb")``.
+ You should not instantiate this class directly.
+
+.. class:: TextIOWrapper(...)
+
+ This is type of a file open in text mode, e.g. using ``open(name, "rt")``.
+ You should not instantiate this class directly.
+
+.. class:: StringIO([string])
+.. class:: BytesIO([string])
+
+ In-memory file-like objects for input/output. `StringIO` is used for
+ text-mode I/O (similar to a normal file opened with "t" modifier).
+ `BytesIO` is used for binary-mode I/O (similar to a normal file
+ opened with "b" modifier). Initial contents of file-like objects
+ can be specified with *string* parameter (should be normal string
+ for `StringIO` or bytes object for `BytesIO`). All the usual file
+ methods like ``read()``, ``write()``, ``seek()``, ``flush()``,
+ ``close()`` are available on these objects, and additionally, a
+ following method:
+
+ .. method:: getvalue()
+
+ Get the current contents of the underlying buffer which holds data.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/ujson.rst b/MicroPython_BUILD/components/micropython/docs/library/ujson.rst
new file mode 100644
index 0000000..5668eb2
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/ujson.rst
@@ -0,0 +1,35 @@
+:mod:`ujson` -- JSON encoding and decoding
+==========================================
+
+.. module:: ujson
+ :synopsis: JSON encoding and decoding
+
+|see_cpython_module| :mod:`python:json`.
+
+This modules allows to convert between Python objects and the JSON
+data format.
+
+Functions
+---------
+
+.. function:: dump(obj, stream)
+
+ Serialise *obj* to a JSON string, writing it to the given *stream*.
+
+.. function:: dumps(obj)
+
+ Return *obj* represented as a JSON string.
+
+.. function:: load(stream)
+
+ Parse the given *stream*, interpreting it as a JSON string and
+ deserialising the data to a Python object. The resulting object is
+ returned.
+
+ Parsing continues until end-of-file is encountered.
+ A :exc:`ValueError` is raised if the data in *stream* is not correctly formed.
+
+.. function:: loads(str)
+
+ Parse the JSON *str* and return an object. Raises :exc:`ValueError` if the
+ string is not correctly formed.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/uos.rst b/MicroPython_BUILD/components/micropython/docs/library/uos.rst
new file mode 100644
index 0000000..27f339b
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/uos.rst
@@ -0,0 +1,249 @@
+:mod:`uos` -- basic "operating system" services
+===============================================
+
+.. module:: uos
+ :synopsis: basic "operating system" services
+
+|see_cpython_module| :mod:`python:os`.
+
+The ``uos`` module contains functions for filesystem access and mounting,
+terminal redirection and duplication, and the ``uname`` and ``urandom``
+functions.
+
+General functions
+-----------------
+
+.. function:: uname()
+
+ Return a tuple (possibly a named tuple) containing information about the
+ underlying machine and/or its operating system. The tuple has five fields
+ in the following order, each of them being a string:
+
+ * ``sysname`` -- the name of the underlying system
+ * ``nodename`` -- the network name (can be the same as ``sysname``)
+ * ``release`` -- the version of the underlying system
+ * ``version`` -- the MicroPython version and build date
+ * ``machine`` -- an identifier for the underlying hardware (eg board, CPU)
+
+.. function:: urandom(n)
+
+ Return a bytes object with *n* random bytes. Whenever possible, it is
+ generated by the hardware random number generator.
+
+Filesystem access
+-----------------
+
+.. function:: chdir(path)
+
+ Change current directory.
+
+.. function:: getcwd()
+
+ Get the current directory.
+
+.. function:: ilistdir([dir])
+
+ This function returns an iterator which then yields tuples corresponding to
+ the entries in the directory that it is listing. With no argument it lists the
+ current directory, otherwise it lists the directory given by *dir*.
+
+ The tuples have the form *(name, type, inode[, size])*:
+
+ - *name* is a string (or bytes if *dir* is a bytes object) and is the name of
+ the entry;
+ - *type* is an integer that specifies the type of the entry, with 0x4000 for
+ directories and 0x8000 for regular files;
+ - *inode* is an integer corresponding to the inode of the file, and may be 0
+ for filesystems that don't have such a notion.
+ - Some platforms may return a 4-tuple that includes the entry's *size*. For
+ file entries, *size* is an integer representing the size of the file
+ or -1 if unknown. Its meaning is currently undefined for directory
+ entries.
+
+.. function:: listdir([dir])
+
+ With no argument, list the current directory. Otherwise list the given directory.
+
+.. function:: mkdir(path)
+
+ Create a new directory.
+
+.. function:: remove(path)
+
+ Remove a file.
+
+.. function:: rmdir(path)
+
+ Remove a directory.
+
+.. function:: rename(old_path, new_path)
+
+ Rename a file.
+
+.. function:: stat(path)
+
+ Get the status of a file or directory.
+
+.. function:: statvfs(path)
+
+ Get the status of a fileystem.
+
+ Returns a tuple with the filesystem information in the following order:
+
+ * ``f_bsize`` -- file system block size
+ * ``f_frsize`` -- fragment size
+ * ``f_blocks`` -- size of fs in f_frsize units
+ * ``f_bfree`` -- number of free blocks
+ * ``f_bavail`` -- number of free blocks for unpriviliged users
+ * ``f_files`` -- number of inodes
+ * ``f_ffree`` -- number of free inodes
+ * ``f_favail`` -- number of free inodes for unpriviliged users
+ * ``f_flag`` -- mount flags
+ * ``f_namemax`` -- maximum filename length
+
+ Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail``
+ and the ``f_flags`` parameter may return ``0`` as they can be unavailable
+ in a port-specific implementation.
+
+.. function:: sync()
+
+ Sync all filesystems.
+
+Terminal redirection and duplication
+------------------------------------
+
+.. function:: dupterm(stream_object, index=0)
+
+ Duplicate or switch the MicroPython terminal (the REPL) on the given `stream`-like
+ object. The *stream_object* argument must implement the ``readinto()`` and
+ ``write()`` methods. The stream should be in non-blocking mode and
+ ``readinto()`` should return ``None`` if there is no data available for reading.
+
+ After calling this function all terminal output is repeated on this stream,
+ and any input that is available on the stream is passed on to the terminal input.
+
+ The *index* parameter should be a non-negative integer and specifies which
+ duplication slot is set. A given port may implement more than one slot (slot 0
+ will always be available) and in that case terminal input and output is
+ duplicated on all the slots that are set.
+
+ If ``None`` is passed as the *stream_object* then duplication is cancelled on
+ the slot given by *index*.
+
+ The function returns the previous stream-like object in the given slot.
+
+Filesystem mounting
+-------------------
+
+Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple
+"real" filesystems within this VFS. Filesystem objects can be mounted at either
+the root of the VFS, or at a subdirectory that lives in the root. This allows
+dynamic and flexible configuration of the filesystem that is seen by Python
+programs. Ports that have this functionality provide the :func:`mount` and
+:func:`umount` functions, and possibly various filesystem implementations
+represented by VFS classes.
+
+.. function:: mount(fsobj, mount_point, \*, readonly)
+
+ Mount the filesystem object *fsobj* at the location in the VFS given by the
+ *mount_point* string. *fsobj* can be a a VFS object that has a ``mount()``
+ method, or a block device. If it's a block device then the filesystem type
+ is automatically detected (an exception is raised if no filesystem was
+ recognised). *mount_point* may be ``'/'`` to mount *fsobj* at the root,
+ or ``'/'`` to mount it at a subdirectory under the root.
+
+ If *readonly* is ``True`` then the filesystem is mounted read-only.
+
+ During the mount process the method ``mount()`` is called on the filesystem
+ object.
+
+ Will raise ``OSError(EPERM)`` if *mount_point* is already mounted.
+
+.. function:: umount(mount_point)
+
+ Unmount a filesystem. *mount_point* can be a string naming the mount location,
+ or a previously-mounted filesystem object. During the unmount process the
+ method ``umount()`` is called on the filesystem object.
+
+ Will raise ``OSError(EINVAL)`` if *mount_point* is not found.
+
+.. class:: VfsFat(block_dev)
+
+ Create a filesystem object that uses the FAT filesystem format. Storage of
+ the FAT filesystem is provided by *block_dev*.
+ Objects created by this constructor can be mounted using :func:`mount`.
+
+ .. staticmethod:: mkfs(block_dev)
+
+ Build a FAT filesystem on *block_dev*.
+
+Block devices
+-------------
+
+A block device is an object which implements the block protocol, which is a set
+of methods described below by the :class:`AbstractBlockDev` class. A concrete
+implementation of this class will usually allow access to the memory-like
+functionality a piece of hardware (like flash memory). A block device can be
+used by a particular filesystem driver to store the data for its filesystem.
+
+.. class:: AbstractBlockDev(...)
+
+ Construct a block device object. The parameters to the constructor are
+ dependent on the specific block device.
+
+ .. method:: readblocks(block_num, buf)
+
+ Starting at *block_num*, read blocks from the device into *buf* (an array
+ of bytes). The number of blocks to read is given by the length of *buf*,
+ which will be a multiple of the block size.
+
+ .. method:: writeblocks(block_num, buf)
+
+ Starting at *block_num*, write blocks from *buf* (an array of bytes) to
+ the device. The number of blocks to write is given by the length of *buf*,
+ which will be a multiple of the block size.
+
+ .. method:: ioctl(op, arg)
+
+ Control the block device and query its parameters. The operation to
+ perform is given by *op* which is one of the following integers:
+
+ - 1 -- initialise the device (*arg* is unused)
+ - 2 -- shutdown the device (*arg* is unused)
+ - 3 -- sync the device (*arg* is unused)
+ - 4 -- get a count of the number of blocks, should return an integer
+ (*arg* is unused)
+ - 5 -- get the number of bytes in a block, should return an integer,
+ or ``None`` in which case the default value of 512 is used
+ (*arg* is unused)
+
+By way of example, the following class will implement a block device that stores
+its data in RAM using a ``bytearray``::
+
+ class RAMBlockDev:
+ def __init__(self, block_size, num_blocks):
+ self.block_size = block_size
+ self.data = bytearray(block_size * num_blocks)
+
+ def readblocks(self, block_num, buf):
+ for i in range(len(buf)):
+ buf[i] = self.data[block_num * self.block_size + i]
+
+ def writeblocks(self, block_num, buf):
+ for i in range(len(buf)):
+ self.data[block_num * self.block_size + i] = buf[i]
+
+ def ioctl(self, op, arg):
+ if op == 4: # get number of blocks
+ return len(self.data) // self.block_size
+ if op == 5: # get block size
+ return self.block_size
+
+It can be used as follows::
+
+ import uos
+
+ bdev = RAMBlockDev(512, 50)
+ uos.VfsFat.mkfs(bdev)
+ vfs = uos.VfsFat(bdev)
+ uos.mount(vfs, '/ramdisk')
diff --git a/MicroPython_BUILD/components/micropython/docs/library/ure.rst b/MicroPython_BUILD/components/micropython/docs/library/ure.rst
new file mode 100644
index 0000000..f54614f
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/ure.rst
@@ -0,0 +1,102 @@
+:mod:`ure` -- simple regular expressions
+========================================
+
+.. module:: ure
+ :synopsis: regular expressions
+
+|see_cpython_module| :mod:`python:re`.
+
+This module implements regular expression operations. Regular expression
+syntax supported is a subset of CPython ``re`` module (and actually is
+a subset of POSIX extended regular expressions).
+
+Supported operators are:
+
+``'.'``
+ Match any character.
+
+``'[...]'``
+ Match set of characters. Individual characters and ranges are supported,
+ including negated sets (e.g. ``[^a-c]``).
+
+``'^'``
+
+``'$'``
+
+``'?'``
+
+``'*'``
+
+``'+'``
+
+``'??'``
+
+``'*?'``
+
+``'+?'``
+
+``'|'``
+
+``'(...)'``
+ Grouping. Each group is capturing (a substring it captures can be accessed
+ with `match.group()` method).
+
+**NOT SUPPORTED**: Counted repetitions (``{m,n}``), more advanced assertions
+(``\b``, ``\B``), named groups (``(?P...)``), non-capturing groups
+(``(?:...)``), etc.
+
+
+Functions
+---------
+
+.. function:: compile(regex_str, [flags])
+
+ Compile regular expression, return `regex ` object.
+
+.. function:: match(regex_str, string)
+
+ Compile *regex_str* and match against *string*. Match always happens
+ from starting position in a string.
+
+.. function:: search(regex_str, string)
+
+ Compile *regex_str* and search it in a *string*. Unlike `match`, this will search
+ string for first position which matches regex (which still may be
+ 0 if regex is anchored).
+
+.. data:: DEBUG
+
+ Flag value, display debug information about compiled expression.
+ (Availability depends on `MicroPython port`.)
+
+
+.. _regex:
+
+Regex objects
+-------------
+
+Compiled regular expression. Instances of this class are created using
+`ure.compile()`.
+
+.. method:: regex.match(string)
+ regex.search(string)
+
+ Similar to the module-level functions :meth:`match` and :meth:`search`.
+ Using methods is (much) more efficient if the same regex is applied to
+ multiple strings.
+
+.. method:: regex.split(string, max_split=-1)
+
+ Split a *string* using regex. If *max_split* is given, it specifies
+ maximum number of splits to perform. Returns list of strings (there
+ may be up to *max_split+1* elements if it's specified).
+
+Match objects
+-------------
+
+Match objects as returned by `match()` and `search()` methods.
+
+.. method:: match.group([index])
+
+ Return matching (sub)string. *index* is 0 for entire match,
+ 1 and above for each capturing group. Only numeric groups are supported.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/uselect.rst b/MicroPython_BUILD/components/micropython/docs/library/uselect.rst
new file mode 100644
index 0000000..77d4584
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/uselect.rst
@@ -0,0 +1,94 @@
+:mod:`uselect` -- wait for events on a set of streams
+========================================================================
+
+.. module:: uselect
+ :synopsis: wait for events on a set of streams
+
+|see_cpython_module| :mod:`python:select`.
+
+This module provides functions to efficiently wait for events on multiple
+`streams ` (select streams which are ready for operations).
+
+Functions
+---------
+
+.. function:: poll()
+
+ Create an instance of the Poll class.
+
+.. function:: select(rlist, wlist, xlist[, timeout])
+
+ Wait for activity on a set of objects.
+
+ This function is provided by some MicroPython ports for compatibility
+ and is not efficient. Usage of :class:`Poll` is recommended instead.
+
+.. _class: Poll
+
+class ``Poll``
+--------------
+
+Methods
+~~~~~~~
+
+.. method:: poll.register(obj[, eventmask])
+
+ Register `stream` *obj* for polling. *eventmask* is logical OR of:
+
+ * ``uselect.POLLIN`` - data available for reading
+ * ``uselect.POLLOUT`` - more data can be written
+
+ Note that flags like ``uselect.POLLHUP`` and ``uselect.POLLERR`` are
+ *not* valid as input eventmask (these are unsolicited events which
+ will be returned from `poll()` regardless of whether they are asked
+ for). This semantics is per POSIX.
+
+ *eventmask* defaults to ``uselect.POLLIN | uselect.POLLOUT``.
+
+.. method:: poll.unregister(obj)
+
+ Unregister *obj* from polling.
+
+.. method:: poll.modify(obj, eventmask)
+
+ Modify the *eventmask* for *obj*.
+
+.. method:: poll.poll(timeout=-1)
+
+ Wait for at least one of the registered objects to become ready or have an
+ exceptional condition, with optional timeout in milliseconds (if *timeout*
+ arg is not specified or -1, there is no timeout).
+
+ Returns list of (``obj``, ``event``, ...) tuples. There may be other elements in
+ tuple, depending on a platform and version, so don't assume that its size is 2.
+ The ``event`` element specifies which events happened with a stream and
+ is a combination of ``uselect.POLL*`` constants described above. Note that
+ flags ``uselect.POLLHUP`` and ``uselect.POLLERR`` can be returned at any time
+ (even if were not asked for), and must be acted on accordingly (the
+ corresponding stream unregistered from poll and likely closed), because
+ otherwise all further invocations of `poll()` may return immediately with
+ these flags set for this stream again.
+
+ In case of timeout, an empty list is returned.
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ Tuples returned may contain more than 2 elements as described above.
+
+.. method:: poll.ipoll(timeout=-1, flags=0)
+
+ Like :meth:`poll.poll`, but instead returns an iterator which yields a
+ `callee-owned tuple`. This function provides an efficient, allocation-free
+ way to poll on streams.
+
+ If *flags* is 1, one-shot behavior for events is employed: streams for
+ which events happened will have their event masks automatically reset
+ (equivalent to ``poll.modify(obj, 0)``), so new events for such a stream
+ won't be processed until new mask is set with `poll.modify()`. This
+ behavior is useful for asynchronous I/O schedulers.
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ This function is a MicroPython extension.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/usocket.rst b/MicroPython_BUILD/components/micropython/docs/library/usocket.rst
new file mode 100644
index 0000000..3ae477a
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/usocket.rst
@@ -0,0 +1,339 @@
+*******************************
+:mod:`usocket` -- socket module
+*******************************
+
+.. module:: usocket
+ :synopsis: socket module
+
+|see_cpython_module| :mod:`python:socket`.
+
+This module provides access to the BSD socket interface.
+
+.. admonition:: Difference to CPython
+ :class: attention
+
+ For efficiency and consistency, socket objects in MicroPython implement a `stream`
+ (file-like) interface directly. In CPython, you need to convert a socket to
+ a file-like object using `makefile()` method. This method is still supported
+ by MicroPython (but is a no-op), so where compatibility with CPython matters,
+ be sure to use it.
+
+Socket address format(s)
+------------------------
+
+The native socket address format of the ``usocket`` module is an opaque data type
+returned by `getaddrinfo` function, which must be used to resolve textual address
+(including numeric addresses)::
+
+ sockaddr = usocket.getaddrinfo('www.micropython.org', 80)[0][-1]
+ # You must use getaddrinfo() even for numeric addresses
+ sockaddr = usocket.getaddrinfo('127.0.0.1', 80)[0][-1]
+ # Now you can use that address
+ sock.connect(addr)
+
+Using `getaddrinfo` is the most efficient (both in terms of memory and processing
+power) and portable way to work with addresses.
+
+However, ``socket`` module (note the difference with native MicroPython
+``usocket`` module described here) provides CPython-compatible way to specify
+addresses using tuples, as described below. Note that depending on a
+`MicroPython port`, ``socket`` module can be builtin or need to be
+installed from `micropython-lib` (as in the case of `MicroPython Unix port`),
+and some ports still accept only numeric addresses in the tuple format,
+and require to use `getaddrinfo` function to resolve domain names.
+
+Summing up:
+
+* Always use `getaddrinfo` when writing portable applications.
+* Tuple addresses described below can be used as a shortcut for
+ quick hacks and interactive use, if your port supports them.
+
+Tuple address format for ``socket`` module:
+
+* IPv4: *(ipv4_address, port)*, where *ipv4_address* is a string with
+ dot-notation numeric IPv4 address, e.g. ``"8.8.8.8"``, and *port* is and
+ integer port number in the range 1-65535. Note the domain names are not
+ accepted as *ipv4_address*, they should be resolved first using
+ `usocket.getaddrinfo()`.
+* IPv6: *(ipv6_address, port, flowinfo, scopeid)*, where *ipv6_address*
+ is a string with colon-notation numeric IPv6 address, e.g. ``"2001:db8::1"``,
+ and *port* is an integer port number in the range 1-65535. *flowinfo*
+ must be 0. *scopeid* is the interface scope identifier for link-local
+ addresses. Note the domain names are not accepted as *ipv6_address*,
+ they should be resolved first using `usocket.getaddrinfo()`. Availability
+ of IPv6 support depends on a `MicroPython port`.
+
+Functions
+---------
+
+.. function:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP)
+
+ Create a new socket using the given address family, socket type and
+ protocol number. Note that specifying *proto* in most cases is not
+ required (and not recommended, as some MicroPython ports may omit
+ ``IPPROTO_*`` constants). Instead, *type* argument will select needed
+ protocol automatically::
+
+ # Create STREAM TCP socket
+ socket(AF_INET, SOCK_STREAM)
+ # Create DGRAM UDP socket
+ socket(AF_INET, SOCK_DGRAM)
+
+.. function:: getaddrinfo(host, port)
+
+ Translate the host/port argument into a sequence of 5-tuples that contain all the
+ necessary arguments for creating a socket connected to that service. The list of
+ 5-tuples has following structure::
+
+ (family, type, proto, canonname, sockaddr)
+
+ The following example shows how to connect to a given url::
+
+ s = usocket.socket()
+ s.connect(usocket.getaddrinfo('www.micropython.org', 80)[0][-1])
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ CPython raises a ``socket.gaierror`` exception (`OSError` subclass) in case
+ of error in this function. MicroPython doesn't have ``socket.gaierror``
+ and raises OSError directly. Note that error numbers of `getaddrinfo()`
+ form a separate namespace and may not match error numbers from
+ the :mod:`uerrno` module. To distinguish `getaddrinfo()` errors, they are
+ represented by negative numbers, whereas standard system errors are
+ positive numbers (error numbers are accessible using ``e.args[0]`` property
+ from an exception object). The use of negative values is a provisional
+ detail which may change in the future.
+
+.. function:: inet_ntop(af, bin_addr)
+
+ Convert a binary network address *bin_addr* of the given address family *af*
+ to a textual representation::
+
+ >>> usocket.inet_ntop(usocket.AF_INET, b"\x7f\0\0\1")
+ '127.0.0.1'
+
+.. function:: inet_pton(af, txt_addr)
+
+ Convert a textual network address *txt_addr* of the given address family *af*
+ to a binary representation::
+
+ >>> usocket.inet_pton(usocket.AF_INET, "1.2.3.4")
+ b'\x01\x02\x03\x04'
+
+Constants
+---------
+
+.. data:: AF_INET
+ AF_INET6
+
+ Address family types. Availability depends on a particular `MicroPython port`.
+
+.. data:: SOCK_STREAM
+ SOCK_DGRAM
+
+ Socket types.
+
+.. data:: IPPROTO_UDP
+ IPPROTO_TCP
+
+ IP protocol numbers. Availability depends on a particular `MicroPython port`.
+ Note that you don't need to specify these in a call to `usocket.socket()`,
+ because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and
+ `SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants
+ is as an argument to `setsockopt()`.
+
+.. data:: usocket.SOL_*
+
+ Socket option levels (an argument to `setsockopt()`). The exact
+ inventory depends on a `MicroPython port`.
+
+.. data:: usocket.SO_*
+
+ Socket options (an argument to `setsockopt()`). The exact
+ inventory depends on a `MicroPython port`.
+
+Constants specific to WiPy:
+
+.. data:: IPPROTO_SEC
+
+ Special protocol value to create SSL-compatible socket.
+
+class socket
+============
+
+Methods
+-------
+
+.. method:: socket.close()
+
+ Mark the socket closed and release all resources. Once that happens, all future operations
+ on the socket object will fail. The remote end will receive EOF indication if
+ supported by protocol.
+
+ Sockets are automatically closed when they are garbage-collected, but it is recommended
+ to `close()` them explicitly as soon you finished working with them.
+
+.. method:: socket.bind(address)
+
+ Bind the socket to *address*. The socket must not already be bound.
+
+.. method:: socket.listen([backlog])
+
+ Enable a server to accept connections. If *backlog* is specified, it must be at least 0
+ (if it's lower, it will be set to 0); and specifies the number of unaccepted connections
+ that the system will allow before refusing new connections. If not specified, a default
+ reasonable value is chosen.
+
+.. method:: socket.accept()
+
+ Accept a connection. The socket must be bound to an address and listening for connections.
+ The return value is a pair (conn, address) where conn is a new socket object usable to send
+ and receive data on the connection, and address is the address bound to the socket on the
+ other end of the connection.
+
+.. method:: socket.connect(address)
+
+ Connect to a remote socket at *address*.
+
+.. method:: socket.send(bytes)
+
+ Send data to the socket. The socket must be connected to a remote socket.
+ Returns number of bytes sent, which may be smaller than the length of data
+ ("short write").
+
+.. method:: socket.sendall(bytes)
+
+ Send all data to the socket. The socket must be connected to a remote socket.
+ Unlike `send()`, this method will try to send all of data, by sending data
+ chunk by chunk consecutively.
+
+ The behavior of this method on non-blocking sockets is undefined. Due to this,
+ on MicroPython, it's recommended to use `write()` method instead, which
+ has the same "no short writes" policy for blocking sockets, and will return
+ number of bytes sent on non-blocking sockets.
+
+.. method:: socket.recv(bufsize)
+
+ Receive data from the socket. The return value is a bytes object representing the data
+ received. The maximum amount of data to be received at once is specified by bufsize.
+
+.. method:: socket.sendto(bytes, address)
+
+ Send data to the socket. The socket should not be connected to a remote socket, since the
+ destination socket is specified by *address*.
+
+.. method:: socket.recvfrom(bufsize)
+
+ Receive data from the socket. The return value is a pair *(bytes, address)* where *bytes* is a
+ bytes object representing the data received and *address* is the address of the socket sending
+ the data.
+
+.. method:: socket.setsockopt(level, optname, value)
+
+ Set the value of the given socket option. The needed symbolic constants are defined in the
+ socket module (SO_* etc.). The *value* can be an integer or a bytes-like object representing
+ a buffer.
+
+.. method:: socket.settimeout(value)
+
+ **Note**: Not every port supports this method, see below.
+
+ Set a timeout on blocking socket operations. The value argument can be a nonnegative floating
+ point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations
+ will raise an `OSError` exception if the timeout period value has elapsed before the operation has
+ completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket
+ is put in blocking mode.
+
+ Not every `MicroPython port` supports this method. A more portable and
+ generic solution is to use `uselect.poll` object. This allows to wait on
+ multiple objects at the same time (and not just on sockets, but on generic
+ `stream` objects which support polling). Example::
+
+ # Instead of:
+ s.settimeout(1.0) # time in seconds
+ s.read(10) # may timeout
+
+ # Use:
+ poller = uselect.poll()
+ poller.register(s, uselect.POLLIN)
+ res = poller.poll(1000) # time in milliseconds
+ if not res:
+ # s is still not ready for input, i.e. operation timed out
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ CPython raises a ``socket.timeout`` exception in case of timeout,
+ which is an `OSError` subclass. MicroPython raises an OSError directly
+ instead. If you use ``except OSError:`` to catch the exception,
+ your code will work both in MicroPython and CPython.
+
+.. method:: socket.setblocking(flag)
+
+ Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking,
+ else to blocking mode.
+
+ This method is a shorthand for certain `settimeout()` calls:
+
+ * ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)``
+ * ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0)``
+
+.. method:: socket.makefile(mode='rb', buffering=0)
+
+ Return a file object associated with the socket. The exact returned type depends on the arguments
+ given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb').
+ CPython's arguments: *encoding*, *errors* and *newline* are not supported.
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ As MicroPython doesn't support buffered streams, values of *buffering*
+ parameter is ignored and treated as if it was 0 (unbuffered).
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ Closing the file object returned by makefile() WILL close the
+ original socket as well.
+
+.. method:: socket.read([size])
+
+ Read up to size bytes from the socket. Return a bytes object. If *size* is not given, it
+ reads all data available from the socket until EOF; as such the method will not return until
+ the socket is closed. This function tries to read as much data as
+ requested (no "short reads"). This may be not possible with
+ non-blocking socket though, and then less data will be returned.
+
+.. method:: socket.readinto(buf[, nbytes])
+
+ Read bytes into the *buf*. If *nbytes* is specified then read at most
+ that many bytes. Otherwise, read at most *len(buf)* bytes. Just as
+ `read()`, this method follows "no short reads" policy.
+
+ Return value: number of bytes read and stored into *buf*.
+
+.. method:: socket.readline()
+
+ Read a line, ending in a newline character.
+
+ Return value: the line read.
+
+.. method:: socket.write(buf)
+
+ Write the buffer of bytes to the socket. This function will try to
+ write all data to a socket (no "short writes"). This may be not possible
+ with a non-blocking socket though, and returned value will be less than
+ the length of *buf*.
+
+ Return value: number of bytes written.
+
+.. exception:: usocket.error
+
+ MicroPython does NOT have this exception.
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ CPython used to have a ``socket.error`` exception which is now deprecated,
+ and is an alias of `OSError`. In MicroPython, use `OSError` directly.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/ussl.rst b/MicroPython_BUILD/components/micropython/docs/library/ussl.rst
new file mode 100644
index 0000000..be84dc0
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/ussl.rst
@@ -0,0 +1,48 @@
+:mod:`ussl` -- SSL/TLS module
+=============================
+
+.. module:: ussl
+ :synopsis: TLS/SSL wrapper for socket objects
+
+|see_cpython_module| :mod:`python:ssl`.
+
+This module provides access to Transport Layer Security (previously and
+widely known as “Secure Sockets Layer”) encryption and peer authentication
+facilities for network sockets, both client-side and server-side.
+
+Functions
+---------
+
+.. function:: ussl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None)
+
+ Takes a `stream` *sock* (usually usocket.socket instance of ``SOCK_STREAM`` type),
+ and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
+ an SSL context. Returned object has the usual `stream` interface methods like
+ ``read()``, ``write()``, etc. In MicroPython, the returned object does not expose
+ socket interface and methods like ``recv()``, ``send()``. In particular, a
+ server-side SSL socket should be created from a normal socket returned from
+ :meth:`~usocket.socket.accept()` on a non-SSL listening server socket.
+
+ Depending on the underlying module implementation in a particular
+ `MicroPython port`, some or all keyword arguments above may be not supported.
+
+.. warning::
+
+ Some implementations of ``ussl`` module do NOT validate server certificates,
+ which makes an SSL connection established prone to man-in-the-middle attacks.
+
+Exceptions
+----------
+
+.. data:: ssl.SSLError
+
+ This exception does NOT exist. Instead its base class, OSError, is used.
+
+Constants
+---------
+
+.. data:: ussl.CERT_NONE
+ ussl.CERT_OPTIONAL
+ ussl.CERT_REQUIRED
+
+ Supported values for *cert_reqs* parameter.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/ustruct.rst b/MicroPython_BUILD/components/micropython/docs/library/ustruct.rst
new file mode 100644
index 0000000..81915d0
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/ustruct.rst
@@ -0,0 +1,42 @@
+:mod:`ustruct` -- pack and unpack primitive data types
+======================================================
+
+.. module:: ustruct
+ :synopsis: pack and unpack primitive data types
+
+|see_cpython_module| :mod:`python:struct`.
+
+Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``.
+
+Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``,
+``L``, ``q``, ``Q``, ``s``, ``P``, ``f``, ``d`` (the latter 2 depending
+on the floating-point support).
+
+Functions
+---------
+
+.. function:: calcsize(fmt)
+
+ Return the number of bytes needed to store the given *fmt*.
+
+.. function:: pack(fmt, v1, v2, ...)
+
+ Pack the values *v1*, *v2*, ... according to the format string *fmt*.
+ The return value is a bytes object encoding the values.
+
+.. function:: pack_into(fmt, buffer, offset, v1, v2, ...)
+
+ Pack the values *v1*, *v2*, ... according to the format string *fmt*
+ into a *buffer* starting at *offset*. *offset* may be negative to count
+ from the end of *buffer*.
+
+.. function:: unpack(fmt, data)
+
+ Unpack from the *data* according to the format string *fmt*.
+ The return value is a tuple of the unpacked values.
+
+.. function:: unpack_from(fmt, data, offset=0)
+
+ Unpack from the *data* starting at *offset* according to the format string
+ *fmt*. *offset* may be negative to count from the end of *buffer*. The return
+ value is a tuple of the unpacked values.
diff --git a/MicroPython_BUILD/components/micropython/docs/library/utime.rst b/MicroPython_BUILD/components/micropython/docs/library/utime.rst
new file mode 100644
index 0000000..7fe83f5
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/utime.rst
@@ -0,0 +1,229 @@
+:mod:`utime` -- time related functions
+======================================
+
+.. module:: utime
+ :synopsis: time related functions
+
+|see_cpython_module| :mod:`python:time`.
+
+The ``utime`` module provides functions for getting the current time and date,
+measuring time intervals, and for delays.
+
+**Time Epoch**: Unix port uses standard for POSIX systems epoch of
+1970-01-01 00:00:00 UTC. However, embedded ports use epoch of
+2000-01-01 00:00:00 UTC.
+
+**Maintaining actual calendar date/time**: This requires a
+Real Time Clock (RTC). On systems with underlying OS (including some
+RTOS), an RTC may be implicit. Setting and maintaining actual calendar
+time is responsibility of OS/RTOS and is done outside of MicroPython,
+it just uses OS API to query date/time. On baremetal ports however
+system time depends on ``machine.RTC()`` object. The current calendar time
+may be set using ``machine.RTC().datetime(tuple)`` function, and maintained
+by following means:
+
+* By a backup battery (which may be an additional, optional component for
+ a particular board).
+* Using networked time protocol (requires setup by a port/user).
+* Set manually by a user on each power-up (many boards then maintain
+ RTC time across hard resets, though some may require setting it again
+ in such case).
+
+If actual calendar time is not maintained with a system/MicroPython RTC,
+functions below which require reference to current absolute time may
+behave not as expected.
+
+Functions
+---------
+
+.. function:: localtime([secs])
+
+ Convert a time expressed in seconds since the Epoch (see above) into an 8-tuple which
+ contains: (year, month, mday, hour, minute, second, weekday, yearday)
+ If secs is not provided or None, then the current time from the RTC is used.
+
+ * year includes the century (for example 2014).
+ * month is 1-12
+ * mday is 1-31
+ * hour is 0-23
+ * minute is 0-59
+ * second is 0-59
+ * weekday is 0-6 for Mon-Sun
+ * yearday is 1-366
+
+.. function:: mktime()
+
+ This is inverse function of localtime. It's argument is a full 8-tuple
+ which expresses a time as per localtime. It returns an integer which is
+ the number of seconds since Jan 1, 2000.
+
+.. function:: sleep(seconds)
+
+ Sleep for the given number of seconds. Some boards may accept *seconds* as a
+ floating-point number to sleep for a fractional number of seconds. Note that
+ other boards may not accept a floating-point argument, for compatibility with
+ them use `sleep_ms()` and `sleep_us()` functions.
+
+.. function:: sleep_ms(ms)
+
+ Delay for given number of milliseconds, should be positive or 0.
+
+.. function:: sleep_us(us)
+
+ Delay for given number of microseconds, should be positive or 0.
+
+.. function:: ticks_ms()
+
+ Returns an increasing millisecond counter with an arbitrary reference point, that
+ wraps around after some value.
+
+ The wrap-around value is not explicitly exposed, but we will
+ refer to it as *TICKS_MAX* to simplify discussion. Period of the values is
+ *TICKS_PERIOD = TICKS_MAX + 1*. *TICKS_PERIOD* is guaranteed to be a power of
+ two, but otherwise may differ from port to port. The same period value is used
+ for all of `ticks_ms()`, `ticks_us()`, `ticks_cpu()` functions (for
+ simplicity). Thus, these functions will return a value in range [*0* ..
+ *TICKS_MAX*], inclusive, total *TICKS_PERIOD* values. Note that only
+ non-negative values are used. For the most part, you should treat values returned
+ by these functions as opaque. The only operations available for them are
+ `ticks_diff()` and `ticks_add()` functions described below.
+
+ Note: Performing standard mathematical operations (+, -) or relational
+ operators (<, <=, >, >=) directly on these value will lead to invalid
+ result. Performing mathematical operations and then passing their results
+ as arguments to `ticks_diff()` or `ticks_add()` will also lead to
+ invalid results from the latter functions.
+
+.. function:: ticks_us()
+
+ Just like `ticks_ms()` above, but in microseconds.
+
+.. function:: ticks_cpu()
+
+ Similar to `ticks_ms()` and `ticks_us()`, but with the highest possible resolution
+ in the system. This is usually CPU clocks, and that's why the function is named that
+ way. But it doesn't have to be a CPU clock, some other timing source available in a
+ system (e.g. high-resolution timer) can be used instead. The exact timing unit
+ (resolution) of this function is not specified on ``utime`` module level, but
+ documentation for a specific port may provide more specific information. This
+ function is intended for very fine benchmarking or very tight real-time loops.
+ Avoid using it in portable code.
+
+ Availability: Not every port implements this function.
+
+
+.. function:: ticks_add(ticks, delta)
+
+ Offset ticks value by a given number, which can be either positive or negative.
+ Given a *ticks* value, this function allows to calculate ticks value *delta*
+ ticks before or after it, following modular-arithmetic definition of tick values
+ (see `ticks_ms()` above). *ticks* parameter must be a direct result of call
+ to `ticks_ms()`, `ticks_us()`, or `ticks_cpu()` functions (or from previous
+ call to `ticks_add()`). However, *delta* can be an arbitrary integer number
+ or numeric expression. `ticks_add()` is useful for calculating deadlines for
+ events/tasks. (Note: you must use `ticks_diff()` function to work with
+ deadlines.)
+
+ Examples::
+
+ # Find out what ticks value there was 100ms ago
+ print(ticks_add(time.ticks_ms(), -100))
+
+ # Calculate deadline for operation and test for it
+ deadline = ticks_add(time.ticks_ms(), 200)
+ while ticks_diff(deadline, time.ticks_ms()) > 0:
+ do_a_little_of_something()
+
+ # Find out TICKS_MAX used by this port
+ print(ticks_add(0, -1))
+
+
+.. function:: ticks_diff(ticks1, ticks2)
+
+ Measure ticks difference between values returned from `ticks_ms()`, `ticks_us()`,
+ or `ticks_cpu()` functions, as a signed value which may wrap around.
+
+ The argument order is the same as for subtraction
+ operator, ``ticks_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``.
+ However, values returned by `ticks_ms()`, etc. functions may wrap around, so
+ directly using subtraction on them will produce incorrect result. That is why
+ `ticks_diff()` is needed, it implements modular (or more specifically, ring)
+ arithmetics to produce correct result even for wrap-around values (as long as they not
+ too distant inbetween, see below). The function returns **signed** value in the range
+ [*-TICKS_PERIOD/2* .. *TICKS_PERIOD/2-1*] (that's a typical range definition for
+ two's-complement signed binary integers). If the result is negative, it means that
+ *ticks1* occurred earlier in time than *ticks2*. Otherwise, it means that
+ *ticks1* occurred after *ticks2*. This holds **only** if *ticks1* and *ticks2*
+ are apart from each other for no more than *TICKS_PERIOD/2-1* ticks. If that does
+ not hold, incorrect result will be returned. Specifically, if two tick values are
+ apart for *TICKS_PERIOD/2-1* ticks, that value will be returned by the function.
+ However, if *TICKS_PERIOD/2* of real-time ticks has passed between them, the
+ function will return *-TICKS_PERIOD/2* instead, i.e. result value will wrap around
+ to the negative range of possible values.
+
+ Informal rationale of the constraints above: Suppose you are locked in a room with no
+ means to monitor passing of time except a standard 12-notch clock. Then if you look at
+ dial-plate now, and don't look again for another 13 hours (e.g., if you fall for a
+ long sleep), then once you finally look again, it may seem to you that only 1 hour
+ has passed. To avoid this mistake, just look at the clock regularly. Your application
+ should do the same. "Too long sleep" metaphor also maps directly to application
+ behavior: don't let your application run any single task for too long. Run tasks
+ in steps, and do time-keeping inbetween.
+
+ `ticks_diff()` is designed to accommodate various usage patterns, among them:
+
+ * Polling with timeout. In this case, the order of events is known, and you will deal
+ only with positive results of `ticks_diff()`::
+
+ # Wait for GPIO pin to be asserted, but at most 500us
+ start = time.ticks_us()
+ while pin.value() == 0:
+ if time.ticks_diff(time.ticks_us(), start) > 500:
+ raise TimeoutError
+
+ * Scheduling events. In this case, `ticks_diff()` result may be negative
+ if an event is overdue::
+
+ # This code snippet is not optimized
+ now = time.ticks_ms()
+ scheduled_time = task.scheduled_time()
+ if ticks_diff(scheduled_time, now) > 0:
+ print("Too early, let's nap")
+ sleep_ms(ticks_diff(scheduled_time, now))
+ task.run()
+ elif ticks_diff(scheduled_time, now) == 0:
+ print("Right at time!")
+ task.run()
+ elif ticks_diff(scheduled_time, now) < 0:
+ print("Oops, running late, tell task to run faster!")
+ task.run(run_faster=true)
+
+ Note: Do not pass `time()` values to `ticks_diff()`, you should use
+ normal mathematical operations on them. But note that `time()` may (and will)
+ also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem .
+
+
+.. function:: time()
+
+ Returns the number of seconds, as an integer, since the Epoch, assuming that
+ underlying RTC is set and maintained as described above. If an RTC is not set, this
+ function returns number of seconds since a port-specific reference point in time (for
+ embedded boards without a battery-backed RTC, usually since power up or reset). If you
+ want to develop portable MicroPython application, you should not rely on this function
+ to provide higher than second precision. If you need higher precision, use
+ `ticks_ms()` and `ticks_us()` functions, if you need calendar time,
+ `localtime()` without an argument is a better choice.
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ In CPython, this function returns number of
+ seconds since Unix epoch, 1970-01-01 00:00 UTC, as a floating-point,
+ usually having microsecond precision. With MicroPython, only Unix port
+ uses the same Epoch, and if floating-point precision allows,
+ returns sub-second precision. Embedded hardware usually doesn't have
+ floating-point precision to represent both long time ranges and subsecond
+ precision, so they use integer value with second precision. Some embedded
+ hardware also lacks battery-powered RTC, so returns number of seconds
+ since last power-up or from other relative, hardware-specific point
+ (e.g. reset).
diff --git a/MicroPython_BUILD/components/micropython/docs/library/uzlib.rst b/MicroPython_BUILD/components/micropython/docs/library/uzlib.rst
new file mode 100644
index 0000000..0b399f2
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/library/uzlib.rst
@@ -0,0 +1,38 @@
+:mod:`uzlib` -- zlib decompression
+==================================
+
+.. module:: uzlib
+ :synopsis: zlib decompression
+
+|see_cpython_module| :mod:`python:zlib`.
+
+This module allows to decompress binary data compressed with
+`DEFLATE algorithm `_
+(commonly used in zlib library and gzip archiver). Compression
+is not yet implemented.
+
+Functions
+---------
+
+.. function:: decompress(data, wbits=0, bufsize=0)
+
+ Return decompressed *data* as bytes. *wbits* is DEFLATE dictionary window
+ size used during compression (8-15, the dictionary size is power of 2 of
+ that value). Additionally, if value is positive, *data* is assumed to be
+ zlib stream (with zlib header). Otherwise, if it's negative, it's assumed
+ to be raw DEFLATE stream. *bufsize* parameter is for compatibility with
+ CPython and is ignored.
+
+.. class:: DecompIO(stream, wbits=0)
+
+ Create a `stream` wrapper which allows transparent decompression of
+ compressed data in another *stream*. This allows to process compressed
+ streams with data larger than available heap size. In addition to
+ values described in :func:`decompress`, *wbits* may take values
+ 24..31 (16 + 8..15), meaning that input stream has gzip header.
+
+ .. admonition:: Difference to CPython
+ :class: attention
+
+ This class is MicroPython extension. It's included on provisional
+ basis and may be changed considerably or removed in later versions.
diff --git a/MicroPython_BUILD/components/micropython/docs/license.rst b/MicroPython_BUILD/components/micropython/docs/license.rst
new file mode 100644
index 0000000..73caa90
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/docs/license.rst
@@ -0,0 +1,24 @@
+MicroPython license information
+===============================
+
+The MIT License (MIT)
+
+Copyright (c) 2013-2017 Damien P. George, and others
+
+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.
diff --git a/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01.py b/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01.py
index 7274a79..a95d2b5 100644
--- a/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01.py
+++ b/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01.py
@@ -62,12 +62,11 @@ class NRF24L01:
# init the SPI bus and pins
self.init_spi(4000000)
- cs.init(cs.OUT, value=1)
- ce.init(ce.OUT, value=0)
# reset everything
- self.ce(0)
- self.cs(1)
+ ce.init(ce.OUT, value=0)
+ cs.init(cs.OUT, value=1)
+
self.payload_size = payload_size
self.pipe0_read_addr = None
utime.sleep_ms(5)
@@ -215,7 +214,7 @@ class NRF24L01:
# blocking wait for tx complete
def send(self, buf, timeout=500):
- send_nonblock = self.send_start(buf)
+ self.send_start(buf)
start = utime.ticks_ms()
result = None
while result is None and utime.ticks_diff(utime.ticks_ms(), start) < timeout:
diff --git a/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01test.py b/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01test.py
index 5413511..876b2bb 100644
--- a/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01test.py
+++ b/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01test.py
@@ -1,14 +1,38 @@
-"""Test for nrf24l01 module."""
+"""Test for nrf24l01 module. Portable between MicroPython targets."""
-import struct
+import sys
+import ustruct as struct
import utime
from machine import Pin, SPI
from nrf24l01 import NRF24L01
+from micropython import const
+
+# Slave pause between receiving data and checking for further packets.
+_RX_POLL_DELAY = const(15)
+# Slave pauses an additional _SLAVE_SEND_DELAY ms after receiving data and before
+# transmitting to allow the (remote) master time to get into receive mode. The
+# master may be a slow device. Value tested with Pyboard, ESP32 and ESP8266.
+_SLAVE_SEND_DELAY = const(10)
+
+if sys.platform == 'pyboard':
+ cfg = {'spi': 2, 'miso': 'Y7', 'mosi': 'Y8', 'sck': 'Y6', 'csn': 'Y5', 'ce': 'Y4'}
+elif sys.platform == 'esp8266': # Hardware SPI
+ cfg = {'spi': 1, 'miso': 12, 'mosi': 13, 'sck': 14, 'csn': 4, 'ce': 5}
+elif sys.platform == 'esp32': # Software SPI
+ cfg = {'spi': -1, 'miso': 32, 'mosi': 33, 'sck': 25, 'csn': 26, 'ce': 27}
+else:
+ raise ValueError('Unsupported platform {}'.format(sys.platform))
pipes = (b'\xf0\xf0\xf0\xf0\xe1', b'\xf0\xf0\xf0\xf0\xd2')
def master():
- nrf = NRF24L01(SPI(2), Pin('Y5'), Pin('Y4'), payload_size=8)
+ csn = Pin(cfg['csn'], mode=Pin.OUT, value=1)
+ ce = Pin(cfg['ce'], mode=Pin.OUT, value=0)
+ if cfg['spi'] == -1:
+ spi = SPI(-1, sck=Pin(cfg['sck']), mosi=Pin(cfg['mosi']), miso=Pin(cfg['miso']))
+ nrf = NRF24L01(spi, csn, ce, payload_size=8)
+ else:
+ nrf = NRF24L01(SPI(cfg['spi']), csn, ce, payload_size=8)
nrf.open_tx_pipe(pipes[0])
nrf.open_rx_pipe(1, pipes[1])
@@ -60,7 +84,13 @@ def master():
print('master finished sending; successes=%d, failures=%d' % (num_successes, num_failures))
def slave():
- nrf = NRF24L01(SPI(2), Pin('Y5'), Pin('Y4'), payload_size=8)
+ csn = Pin(cfg['csn'], mode=Pin.OUT, value=1)
+ ce = Pin(cfg['ce'], mode=Pin.OUT, value=0)
+ if cfg['spi'] == -1:
+ spi = SPI(-1, sck=Pin(cfg['sck']), mosi=Pin(cfg['mosi']), miso=Pin(cfg['miso']))
+ nrf = NRF24L01(spi, csn, ce, payload_size=8)
+ else:
+ nrf = NRF24L01(SPI(cfg['spi']), csn, ce, payload_size=8)
nrf.open_tx_pipe(pipes[1])
nrf.open_rx_pipe(1, pipes[0])
@@ -69,7 +99,6 @@ def slave():
print('NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)')
while True:
- machine.idle()
if nrf.any():
while nrf.any():
buf = nrf.recv()
@@ -81,8 +110,10 @@ def slave():
else:
led.off()
led_state >>= 1
- utime.sleep_ms(15)
+ utime.sleep_ms(_RX_POLL_DELAY)
+ # Give master time to get into receive mode.
+ utime.sleep_ms(_SLAVE_SEND_DELAY)
nrf.stop_listening()
try:
nrf.send(struct.pack('i', millis))
@@ -99,9 +130,9 @@ except:
print('NRF24L01 test module loaded')
print('NRF24L01 pinout for test:')
-print(' CE on Y4')
-print(' CSN on Y5')
-print(' SCK on Y6')
-print(' MISO on Y7')
-print(' MOSI on Y8')
+print(' CE on', cfg['ce'])
+print(' CSN on', cfg['csn'])
+print(' SCK on', cfg['sck'])
+print(' MISO on', cfg['miso'])
+print(' MOSI on', cfg['mosi'])
print('run nrf24l01test.slave() on slave, then nrf24l01test.master() on master')
diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.c b/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.c
index 8c9989d..0b6874d 100644
--- a/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.c
+++ b/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.c
@@ -31,7 +31,7 @@
#include "sdkconfig.h"
-#if CONFIG_MICROPY_USE_EVE
+#if CONFIG_MICROPY_USE_EVE_NOT_USE
#include
diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_adc.c b/MicroPython_BUILD/components/micropython/esp32/machine_adc.c
index 331e77e..08c9c4c 100644
--- a/MicroPython_BUILD/components/micropython/esp32/machine_adc.c
+++ b/MicroPython_BUILD/components/micropython/esp32/machine_adc.c
@@ -142,13 +142,17 @@ STATIC mp_obj_t madc_read(mp_obj_t self_in) {
if (err != ESP_OK) mp_raise_ValueError("Set width Error");
}
- int val = 0;
- if (self->gpio_id == GPIO_NUM_MAX) val= hall_sensor_read();
+ int adc_val = 0;
+ if (self->gpio_id == GPIO_NUM_MAX) adc_val= hall_sensor_read();
else {
- esp_adc_cal_get_characteristics(adc_vref, self->atten, self->width, &characteristics);
- val = adc1_to_voltage(self->adc1_id, &characteristics);
+ // Deprecated
+ //esp_adc_cal_get_characteristics(adc_vref, self->atten, self->width, &characteristics);
+ //adc_val = adc1_to_voltage(self->adc1_id, &characteristics);
+
+ esp_adc_cal_value_t adc_val = esp_adc_cal_characterize(self->adc1_id, self->atten, self->width, adc_vref, &characteristics);
+ esp_adc_cal_get_voltage(self->adc1_id, &characteristics, &adc_val);
}
- return MP_OBJ_NEW_SMALL_INT(val);
+ return MP_OBJ_NEW_SMALL_INT(adc_val);
}
MP_DEFINE_CONST_FUN_OBJ_1(madc_read_obj, madc_read);
diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c b/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c
index 10858b9..59e96c0 100644
--- a/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c
+++ b/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c
@@ -596,7 +596,7 @@ STATIC mp_obj_t machine_neopixel_corder(size_t n_args, const mp_obj_t *pos_args,
}
sprintf(colorder, self->px.color_order);
if (self->px.nbits == 24) colorder[3] = '\0';
- return mp_obj_new_str(colorder, strlen(colorder), 0);
+ return mp_obj_new_str(colorder, strlen(colorder));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_neopixel_corder_obj, 0, machine_neopixel_corder);
@@ -711,7 +711,7 @@ STATIC mp_obj_t machine_neopixel_info(mp_obj_t self_in)
tuple[2] = mp_obj_new_int(self->px.nbits);
tuple[3] = mp_obj_new_int(self->channel);
tuple[4] = mp_obj_new_int(sizeof(uint32_t) * self->px.pixel_count);
- tuple[5] = mp_obj_new_str(colorder, strlen(colorder), false);
+ tuple[5] = mp_obj_new_str(colorder, strlen(colorder));
return mp_obj_new_tuple(6, tuple);
diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_ow.c b/MicroPython_BUILD/components/micropython/esp32/machine_ow.c
index 93f8ec4..9c36fd7 100644
--- a/MicroPython_BUILD/components/micropython/esp32/machine_ow.c
+++ b/MicroPython_BUILD/components/micropython/esp32/machine_ow.c
@@ -231,7 +231,7 @@ STATIC mp_obj_t machine_onewire_readbytes(mp_obj_t self_in, mp_obj_t len_in) {
owb_read_bytes(self->owb, buff, len);
- return mp_obj_new_str((const char *)buff, len, 0);
+ return mp_obj_new_str((const char *)buff, len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_onewire_readbytes_obj, machine_onewire_readbytes);
@@ -292,7 +292,7 @@ STATIC mp_obj_t machine_onewire_rom_code(mp_obj_t self_in, mp_obj_t device_in) {
char rom_code[17];
owb_string_from_rom_code(self->device_rom_codes[device], rom_code, sizeof(rom_code));
- return mp_obj_new_str(rom_code, strlen(rom_code), 0);
+ return mp_obj_new_str(rom_code, strlen(rom_code));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_onewire_rom_code_obj, machine_onewire_rom_code);
@@ -330,7 +330,7 @@ STATIC mp_obj_t machine_onewire_search(size_t n_args, const mp_obj_t *pos_args,
}
else {
owb_string_from_rom_code(self->device_rom_codes[i], rom_code_s, sizeof(rom_code_s));
- tuple[i] = mp_obj_new_str(rom_code_s, strlen(rom_code_s), 0);
+ tuple[i] = mp_obj_new_str(rom_code_s, strlen(rom_code_s));
}
}
@@ -582,8 +582,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_ds18x20_get_pwrmode_obj, machine_ds18x2
//--------------------------------------------------------------
STATIC mp_obj_t machine_ds18x20_get_convtime(mp_obj_t self_in) {
- ds18x20_obj_t *self = self_in;
-
int64_t conv_time = 0;
if (conv_end_time) {
conv_time = mp_hal_ticks_ms() - conv_end_time;
@@ -600,7 +598,7 @@ STATIC mp_obj_t machine_ds18x20_rom_code(mp_obj_t self_in) {
char rom_code[17];
owb_string_from_rom_code(self->owb_obj->device_rom_codes[self->device], rom_code, sizeof(rom_code));
- return mp_obj_new_str(rom_code, strlen(rom_code), 0);
+ return mp_obj_new_str(rom_code, strlen(rom_code));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_ds18x20_rom_code_obj, machine_ds18x20_rom_code);
diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_pin.c b/MicroPython_BUILD/components/micropython/esp32/machine_pin.c
index 490d4ef..c51541c 100644
--- a/MicroPython_BUILD/components/micropython/esp32/machine_pin.c
+++ b/MicroPython_BUILD/components/micropython/esp32/machine_pin.c
@@ -281,7 +281,7 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_
mp_raise_ValueError("invalid trigger type");
}
if (gpio_isr_handler_add(self->id, machine_pin_isr_handler, (void*)self) != ESP_OK) {
- mp_raise_OSError("error adding ISR handler");
+ mp_raise_ValueError("error adding ISR handler");
}
}
diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c b/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c
index 49c5342..8b3c186 100644
--- a/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c
+++ b/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c
@@ -477,7 +477,7 @@ STATIC mp_obj_t machine_rtc_wake_on_ext1(size_t n_args, const mp_obj_t *pos_args
machine_rtc_config.ext1_level = (uint8_t)ext1_level;
for (int i=0; i 0) {
mp_obj_t sms_tuple[7];
sms_tuple[0] = mp_obj_new_int(smsmsg.idx);
- sms_tuple[1] = mp_obj_new_str(smsmsg.stat, strlen(smsmsg.stat), false);
- sms_tuple[2] = mp_obj_new_str(smsmsg.from, strlen(smsmsg.from), false);
- sms_tuple[3] = mp_obj_new_str(smsmsg.time, strlen(smsmsg.time), false);
+ sms_tuple[1] = mp_obj_new_str(smsmsg.stat, strlen(smsmsg.stat));
+ sms_tuple[2] = mp_obj_new_str(smsmsg.from, strlen(smsmsg.from));
+ sms_tuple[3] = mp_obj_new_str(smsmsg.time, strlen(smsmsg.time));
sms_tuple[4] = mp_obj_new_int(smsmsg.time_value);
sms_tuple[5] = mp_obj_new_int(smsmsg.tz);
if (smsmsg.msg) {
- sms_tuple[6] = mp_obj_new_str(smsmsg.msg, strlen(smsmsg.msg), false);
+ sms_tuple[6] = mp_obj_new_str(smsmsg.msg, strlen(smsmsg.msg));
free(smsmsg.msg);
}
else sms_tuple[6] = mp_const_none;
@@ -329,7 +326,7 @@ STATIC mp_obj_t mod_gsm_atCmd(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
char **pbuffer = &buffer;
int res = at_Cmd(atcmd, resp, pbuffer, 1024, tmo, cmddata);
if (res == 0) {
- mp_obj_t response = mp_obj_new_str("", 0, false);
+ mp_obj_t response = mp_obj_new_str("", 0);
free(*pbuffer);
return response;
}
@@ -341,7 +338,7 @@ STATIC mp_obj_t mod_gsm_atCmd(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
}
}
}
- mp_obj_t response = mp_obj_new_str(buffer, strlen(buffer), false);
+ mp_obj_t response = mp_obj_new_str(buffer, strlen(buffer));
free(*pbuffer);
return response;
}
diff --git a/MicroPython_BUILD/components/micropython/esp32/modmachine.c b/MicroPython_BUILD/components/micropython/esp32/modmachine.c
index 2ad2645..0b897f9 100644
--- a/MicroPython_BUILD/components/micropython/esp32/modmachine.c
+++ b/MicroPython_BUILD/components/micropython/esp32/modmachine.c
@@ -47,7 +47,7 @@
#include "soc/dport_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "rom/uart.h"
-#include "esp_deep_sleep.h"
+#include "esp_sleep.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "esp_err.h"
@@ -451,8 +451,8 @@ STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *pos_args, mp_ma
}
if (sleep_time > 0) {
- if (stub_sleep) esp_deep_sleep_enable_timer_wakeup((uint64_t)(stub_sleep * 1000));
- else esp_deep_sleep_enable_timer_wakeup((uint64_t)(sleep_time * 1000));
+ if (stub_sleep) esp_sleep_enable_timer_wakeup((uint64_t)(stub_sleep * 1000));
+ else esp_sleep_enable_timer_wakeup((uint64_t)(sleep_time * 1000));
machine_rtc_config.deepsleep_time = sleep_time;
}
else {
@@ -463,7 +463,7 @@ STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *pos_args, mp_ma
if (machine_rtc_config.ext0_pin >= 0) {
printf("EXT0=%d\n", machine_rtc_config.ext0_pin);
- esp_deep_sleep_enable_ext0_wakeup((gpio_num_t)machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? 1 : 0);
+ esp_sleep_enable_ext0_wakeup((gpio_num_t)machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? 1 : 0);
esp_set_deep_sleep_wake_stub(&wake_stub);
}
@@ -479,12 +479,12 @@ STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *pos_args, mp_ma
//esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
uint8_t ext1_level = machine_rtc_config.ext1_level;
if (machine_rtc_config.ext1_level == EXT1_WAKEUP_ALL_HIGH) ext1_level = ESP_EXT1_WAKEUP_ANY_HIGH;
- esp_deep_sleep_enable_ext1_wakeup(ext1_pins, ext1_level);
+ esp_sleep_enable_ext1_wakeup(ext1_pins, ext1_level);
esp_set_deep_sleep_wake_stub(&wake_stub);
}
if (machine_rtc_config.wake_on_touch) {
- esp_deep_sleep_enable_touchpad_wakeup();
+ esp_sleep_enable_touchpad_wakeup();
}
printf("Sleep time: time=%d, interval=%d, pin=%d, level=%d, wait=%llu\n",
@@ -537,9 +537,9 @@ STATIC mp_obj_t machine_wake_desc (void) {
mp_obj_t tuple[2];
mpsleep_get_reset_desc(reason);
- tuple[0] = mp_obj_new_str(reason, strlen(reason), 0);
+ tuple[0] = mp_obj_new_str(reason, strlen(reason));
mpsleep_get_wake_desc(reason);
- tuple[1] = mp_obj_new_str(reason, strlen(reason), 0);
+ tuple[1] = mp_obj_new_str(reason, strlen(reason));
return mp_obj_new_tuple(2, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_wake_desc_obj, machine_wake_desc);
@@ -714,7 +714,7 @@ STATIC mp_obj_t mod_machine_nvs_get_str (mp_obj_t _key) {
if (value) {
esp_err_t ret = nvs_get_str(mpy_nvs_handle, key, value, &len);
if ((ret == ESP_OK ) && (len > 0)) {
- strval = mp_obj_new_str(value, strlen(value), 0);
+ strval = mp_obj_new_str(value, strlen(value));
free(value);
}
}
diff --git a/MicroPython_BUILD/components/micropython/esp32/modmqtt.c b/MicroPython_BUILD/components/micropython/esp32/modmqtt.c
index d06c9b7..2190e5c 100644
--- a/MicroPython_BUILD/components/micropython/esp32/modmqtt.c
+++ b/MicroPython_BUILD/components/micropython/esp32/modmqtt.c
@@ -536,7 +536,7 @@ STATIC mp_obj_t mqtt_op_status(mp_obj_t self_in)
else if (self->client->status == MQTT_STATUS_STOPPED) sprintf(sstat, "Stopped");
else sprintf(sstat, "Unknown");
}
- tuple[1] = mp_obj_new_str(sstat, strlen(sstat), 0);
+ tuple[1] = mp_obj_new_str(sstat, strlen(sstat));
return mp_obj_new_tuple(2, tuple);
}
diff --git a/MicroPython_BUILD/components/micropython/esp32/modnetwork.c b/MicroPython_BUILD/components/micropython/esp32/modnetwork.c
index 66b2be5..2eaaef6 100644
--- a/MicroPython_BUILD/components/micropython/esp32/modnetwork.c
+++ b/MicroPython_BUILD/components/micropython/esp32/modnetwork.c
@@ -45,7 +45,7 @@
#include "py/runtime.h"
#include "py/mphal.h"
#include "py/mperrno.h"
-#include "py/obj.h"
+//#include "py/obj.h"
#include "netutils.h"
#include "esp_wifi.h"
#include "esp_wifi_types.h"
@@ -76,7 +76,7 @@ NORETURN void _esp_exceptions(esp_err_t e) {
case ESP_ERR_WIFI_SSID:
mp_raise_msg(&mp_type_OSError, "Wifi SSID Invalid");
break;
- case ESP_ERR_WIFI_FAIL:
+ case ESP_FAIL:
mp_raise_msg(&mp_type_OSError, "Wifi Internal Failure");
break;
case ESP_ERR_WIFI_IF:
@@ -85,7 +85,7 @@ NORETURN void _esp_exceptions(esp_err_t e) {
case ESP_ERR_WIFI_MAC:
mp_raise_msg(&mp_type_OSError, "Wifi Invalid MAC Address");
break;
- case ESP_ERR_WIFI_ARG:
+ case ESP_ERR_INVALID_ARG:
mp_raise_msg(&mp_type_OSError, "Wifi Invalid Argument");
break;
case ESP_ERR_WIFI_MODE:
@@ -110,7 +110,7 @@ NORETURN void _esp_exceptions(esp_err_t e) {
mp_raise_OSError(MP_ETIMEDOUT);
break;
case ESP_ERR_TCPIP_ADAPTER_NO_MEM:
- case ESP_ERR_WIFI_NO_MEM:
+ case ESP_ERR_NO_MEM:
mp_raise_OSError(MP_ENOMEM);
break;
default:
@@ -297,6 +297,7 @@ static void processEvent_callback(system_event_t *event)
case SYSTEM_EVENT_STA_LOST_IP: {
system_event_sta_got_ip_t *info = (system_event_sta_got_ip_t *)&event->event_info;
wifi_sta_has_ipaddress = false;
+ wifi_sta_changed_ipaddress = info->ip_changed;
wifi_sta_changed_ipaddress = true;
break;
}
@@ -525,11 +526,37 @@ STATIC mp_obj_t esp_disconnect(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_disconnect_obj, esp_disconnect);
-//--------------------------------------------
-STATIC mp_obj_t esp_status(mp_obj_t self_in) {
+//---------------------------------------------------------------
+STATIC mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) {
+ if (n_args == 1) {
+ // no arguments: return None until link status is implemented
+ return mp_const_none;
+ }
+
+ // one argument: return status based on query parameter
+ switch ((uintptr_t)args[1]) {
+ case (uintptr_t)MP_OBJ_NEW_QSTR(MP_QSTR_stations): {
+ // return list of connected stations, only if in soft-AP mode
+ require_if(args[0], WIFI_IF_AP);
+ wifi_sta_list_t station_list;
+ ESP_EXCEPTIONS(esp_wifi_ap_get_sta_list(&station_list));
+ wifi_sta_info_t *stations = (wifi_sta_info_t*)station_list.sta;
+ mp_obj_t list = mp_obj_new_list(0, NULL);
+ for (int i = 0; i < station_list.num; ++i) {
+ mp_obj_tuple_t *t = mp_obj_new_tuple(1, NULL);
+ t->items[0] = mp_obj_new_bytes(stations[i].mac, sizeof(stations[i].mac));
+ mp_obj_list_append(list, t);
+ }
+ return list;
+ }
+
+ default:
+ mp_raise_ValueError("unknown status param");
+ }
+
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_status_obj, esp_status);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_status_obj, 1, 2, esp_status);
//------------------------------------------
STATIC mp_obj_t esp_scan(mp_obj_t self_in) {
@@ -700,6 +727,11 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value);
break;
}
+ case QS(MP_QSTR_dhcp_hostname): {
+ const char *s = mp_obj_str_get_str(kwargs->table[i].value);
+ ESP_EXCEPTIONS(tcpip_adapter_set_hostname(self->if_id, s));
+ break;
+ }
default:
goto unknown;
}
@@ -734,7 +766,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
}
case QS(MP_QSTR_essid):
req_if = WIFI_IF_AP;
- val = mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len, false);
+ val = mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len);
break;
case QS(MP_QSTR_hidden):
req_if = WIFI_IF_AP;
@@ -748,6 +780,12 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
req_if = WIFI_IF_AP;
val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel);
break;
+ case QS(MP_QSTR_dhcp_hostname): {
+ const char *s;
+ ESP_EXCEPTIONS(tcpip_adapter_get_hostname(self->if_id, &s));
+ val = mp_obj_new_str(s, strlen(s));
+ break;
+ }
default:
goto unknown;
}
@@ -927,7 +965,7 @@ STATIC mp_obj_t mod_network_stateTelnet()
else sprintf(state, "Unknown");
tuple[0] = mp_obj_new_int(telnet_state);
- tuple[1] = mp_obj_new_str(state, strlen(state), false);
+ tuple[1] = mp_obj_new_str(state, strlen(state));
return mp_obj_new_tuple(2, tuple);
}
@@ -935,12 +973,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_network_stateTelnet_obj, mod_network_stateT
//===============================================================
STATIC const mp_map_elem_t network_telnet_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&mod_network_startTelnet_obj) },
- { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&mod_network_pauseTelnet_obj) },
- { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&mod_network_resumeTelnet_obj) },
- { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mod_network_stopTelnet_obj) },
- { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&mod_network_stateTelnet_obj) },
- { MP_ROM_QSTR(MP_QSTR_stack), MP_ROM_PTR(&mod_network_TelnetMaxStack_obj) }
+ { MP_ROM_QSTR(MP_QSTR_start), (mp_obj_t)&mod_network_startTelnet_obj },
+ { MP_ROM_QSTR(MP_QSTR_pause), (mp_obj_t)&mod_network_pauseTelnet_obj },
+ { MP_ROM_QSTR(MP_QSTR_resume), (mp_obj_t)&mod_network_resumeTelnet_obj },
+ { MP_ROM_QSTR(MP_QSTR_stop), (mp_obj_t)&mod_network_stopTelnet_obj },
+ { MP_ROM_QSTR(MP_QSTR_status), (mp_obj_t)&mod_network_stateTelnet_obj },
+ { MP_ROM_QSTR(MP_QSTR_stack), (mp_obj_t)&mod_network_TelnetMaxStack_obj }
};
STATIC MP_DEFINE_CONST_DICT(network_telnet_locals_dict, network_telnet_locals_dict_table);
@@ -1064,13 +1102,13 @@ STATIC mp_obj_t mod_network_stateFtp()
else if (ftp_state == -1) sprintf(state, "Not started");
else if (ftp_state == -2) sprintf(state, "Busy!");
else sprintf(state, "Unknown");
- tuple[2] = mp_obj_new_str(state, strlen(state), false);
+ tuple[2] = mp_obj_new_str(state, strlen(state));
if (ftp_substate == E_FTP_STE_SUB_DISCONNECTED) sprintf(state, "Data: Disconnected");
else if (ftp_substate == E_FTP_STE_SUB_LISTEN_FOR_DATA) sprintf(state, "Data: Listen");
else if (ftp_substate == E_FTP_STE_SUB_DATA_CONNECTED) sprintf(state, "Data: Connected");
else sprintf(state, "Unknown");
- tuple[3] = mp_obj_new_str(state, strlen(state), false);
+ tuple[3] = mp_obj_new_str(state, strlen(state));
return mp_obj_new_tuple(4, tuple);
}
@@ -1078,12 +1116,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_network_stateFtp_obj, mod_network_stateFtp)
//============================================================
STATIC const mp_map_elem_t network_ftp_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&mod_network_startFtp_obj) },
- { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&mod_network_pauseFtp_obj) },
- { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&mod_network_resumeFtp_obj) },
- { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mod_network_stopFtp_obj) },
- { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&mod_network_stateFtp_obj) },
- { MP_ROM_QSTR(MP_QSTR_stack), MP_ROM_PTR(&mod_network_FtpMaxStack_obj) }
+ { MP_ROM_QSTR(MP_QSTR_start), (mp_obj_t)&mod_network_startFtp_obj },
+ { MP_ROM_QSTR(MP_QSTR_pause), (mp_obj_t)&mod_network_pauseFtp_obj },
+ { MP_ROM_QSTR(MP_QSTR_resume), (mp_obj_t)&mod_network_resumeFtp_obj },
+ { MP_ROM_QSTR(MP_QSTR_stop), (mp_obj_t)&mod_network_stopFtp_obj },
+ { MP_ROM_QSTR(MP_QSTR_status), (mp_obj_t)&mod_network_stateFtp_obj },
+ { MP_ROM_QSTR(MP_QSTR_stack), (mp_obj_t)&mod_network_FtpMaxStack_obj }
};
STATIC MP_DEFINE_CONST_DICT(network_ftp_locals_dict, network_ftp_locals_dict_table);
@@ -1112,16 +1150,16 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_LAN), (mp_obj_t)&get_lan_obj },
#endif
#ifdef CONFIG_MICROPY_USE_MQTT
- { MP_ROM_QSTR(MP_QSTR_mqtt), MP_ROM_PTR(&mqtt_type) },
+ { MP_ROM_QSTR(MP_QSTR_mqtt), (mp_obj_type_t *)&mqtt_type },
#endif
#ifdef CONFIG_MICROPY_USE_TELNET
- { MP_ROM_QSTR(MP_QSTR_telnet), MP_ROM_PTR(&network_telnet_type) },
+ { MP_ROM_QSTR(MP_QSTR_telnet), (mp_obj_type_t *)&network_telnet_type },
#endif
#ifdef CONFIG_MICROPY_USE_FTPSERVER
- { MP_ROM_QSTR(MP_QSTR_ftp), MP_ROM_PTR(&network_ftp_type) },
+ { MP_ROM_QSTR(MP_QSTR_ftp), (mp_obj_type_t *)&network_ftp_type },
#endif
#ifdef CONFIG_MICROPY_USE_MDNS
- { MP_ROM_QSTR(MP_QSTR_mDNS), MP_ROM_PTR(&mdns_type) },
+ { MP_ROM_QSTR(MP_QSTR_mDNS), (mp_obj_type_t *)&mdns_type },
#endif
#if MODNETWORK_INCLUDE_CONSTANTS
diff --git a/MicroPython_BUILD/components/micropython/esp32/modsocket.c b/MicroPython_BUILD/components/micropython/esp32/modsocket.c
index e8891b9..c0ab698 100644
--- a/MicroPython_BUILD/components/micropython/esp32/modsocket.c
+++ b/MicroPython_BUILD/components/micropython/esp32/modsocket.c
@@ -107,7 +107,7 @@ static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struc
if (MP_OBJ_IS_SMALL_INT(port)) {
// This is perverse, because lwip_getaddrinfo promptly converts it back to an int, but
// that's the API we have to work with ...
- port = mp_obj_str_binary_op(MP_BINARY_OP_MODULO, mp_obj_new_str("%s", 2, true), port);
+ port = mp_obj_str_binary_op(MP_BINARY_OP_MODULO, mp_obj_new_str_via_qstr("%s", 2), port);
}
const char *host_str = mp_obj_str_get_str(host);
@@ -581,9 +581,11 @@ STATIC mp_obj_t get_socket(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_socket_obj, 0, 3, get_socket);
-STATIC mp_obj_t esp_socket_getaddrinfo(const mp_obj_t host, const mp_obj_t port) {
+STATIC mp_obj_t esp_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) {
+ // TODO support additional args beyond the first two
+
struct addrinfo *res = NULL;
- _socket_getaddrinfo2(host, port, &res);
+ _socket_getaddrinfo2(args[0], args[1], &res);
mp_obj_t ret_list = mp_obj_new_list(0, NULL);
for (struct addrinfo *resi = res; resi; resi = resi->ai_next) {
@@ -591,7 +593,7 @@ STATIC mp_obj_t esp_socket_getaddrinfo(const mp_obj_t host, const mp_obj_t port)
mp_obj_new_int(resi->ai_family),
mp_obj_new_int(resi->ai_socktype),
mp_obj_new_int(resi->ai_protocol),
- mp_obj_new_str(resi->ai_canonname, strlen(resi->ai_canonname), false),
+ mp_obj_new_str(resi->ai_canonname, strlen(resi->ai_canonname)),
mp_const_none
};
@@ -602,7 +604,7 @@ STATIC mp_obj_t esp_socket_getaddrinfo(const mp_obj_t host, const mp_obj_t port)
char buf[16];
ip4addr_ntoa_r(&ip4_addr, buf, sizeof(buf));
mp_obj_t inaddr_objs[2] = {
- mp_obj_new_str(buf, strlen(buf), false),
+ mp_obj_new_str(buf, strlen(buf)),
mp_obj_new_int(ntohs(addr->sin_port))
};
addrinfo_objs[4] = mp_obj_new_tuple(2, inaddr_objs);
@@ -613,7 +615,7 @@ STATIC mp_obj_t esp_socket_getaddrinfo(const mp_obj_t host, const mp_obj_t port)
if (res) lwip_freeaddrinfo(res);
return ret_list;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_getaddrinfo_obj, esp_socket_getaddrinfo);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_socket_getaddrinfo_obj, 2, 6, esp_socket_getaddrinfo);
STATIC mp_obj_t esp_socket_initialize() {
static int initialized = 0;
diff --git a/MicroPython_BUILD/components/micropython/esp32/moduos.c b/MicroPython_BUILD/components/micropython/esp32/moduos.c
index d05b891..568160c 100644
--- a/MicroPython_BUILD/components/micropython/esp32/moduos.c
+++ b/MicroPython_BUILD/components/micropython/esp32/moduos.c
@@ -110,14 +110,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_dupterm_notify_obj, os_dupterm_notify);
//------------------------------------------------------------------
STATIC mp_obj_t os_mount_sdcard(size_t n_args, const mp_obj_t *args)
{
- int res = -1;
if (n_args > 0) {
int chd = mp_obj_get_int(args[0]);
if (chd) {
- int res = mount_vfs(VFS_NATIVE_TYPE_SDCARD, VFS_NATIVE_EXTERNAL_MP);
+ mount_vfs(VFS_NATIVE_TYPE_SDCARD, VFS_NATIVE_EXTERNAL_MP);
}
}
- else res = mount_vfs(VFS_NATIVE_TYPE_SDCARD, NULL);
+ else mount_vfs(VFS_NATIVE_TYPE_SDCARD, NULL);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_mount_sdcard_obj, 0, 1, os_mount_sdcard);
@@ -126,11 +125,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_mount_sdcard_obj, 0, 1, os_mount_s
STATIC mp_obj_t os_umount_sdcard(void)
{
// umount external (sdcard) file system
- mp_obj_t sddir = mp_obj_new_str(VFS_NATIVE_EXTERNAL_MP, strlen(VFS_NATIVE_EXTERNAL_MP), false);
+ mp_obj_t sddir = mp_obj_new_str(VFS_NATIVE_EXTERNAL_MP, strlen(VFS_NATIVE_EXTERNAL_MP));
mp_call_function_1(MP_OBJ_FROM_PTR(&mp_vfs_umount_obj), sddir);
// Change directory to /flash
- sddir = mp_obj_new_str(VFS_NATIVE_INTERNAL_MP, strlen(VFS_NATIVE_INTERNAL_MP), false);
+ sddir = mp_obj_new_str(VFS_NATIVE_INTERNAL_MP, strlen(VFS_NATIVE_INTERNAL_MP));
mp_call_function_1(MP_OBJ_FROM_PTR(&mp_vfs_chdir_obj), sddir);
return mp_const_none;
@@ -177,7 +176,6 @@ STATIC mp_obj_t os_sdcard_config(size_t n_args, const mp_obj_t *pos_args, mp_map
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(os_sdcard_config_obj, 0, os_sdcard_config);
-
#if CONFIG_MICROPY_FILESYSTEM_TYPE == 2
//----------------------------------------------------------
STATIC mp_obj_t os_trim(size_t n_args, const mp_obj_t *args)
diff --git a/MicroPython_BUILD/components/micropython/esp32/modutime.c b/MicroPython_BUILD/components/micropython/esp32/modutime.c
index 386c3c5..de03356 100644
--- a/MicroPython_BUILD/components/micropython/esp32/modutime.c
+++ b/MicroPython_BUILD/components/micropython/esp32/modutime.c
@@ -143,7 +143,7 @@ STATIC mp_obj_t time_strftime(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
strftime(str_time, 127, fmt, tm_info);
- return mp_obj_new_str(str_time, strlen(str_time), false);
+ return mp_obj_new_str(str_time, strlen(str_time));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(time_strftime_obj, 1, time_strftime);
diff --git a/MicroPython_BUILD/components/micropython/esp32/modymodem.c b/MicroPython_BUILD/components/micropython/esp32/modymodem.c
index b9928c7..d181f6d 100644
--- a/MicroPython_BUILD/components/micropython/esp32/modymodem.c
+++ b/MicroPython_BUILD/components/micropython/esp32/modymodem.c
@@ -96,7 +96,6 @@ static int32_t receive_Bytes (unsigned char *buf, int size, uint32_t timeout)
//--------------------------------------------------------------
static int32_t Receive_Byte (unsigned char *c, uint32_t timeout)
{
- unsigned char ch;
int cb = mp_hal_stdin_rx_chr(timeout);
if (cb < 0) return -1;
@@ -508,7 +507,7 @@ int Ymodem_Transmit (char* sendFileName, unsigned int sizeFile, FILE *ffd, char
uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD];
uint16_t blkNumber;
unsigned char receivedC;
- int i, err;
+ int err;
uint32_t size = 0;
// Wait for response from receiver
@@ -720,11 +719,8 @@ STATIC mp_obj_t ymodem_send(mp_obj_t fname_in)
#if CONFIG_MICROPY_RX_BUFFER_SIZE > 1079
const char *fname = mp_obj_str_get_str(fname_in);
int fsize = 0, err = 0;
- char fullname[128] = {'\0'};;
+ char fullname[128] = {'\0'};
char err_msg[128] = {'\0'};
- char cwd[128] = {'\0'};;
- char orig_name[128] = {'\0'};
- char *pcwd = NULL;
if (physicalPath(fname, fullname) != 0) {
sprintf(err_msg, "File name cannot be resolved");
@@ -750,7 +746,7 @@ STATIC mp_obj_t ymodem_send(mp_obj_t fname_in)
uart0_raw_input = 1;
xSemaphoreGive(uart0_mutex);
- int trans_res = Ymodem_Transmit(fname, fsize, ffd, err_msg);
+ int trans_res = Ymodem_Transmit((char *)fname, fsize, ffd, err_msg);
xSemaphoreTake(uart0_mutex, UART_SEMAPHORE_WAIT);
uart0_raw_input = 0;
diff --git a/MicroPython_BUILD/components/micropython/esp32/mpconfigport.h b/MicroPython_BUILD/components/micropython/esp32/mpconfigport.h
index 7c0433c..bc4a0bd 100644
--- a/MicroPython_BUILD/components/micropython/esp32/mpconfigport.h
+++ b/MicroPython_BUILD/components/micropython/esp32/mpconfigport.h
@@ -121,6 +121,7 @@
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
#define MICROPY_PY_ATTRTUPLE (1)
#define MICROPY_PY_COLLECTIONS (1)
+#define MICROPY_PY_COLLECTIONS_DEQUE (1)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
#define MICROPY_PY_MATH (1)
#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1)
@@ -151,8 +152,6 @@
#define MICROPY_PY_URE (1)
#define MICROPY_PY_UHEAPQ (1)
#define MICROPY_PY_UTIMEQ (1)
-#define MICROPY_PY_UHASHLIB (0) // We use the ESP32 version
-#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_AXTLS)
#define MICROPY_PY_UBINASCII (1)
#define MICROPY_PY_UBINASCII_CRC32 (1)
#define MICROPY_PY_URANDOM (1)
@@ -169,6 +168,10 @@
#define MICROPY_PY_MACHINE_SPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly
#define MICROPY_PY_USSL (1)
#define MICROPY_SSL_MBEDTLS (1)
+#define MICROPY_PY_USSL_FINALISER (1)
+#define MICROPY_PY_UHASHLIB (0) // We use the ESP32 version
+#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_MBEDTLS)
+
#ifdef CONFIG_MICROPY_USE_WEBSOCKETS
#define MICROPY_PY_WEBSOCKET (1)
#else
diff --git a/MicroPython_BUILD/components/micropython/esp32/mpsleep.c b/MicroPython_BUILD/components/micropython/esp32/mpsleep.c
index 57cfc3e..6e957a5 100644
--- a/MicroPython_BUILD/components/micropython/esp32/mpsleep.c
+++ b/MicroPython_BUILD/components/micropython/esp32/mpsleep.c
@@ -40,7 +40,7 @@
#include "sdkconfig.h"
#include "rom/rtc.h"
#include "esp_system.h"
-#include "esp_deep_sleep.h"
+#include "esp_sleep.h"
#include "esp_log.h"
#include "mpsleep.h"
@@ -80,20 +80,20 @@ void mpsleep_init0 (void) {
}
// check the wakeup reason
- switch (esp_deep_sleep_get_wakeup_cause()) {
- case ESP_DEEP_SLEEP_WAKEUP_EXT0:
+ switch (esp_sleep_get_wakeup_cause()) {
+ case ESP_SLEEP_WAKEUP_EXT0:
mpsleep_wake_reason = MPSLEEP_GPIO0_WAKE;
break;
- case ESP_DEEP_SLEEP_WAKEUP_EXT1:
+ case ESP_SLEEP_WAKEUP_EXT1:
mpsleep_wake_reason = MPSLEEP_GPIO1_WAKE;
break;
- case ESP_DEEP_SLEEP_WAKEUP_TOUCHPAD:
+ case ESP_SLEEP_WAKEUP_TOUCHPAD:
mpsleep_wake_reason = MPSLEEP_TOUCH_WAKE;
break;
- case ESP_DEEP_SLEEP_WAKEUP_TIMER:
+ case ESP_SLEEP_WAKEUP_TIMER:
mpsleep_wake_reason = MPSLEEP_RTC_WAKE;
break;
- case ESP_DEEP_SLEEP_WAKEUP_UNDEFINED:
+ case ESP_SLEEP_WAKEUP_UNDEFINED:
default:
mpsleep_wake_reason = MPSLEEP_NONE_WAKE;
break;
diff --git a/MicroPython_BUILD/components/micropython/esp32/mpversion.h b/MicroPython_BUILD/components/micropython/esp32/mpversion.h
index 25cae41..289fdb4 100644
--- a/MicroPython_BUILD/components/micropython/esp32/mpversion.h
+++ b/MicroPython_BUILD/components/micropython/esp32/mpversion.h
@@ -24,10 +24,12 @@
* THE SOFTWARE.
*/
-#define MICROPY_GIT_TAG "ESP32_LoBo_v3.1.29"
-#define MICROPY_GIT_HASH "g84788230"
-#define MICROPY_BUILD_DATE "2018-03-31"
+#define MICROPY_GIT_TAG "ESP32_LoBo_v3.2.4"
+#define MICROPY_GIT_HASH "g139d4989"
+#define MICROPY_BUILD_DATE "2018-04-06"
#define MICROPY_VERSION_MAJOR (3)
-#define MICROPY_VERSION_MINOR (1)
-#define MICROPY_VERSION_MICRO (29)
-#define MICROPY_VERSION_STRING "3.1.29"
+#define MICROPY_VERSION_MINOR (2)
+#define MICROPY_VERSION_MICRO (4)
+#define MICROPY_VERSION_STRING "3.2.4"
+#define MICROPY_CORE_VERSION "bcfff4f"
+#define MICROPY_CORE_DATE "2018-03-30"
diff --git a/MicroPython_BUILD/components/micropython/esp32/network_mdns.c b/MicroPython_BUILD/components/micropython/esp32/network_mdns.c
index c77aa30..f20ddce 100644
--- a/MicroPython_BUILD/components/micropython/esp32/network_mdns.c
+++ b/MicroPython_BUILD/components/micropython/esp32/network_mdns.c
@@ -270,7 +270,7 @@ STATIC mp_obj_t mdns_host_query(mp_uint_t n_args, const mp_obj_t *pos_args, mp_m
else if (res == ESP_ERR_NOT_FOUND) sprintf(tmps, "Host was not found!");
else sprintf(tmps, "Query Failed");
- return mp_obj_new_str(tmps, strlen(tmps), false);;
+ return mp_obj_new_str(tmps, strlen(tmps));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mdns_host_query_obj, 2, mdns_host_query);
@@ -320,21 +320,21 @@ STATIC mp_obj_t mdns_service_query(mp_uint_t n_args, const mp_obj_t *pos_args, m
while (r) {
// Interface type
sprintf(tmps, "%s", if_str[r->tcpip_if]);
- t->items[0] = mp_obj_new_str(tmps, strlen(tmps), false);
+ t->items[0] = mp_obj_new_str(tmps, strlen(tmps));
// Protocol, V4 or V6
sprintf(tmps, "%s", ip_protocol_str[r->ip_protocol]);
- t->items[1] = mp_obj_new_str(tmps, strlen(tmps), false);
+ t->items[1] = mp_obj_new_str(tmps, strlen(tmps));
// Instance name
if (r->instance_name) sprintf(tmps, "%s", r->instance_name);
else sprintf(tmps, "?");
- t->items[2] = mp_obj_new_str(tmps, strlen(tmps), false);
+ t->items[2] = mp_obj_new_str(tmps, strlen(tmps));
// Host name & port
if(r->hostname) {
sprintf(tmps, "%s.local", r->hostname);
- t->items[3] = mp_obj_new_str(tmps, strlen(tmps), false);
+ t->items[3] = mp_obj_new_str(tmps, strlen(tmps));
t->items[4] = mp_obj_new_int(r->port);
}
else {
@@ -353,7 +353,7 @@ STATIC mp_obj_t mdns_service_query(mp_uint_t n_args, const mp_obj_t *pos_args, m
else {
sprintf(tmps, IPSTR, IP2STR(&(a->addr.u_addr.ip4)));
}
- mp_obj_list_append(addrlist, mp_obj_new_str(tmps, strlen(tmps), false));
+ mp_obj_list_append(addrlist, mp_obj_new_str(tmps, strlen(tmps)));
a = a->next;
}
t->items[5] = addrlist;
@@ -364,7 +364,7 @@ STATIC mp_obj_t mdns_service_query(mp_uint_t n_args, const mp_obj_t *pos_args, m
if(r->txt_count){
mp_obj_dict_t *dct = mp_obj_new_dict(0);
for(int i=0; itxt_count; i++){
- mp_obj_dict_store(dct, mp_obj_new_str(r->txt[i].key, strlen(r->txt[i].key), false), mp_obj_new_str(r->txt[i].value, strlen(r->txt[i].key), false));
+ mp_obj_dict_store(dct, mp_obj_new_str(r->txt[i].key, strlen(r->txt[i].key)), mp_obj_new_str(r->txt[i].value, strlen(r->txt[i].key)));
}
t->items[6] = dct;
}
diff --git a/MicroPython_BUILD/components/micropython/extmod/machine_pulse.c b/MicroPython_BUILD/components/micropython/extmod/machine_pulse.c
index bb57a4c..508ba67 100644
--- a/MicroPython_BUILD/components/micropython/extmod/machine_pulse.c
+++ b/MicroPython_BUILD/components/micropython/extmod/machine_pulse.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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/MicroPython_BUILD/components/micropython/extmod/machine_signal.c b/MicroPython_BUILD/components/micropython/extmod/machine_signal.c
index 78d0c3f..3f9f5af 100644
--- a/MicroPython_BUILD/components/micropython/extmod/machine_signal.c
+++ b/MicroPython_BUILD/components/micropython/extmod/machine_signal.c
@@ -58,7 +58,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
// If first argument isn't a Pin-like object, we filter out "invert"
// from keyword arguments and pass them all to the exported Pin
// constructor to create one.
- mp_obj_t pin_args[n_args + n_kw * 2];
+ mp_obj_t *pin_args = mp_local_alloc((n_args + n_kw * 2) * sizeof(mp_obj_t));
memcpy(pin_args, args, n_args * sizeof(mp_obj_t));
const mp_obj_t *src = args + n_args;
mp_obj_t *dst = pin_args + n_args;
@@ -88,6 +88,8 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
// will just ignore it as set a concrete type. If not, we'd need
// to expose port's "default" pin type too.
pin = MICROPY_PY_MACHINE_PIN_MAKE_NEW(NULL, n_args, n_kw, pin_args);
+
+ mp_local_free(pin_args);
}
else
#endif
diff --git a/MicroPython_BUILD/components/micropython/extmod/modbtree.c b/MicroPython_BUILD/components/micropython/extmod/modbtree.c
index f509eda..dd9e348 100644
--- a/MicroPython_BUILD/components/micropython/extmod/modbtree.c
+++ b/MicroPython_BUILD/components/micropython/extmod/modbtree.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -282,7 +283,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
STATIC mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in);
switch (op) {
- case MP_BINARY_OP_IN: {
+ case MP_BINARY_OP_CONTAINS: {
DBT key, val;
key.data = (void*)mp_obj_str_get_data(rhs_in, &key.size);
int res = __bt_get(self->db, &key, &val, 0);
diff --git a/MicroPython_BUILD/components/micropython/extmod/modframebuf.c b/MicroPython_BUILD/components/micropython/extmod/modframebuf.c
index c9fb682..7f809ab 100644
--- a/MicroPython_BUILD/components/micropython/extmod/modframebuf.c
+++ b/MicroPython_BUILD/components/micropython/extmod/modframebuf.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -54,7 +55,9 @@ typedef struct _mp_framebuf_p_t {
// constants for formats
#define FRAMEBUF_MVLSB (0)
#define FRAMEBUF_RGB565 (1)
+#define FRAMEBUF_GS2_HMSB (5)
#define FRAMEBUF_GS4_HMSB (2)
+#define FRAMEBUF_GS8 (6)
#define FRAMEBUF_MHLSB (3)
#define FRAMEBUF_MHMSB (4)
@@ -130,6 +133,30 @@ STATIC void rgb565_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, i
}
}
+// Functions for GS2_HMSB format
+
+STATIC void gs2_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) {
+ uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride) >> 2];
+ uint8_t shift = (x & 0x3) << 1;
+ uint8_t mask = 0x3 << shift;
+ uint8_t color = (col & 0x3) << shift;
+ *pixel = color | (*pixel & (~mask));
+}
+
+STATIC uint32_t gs2_hmsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) {
+ uint8_t pixel = ((uint8_t*)fb->buf)[(x + y * fb->stride) >> 2];
+ uint8_t shift = (x & 0x3) << 1;
+ return (pixel >> shift) & 0x3;
+}
+
+STATIC void gs2_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
+ for (int xx=x; xx < x+w; xx++) {
+ for (int yy=y; yy < y+h; yy++) {
+ gs2_hmsb_setpixel(fb, xx, yy, col);
+ }
+ }
+}
+
// Functions for GS4_HMSB format
STATIC void gs4_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) {
@@ -181,10 +208,31 @@ STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w,
}
}
+// Functions for GS8 format
+
+STATIC void gs8_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) {
+ uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride)];
+ *pixel = col & 0xff;
+}
+
+STATIC uint32_t gs8_getpixel(const mp_obj_framebuf_t *fb, int x, int y) {
+ return ((uint8_t*)fb->buf)[(x + y * fb->stride)];
+}
+
+STATIC void gs8_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
+ uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride)];
+ while (h--) {
+ memset(pixel, col, w);
+ pixel += fb->stride;
+ }
+}
+
STATIC mp_framebuf_p_t formats[] = {
[FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect},
[FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect},
+ [FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect},
[FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect},
+ [FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect},
[FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
[FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
};
@@ -240,9 +288,14 @@ STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
case FRAMEBUF_MHMSB:
o->stride = (o->stride + 7) & ~7;
break;
+ case FRAMEBUF_GS2_HMSB:
+ o->stride = (o->stride + 3) & ~3;
+ break;
case FRAMEBUF_GS4_HMSB:
o->stride = (o->stride + 1) & ~1;
break;
+ case FRAMEBUF_GS8:
+ break;
default:
mp_raise_ValueError("invalid format");
}
@@ -579,7 +632,9 @@ STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_MVLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
{ MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
{ MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(FRAMEBUF_RGB565) },
+ { MP_ROM_QSTR(MP_QSTR_GS2_HMSB), MP_ROM_INT(FRAMEBUF_GS2_HMSB) },
{ MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_ROM_INT(FRAMEBUF_GS4_HMSB) },
+ { MP_ROM_QSTR(MP_QSTR_GS8), MP_ROM_INT(FRAMEBUF_GS8) },
{ MP_ROM_QSTR(MP_QSTR_MONO_HLSB), MP_ROM_INT(FRAMEBUF_MHLSB) },
{ MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_ROM_INT(FRAMEBUF_MHMSB) },
};
diff --git a/MicroPython_BUILD/components/micropython/extmod/modlwip.c b/MicroPython_BUILD/components/micropython/extmod/modlwip.c
index c21c809..2a8496f 100644
--- a/MicroPython_BUILD/components/micropython/extmod/modlwip.c
+++ b/MicroPython_BUILD/components/micropython/extmod/modlwip.c
@@ -6,6 +6,7 @@
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Galen Hazelwood
* Copyright (c) 2015-2017 Paul Sokolovsky
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -498,6 +499,11 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
err_t err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY);
+ // If the output buffer is getting full then send the data to the lower layers
+ if (err == ERR_OK && tcp_sndbuf(socket->pcb.tcp) < TCP_SND_BUF / 4) {
+ err = tcp_output(socket->pcb.tcp);
+ }
+
if (err != ERR_OK) {
*_errno = error_lookup_table[-err];
return MP_STREAM_ERROR;
diff --git a/MicroPython_BUILD/components/micropython/extmod/moduhashlib.c b/MicroPython_BUILD/components/micropython/extmod/moduhashlib.c
index 3fad692..65e1ae4 100644
--- a/MicroPython_BUILD/components/micropython/extmod/moduhashlib.c
+++ b/MicroPython_BUILD/components/micropython/extmod/moduhashlib.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2014 Paul Sokolovsky
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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,7 +34,7 @@
#include "crypto-algorithms/sha256.h"
#if MICROPY_PY_UHASHLIB_SHA1
-#include "lib/axtls/crypto/crypto.h"
+#include "mbedtls/sha1.h"
#endif
typedef struct _mp_obj_hash_t {
@@ -59,9 +60,10 @@ STATIC mp_obj_t sha1_update(mp_obj_t self_in, mp_obj_t arg);
STATIC mp_obj_t sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
- mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(SHA1_CTX));
+ mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context));
o->base.type = type;
- SHA1_Init((SHA1_CTX*)o->state);
+ mbedtls_sha1_init((mbedtls_sha1_context*)o->state);
+ mbedtls_sha1_starts((mbedtls_sha1_context*)o->state);
if (n_args == 1) {
sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
}
@@ -83,7 +85,7 @@ STATIC mp_obj_t sha1_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- SHA1_Update((SHA1_CTX*)self->state, bufinfo.buf, bufinfo.len);
+ mbedtls_sha1_update((mbedtls_sha1_context*)self->state, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(sha1_update_obj, sha1_update);
@@ -102,8 +104,9 @@ MP_DEFINE_CONST_FUN_OBJ_1(hash_digest_obj, hash_digest);
STATIC mp_obj_t sha1_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
- vstr_init_len(&vstr, SHA1_SIZE);
- SHA1_Final((byte*)vstr.buf, (SHA1_CTX*)self->state);
+ vstr_init_len(&vstr, 20);
+ mbedtls_sha1_finish((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);
}
MP_DEFINE_CONST_FUN_OBJ_1(sha1_digest_obj, sha1_digest);
diff --git a/MicroPython_BUILD/components/micropython/extmod/modujson.c b/MicroPython_BUILD/components/micropython/extmod/modujson.c
index f14682d..f731d71 100644
--- a/MicroPython_BUILD/components/micropython/extmod/modujson.c
+++ b/MicroPython_BUILD/components/micropython/extmod/modujson.c
@@ -34,6 +34,16 @@
#if MICROPY_PY_UJSON
+STATIC mp_obj_t mod_ujson_dump(mp_obj_t obj, mp_obj_t stream) {
+ if (!MP_OBJ_IS_OBJ(stream)) {
+ mp_raise_TypeError(NULL);
+ }
+ mp_print_t print = {MP_OBJ_TO_PTR(stream), mp_stream_write_adaptor};
+ mp_obj_print_helper(&print, obj, PRINT_JSON);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ujson_dump_obj, mod_ujson_dump);
+
STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) {
vstr_t vstr;
mp_print_t print;
@@ -166,7 +176,7 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
goto fail;
}
S_NEXT(s);
- next = mp_obj_new_str(vstr.buf, vstr.len, false);
+ next = mp_obj_new_str(vstr.buf, vstr.len);
break;
case '-':
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': {
@@ -283,6 +293,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads);
STATIC const mp_rom_map_elem_t mp_module_ujson_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ujson) },
+ { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_ujson_dump_obj) },
{ MP_ROM_QSTR(MP_QSTR_dumps), MP_ROM_PTR(&mod_ujson_dumps_obj) },
{ MP_ROM_QSTR(MP_QSTR_load), MP_ROM_PTR(&mod_ujson_load_obj) },
{ MP_ROM_QSTR(MP_QSTR_loads), MP_ROM_PTR(&mod_ujson_loads_obj) },
diff --git a/MicroPython_BUILD/components/micropython/extmod/modure.c b/MicroPython_BUILD/components/micropython/extmod/modure.c
index 78de470..31c2b98 100644
--- a/MicroPython_BUILD/components/micropython/extmod/modure.c
+++ b/MicroPython_BUILD/components/micropython/extmod/modure.c
@@ -144,7 +144,7 @@ STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
}
mp_obj_t retval = mp_obj_new_list(0, NULL);
- const char **caps = alloca(caps_num * sizeof(char*));
+ const char **caps = mp_local_alloc(caps_num * sizeof(char*));
while (true) {
// cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
memset((char**)caps, 0, caps_num * sizeof(char*));
@@ -165,6 +165,8 @@ STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
break;
}
}
+ // cast is a workaround for a bug in msvc (see above)
+ mp_local_free((char**)caps);
mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte*)subj.begin, subj.end - subj.begin);
mp_obj_list_append(retval, s);
diff --git a/MicroPython_BUILD/components/micropython/extmod/moduselect.c b/MicroPython_BUILD/components/micropython/extmod/moduselect.c
index dfb5097..2e9225a 100644
--- a/MicroPython_BUILD/components/micropython/extmod/moduselect.c
+++ b/MicroPython_BUILD/components/micropython/extmod/moduselect.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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/MicroPython_BUILD/components/micropython/extmod/modussl_mbedtls.c b/MicroPython_BUILD/components/micropython/extmod/modussl_mbedtls.c
index 375c648..aab1d65 100644
--- a/MicroPython_BUILD/components/micropython/extmod/modussl_mbedtls.c
+++ b/MicroPython_BUILD/components/micropython/extmod/modussl_mbedtls.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016 Linaro Ltd.
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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/MicroPython_BUILD/components/micropython/extmod/modutimeq.c b/MicroPython_BUILD/components/micropython/extmod/modutimeq.c
index 0c07ae9..ba112ee 100644
--- a/MicroPython_BUILD/components/micropython/extmod/modutimeq.c
+++ b/MicroPython_BUILD/components/micropython/extmod/modutimeq.c
@@ -5,6 +5,7 @@
*
* Copyright (c) 2014 Damien P. George
* Copyright (c) 2016-2017 Paul Sokolovsky
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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,7 +38,7 @@
#define DEBUG 0
-// the algorithm here is modeled on CPython's heapq.py
+// the algorithm here is modelled on CPython's heapq.py
struct qentry {
mp_uint_t time;
diff --git a/MicroPython_BUILD/components/micropython/extmod/utime_mphal.c b/MicroPython_BUILD/components/micropython/extmod/utime_mphal.c
index db7906c..850e6b5 100644
--- a/MicroPython_BUILD/components/micropython/extmod/utime_mphal.c
+++ b/MicroPython_BUILD/components/micropython/extmod/utime_mphal.c
@@ -5,6 +5,7 @@
*
* Copyright (c) 2013-2016 Damien P. George
* Copyright (c) 2016 Paul Sokolovsky
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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/MicroPython_BUILD/components/micropython/extmod/utime_mphal.h b/MicroPython_BUILD/components/micropython/extmod/utime_mphal.h
index bc517e9..acb1b78 100644
--- a/MicroPython_BUILD/components/micropython/extmod/utime_mphal.h
+++ b/MicroPython_BUILD/components/micropython/extmod/utime_mphal.h
@@ -5,6 +5,7 @@
*
* Copyright (c) 2013-2016 Damien P. George
* Copyright (c) 2016 Paul Sokolovsky
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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/MicroPython_BUILD/components/micropython/extmod/vfs.c b/MicroPython_BUILD/components/micropython/extmod/vfs.c
index 64fef2e..d2c6c74 100644
--- a/MicroPython_BUILD/components/micropython/extmod/vfs.c
+++ b/MicroPython_BUILD/components/micropython/extmod/vfs.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2017 Damien P. George
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -257,7 +258,7 @@ mp_obj_t mp_vfs_chdir(mp_obj_t path_in) {
// subsequent relative paths begin at the root of that VFS.
for (vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
if (vfs->len == 1) {
- mp_obj_t root = mp_obj_new_str("/", 1, false);
+ mp_obj_t root = mp_obj_new_str("/", 1);
mp_vfs_proxy_call(vfs, MP_QSTR_chdir, 1, &root);
break;
}
@@ -314,7 +315,7 @@ STATIC mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in) {
self->cur.vfs = vfs->next;
if (vfs->len == 1) {
// vfs is mounted at root dir, delegate to it
- mp_obj_t root = mp_obj_new_str("/", 1, false);
+ mp_obj_t root = mp_obj_new_str("/", 1);
self->is_iter = true;
self->cur.iter = mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &root);
return mp_iternext(self->cur.iter);
@@ -362,9 +363,7 @@ mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) {
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
mp_obj_t next;
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
- mp_obj_t *items;
- mp_obj_get_array_fixed_n(next, 3, &items);
- mp_obj_list_append(dir_list, items[0]);
+ mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL));
}
return dir_list;
}
diff --git a/MicroPython_BUILD/components/micropython/extmod/vfs_native.c b/MicroPython_BUILD/components/micropython/extmod/vfs_native.c
index 5583856..f14a73d 100644
--- a/MicroPython_BUILD/components/micropython/extmod/vfs_native.c
+++ b/MicroPython_BUILD/components/micropython/extmod/vfs_native.c
@@ -490,7 +490,7 @@ STATIC mp_obj_t native_vfs_getcwd(mp_obj_t vfs_in) {
return mp_const_none;
}
- return mp_obj_new_str(buf, strlen(buf), false);
+ return mp_obj_new_str(buf, strlen(buf));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(native_vfs_getcwd_obj, native_vfs_getcwd);
@@ -509,7 +509,7 @@ STATIC mp_obj_t native_vfs_getdrive() {
else sprintf(drive, "/");
}
- return mp_obj_new_str(drive, strlen(drive), false);
+ return mp_obj_new_str(drive, strlen(drive));
}
MP_DEFINE_CONST_FUN_OBJ_0(native_vfs_getdrive_obj, native_vfs_getdrive);
@@ -749,7 +749,7 @@ static void _sdcard_mount()
else {
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
- if (sdcard_config.mode == 1) {
+ if (sdcard_config.mode == 2) {
// Use 1-line SD mode
gpio_set_pull_mode(2, GPIO_PULLUP_ONLY);
gpio_set_pull_mode(14, GPIO_PULLUP_ONLY);
@@ -890,9 +890,6 @@ STATIC mp_obj_t native_vfs_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t m
}
#elif CONFIG_MICROPY_FILESYSTEM_TYPE == 2
printf("(LittleFS ver %d.%d): ", LFS_VERSION_MAJOR, LFS_VERSION_MINOR);
- #ifdef CONFIG_LITTLEFLASH_USE_WEAR_LEVELING
- printf("[on top of ESP32 wear leveling]");
- #endif
uint32_t used = littleFlash_getUsedBlocks();
f_bsize = littleFlash.lfs_cfg.block_size;
f_blocks = littleFlash.lfs_cfg.block_count;
@@ -911,7 +908,7 @@ STATIC mp_obj_t native_vfs_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t m
ret = ESP_OK;
}
#endif
- printf("\nMounted on partition '%s' [size: %d; Flash address: 0x%6X]\n", fs_partition->label, fs_partition->size, fs_partition->address);
+ printf("Mounted on partition '%s' [size: %d; Flash address: 0x%6X]\n", fs_partition->label, fs_partition->size, fs_partition->address);
if (ret == ESP_OK) {
printf("----------------\n");
printf("Filesystem size: %d B\n", f_blocks * f_bsize);
@@ -1007,7 +1004,7 @@ int mount_vfs(int type, char *chdir_to)
// mount flash file system
args2[0] = vfso;
- args2[1] = mp_obj_new_str(mp, strlen(mp), false);
+ args2[1] = mp_obj_new_str(mp, strlen(mp));
mp_call_function_n_kw(MP_OBJ_FROM_PTR(&mp_vfs_mount_obj), 2, 0, args2);
if (native_vfs_mounted[type]) {
diff --git a/MicroPython_BUILD/components/micropython/extmod/vfs_native_file.c b/MicroPython_BUILD/components/micropython/extmod/vfs_native_file.c
index cd80a29..d9a76c3 100644
--- a/MicroPython_BUILD/components/micropython/extmod/vfs_native_file.c
+++ b/MicroPython_BUILD/components/micropython/extmod/vfs_native_file.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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/MicroPython_BUILD/components/micropython/extmod/vfs_native_misc.c b/MicroPython_BUILD/components/micropython/extmod/vfs_native_misc.c
index f2f9a31..2de7299 100644
--- a/MicroPython_BUILD/components/micropython/extmod/vfs_native_misc.c
+++ b/MicroPython_BUILD/components/micropython/extmod/vfs_native_misc.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -79,7 +80,7 @@ STATIC mp_obj_t mp_vfs_native_ilistdir_it_iternext(mp_obj_t self_in) {
// make 3-tuple with info about this entry
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
if (self->is_str) {
- t->items[0] = mp_obj_new_str(fn, strlen(fn), false);
+ t->items[0] = mp_obj_new_str(fn, strlen(fn));
} else {
t->items[0] = mp_obj_new_bytes((const byte*)fn, strlen(fn));
}
diff --git a/MicroPython_BUILD/components/micropython/extmod/vfs_reader.c b/MicroPython_BUILD/components/micropython/extmod/vfs_reader.c
index 891098a..e1ee45a 100644
--- a/MicroPython_BUILD/components/micropython/extmod/vfs_reader.c
+++ b/MicroPython_BUILD/components/micropython/extmod/vfs_reader.c
@@ -71,7 +71,7 @@ STATIC void mp_reader_vfs_close(void *data) {
void mp_reader_new_file(mp_reader_t *reader, const char *filename) {
mp_reader_vfs_t *rf = m_new_obj(mp_reader_vfs_t);
- mp_obj_t arg = mp_obj_new_str(filename, strlen(filename), false);
+ mp_obj_t arg = mp_obj_new_str(filename, strlen(filename));
rf->file = mp_vfs_open(1, &arg, (mp_map_t*)&mp_const_empty_map);
int errcode;
rf->len = mp_stream_rw(rf->file, rf->buf, sizeof(rf->buf), &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE);
diff --git a/MicroPython_BUILD/components/micropython/lib/berkeley-db-1.xx/btree/btree.h b/MicroPython_BUILD/components/micropython/lib/berkeley-db-1.xx/btree/btree.h
index 3266420..aa80c09 100644
--- a/MicroPython_BUILD/components/micropython/lib/berkeley-db-1.xx/btree/btree.h
+++ b/MicroPython_BUILD/components/micropython/lib/berkeley-db-1.xx/btree/btree.h
@@ -44,9 +44,13 @@
#include "lib/berkeley-db-1.xx/include/mpool.h"
#define DEFMINKEYPAGE (2) /* Minimum keys per page */
+#ifndef MINCACHE
#define MINCACHE (5) /* Minimum cached pages */
+#endif
#define MINPSIZE (512) /* Minimum page size */
+#ifndef DEFPSIZE
#define DEFPSIZE (4096) /* Default page size */
+#endif
/*
* Page 0 of a btree file contains a copy of the meta-data. This page is also
diff --git a/MicroPython_BUILD/components/micropython/lib/mp-readline/readline.c b/MicroPython_BUILD/components/micropython/lib/mp-readline/readline.c
index 074f553..93c38e6 100644
--- a/MicroPython_BUILD/components/micropython/lib/mp-readline/readline.c
+++ b/MicroPython_BUILD/components/micropython/lib/mp-readline/readline.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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/MicroPython_BUILD/components/micropython/lib/netutils/netutils.c b/MicroPython_BUILD/components/micropython/lib/netutils/netutils.c
index 06c3ff9..073f46b 100644
--- a/MicroPython_BUILD/components/micropython/lib/netutils/netutils.c
+++ b/MicroPython_BUILD/components/micropython/lib/netutils/netutils.c
@@ -41,7 +41,7 @@ mp_obj_t netutils_format_ipv4_addr(uint8_t *ip, netutils_endian_t endian) {
} else {
ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
}
- return mp_obj_new_str(ip_str, ip_len, false);
+ return mp_obj_new_str(ip_str, ip_len);
}
// Takes an array with a raw IP address, and a port, and returns a net-address
diff --git a/MicroPython_BUILD/components/micropython/lib/utils/pyexec.c b/MicroPython_BUILD/components/micropython/lib/utils/pyexec.c
index 07377c2..c8f7b68 100644
--- a/MicroPython_BUILD/components/micropython/lib/utils/pyexec.c
+++ b/MicroPython_BUILD/components/micropython/lib/utils/pyexec.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -35,7 +36,7 @@
#include "py/gc.h"
#include "py/frozenmod.h"
#include "py/mphal.h"
-#if defined(USE_DEVICE_MODE)
+#if MICROPY_HW_ENABLE_USB
#include "irq.h"
#include "usb.h"
#endif
@@ -346,6 +347,11 @@ raw_repl_reset:
vstr_reset(&line);
} else if (c == CHAR_CTRL_D) {
// input finished
+ if (line.len == 0) {
+ mp_hal_stdout_tx_str("soft reboot\r\n");
+ vTaskDelay(1000);
+ goto raw_repl_reset;
+ }
break;
} else {
// let through any other raw 8-bit value
@@ -408,7 +414,7 @@ friendly_repl_reset:
for (;;) {
input_restart:
- #if defined(USE_DEVICE_MODE)
+ #if MICROPY_HW_ENABLE_USB
if (usb_vcp_is_enabled()) {
// If the user gets to here and interrupts are disabled then
// they'll never see the prompt, traceback etc. The USB REPL needs
@@ -465,7 +471,7 @@ friendly_repl_reset:
if (c == '\r') {
mp_hal_stdout_tx_str("\r\n=== ");
} else {
- mp_hal_stdout_tx_strn(&c, 1);
+ mp_hal_stdout_tx_strn((const char *)&c, 1);
}
}
}
diff --git a/MicroPython_BUILD/components/micropython/lib/utils/pyexec.h b/MicroPython_BUILD/components/micropython/lib/utils/pyexec.h
index bc98ba9..678c56c 100644
--- a/MicroPython_BUILD/components/micropython/lib/utils/pyexec.h
+++ b/MicroPython_BUILD/components/micropython/lib/utils/pyexec.h
@@ -26,6 +26,8 @@
#ifndef MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H
#define MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H
+#include "py/obj.h"
+
typedef enum {
PYEXEC_MODE_RAW_REPL,
PYEXEC_MODE_FRIENDLY_REPL,
diff --git a/MicroPython_BUILD/components/micropython/lib/utils/sys_stdio_mphal.c b/MicroPython_BUILD/components/micropython/lib/utils/sys_stdio_mphal.c
index 2eb73f6..a9f57f3 100644
--- a/MicroPython_BUILD/components/micropython/lib/utils/sys_stdio_mphal.c
+++ b/MicroPython_BUILD/components/micropython/lib/utils/sys_stdio_mphal.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2013-2017 Damien P. George
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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/MicroPython_BUILD/components/micropython/py/asmarm.c b/MicroPython_BUILD/components/micropython/py/asmarm.c
index 552fdfb..1a8923b 100644
--- a/MicroPython_BUILD/components/micropython/py/asmarm.c
+++ b/MicroPython_BUILD/components/micropython/py/asmarm.c
@@ -150,10 +150,7 @@ void asm_arm_bkpt(asm_arm_t *as) {
// | low address | high address in RAM
void asm_arm_entry(asm_arm_t *as, int num_locals) {
-
- if (num_locals < 0) {
- num_locals = 0;
- }
+ assert(num_locals >= 0);
as->stack_adjust = 0;
as->push_reglist = 1 << ASM_ARM_REG_R1
diff --git a/MicroPython_BUILD/components/micropython/py/asmarm.h b/MicroPython_BUILD/components/micropython/py/asmarm.h
index a302b15..871e358 100644
--- a/MicroPython_BUILD/components/micropython/py/asmarm.h
+++ b/MicroPython_BUILD/components/micropython/py/asmarm.h
@@ -167,17 +167,12 @@ void asm_arm_bl_ind(asm_arm_t *as, void *fun_ptr, uint fun_id, uint reg_temp);
} while (0)
#define ASM_CALL_IND(as, ptr, idx) asm_arm_bl_ind(as, ptr, idx, ASM_ARM_REG_R3)
-#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_arm_mov_local_reg(as, (local_num), (reg))
-#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_arm_mov_reg_i32(as, (reg), (imm))
-#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_arm_mov_reg_i32(as, (reg), (imm))
-#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
- do { \
- asm_arm_mov_reg_i32(as, (reg_temp), (imm)); \
- asm_arm_mov_local_reg(as, (local_num), (reg_temp)); \
- } while (false)
-#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_arm_mov_reg_local(as, (reg), (local_num))
+#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_arm_mov_local_reg((as), (local_num), (reg_src))
+#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_arm_mov_reg_i32((as), (reg_dest), (imm))
+#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_arm_mov_reg_i32((as), (reg_dest), (imm))
+#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_arm_mov_reg_local((as), (reg_dest), (local_num))
#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_arm_mov_reg_reg((as), (reg_dest), (reg_src))
-#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_arm_mov_reg_local_addr(as, (reg), (local_num))
+#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_arm_mov_reg_local_addr((as), (reg_dest), (local_num))
#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_arm_lsl_reg_reg((as), (reg_dest), (reg_shift))
#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_arm_asr_reg_reg((as), (reg_dest), (reg_shift))
diff --git a/MicroPython_BUILD/components/micropython/py/asmbase.c b/MicroPython_BUILD/components/micropython/py/asmbase.c
index c941e91..4c84c3b 100644
--- a/MicroPython_BUILD/components/micropython/py/asmbase.c
+++ b/MicroPython_BUILD/components/micropython/py/asmbase.c
@@ -46,10 +46,10 @@ void mp_asm_base_deinit(mp_asm_base_t *as, bool free_code) {
}
void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) {
- if (pass == MP_ASM_PASS_COMPUTE) {
- // reset all labels
+ if (pass < MP_ASM_PASS_EMIT) {
+ // Reset labels so we can detect backwards jumps (and verify unique assignment)
memset(as->label_offsets, -1, as->max_num_labels * sizeof(size_t));
- } else if (pass == MP_ASM_PASS_EMIT) {
+ } else {
// allocating executable RAM is platform specific
MP_PLAT_ALLOC_EXEC(as->code_offset, (void**)&as->code_base, &as->code_size);
assert(as->code_base != NULL);
diff --git a/MicroPython_BUILD/components/micropython/py/asmthumb.c b/MicroPython_BUILD/components/micropython/py/asmthumb.c
index 5316a7e..c5b45f2 100644
--- a/MicroPython_BUILD/components/micropython/py/asmthumb.c
+++ b/MicroPython_BUILD/components/micropython/py/asmthumb.c
@@ -104,6 +104,8 @@ STATIC void asm_thumb_write_word32(asm_thumb_t *as, int w32) {
// | low address | high address in RAM
void asm_thumb_entry(asm_thumb_t *as, int num_locals) {
+ assert(num_locals >= 0);
+
// work out what to push and how many extra spaces to reserve on stack
// so that we have enough for all locals and it's aligned an 8-byte boundary
// we push extra regs (r1, r2, r3) to help do the stack adjustment
@@ -111,9 +113,6 @@ void asm_thumb_entry(asm_thumb_t *as, int num_locals) {
// for push rlist, lowest numbered register at the lowest address
uint reglist;
uint stack_adjust;
- if (num_locals < 0) {
- num_locals = 0;
- }
// don't pop r0 because it's used for return value
switch (num_locals) {
case 0:
diff --git a/MicroPython_BUILD/components/micropython/py/asmthumb.h b/MicroPython_BUILD/components/micropython/py/asmthumb.h
index 7070e03..552ad75 100644
--- a/MicroPython_BUILD/components/micropython/py/asmthumb.h
+++ b/MicroPython_BUILD/components/micropython/py/asmthumb.h
@@ -283,17 +283,12 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp
} while (0)
#define ASM_CALL_IND(as, ptr, idx) asm_thumb_bl_ind(as, ptr, idx, ASM_THUMB_REG_R3)
-#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_thumb_mov_local_reg(as, (local_num), (reg))
-#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_thumb_mov_reg_i32_optimised(as, (reg), (imm))
-#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_thumb_mov_reg_i32_aligned(as, (reg), (imm))
-#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
- do { \
- asm_thumb_mov_reg_i32_optimised(as, (reg_temp), (imm)); \
- asm_thumb_mov_local_reg(as, (local_num), (reg_temp)); \
- } while (false)
-#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_thumb_mov_reg_local(as, (reg), (local_num))
+#define ASM_MOV_LOCAL_REG(as, local_num, reg) asm_thumb_mov_local_reg((as), (local_num), (reg))
+#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_thumb_mov_reg_i32_optimised((as), (reg_dest), (imm))
+#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_thumb_mov_reg_i32_aligned((as), (reg_dest), (imm))
+#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_thumb_mov_reg_local((as), (reg_dest), (local_num))
#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_thumb_mov_reg_reg((as), (reg_dest), (reg_src))
-#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_thumb_mov_reg_local_addr(as, (reg), (local_num))
+#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_thumb_mov_reg_local_addr((as), (reg_dest), (local_num))
#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_LSL, (reg_dest), (reg_shift))
#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_ASR, (reg_dest), (reg_shift))
diff --git a/MicroPython_BUILD/components/micropython/py/asmx64.c b/MicroPython_BUILD/components/micropython/py/asmx64.c
index aa2a8ec..c900a08 100644
--- a/MicroPython_BUILD/components/micropython/py/asmx64.c
+++ b/MicroPython_BUILD/components/micropython/py/asmx64.c
@@ -526,11 +526,9 @@ void asm_x64_jcc_label(asm_x64_t *as, int jcc_type, mp_uint_t label) {
}
void asm_x64_entry(asm_x64_t *as, int num_locals) {
+ assert(num_locals >= 0);
asm_x64_push_r64(as, ASM_X64_REG_RBP);
asm_x64_mov_r64_r64(as, ASM_X64_REG_RBP, ASM_X64_REG_RSP);
- if (num_locals < 0) {
- num_locals = 0;
- }
num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE);
asm_x64_push_r64(as, ASM_X64_REG_RBX);
diff --git a/MicroPython_BUILD/components/micropython/py/asmx64.h b/MicroPython_BUILD/components/micropython/py/asmx64.h
index 425bdf2..2fbbfa9 100644
--- a/MicroPython_BUILD/components/micropython/py/asmx64.h
+++ b/MicroPython_BUILD/components/micropython/py/asmx64.h
@@ -162,17 +162,12 @@ void asm_x64_call_ind(asm_x64_t* as, void* ptr, int temp_r32);
} while (0)
#define ASM_CALL_IND(as, ptr, idx) asm_x64_call_ind(as, ptr, ASM_X64_REG_RAX)
-#define ASM_MOV_REG_TO_LOCAL asm_x64_mov_r64_to_local
-#define ASM_MOV_IMM_TO_REG asm_x64_mov_i64_to_r64_optimised
-#define ASM_MOV_ALIGNED_IMM_TO_REG asm_x64_mov_i64_to_r64_aligned
-#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
- do { \
- asm_x64_mov_i64_to_r64_optimised(as, (imm), (reg_temp)); \
- asm_x64_mov_r64_to_local(as, (reg_temp), (local_num)); \
- } while (false)
-#define ASM_MOV_LOCAL_TO_REG asm_x64_mov_local_to_r64
+#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_x64_mov_r64_to_local((as), (reg_src), (local_num))
+#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_x64_mov_i64_to_r64_optimised((as), (imm), (reg_dest))
+#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_x64_mov_i64_to_r64_aligned((as), (imm), (reg_dest))
+#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_x64_mov_local_to_r64((as), (local_num), (reg_dest))
#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x64_mov_r64_r64((as), (reg_dest), (reg_src))
-#define ASM_MOV_LOCAL_ADDR_TO_REG asm_x64_mov_local_addr_to_r64
+#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x64_mov_local_addr_to_r64((as), (local_num), (reg_dest))
#define ASM_LSL_REG(as, reg) asm_x64_shl_r64_cl((as), (reg))
#define ASM_ASR_REG(as, reg) asm_x64_sar_r64_cl((as), (reg))
diff --git a/MicroPython_BUILD/components/micropython/py/asmx86.c b/MicroPython_BUILD/components/micropython/py/asmx86.c
index 6a78fbd..3938baa 100644
--- a/MicroPython_BUILD/components/micropython/py/asmx86.c
+++ b/MicroPython_BUILD/components/micropython/py/asmx86.c
@@ -387,7 +387,8 @@ void asm_x86_jcc_label(asm_x86_t *as, mp_uint_t jcc_type, mp_uint_t label) {
}
}
-void asm_x86_entry(asm_x86_t *as, mp_uint_t num_locals) {
+void asm_x86_entry(asm_x86_t *as, int num_locals) {
+ assert(num_locals >= 0);
asm_x86_push_r32(as, ASM_X86_REG_EBP);
asm_x86_mov_r32_r32(as, ASM_X86_REG_EBP, ASM_X86_REG_ESP);
if (num_locals > 0) {
diff --git a/MicroPython_BUILD/components/micropython/py/asmx86.h b/MicroPython_BUILD/components/micropython/py/asmx86.h
index 0a00e2e..0955985 100644
--- a/MicroPython_BUILD/components/micropython/py/asmx86.h
+++ b/MicroPython_BUILD/components/micropython/py/asmx86.h
@@ -104,7 +104,7 @@ void asm_x86_test_r8_with_r8(asm_x86_t* as, int src_r32_a, int src_r32_b);
void asm_x86_setcc_r8(asm_x86_t* as, mp_uint_t jcc_type, int dest_r8);
void asm_x86_jmp_label(asm_x86_t* as, mp_uint_t label);
void asm_x86_jcc_label(asm_x86_t* as, mp_uint_t jcc_type, mp_uint_t label);
-void asm_x86_entry(asm_x86_t* as, mp_uint_t num_locals);
+void asm_x86_entry(asm_x86_t* as, int num_locals);
void asm_x86_exit(asm_x86_t* as);
void asm_x86_mov_arg_to_r32(asm_x86_t *as, int src_arg_num, int dest_r32);
void asm_x86_mov_local_to_r32(asm_x86_t* as, int src_local_num, int dest_r32);
@@ -160,17 +160,12 @@ void asm_x86_call_ind(asm_x86_t* as, void* ptr, mp_uint_t n_args, int temp_r32);
} while (0)
#define ASM_CALL_IND(as, ptr, idx) asm_x86_call_ind(as, ptr, mp_f_n_args[idx], ASM_X86_REG_EAX)
-#define ASM_MOV_REG_TO_LOCAL asm_x86_mov_r32_to_local
-#define ASM_MOV_IMM_TO_REG asm_x86_mov_i32_to_r32
-#define ASM_MOV_ALIGNED_IMM_TO_REG asm_x86_mov_i32_to_r32_aligned
-#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
- do { \
- asm_x86_mov_i32_to_r32(as, (imm), (reg_temp)); \
- asm_x86_mov_r32_to_local(as, (reg_temp), (local_num)); \
- } while (false)
-#define ASM_MOV_LOCAL_TO_REG asm_x86_mov_local_to_r32
+#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_x86_mov_r32_to_local((as), (reg_src), (local_num))
+#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_x86_mov_i32_to_r32((as), (imm), (reg_dest))
+#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_x86_mov_i32_to_r32_aligned((as), (imm), (reg_dest))
+#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_x86_mov_local_to_r32((as), (local_num), (reg_dest))
#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x86_mov_r32_r32((as), (reg_dest), (reg_src))
-#define ASM_MOV_LOCAL_ADDR_TO_REG asm_x86_mov_local_addr_to_r32
+#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x86_mov_local_addr_to_r32((as), (local_num), (reg_dest))
#define ASM_LSL_REG(as, reg) asm_x86_shl_r32_cl((as), (reg))
#define ASM_ASR_REG(as, reg) asm_x86_sar_r32_cl((as), (reg))
diff --git a/MicroPython_BUILD/components/micropython/py/asmxtensa.h b/MicroPython_BUILD/components/micropython/py/asmxtensa.h
index 7db6c0d..e6d4158 100644
--- a/MicroPython_BUILD/components/micropython/py/asmxtensa.h
+++ b/MicroPython_BUILD/components/micropython/py/asmxtensa.h
@@ -280,17 +280,12 @@ void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_nu
asm_xtensa_op_callx0(as, ASM_XTENSA_REG_A0); \
} while (0)
-#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_xtensa_mov_local_reg(as, (local_num), (reg))
-#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_xtensa_mov_reg_i32(as, (reg), (imm))
-#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_xtensa_mov_reg_i32(as, (reg), (imm))
-#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
- do { \
- asm_xtensa_mov_reg_i32(as, (reg_temp), (imm)); \
- asm_xtensa_mov_local_reg(as, (local_num), (reg_temp)); \
- } while (0)
-#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_xtensa_mov_reg_local(as, (reg), (local_num))
+#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_xtensa_mov_local_reg((as), (local_num), (reg_src))
+#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_xtensa_mov_reg_i32((as), (reg_dest), (imm))
+#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_xtensa_mov_reg_i32((as), (reg_dest), (imm))
+#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_xtensa_mov_reg_local((as), (reg_dest), (local_num))
#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mov_n((as), (reg_dest), (reg_src))
-#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_xtensa_mov_reg_local_addr(as, (reg), (local_num))
+#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_xtensa_mov_reg_local_addr((as), (reg_dest), (local_num))
#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) \
do { \
diff --git a/MicroPython_BUILD/components/micropython/py/binary.c b/MicroPython_BUILD/components/micropython/py/binary.c
index 870a094..f509ff0 100644
--- a/MicroPython_BUILD/components/micropython/py/binary.c
+++ b/MicroPython_BUILD/components/micropython/py/binary.c
@@ -206,7 +206,7 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
return (mp_obj_t)(mp_uint_t)val;
} else if (val_type == 'S') {
const char *s_val = (const char*)(uintptr_t)(mp_uint_t)val;
- return mp_obj_new_str(s_val, strlen(s_val), false);
+ return mp_obj_new_str(s_val, strlen(s_val));
#if MICROPY_PY_BUILTINS_FLOAT
} else if (val_type == 'f') {
union { uint32_t i; float f; } fpu = {val};
diff --git a/MicroPython_BUILD/components/micropython/py/builtinhelp.c b/MicroPython_BUILD/components/micropython/py/builtinhelp.c
index ea7a6cd..22fde16 100644
--- a/MicroPython_BUILD/components/micropython/py/builtinhelp.c
+++ b/MicroPython_BUILD/components/micropython/py/builtinhelp.c
@@ -70,7 +70,7 @@ STATIC void mp_help_add_from_names(mp_obj_t list, const char *name) {
while (*name) {
size_t l = strlen(name);
// name should end in '.py' and we strip it off
- mp_obj_list_append(list, mp_obj_new_str(name, l - 3, false));
+ mp_obj_list_append(list, mp_obj_new_str(name, l - 3));
name += l + 1;
}
}
diff --git a/MicroPython_BUILD/components/micropython/py/builtinimport.c b/MicroPython_BUILD/components/micropython/py/builtinimport.c
index 095ce36..b8ed096 100644
--- a/MicroPython_BUILD/components/micropython/py/builtinimport.c
+++ b/MicroPython_BUILD/components/micropython/py/builtinimport.c
@@ -44,6 +44,8 @@
#define DEBUG_printf(...) (void)0
#endif
+#if MICROPY_ENABLE_EXTERNAL_IMPORT
+
#define PATH_SEP_CHAR '/'
bool mp_obj_is_package(mp_obj_t module) {
@@ -318,7 +320,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
}
uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len);
- char *new_mod = alloca(new_mod_l);
+ char *new_mod = mp_local_alloc(new_mod_l);
memcpy(new_mod, this_name, p - this_name);
if (mod_len != 0) {
new_mod[p - this_name] = '.';
@@ -326,9 +328,10 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
}
qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l);
+ mp_local_free(new_mod);
DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q));
module_name = MP_OBJ_NEW_QSTR(new_mod_q);
- mod_str = new_mod;
+ mod_str = qstr_str(new_mod_q);
mod_len = new_mod_l;
}
@@ -388,19 +391,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
}
// found weak linked module
module_obj = el->value;
- if (MICROPY_MODULE_BUILTIN_INIT) {
- // look for __init__ and call it if it exists
- // Note: this code doesn't work fully correctly because it allows the
- // __init__ function to be called twice if the module is imported by its
- // non-weak-link name. Also, this code is duplicated in objmodule.c.
- mp_obj_t dest[2];
- mp_load_method_maybe(el->value, MP_QSTR___init__, dest);
- if (dest[0] != MP_OBJ_NULL) {
- mp_call_method_n_kw(0, 0, dest);
- // register module so __init__ is not called again
- mp_module_register(mod_name, el->value);
- }
- }
+ mp_module_call_init(mod_name, module_obj);
} else {
no_exist:
#else
@@ -447,7 +438,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
DEBUG_printf("%.*s is dir\n", vstr_len(&path), vstr_str(&path));
// https://docs.python.org/3/reference/import.html
// "Specifically, any module that contains a __path__ attribute is considered a package."
- mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path), false));
+ mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path)));
size_t orig_path_len = path.len;
vstr_add_char(&path, PATH_SEP_CHAR);
vstr_add_str(&path, "__init__.py");
@@ -484,4 +475,41 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
// Otherwise, we need to return top-level package
return top_module_obj;
}
+
+#else // MICROPY_ENABLE_EXTERNAL_IMPORT
+
+mp_obj_t mp_builtin___import__(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("relative import");
+ }
+
+ // Check if module already exists, and return it if it does
+ qstr module_name_qstr = mp_obj_str_get_qstr(args[0]);
+ mp_obj_t module_obj = mp_module_get(module_name_qstr);
+ if (module_obj != MP_OBJ_NULL) {
+ return module_obj;
+ }
+
+ #if MICROPY_MODULE_WEAK_LINKS
+ // Check if there is a weak link to this module
+ mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_map, MP_OBJ_NEW_QSTR(module_name_qstr), MP_MAP_LOOKUP);
+ if (el != NULL) {
+ // Found weak-linked module
+ mp_module_call_init(module_name_qstr, el->value);
+ return el->value;
+ }
+ #endif
+
+ // Couldn't find the module, so fail
+ if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+ mp_raise_msg(&mp_type_ImportError, "module not found");
+ } else {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
+ "no module named '%q'", module_name_qstr));
+ }
+}
+
+#endif // MICROPY_ENABLE_EXTERNAL_IMPORT
+
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj, 1, 5, mp_builtin___import__);
diff --git a/MicroPython_BUILD/components/micropython/py/compile.c b/MicroPython_BUILD/components/micropython/py/compile.c
index 4e704ab..9200b34 100644
--- a/MicroPython_BUILD/components/micropython/py/compile.c
+++ b/MicroPython_BUILD/components/micropython/py/compile.c
@@ -376,6 +376,7 @@ STATIC void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, as
EMIT(store_subscr);
}
}
+ return;
} else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
if (assign_kind == ASSIGN_AUG_LOAD) {
@@ -387,16 +388,10 @@ STATIC void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, as
}
EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
}
- } else {
- goto cannot_assign;
+ return;
}
- } else {
- goto cannot_assign;
}
- return;
-
-cannot_assign:
compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
}
@@ -1050,8 +1045,8 @@ STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {
for (int i = 0; i < n; i++) {
len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
}
- byte *q_ptr;
- byte *str_dest = qstr_build_start(len, &q_ptr);
+ char *q_ptr = mp_local_alloc(len);
+ char *str_dest = q_ptr;
for (int i = 0; i < n; i++) {
if (i > 0) {
*str_dest++ = '.';
@@ -1061,7 +1056,8 @@ STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {
memcpy(str_dest, str_src, str_src_len);
str_dest += str_src_len;
}
- qstr q_full = qstr_build_end(q_ptr);
+ qstr q_full = qstr_from_strn(q_ptr, len);
+ mp_local_free(q_ptr);
EMIT_ARG(import_name, q_full);
if (is_as) {
for (int i = 1; i < n; i++) {
@@ -1940,51 +1936,52 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
}
} else {
plain_assign:
- if (MICROPY_COMP_DOUBLE_TUPLE_ASSIGN
- && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)
- && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
- && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 2
- && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
- // optimisation for a, b = c, d
- mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1];
+ #if MICROPY_COMP_DOUBLE_TUPLE_ASSIGN
+ if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)
+ && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)) {
mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
- if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
- || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)) {
- // can't optimise when it's a star expression on the lhs
- goto no_optimisation;
+ pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
+ uint32_t n_pns0 = MP_PARSE_NODE_STRUCT_NUM_NODES(pns0);
+ // Can only optimise a tuple-to-tuple assignment when all of the following hold:
+ // - equal number of items in LHS and RHS tuples
+ // - 2 or 3 items in the tuples
+ // - there are no star expressions in the LHS tuple
+ if (n_pns0 == MP_PARSE_NODE_STRUCT_NUM_NODES(pns1)
+ && (n_pns0 == 2
+ #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
+ || n_pns0 == 3
+ #endif
+ )
+ && !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
+ && !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)
+ #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
+ && (n_pns0 == 2 || !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr))
+ #endif
+ ) {
+ // Optimisation for a, b = c, d or a, b, c = d, e, f
+ compile_node(comp, pns1->nodes[0]); // rhs
+ compile_node(comp, pns1->nodes[1]); // rhs
+ #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
+ if (n_pns0 == 3) {
+ compile_node(comp, pns1->nodes[2]); // rhs
+ EMIT(rot_three);
+ }
+ #endif
+ EMIT(rot_two);
+ c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
+ c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
+ #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
+ if (n_pns0 == 3) {
+ c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
+ }
+ #endif
+ return;
}
- compile_node(comp, pns10->nodes[0]); // rhs
- compile_node(comp, pns10->nodes[1]); // rhs
- EMIT(rot_two);
- c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
- c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
- } else if (MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
- && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)
- && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
- && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 3
- && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
- // optimisation for a, b, c = d, e, f
- mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1];
- mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
- if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
- || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)
- || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) {
- // can't optimise when it's a star expression on the lhs
- goto no_optimisation;
- }
- compile_node(comp, pns10->nodes[0]); // rhs
- compile_node(comp, pns10->nodes[1]); // rhs
- compile_node(comp, pns10->nodes[2]); // rhs
- EMIT(rot_three);
- EMIT(rot_two);
- c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
- c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
- c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
- } else {
- no_optimisation:
- compile_node(comp, pns->nodes[1]); // rhs
- c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
}
+ #endif
+
+ compile_node(comp, pns->nodes[1]); // rhs
+ c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
}
} else {
goto plain_assign;
diff --git a/MicroPython_BUILD/components/micropython/py/emitbc.c b/MicroPython_BUILD/components/micropython/py/emitbc.c
index 3f4dfc1..32e8330 100644
--- a/MicroPython_BUILD/components/micropython/py/emitbc.c
+++ b/MicroPython_BUILD/components/micropython/py/emitbc.c
@@ -313,9 +313,12 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
emit->scope = scope;
emit->last_source_line_offset = 0;
emit->last_source_line = 1;
+ #ifndef NDEBUG
+ // With debugging enabled labels are checked for unique assignment
if (pass < MP_PASS_EMIT) {
memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(mp_uint_t));
}
+ #endif
emit->bytecode_offset = 0;
emit->code_info_offset = 0;
@@ -434,7 +437,9 @@ void mp_emit_bc_end_pass(emit_t *emit) {
} else if (emit->pass == MP_PASS_EMIT) {
mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base,
+ #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
emit->code_info_size + emit->bytecode_size,
+ #endif
emit->const_table,
#if MICROPY_PERSISTENT_CODE_SAVE
emit->ct_cur_obj, emit->ct_cur_raw_code,
@@ -495,7 +500,6 @@ void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) {
emit->label_offsets[l] = emit->bytecode_offset;
} else {
// ensure label offset has not changed from MP_PASS_CODE_SIZE to MP_PASS_EMIT
- //printf("l%d: (at %d vs %d)\n", l, emit->bytecode_offset, emit->label_offsets[l]);
assert(emit->label_offsets[l] == emit->bytecode_offset);
}
}
diff --git a/MicroPython_BUILD/components/micropython/py/emitglue.c b/MicroPython_BUILD/components/micropython/py/emitglue.c
index d2add98..74bf8dd 100644
--- a/MicroPython_BUILD/components/micropython/py/emitglue.c
+++ b/MicroPython_BUILD/components/micropython/py/emitglue.c
@@ -55,7 +55,10 @@ mp_raw_code_t *mp_emit_glue_new_raw_code(void) {
return rc;
}
-void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, mp_uint_t len,
+void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code,
+ #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
+ size_t len,
+ #endif
const mp_uint_t *const_table,
#if MICROPY_PERSISTENT_CODE_SAVE
uint16_t n_obj, uint16_t n_raw_code,
diff --git a/MicroPython_BUILD/components/micropython/py/emitglue.h b/MicroPython_BUILD/components/micropython/py/emitglue.h
index 4393033..0830a0d 100644
--- a/MicroPython_BUILD/components/micropython/py/emitglue.h
+++ b/MicroPython_BUILD/components/micropython/py/emitglue.h
@@ -40,7 +40,7 @@ typedef enum {
} mp_raw_code_kind_t;
typedef struct _mp_raw_code_t {
- mp_raw_code_kind_t kind : 3;
+ mp_uint_t kind : 3; // of type mp_raw_code_kind_t
mp_uint_t scope_flags : 7;
mp_uint_t n_pos_args : 11;
union {
@@ -63,7 +63,10 @@ typedef struct _mp_raw_code_t {
mp_raw_code_t *mp_emit_glue_new_raw_code(void);
-void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, mp_uint_t len,
+void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code,
+ #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
+ size_t len,
+ #endif
const mp_uint_t *const_table,
#if MICROPY_PERSISTENT_CODE_SAVE
uint16_t n_obj, uint16_t n_raw_code,
diff --git a/MicroPython_BUILD/components/micropython/py/emitnative.c b/MicroPython_BUILD/components/micropython/py/emitnative.c
index 8e97dda..964db95 100644
--- a/MicroPython_BUILD/components/micropython/py/emitnative.c
+++ b/MicroPython_BUILD/components/micropython/py/emitnative.c
@@ -66,6 +66,13 @@
// this is defined so that the assembler exports generic assembler API macros
#define GENERIC_ASM_API (1)
+// define additional generic helper macros
+#define ASM_MOV_LOCAL_IMM_VIA(as, local_num, imm, reg_temp) \
+ do { \
+ ASM_MOV_REG_IMM((as), (reg_temp), (imm)); \
+ ASM_MOV_LOCAL_REG((as), (local_num), (reg_temp)); \
+ } while (false)
+
#if N_X64
// x64 specific stuff
@@ -389,7 +396,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_3);
} else {
assert(i == 3); // should be true; max 4 args is checked above
- ASM_MOV_REG_TO_LOCAL(emit->as, REG_ARG_4, i - REG_LOCAL_NUM);
+ ASM_MOV_LOCAL_REG(emit->as, i - REG_LOCAL_NUM, REG_ARG_4);
}
}
#endif
@@ -418,14 +425,14 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
#endif
// set code_state.fun_bc
- ASM_MOV_REG_TO_LOCAL(emit->as, REG_ARG_1, offsetof(mp_code_state_t, fun_bc) / sizeof(uintptr_t));
+ ASM_MOV_LOCAL_REG(emit->as, offsetof(mp_code_state_t, fun_bc) / sizeof(uintptr_t), REG_ARG_1);
// set code_state.ip (offset from start of this function to prelude info)
// XXX this encoding may change size
- ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(uintptr_t), REG_ARG_1);
+ ASM_MOV_LOCAL_IMM_VIA(emit->as, offsetof(mp_code_state_t, ip) / sizeof(uintptr_t), emit->prelude_offset, REG_ARG_1);
// put address of code_state into first arg
- ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, 0, REG_ARG_1);
+ ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, 0);
// call mp_setup_code_state to prepare code_state structure
#if N_THUMB
@@ -438,11 +445,11 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
// cache some locals in registers
if (scope->num_locals > 0) {
- ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 0, REG_LOCAL_1);
+ ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_1, STATE_START + emit->n_state - 1 - 0);
if (scope->num_locals > 1) {
- ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 1, REG_LOCAL_2);
+ ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_2, STATE_START + emit->n_state - 1 - 1);
if (scope->num_locals > 2) {
- ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 2, REG_LOCAL_3);
+ ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_3, STATE_START + emit->n_state - 1 - 2);
}
}
}
@@ -606,7 +613,7 @@ STATIC void need_reg_single(emit_t *emit, int reg_needed, int skip_stack_pos) {
stack_info_t *si = &emit->stack_info[i];
if (si->kind == STACK_REG && si->data.u_reg == reg_needed) {
si->kind = STACK_VALUE;
- ASM_MOV_REG_TO_LOCAL(emit->as, si->data.u_reg, emit->stack_start + i);
+ ASM_MOV_LOCAL_REG(emit->as, emit->stack_start + i, si->data.u_reg);
}
}
}
@@ -617,7 +624,7 @@ STATIC void need_reg_all(emit_t *emit) {
stack_info_t *si = &emit->stack_info[i];
if (si->kind == STACK_REG) {
si->kind = STACK_VALUE;
- ASM_MOV_REG_TO_LOCAL(emit->as, si->data.u_reg, emit->stack_start + i);
+ ASM_MOV_LOCAL_REG(emit->as, emit->stack_start + i, si->data.u_reg);
}
}
}
@@ -629,7 +636,7 @@ STATIC void need_stack_settled(emit_t *emit) {
if (si->kind == STACK_REG) {
DEBUG_printf(" reg(%u) to local(%u)\n", si->data.u_reg, emit->stack_start + i);
si->kind = STACK_VALUE;
- ASM_MOV_REG_TO_LOCAL(emit->as, si->data.u_reg, emit->stack_start + i);
+ ASM_MOV_LOCAL_REG(emit->as, emit->stack_start + i, si->data.u_reg);
}
}
for (int i = 0; i < emit->stack_size; i++) {
@@ -637,7 +644,7 @@ STATIC void need_stack_settled(emit_t *emit) {
if (si->kind == STACK_IMM) {
DEBUG_printf(" imm(" INT_FMT ") to local(%u)\n", si->data.u_imm, emit->stack_start + i);
si->kind = STACK_VALUE;
- ASM_MOV_IMM_TO_LOCAL_USING(emit->as, si->data.u_imm, emit->stack_start + i, REG_TEMP0);
+ ASM_MOV_LOCAL_IMM_VIA(emit->as, emit->stack_start + i, si->data.u_imm, REG_TEMP0);
}
}
}
@@ -649,7 +656,7 @@ STATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int re
*vtype = si->vtype;
switch (si->kind) {
case STACK_VALUE:
- ASM_MOV_LOCAL_TO_REG(emit->as, emit->stack_start + emit->stack_size - pos, reg_dest);
+ ASM_MOV_REG_LOCAL(emit->as, reg_dest, emit->stack_start + emit->stack_size - pos);
break;
case STACK_REG:
@@ -659,7 +666,7 @@ STATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int re
break;
case STACK_IMM:
- ASM_MOV_IMM_TO_REG(emit->as, si->data.u_imm, reg_dest);
+ ASM_MOV_REG_IMM(emit->as, reg_dest, si->data.u_imm);
break;
}
}
@@ -671,7 +678,7 @@ STATIC void emit_fold_stack_top(emit_t *emit, int reg_dest) {
si[0] = si[1];
if (si->kind == STACK_VALUE) {
// if folded element was on the stack we need to put it in a register
- ASM_MOV_LOCAL_TO_REG(emit->as, emit->stack_start + emit->stack_size - 1, reg_dest);
+ ASM_MOV_REG_LOCAL(emit->as, reg_dest, emit->stack_start + emit->stack_size - 1);
si->kind = STACK_REG;
si->data.u_reg = reg_dest;
}
@@ -765,30 +772,30 @@ STATIC void emit_call(emit_t *emit, mp_fun_kind_t fun_kind) {
STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg) {
need_reg_all(emit);
- ASM_MOV_IMM_TO_REG(emit->as, arg_val, arg_reg);
+ ASM_MOV_REG_IMM(emit->as, arg_reg, arg_val);
ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
}
// the first arg is stored in the code aligned on a mp_uint_t boundary
STATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg) {
need_reg_all(emit);
- ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, arg_val, arg_reg);
+ ASM_MOV_REG_ALIGNED_IMM(emit->as, arg_reg, arg_val);
ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
}
STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2) {
need_reg_all(emit);
- ASM_MOV_IMM_TO_REG(emit->as, arg_val1, arg_reg1);
- ASM_MOV_IMM_TO_REG(emit->as, arg_val2, arg_reg2);
+ ASM_MOV_REG_IMM(emit->as, arg_reg1, arg_val1);
+ ASM_MOV_REG_IMM(emit->as, arg_reg2, arg_val2);
ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
}
// the first arg is stored in the code aligned on a mp_uint_t boundary
STATIC void emit_call_with_3_imm_args_and_first_aligned(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2, mp_int_t arg_val3, int arg_reg3) {
need_reg_all(emit);
- ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, arg_val1, arg_reg1);
- ASM_MOV_IMM_TO_REG(emit->as, arg_val2, arg_reg2);
- ASM_MOV_IMM_TO_REG(emit->as, arg_val3, arg_reg3);
+ ASM_MOV_REG_ALIGNED_IMM(emit->as, arg_reg1, arg_val1);
+ ASM_MOV_REG_IMM(emit->as, arg_reg2, arg_val2);
+ ASM_MOV_REG_IMM(emit->as, arg_reg3, arg_val3);
ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
}
@@ -808,19 +815,19 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_de
si->kind = STACK_VALUE;
switch (si->vtype) {
case VTYPE_PYOBJ:
- ASM_MOV_IMM_TO_LOCAL_USING(emit->as, si->data.u_imm, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
+ ASM_MOV_LOCAL_IMM_VIA(emit->as, emit->stack_start + emit->stack_size - 1 - i, si->data.u_imm, reg_dest);
break;
case VTYPE_BOOL:
if (si->data.u_imm == 0) {
- ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (mp_uint_t)mp_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
+ ASM_MOV_LOCAL_IMM_VIA(emit->as, emit->stack_start + emit->stack_size - 1 - i, (mp_uint_t)mp_const_false, reg_dest);
} else {
- ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (mp_uint_t)mp_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
+ ASM_MOV_LOCAL_IMM_VIA(emit->as, emit->stack_start + emit->stack_size - 1 - i, (mp_uint_t)mp_const_true, reg_dest);
}
si->vtype = VTYPE_PYOBJ;
break;
case VTYPE_INT:
case VTYPE_UINT:
- ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (uintptr_t)MP_OBJ_NEW_SMALL_INT(si->data.u_imm), emit->stack_start + emit->stack_size - 1 - i, reg_dest);
+ ASM_MOV_LOCAL_IMM_VIA(emit->as, emit->stack_start + emit->stack_size - 1 - i, (uintptr_t)MP_OBJ_NEW_SMALL_INT(si->data.u_imm), reg_dest);
si->vtype = VTYPE_PYOBJ;
break;
default:
@@ -838,9 +845,9 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_de
stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i];
if (si->vtype != VTYPE_PYOBJ) {
mp_uint_t local_num = emit->stack_start + emit->stack_size - 1 - i;
- ASM_MOV_LOCAL_TO_REG(emit->as, local_num, REG_ARG_1);
+ ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, local_num);
emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, si->vtype, REG_ARG_2); // arg2 = type
- ASM_MOV_REG_TO_LOCAL(emit->as, REG_RET, local_num);
+ ASM_MOV_LOCAL_REG(emit->as, local_num, REG_RET);
si->vtype = VTYPE_PYOBJ;
DEBUG_printf(" convert_native_to_obj(local_num=" UINT_FMT ")\n", local_num);
}
@@ -848,7 +855,7 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_de
// Adujust the stack for a pop of n_pop items, and load the stack pointer into reg_dest.
adjust_stack(emit, -n_pop);
- ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, emit->stack_start + emit->stack_size, reg_dest);
+ ASM_MOV_REG_LOCAL_ADDR(emit->as, reg_dest, emit->stack_start + emit->stack_size);
}
// vtype of all n_push objects is VTYPE_PYOBJ
@@ -858,7 +865,7 @@ STATIC void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, mp_uint_t reg_d
emit->stack_info[emit->stack_size + i].kind = STACK_VALUE;
emit->stack_info[emit->stack_size + i].vtype = VTYPE_PYOBJ;
}
- ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, emit->stack_start + emit->stack_size, reg_dest);
+ ASM_MOV_REG_LOCAL_ADDR(emit->as, reg_dest, emit->stack_start + emit->stack_size);
adjust_stack(emit, n_push);
}
@@ -881,7 +888,7 @@ STATIC void emit_native_import_name(emit_t *emit, qstr qst) {
stack_info_t *top = peek_stack(emit, 0);
if (top->vtype == VTYPE_PTR_NONE) {
emit_pre_pop_discard(emit);
- ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)mp_const_none, REG_ARG_2);
+ ASM_MOV_REG_IMM(emit->as, REG_ARG_2, (mp_uint_t)mp_const_none);
} else {
vtype_kind_t vtype_fromlist;
emit_pre_pop_reg(emit, &vtype_fromlist, REG_ARG_2);
@@ -891,7 +898,7 @@ STATIC void emit_native_import_name(emit_t *emit, qstr qst) {
// level argument should be an immediate integer
top = peek_stack(emit, 0);
assert(top->vtype == VTYPE_INT && top->kind == STACK_IMM);
- ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_NEW_SMALL_INT(top->data.u_imm), REG_ARG_3);
+ ASM_MOV_REG_IMM(emit->as, REG_ARG_3, (mp_uint_t)MP_OBJ_NEW_SMALL_INT(top->data.u_imm));
emit_pre_pop_discard(emit);
} else {
@@ -981,7 +988,7 @@ STATIC void emit_native_load_const_str(emit_t *emit, qstr qst) {
STATIC void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj) {
emit_native_pre(emit);
need_reg_single(emit, REG_RET, 0);
- ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, (mp_uint_t)obj, REG_RET);
+ ASM_MOV_REG_ALIGNED_IMM(emit->as, REG_RET, (mp_uint_t)obj);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
@@ -1006,9 +1013,9 @@ STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
} else {
need_reg_single(emit, REG_TEMP0, 0);
if (emit->do_viper_types) {
- ASM_MOV_LOCAL_TO_REG(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);
+ ASM_MOV_REG_LOCAL(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);
} else {
- ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - local_num, REG_TEMP0);
+ ASM_MOV_REG_LOCAL(emit->as, REG_TEMP0, STATE_START + emit->n_state - 1 - local_num);
}
emit_post_push_reg(emit, vtype, REG_TEMP0);
}
@@ -1134,7 +1141,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) {
break;
}
#endif
- ASM_MOV_IMM_TO_REG(emit->as, index_value, reg_index);
+ 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;
}
@@ -1151,7 +1158,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) {
break;
}
#endif
- ASM_MOV_IMM_TO_REG(emit->as, index_value << 1, reg_index);
+ 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;
}
@@ -1168,7 +1175,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) {
break;
}
#endif
- ASM_MOV_IMM_TO_REG(emit->as, index_value << 2, reg_index);
+ 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;
}
@@ -1233,9 +1240,9 @@ STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num)
} else {
emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
if (emit->do_viper_types) {
- ASM_MOV_REG_TO_LOCAL(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);
+ ASM_MOV_LOCAL_REG(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);
} else {
- ASM_MOV_REG_TO_LOCAL(emit->as, REG_TEMP0, STATE_START + emit->n_state - 1 - local_num);
+ ASM_MOV_LOCAL_REG(emit->as, STATE_START + emit->n_state - 1 - local_num, REG_TEMP0);
}
}
emit_post(emit);
@@ -1354,7 +1361,7 @@ STATIC void emit_native_store_subscr(emit_t *emit) {
break;
}
#endif
- ASM_MOV_IMM_TO_REG(emit->as, index_value, reg_index);
+ ASM_MOV_REG_IMM(emit->as, reg_index, index_value);
#if N_ARM
asm_arm_strb_reg_reg_reg(emit->as, reg_value, reg_base, reg_index);
return;
@@ -1375,7 +1382,7 @@ STATIC void emit_native_store_subscr(emit_t *emit) {
break;
}
#endif
- ASM_MOV_IMM_TO_REG(emit->as, index_value << 1, reg_index);
+ ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 1);
#if N_ARM
asm_arm_strh_reg_reg_reg(emit->as, reg_value, reg_base, reg_index);
return;
@@ -1396,7 +1403,7 @@ STATIC void emit_native_store_subscr(emit_t *emit) {
break;
}
#endif
- ASM_MOV_IMM_TO_REG(emit->as, index_value << 2, reg_index);
+ ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 2);
#if N_ARM
asm_arm_str_reg_reg_reg(emit->as, reg_value, reg_base, reg_index);
return;
@@ -1773,7 +1780,7 @@ STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) {
emit_call(emit, MP_F_NATIVE_GETITER);
} else {
// mp_getiter will allocate the iter_buf on the heap
- ASM_MOV_IMM_TO_REG(emit->as, 0, REG_ARG_2);
+ ASM_MOV_REG_IMM(emit->as, REG_ARG_2, 0);
emit_call(emit, MP_F_NATIVE_GETITER);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
@@ -1784,7 +1791,7 @@ STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) {
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, MP_OBJ_ITER_BUF_NSLOTS);
adjust_stack(emit, MP_OBJ_ITER_BUF_NSLOTS);
emit_call(emit, MP_F_NATIVE_ITERNEXT);
- ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
+ ASM_MOV_REG_IMM(emit->as, REG_TEMP1, (mp_uint_t)MP_OBJ_STOP_ITERATION);
ASM_JUMP_IF_REG_EQ(emit->as, REG_RET, REG_TEMP1, label);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
@@ -2128,12 +2135,12 @@ STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_c
emit_native_pre(emit);
if (n_pos_defaults == 0 && n_kw_defaults == 0) {
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_closed_over);
- ASM_MOV_IMM_TO_REG(emit->as, n_closed_over, REG_ARG_2);
+ ASM_MOV_REG_IMM(emit->as, REG_ARG_2, n_closed_over);
} else {
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_closed_over + 2);
- ASM_MOV_IMM_TO_REG(emit->as, 0x100 | n_closed_over, REG_ARG_2);
+ ASM_MOV_REG_IMM(emit->as, REG_ARG_2, 0x100 | n_closed_over);
}
- ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, (mp_uint_t)scope->raw_code, REG_ARG_1);
+ ASM_MOV_REG_ALIGNED_IMM(emit->as, REG_ARG_1, (mp_uint_t)scope->raw_code);
ASM_CALL_IND(emit->as, mp_fun_table[MP_F_MAKE_CLOSURE_FROM_RAW_CODE], MP_F_MAKE_CLOSURE_FROM_RAW_CODE);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
@@ -2212,9 +2219,9 @@ STATIC void emit_native_return_value(emit_t *emit) {
if (peek_vtype(emit, 0) == VTYPE_PTR_NONE) {
emit_pre_pop_discard(emit);
if (emit->return_vtype == VTYPE_PYOBJ) {
- ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)mp_const_none, REG_RET);
+ ASM_MOV_REG_IMM(emit->as, REG_RET, (mp_uint_t)mp_const_none);
} else {
- ASM_MOV_IMM_TO_REG(emit->as, 0, REG_RET);
+ ASM_MOV_REG_IMM(emit->as, REG_RET, 0);
}
} else {
vtype_kind_t vtype;
diff --git a/MicroPython_BUILD/components/micropython/py/formatfloat.c b/MicroPython_BUILD/components/micropython/py/formatfloat.c
index 4228f99..dc7fc1d 100644
--- a/MicroPython_BUILD/components/micropython/py/formatfloat.c
+++ b/MicroPython_BUILD/components/micropython/py/formatfloat.c
@@ -258,7 +258,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
}
// It can be that f was right on the edge of an entry in pos_pow needs to be reduced
- if (f >= FPCONST(10.0)) {
+ if ((int)f >= 10) {
e += 1;
f *= FPCONST(0.1);
}
@@ -330,7 +330,11 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
// Print the digits of the mantissa
for (int i = 0; i < num_digits; ++i, --dec) {
int32_t d = (int32_t)f;
- *s++ = '0' + d;
+ if (d < 0) {
+ *s++ = '0';
+ } else {
+ *s++ = '0' + d;
+ }
if (dec == 0 && prec > 0) {
*s++ = '.';
}
@@ -341,7 +345,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
// Round
// If we print non-exponential format (i.e. 'f'), but a digit we're going
// to round by (e) is too far away, then there's nothing to round.
- if ((org_fmt != 'f' || e <= 1) && f >= FPCONST(5.0)) {
+ if ((org_fmt != 'f' || e <= num_digits) && f >= FPCONST(5.0)) {
char *rs = s;
rs--;
while (1) {
diff --git a/MicroPython_BUILD/components/micropython/py/gc.c b/MicroPython_BUILD/components/micropython/py/gc.c
index 9752b35..84c9918 100644
--- a/MicroPython_BUILD/components/micropython/py/gc.c
+++ b/MicroPython_BUILD/components/micropython/py/gc.c
@@ -44,6 +44,10 @@
// make this 1 to dump the heap each time it changes
#define EXTENSIVE_HEAP_PROFILING (0)
+// make this 1 to zero out swept memory to more eagerly
+// detect untraced object still in use
+#define CLEAR_ON_SWEEP (0)
+
#define WORDS_PER_BLOCK ((MICROPY_BYTES_PER_GC_BLOCK) / BYTES_PER_WORD)
#define BYTES_PER_BLOCK (MICROPY_BYTES_PER_GC_BLOCK)
@@ -191,29 +195,22 @@ bool gc_is_locked(void) {
&& ptr < (void*)MP_STATE_MEM(gc_pool_end) /* must be below end of pool */ \
)
-// ptr should be of type void*
-#define VERIFY_MARK_AND_PUSH(ptr) \
- do { \
- if (VERIFY_PTR(ptr)) { \
- size_t _block = BLOCK_FROM_PTR(ptr); \
- if (ATB_GET_KIND(_block) == AT_HEAD) { \
- /* an unmarked head, mark it, and push it on gc stack */ \
- DEBUG_printf("gc_mark(%p)\n", ptr); \
- ATB_HEAD_TO_MARK(_block); \
- if (MP_STATE_MEM(gc_sp) < &MP_STATE_MEM(gc_stack)[MICROPY_ALLOC_GC_STACK_SIZE]) { \
- *MP_STATE_MEM(gc_sp)++ = _block; \
- } else { \
- MP_STATE_MEM(gc_stack_overflow) = 1; \
- } \
- } \
- } \
- } while (0)
-
-STATIC void gc_drain_stack(void) {
- while (MP_STATE_MEM(gc_sp) > MP_STATE_MEM(gc_stack)) {
- // pop the next block off the stack
- size_t block = *--MP_STATE_MEM(gc_sp);
+#ifndef TRACE_MARK
+#if DEBUG_PRINT
+#define TRACE_MARK(block, ptr) DEBUG_printf("gc_mark(%p)\n", ptr)
+#else
+#define TRACE_MARK(block, ptr)
+#endif
+#endif
+// Take the given block as the topmost block on the stack. Check all it's
+// children: mark the unmarked child blocks and put those newly marked
+// blocks on the stack. When all children have been checked, pop off the
+// topmost block on the stack and repeat with that one.
+STATIC void gc_mark_subtree(size_t block) {
+ // Start with the block passed in the argument.
+ size_t sp = 0;
+ for (;;) {
// work out number of consecutive blocks in the chain starting with this one
size_t n_blocks = 0;
do {
@@ -224,22 +221,41 @@ STATIC void gc_drain_stack(void) {
void **ptrs = (void**)PTR_FROM_BLOCK(block);
for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void*); i > 0; i--, ptrs++) {
void *ptr = *ptrs;
- VERIFY_MARK_AND_PUSH(ptr);
+ 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;
+ }
+ }
+ }
}
+
+ // Are there any blocks on the stack?
+ if (sp == 0) {
+ break; // No, stack is empty, we're done.
+ }
+
+ // pop the next block off the stack
+ block = MP_STATE_MEM(gc_stack)[--sp];
}
}
STATIC void gc_deal_with_stack_overflow(void) {
while (MP_STATE_MEM(gc_stack_overflow)) {
MP_STATE_MEM(gc_stack_overflow) = 0;
- MP_STATE_MEM(gc_sp) = MP_STATE_MEM(gc_stack);
// 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++) {
// trace (again) if mark bit set
if (ATB_GET_KIND(block) == AT_MARK) {
- *MP_STATE_MEM(gc_sp)++ = block;
- gc_drain_stack();
+ gc_mark_subtree(block);
}
}
}
@@ -277,7 +293,7 @@ STATIC void gc_sweep(void) {
}
#endif
free_tail = 1;
- DEBUG_printf("gc_sweep(%x)\n", PTR_FROM_BLOCK(block));
+ DEBUG_printf("gc_sweep(%p)\n", PTR_FROM_BLOCK(block));
#if MICROPY_PY_GC_COLLECT_RETVAL
MP_STATE_MEM(gc_collected)++;
#endif
@@ -286,6 +302,9 @@ STATIC void gc_sweep(void) {
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;
@@ -304,19 +323,32 @@ void gc_collect_start(void) {
MP_STATE_MEM(gc_alloc_amount) = 0;
#endif
MP_STATE_MEM(gc_stack_overflow) = 0;
- MP_STATE_MEM(gc_sp) = MP_STATE_MEM(gc_stack);
+
// Trace root pointers. This relies on the root pointers being organised
// correctly in the mp_state_ctx structure. We scan nlr_top, dict_locals,
// dict_globals, then the root pointer section of mp_state_vm.
void **ptrs = (void**)(void*)&mp_state_ctx;
gc_collect_root(ptrs, offsetof(mp_state_ctx_t, vm.qstr_last_chunk) / sizeof(void*));
+
+ #if MICROPY_ENABLE_PYSTACK
+ // Trace root pointers from the Python stack.
+ ptrs = (void**)(void*)MP_STATE_THREAD(pystack_start);
+ gc_collect_root(ptrs, (MP_STATE_THREAD(pystack_cur) - MP_STATE_THREAD(pystack_start)) / sizeof(void*));
+ #endif
}
void gc_collect_root(void **ptrs, size_t len) {
for (size_t i = 0; i < len; i++) {
void *ptr = ptrs[i];
- VERIFY_MARK_AND_PUSH(ptr);
- gc_drain_stack();
+ 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);
+ }
+ }
}
}
@@ -628,27 +660,18 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {
void *ptr = ptr_in;
- // sanity check the ptr
- if (!VERIFY_PTR(ptr)) {
- return NULL;
- }
-
- // get first block
- size_t block = BLOCK_FROM_PTR(ptr);
-
GC_ENTER();
- // sanity check the ptr is pointing to the head of a block
- if (ATB_GET_KIND(block) != AT_HEAD) {
- GC_EXIT();
- return NULL;
- }
-
if (MP_STATE_MEM(gc_lock_depth) > 0) {
GC_EXIT();
return NULL;
}
+ // 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);
+
// compute number of new blocks that are requested
size_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK;
diff --git a/MicroPython_BUILD/components/micropython/py/makeqstrdefs.py b/MicroPython_BUILD/components/micropython/py/makeqstrdefs.py
index 115a4e9..1764401 100644
--- a/MicroPython_BUILD/components/micropython/py/makeqstrdefs.py
+++ b/MicroPython_BUILD/components/micropython/py/makeqstrdefs.py
@@ -24,12 +24,16 @@ def write_out(fname, output):
f.write("\n".join(output) + "\n")
def process_file(f):
+ re_line = re.compile(r"#[line]*\s\d+\s\"([^\"]+)\"")
+ re_qstr = re.compile(r'MP_QSTR_[_a-zA-Z0-9]+')
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 and (line[0:2] == "# " or line[0:5] == "#line"):
- m = re.match(r"#[line]*\s\d+\s\"([^\"]+)\"", line)
+ if line.startswith(('# ', '#line')):
+ m = re_line.match(line)
assert m is not None
fname = m.group(1)
if not fname.endswith(".c"):
@@ -39,7 +43,7 @@ def process_file(f):
output = []
last_fname = fname
continue
- for match in re.findall(r'MP_QSTR_[_a-zA-Z0-9]+', line):
+ for match in re_qstr.findall(line):
name = match.replace('MP_QSTR_', '')
if name not in QSTRING_BLACK_LIST:
output.append('Q(' + name + ')')
@@ -81,6 +85,8 @@ def cat_together():
os.rename(args.output_dir + "/out", args.output_file)
with open(args.output_file + ".hash", "w") as f:
f.write(new_hash)
+ else:
+ print("QSTR not updated")
if __name__ == "__main__":
diff --git a/MicroPython_BUILD/components/micropython/py/makeversionhdr.py b/MicroPython_BUILD/components/micropython/py/makeversionhdr.py
index 749160b..aedc292 100644
--- a/MicroPython_BUILD/components/micropython/py/makeversionhdr.py
+++ b/MicroPython_BUILD/components/micropython/py/makeversionhdr.py
@@ -99,7 +99,7 @@ def make_version_header(filename):
# Only write the file if we need to
if write_file:
- print("Generating %s" % filename)
+ print("GEN %s" % filename)
with open(filename, 'w') as f:
f.write(file_data)
diff --git a/MicroPython_BUILD/components/micropython/py/malloc.c b/MicroPython_BUILD/components/micropython/py/malloc.c
index ea1d4c4..ba5c952 100644
--- a/MicroPython_BUILD/components/micropython/py/malloc.c
+++ b/MicroPython_BUILD/components/micropython/py/malloc.c
@@ -39,6 +39,9 @@
#endif
#if MICROPY_MEM_STATS
+#if !MICROPY_MALLOC_USES_ALLOCATED_SIZE
+#error MICROPY_MEM_STATS requires MICROPY_MALLOC_USES_ALLOCATED_SIZE
+#endif
#define UPDATE_PEAK() { if (MP_STATE_MEM(current_bytes_allocated) > MP_STATE_MEM(peak_bytes_allocated)) MP_STATE_MEM(peak_bytes_allocated) = MP_STATE_MEM(current_bytes_allocated); }
#endif
@@ -114,9 +117,6 @@ void *m_malloc_with_finaliser(size_t num_bytes) {
void *m_malloc0(size_t num_bytes) {
void *ptr = m_malloc(num_bytes);
- if (ptr == NULL && num_bytes != 0) {
- m_malloc_fail(num_bytes);
- }
// If this config is set then the GC clears all memory, so we don't need to.
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(ptr, 0, num_bytes);
@@ -144,7 +144,11 @@ void *m_realloc(void *ptr, size_t new_num_bytes) {
MP_STATE_MEM(current_bytes_allocated) += diff;
UPDATE_PEAK();
#endif
+ #if MICROPY_MALLOC_USES_ALLOCATED_SIZE
DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
+ #else
+ DEBUG_printf("realloc %p, %d : %p\n", ptr, new_num_bytes, new_ptr);
+ #endif
return new_ptr;
}
@@ -168,7 +172,11 @@ void *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move) {
UPDATE_PEAK();
}
#endif
+ #if MICROPY_MALLOC_USES_ALLOCATED_SIZE
DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
+ #else
+ DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, new_num_bytes, new_ptr);
+ #endif
return new_ptr;
}
@@ -181,7 +189,11 @@ void m_free(void *ptr) {
#if MICROPY_MEM_STATS
MP_STATE_MEM(current_bytes_allocated) -= num_bytes;
#endif
+ #if MICROPY_MALLOC_USES_ALLOCATED_SIZE
DEBUG_printf("free %p, %d\n", ptr, num_bytes);
+ #else
+ DEBUG_printf("free %p\n", ptr);
+ #endif
}
#if MICROPY_MEM_STATS
diff --git a/MicroPython_BUILD/components/micropython/py/map.c b/MicroPython_BUILD/components/micropython/py/map.c
index 4f76b9b..6abf485 100644
--- a/MicroPython_BUILD/components/micropython/py/map.c
+++ b/MicroPython_BUILD/components/micropython/py/map.c
@@ -33,6 +33,13 @@
#include "py/misc.h"
#include "py/runtime.h"
+#if MICROPY_DEBUG_VERBOSE // print debugging info
+#define DEBUG_PRINT (1)
+#else // don't print debugging info
+#define DEBUG_PRINT (0)
+#define DEBUG_printf(...) (void)0
+#endif
+
// Fixed empty map. Useful when need to call kw-receiving functions
// without any keywords from C, etc.
const mp_map_t mp_const_empty_map = {
@@ -114,6 +121,7 @@ void mp_map_clear(mp_map_t *map) {
STATIC void mp_map_rehash(mp_map_t *map) {
size_t old_alloc = map->alloc;
size_t new_alloc = get_hash_alloc_greater_or_equal_to(map->alloc + 1);
+ DEBUG_printf("mp_map_rehash(%p): " UINT_FMT " -> " UINT_FMT "\n", map, old_alloc, new_alloc);
mp_map_elem_t *old_table = map->table;
mp_map_elem_t *new_table = m_new0(mp_map_elem_t, new_alloc);
// If we reach this point, table resizing succeeded, now we can edit the old map.
@@ -162,6 +170,7 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
if (map->is_ordered) {
for (mp_map_elem_t *elem = &map->table[0], *top = &map->table[map->used]; elem < top; elem++) {
if (elem->key == index || (!compare_only_ptrs && mp_obj_equal(elem->key, index))) {
+ #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
if (MP_UNLIKELY(lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND)) {
// remove the found element by moving the rest of the array down
mp_obj_t value = elem->value;
@@ -172,9 +181,11 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
elem->key = MP_OBJ_NULL;
elem->value = value;
}
+ #endif
return elem;
}
}
+ #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
if (MP_LIKELY(lookup_kind != MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)) {
return NULL;
}
@@ -190,6 +201,9 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
map->all_keys_are_qstrs = 0;
}
return elem;
+ #else
+ return NULL;
+ #endif
}
// map is a hash table (not an ordered array), so do a hash lookup
diff --git a/MicroPython_BUILD/components/micropython/py/misc.h b/MicroPython_BUILD/components/micropython/py/misc.h
index b9f2dae..72560da 100644
--- a/MicroPython_BUILD/components/micropython/py/misc.h
+++ b/MicroPython_BUILD/components/micropython/py/misc.h
@@ -63,8 +63,10 @@ typedef unsigned int uint;
#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))))
+#define m_new_obj_var_with_finaliser(type, var_type, var_num) ((type*)m_malloc_with_finaliser(sizeof(type) + sizeof(var_type) * (var_num)))
#else
#define m_new_obj_with_finaliser(type) m_new_obj(type)
+#define m_new_obj_var_with_finaliser(type, var_type, var_num) m_new_obj_var(type, var_type, var_num)
#endif
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
#define m_renew(type, ptr, old_num, new_num) ((type*)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num))))
@@ -119,8 +121,15 @@ typedef uint32_t unichar;
typedef uint unichar;
#endif
+#if MICROPY_PY_BUILTINS_STR_UNICODE
unichar utf8_get_char(const byte *s);
const byte *utf8_next_char(const byte *s);
+size_t utf8_charlen(const byte *str, size_t len);
+#else
+static inline unichar utf8_get_char(const byte *s) { return *s; }
+static inline const byte *utf8_next_char(const byte *s) { return s + 1; }
+static inline size_t utf8_charlen(const byte *str, size_t len) { (void)str; return len; }
+#endif
bool unichar_isspace(unichar c);
bool unichar_isalpha(unichar c);
@@ -133,7 +142,6 @@ bool unichar_islower(unichar c);
unichar unichar_tolower(unichar c);
unichar unichar_toupper(unichar c);
mp_uint_t unichar_xdigit_value(unichar c);
-mp_uint_t unichar_charlen(const char *str, mp_uint_t len);
#define UTF8_IS_NONASCII(ch) ((ch) & 0x80)
#define UTF8_IS_CONT(ch) (((ch) & 0xC0) == 0x80)
@@ -196,20 +204,6 @@ int DEBUG_printf(const char *fmt, ...);
extern mp_uint_t mp_verbose_flag;
-// This is useful for unicode handling. Some CPU archs has
-// special instructions for efficient implementation of this
-// function (e.g. CLZ on ARM).
-// NOTE: this function is unused at the moment
-#ifndef count_lead_ones
-static inline mp_uint_t count_lead_ones(byte val) {
- mp_uint_t c = 0;
- for (byte mask = 0x80; val & mask; mask >>= 1) {
- c++;
- }
- return c;
-}
-#endif
-
/** float internals *************/
#if MICROPY_PY_BUILTINS_FLOAT
diff --git a/MicroPython_BUILD/components/micropython/py/mkrules.mk b/MicroPython_BUILD/components/micropython/py/mkrules.mk
index ac5ddb1..ffb12d9 100644
--- a/MicroPython_BUILD/components/micropython/py/mkrules.mk
+++ b/MicroPython_BUILD/components/micropython/py/mkrules.mk
@@ -112,7 +112,7 @@ FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/frozen_mpy/,$(FROZEN_MPY_PY_FILES:.
$(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py
@$(ECHO) "MPY $<"
$(Q)$(MKDIR) -p $(dir $@)
- $(Q)$(MPY_CROSS) -o $@ -s $(<:$(FROZEN_MPY_DIR)/%=%) $(MPY_CROSS_FLAGS) $<
+ $(Q)$(MPY_CROSS) -o $@ -s $(<:$(FROZEN_MPY_DIR)/%=%) $<
# to build frozen_mpy.c from all .mpy files
$(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h
diff --git a/MicroPython_BUILD/components/micropython/py/modbuiltins.c b/MicroPython_BUILD/components/micropython/py/modbuiltins.c
index 65c03d5..5d4ec8f 100644
--- a/MicroPython_BUILD/components/micropython/py/modbuiltins.c
+++ b/MicroPython_BUILD/components/micropython/py/modbuiltins.c
@@ -137,7 +137,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable);
STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
#if MICROPY_PY_BUILTINS_STR_UNICODE
mp_uint_t c = mp_obj_get_int(o_in);
- char str[4];
+ uint8_t str[4];
int len = 0;
if (c < 0x80) {
*str = c; len = 1;
@@ -159,12 +159,12 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
} else {
mp_raise_ValueError("chr() arg not in range(0x110000)");
}
- return mp_obj_new_str(str, len, true);
+ return mp_obj_new_str_via_qstr((char*)str, len);
#else
mp_int_t ord = mp_obj_get_int(o_in);
if (0 <= ord && ord <= 0xff) {
- char str[1] = {ord};
- return mp_obj_new_str(str, 1, true);
+ uint8_t str[1] = {ord};
+ return mp_obj_new_str_via_qstr((char*)str, 1);
} else {
mp_raise_ValueError("chr() arg not in range(256)");
}
@@ -173,46 +173,24 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr);
STATIC mp_obj_t mp_builtin_dir(size_t n_args, const mp_obj_t *args) {
- // TODO make this function more general and less of a hack
-
- mp_obj_dict_t *dict = NULL;
- mp_map_t *members = NULL;
- if (n_args == 0) {
- // make a list of names in the local name space
- dict = mp_locals_get();
- } else { // n_args == 1
- // make a list of names in the given object
- if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) {
- dict = mp_obj_module_get_globals(args[0]);
- } else {
- mp_obj_type_t *type;
- if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) {
- type = MP_OBJ_TO_PTR(args[0]);
- } else {
- type = mp_obj_get_type(args[0]);
- }
- if (type->locals_dict != NULL && type->locals_dict->base.type == &mp_type_dict) {
- dict = type->locals_dict;
- }
- }
- if (mp_obj_is_instance_type(mp_obj_get_type(args[0]))) {
- mp_obj_instance_t *inst = MP_OBJ_TO_PTR(args[0]);
- members = &inst->members;
- }
- }
-
mp_obj_t dir = mp_obj_new_list(0, NULL);
- if (dict != NULL) {
+ if (n_args == 0) {
+ // Make a list of names in the local namespace
+ mp_obj_dict_t *dict = mp_locals_get();
for (size_t i = 0; i < dict->map.alloc; i++) {
if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
mp_obj_list_append(dir, dict->map.table[i].key);
}
}
- }
- if (members != NULL) {
- for (size_t i = 0; i < members->alloc; i++) {
- if (MP_MAP_SLOT_IS_FILLED(members, i)) {
- mp_obj_list_append(dir, members->table[i].key);
+ } else { // n_args == 1
+ // Make a list of names in the given object
+ // Implemented by probing all possible qstrs with mp_load_method_maybe
+ size_t nqstr = QSTR_TOTAL();
+ for (size_t i = 1; i < nqstr; ++i) {
+ mp_obj_t dest[2];
+ mp_load_method_maybe(args[0], i, dest);
+ if (dest[0] != MP_OBJ_NULL) {
+ mp_obj_list_append(dir, MP_OBJ_NEW_QSTR(i));
}
}
}
@@ -343,19 +321,19 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct);
STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
size_t len;
- const char *str = mp_obj_str_get_data(o_in, &len);
+ const byte *str = (const byte*)mp_obj_str_get_data(o_in, &len);
#if MICROPY_PY_BUILTINS_STR_UNICODE
if (MP_OBJ_IS_STR(o_in)) {
- len = unichar_charlen(str, len);
+ len = utf8_charlen(str, len);
if (len == 1) {
- return mp_obj_new_int(utf8_get_char((const byte*)str));
+ return mp_obj_new_int(utf8_get_char(str));
}
} else
#endif
{
// a bytes object, or a str without unicode support (don't sign extend the char)
if (len == 1) {
- return MP_OBJ_NEW_SMALL_INT(((const byte*)str)[0]);
+ return MP_OBJ_NEW_SMALL_INT(str[0]);
}
}
@@ -383,46 +361,52 @@ STATIC mp_obj_t mp_builtin_pow(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj, 2, 3, mp_builtin_pow);
-STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
- mp_map_elem_t *sep_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_MAP_LOOKUP);
- mp_map_elem_t *end_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_MAP_LOOKUP);
- const char *sep_data = " ";
- size_t sep_len = 1;
- const char *end_data = "\n";
- size_t end_len = 1;
- if (sep_elem != NULL && sep_elem->value != mp_const_none) {
- sep_data = mp_obj_str_get_data(sep_elem->value, &sep_len);
- }
- if (end_elem != NULL && end_elem->value != mp_const_none) {
- end_data = mp_obj_str_get_data(end_elem->value, &end_len);
- }
- #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
- void *stream_obj = &mp_sys_stdout_obj;
- mp_map_elem_t *file_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_file), MP_MAP_LOOKUP);
- if (file_elem != NULL && file_elem->value != mp_const_none) {
- stream_obj = MP_OBJ_TO_PTR(file_elem->value); // XXX may not be a concrete object
- }
+STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_sep, ARG_end, ARG_file };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_sep, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR__space_)} },
+ { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR__0x0a_)} },
+ #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
+ { MP_QSTR_file, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_sys_stdout_obj)} },
+ #endif
+ };
- mp_print_t print = {stream_obj, mp_stream_write_adaptor};
+ // parse args (a union is used to reduce the amount of C stack that is needed)
+ union {
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ size_t len[2];
+ } u;
+ mp_arg_parse_all(0, NULL, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, u.args);
+
+ #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
+ // TODO file may not be a concrete object (eg it could be a small-int)
+ mp_print_t print = {MP_OBJ_TO_PTR(u.args[ARG_file].u_obj), mp_stream_write_adaptor};
#endif
+
+ // extract the objects first because we are going to use the other part of the union
+ mp_obj_t sep = u.args[ARG_sep].u_obj;
+ mp_obj_t end = u.args[ARG_end].u_obj;
+ const char *sep_data = mp_obj_str_get_data(sep, &u.len[0]);
+ const char *end_data = mp_obj_str_get_data(end, &u.len[1]);
+
for (size_t i = 0; i < n_args; i++) {
if (i > 0) {
#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
- mp_stream_write_adaptor(stream_obj, sep_data, sep_len);
+ mp_stream_write_adaptor(print.data, sep_data, u.len[0]);
#else
- mp_print_strn(&mp_plat_print, sep_data, sep_len, 0, 0, 0);
+ mp_print_strn(&mp_plat_print, sep_data, u.len[0], 0, 0, 0);
#endif
}
#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
- mp_obj_print_helper(&print, args[i], PRINT_STR);
+ mp_obj_print_helper(&print, pos_args[i], PRINT_STR);
#else
- mp_obj_print_helper(&mp_plat_print, args[i], PRINT_STR);
+ mp_obj_print_helper(&mp_plat_print, pos_args[i], PRINT_STR);
#endif
}
#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
- mp_stream_write_adaptor(stream_obj, end_data, end_len);
+ mp_stream_write_adaptor(print.data, end_data, u.len[1]);
#else
- mp_print_strn(&mp_plat_print, end_data, end_len, 0, 0, 0);
+ mp_print_strn(&mp_plat_print, end_data, u.len[1], 0, 0, 0);
#endif
return mp_const_none;
}
@@ -457,16 +441,14 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) {
return o_in;
}
#if MICROPY_PY_BUILTINS_FLOAT
- mp_int_t num_dig = 0;
+ mp_float_t val = mp_obj_get_float(o_in);
if (n_args > 1) {
- num_dig = mp_obj_get_int(args[1]);
- mp_float_t val = mp_obj_get_float(o_in);
+ mp_int_t num_dig = mp_obj_get_int(args[1]);
mp_float_t mult = MICROPY_FLOAT_C_FUN(pow)(10, num_dig);
// TODO may lead to overflow
mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val * mult) / mult;
return mp_obj_new_float(rounded);
}
- mp_float_t val = mp_obj_get_float(o_in);
mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val);
return mp_obj_new_int_from_float(rounded);
#else
diff --git a/MicroPython_BUILD/components/micropython/py/modcollections.c b/MicroPython_BUILD/components/micropython/py/modcollections.c
index 1a15603..bb64884 100644
--- a/MicroPython_BUILD/components/micropython/py/modcollections.c
+++ b/MicroPython_BUILD/components/micropython/py/modcollections.c
@@ -30,6 +30,9 @@
STATIC const mp_rom_map_elem_t mp_module_collections_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ucollections) },
+ #if MICROPY_PY_COLLECTIONS_DEQUE
+ { MP_ROM_QSTR(MP_QSTR_deque), MP_ROM_PTR(&mp_type_deque) },
+ #endif
{ MP_ROM_QSTR(MP_QSTR_namedtuple), MP_ROM_PTR(&mp_namedtuple_obj) },
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
{ MP_ROM_QSTR(MP_QSTR_OrderedDict), MP_ROM_PTR(&mp_type_ordereddict) },
diff --git a/MicroPython_BUILD/components/micropython/py/modio.c b/MicroPython_BUILD/components/micropython/py/modio.c
index 353a002..3a5c69c 100644
--- a/MicroPython_BUILD/components/micropython/py/modio.c
+++ b/MicroPython_BUILD/components/micropython/py/modio.c
@@ -131,7 +131,7 @@ STATIC const mp_obj_type_t bufwriter_type = {
};
#endif // MICROPY_PY_IO_BUFFEREDWRITER
-#if MICROPY_MODULE_FROZEN_STR
+#if MICROPY_PY_IO_RESOURCE_STREAM
STATIC mp_obj_t resource_stream(mp_obj_t package_in, mp_obj_t path_in) {
VSTR_FIXED(path_buf, MICROPY_ALLOC_PATH_MAX);
size_t len;
@@ -176,10 +176,10 @@ STATIC mp_obj_t resource_stream(mp_obj_t package_in, mp_obj_t path_in) {
return MP_OBJ_FROM_PTR(o);
}
- mp_obj_t path_out = mp_obj_new_str(path_buf.buf, path_buf.len, false);
+ mp_obj_t path_out = mp_obj_new_str(path_buf.buf, path_buf.len);
return mp_builtin_open(1, &path_out, (mp_map_t*)&mp_const_empty_map);
}
-MP_DEFINE_CONST_FUN_OBJ_2(resource_stream_obj, resource_stream);
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(resource_stream_obj, resource_stream);
#endif
STATIC const mp_rom_map_elem_t mp_module_io_globals_table[] = {
diff --git a/MicroPython_BUILD/components/micropython/py/modmath.c b/MicroPython_BUILD/components/micropython/py/modmath.c
index c3dec5a..4bf9ba3 100644
--- a/MicroPython_BUILD/components/micropython/py/modmath.c
+++ b/MicroPython_BUILD/components/micropython/py/modmath.c
@@ -171,9 +171,8 @@ MATH_FUN_1(gamma, tgamma)
MATH_FUN_1(lgamma, lgamma)
// hypot(x, y): return sqrt(x*x + y*y)
MATH_FUN_2(hypot, hypot)
-// isfinite(x)
#endif
-//TODO: factorial, fsum
+//TODO: fsum
// Function that takes a variable number of arguments
@@ -236,6 +235,37 @@ STATIC mp_obj_t mp_math_degrees(mp_obj_t x_obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_degrees_obj, mp_math_degrees);
+#include "py/objint.h"
+// factorial(x)
+STATIC mp_obj_t mp_math_factorial(mp_obj_t x_obj) {
+ int n = mp_obj_get_int(x_obj);
+ if ((n < 0) || (n > 50)) {
+ mp_raise_ValueError("range error (0 - 50 allowed)");
+ }
+ if (n < 21) {
+ uint64_t fact = 1;
+ for (int i = 1; i <= n; i++) {
+ fact *= i;
+ }
+
+ return mp_obj_new_int_from_ull(fact);
+ }
+ mp_obj_int_t *fact = mp_obj_int_new_mpz();
+ mp_obj_int_t *zi = mp_obj_int_new_mpz();
+ mp_obj_int_t *z1 = mp_obj_int_new_mpz();
+ mpz_set_from_ll(&fact->mpz, 1, true);
+ mpz_set_from_ll(&zi->mpz, 1, true);
+ mpz_set_from_ll(&z1->mpz, 1, true);
+
+ for (int i = 1; i <= n; i++) {
+ mpz_mul_inpl(&fact->mpz, &fact->mpz, &zi->mpz);
+ mpz_add_inpl(&zi->mpz, &zi->mpz, &z1->mpz);
+ }
+ return MP_OBJ_FROM_PTR(fact);
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_factorial_obj, mp_math_factorial);
+
STATIC const mp_rom_map_elem_t mp_module_math_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_math) },
{ MP_ROM_QSTR(MP_QSTR_e), mp_const_float_e },
@@ -278,6 +308,7 @@ STATIC const mp_rom_map_elem_t mp_module_math_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_trunc), MP_ROM_PTR(&mp_math_trunc_obj) },
{ MP_ROM_QSTR(MP_QSTR_radians), MP_ROM_PTR(&mp_math_radians_obj) },
{ MP_ROM_QSTR(MP_QSTR_degrees), MP_ROM_PTR(&mp_math_degrees_obj) },
+ { MP_ROM_QSTR(MP_QSTR_factorial), MP_ROM_PTR(&mp_math_factorial_obj) },
#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
{ MP_ROM_QSTR(MP_QSTR_erf), MP_ROM_PTR(&mp_math_erf_obj) },
{ MP_ROM_QSTR(MP_QSTR_erfc), MP_ROM_PTR(&mp_math_erfc_obj) },
diff --git a/MicroPython_BUILD/components/micropython/py/modmicropython.c b/MicroPython_BUILD/components/micropython/py/modmicropython.c
index 4ce503f..c677ac8 100644
--- a/MicroPython_BUILD/components/micropython/py/modmicropython.c
+++ b/MicroPython_BUILD/components/micropython/py/modmicropython.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -103,14 +104,21 @@ STATIC mp_obj_t mp_micropython_qstr_info(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_qstr_info_obj, 0, 1, mp_micropython_qstr_info);
-#if MICROPY_STACK_CHECK
+#endif // MICROPY_PY_MICROPYTHON_MEM_INFO
+
+#if MICROPY_PY_MICROPYTHON_STACK_USE
STATIC mp_obj_t mp_micropython_stack_use(void) {
return MP_OBJ_NEW_SMALL_INT(mp_stack_usage());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_stack_use_obj, mp_micropython_stack_use);
#endif
-#endif // MICROPY_PY_MICROPYTHON_MEM_INFO
+#if MICROPY_ENABLE_PYSTACK
+STATIC mp_obj_t mp_micropython_pystack_use(void) {
+ return MP_OBJ_NEW_SMALL_INT(mp_pystack_usage());
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_pystack_use_obj, mp_micropython_pystack_use);
+#endif
#if MICROPY_ENABLE_GC
STATIC mp_obj_t mp_micropython_heap_lock(void) {
@@ -160,13 +168,16 @@ STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = {
#endif
{ MP_ROM_QSTR(MP_QSTR_mem_info), MP_ROM_PTR(&mp_micropython_mem_info_obj) },
{ MP_ROM_QSTR(MP_QSTR_qstr_info), MP_ROM_PTR(&mp_micropython_qstr_info_obj) },
- #if MICROPY_STACK_CHECK
+#endif
+ #if MICROPY_PY_MICROPYTHON_STACK_USE
{ MP_ROM_QSTR(MP_QSTR_stack_use), MP_ROM_PTR(&mp_micropython_stack_use_obj) },
#endif
-#endif
#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && (MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0)
{ MP_ROM_QSTR(MP_QSTR_alloc_emergency_exception_buf), MP_ROM_PTR(&mp_alloc_emergency_exception_buf_obj) },
#endif
+ #if MICROPY_ENABLE_PYSTACK
+ { MP_ROM_QSTR(MP_QSTR_pystack_use), MP_ROM_PTR(&mp_micropython_pystack_use_obj) },
+ #endif
#if MICROPY_ENABLE_GC
{ MP_ROM_QSTR(MP_QSTR_heap_lock), MP_ROM_PTR(&mp_micropython_heap_lock_obj) },
{ MP_ROM_QSTR(MP_QSTR_heap_unlock), MP_ROM_PTR(&mp_micropython_heap_unlock_obj) },
diff --git a/MicroPython_BUILD/components/micropython/py/modsys.c b/MicroPython_BUILD/components/micropython/py/modsys.c
index b45cb04..1ef3ea7 100644
--- a/MicroPython_BUILD/components/micropython/py/modsys.c
+++ b/MicroPython_BUILD/components/micropython/py/modsys.c
@@ -26,6 +26,7 @@
* THE SOFTWARE.
*/
+#include
#include "py/builtin.h"
#include "py/objlist.h"
#include "py/objtuple.h"
@@ -146,6 +147,16 @@ STATIC mp_obj_t mp_sys_getsizeof(mp_obj_t obj) {
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_getsizeof_obj, mp_sys_getsizeof);
+STATIC mp_obj_t mp_sys_mpycore() {
+ mp_obj_t tuple[2];
+ tuple[0] = mp_obj_new_str(MICROPY_CORE_VERSION, strlen(MICROPY_CORE_VERSION));
+ tuple[1] = mp_obj_new_str(MICROPY_CORE_DATE, strlen(MICROPY_CORE_DATE));
+
+ return mp_obj_new_tuple(2, tuple);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_mpycore_obj, mp_sys_mpycore);
+
+//==============================================================
STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys) },
@@ -154,6 +165,7 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_version), MP_ROM_PTR(&version_obj) },
{ MP_ROM_QSTR(MP_QSTR_version_info), MP_ROM_PTR(&mp_sys_version_info_obj) },
{ MP_ROM_QSTR(MP_QSTR_implementation), MP_ROM_PTR(&mp_sys_implementation_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mpycore), MP_ROM_PTR(&mp_sys_mpycore_obj) },
#ifdef MICROPY_PY_SYS_PLATFORM
{ MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_obj) },
#endif
diff --git a/MicroPython_BUILD/components/micropython/py/modthread.c b/MicroPython_BUILD/components/micropython/py/modthread.c
index 3817416..95286c6 100644
--- a/MicroPython_BUILD/components/micropython/py/modthread.c
+++ b/MicroPython_BUILD/components/micropython/py/modthread.c
@@ -97,7 +97,13 @@ STATIC void *thread_entry(void *args_in)
MP_THREAD_GIL_ENTER();
- // signal that we are set up and running
+ #if MICROPY_ENABLE_PYSTACK
+ // TODO threading and pystack is not fully supported, for now just make a small stack
+ mp_obj_t mini_pystack[128];
+ mp_pystack_init(mini_pystack, &mini_pystack[128]);
+ #endif
+
+ // signal that we are set up and running
mp_thread_start();
// TODO set more thread-specific state here:
@@ -377,7 +383,7 @@ STATIC mp_obj_t mod_thread_getmsg()
}
else if (res == THREAD_MSG_TYPE_STRING) {
if (buf != NULL) {
- tuple[2] = mp_obj_new_str((char *)buf, buflen, false);
+ tuple[2] = mp_obj_new_str((char *)buf, buflen);
free(buf);
}
else tuple[2] = mp_const_none;
@@ -396,7 +402,7 @@ STATIC mp_obj_t mod_thread_getname(mp_obj_t in_id) {
if (!res) {
sprintf(name,"unknown");
}
- return mp_obj_new_str((char *)name, strlen(name), false);
+ return mp_obj_new_str((char *)name, strlen(name));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_thread_getname_obj, mod_thread_getname);
@@ -408,7 +414,7 @@ STATIC mp_obj_t mod_thread_getSelfname() {
if (!res) {
sprintf(name,"unknown");
}
- return mp_obj_new_str((char *)name, strlen(name), false);
+ return mp_obj_new_str((char *)name, strlen(name));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_getSelfname_obj, mod_thread_getSelfname);
@@ -474,7 +480,7 @@ STATIC mp_obj_t mod_thread_list(mp_uint_t n_args, const mp_obj_t *args) {
thr = list.threads + (sizeof(threadlistitem_t) * n);
thr_info[0] = mp_obj_new_int(thr->id);
thr_info[1] = mp_obj_new_int(thr->type);
- thr_info[2] = mp_obj_new_str(thr->name, strlen(thr->name), false);
+ thr_info[2] = mp_obj_new_str(thr->name, strlen(thr->name));
if (thr->suspended) thr_info[3] = mp_obj_new_int(1);
else if (thr->waiting) thr_info[3] = mp_obj_new_int(2);
else thr_info[3] = mp_obj_new_int(0);
@@ -487,7 +493,7 @@ STATIC mp_obj_t mod_thread_list(mp_uint_t n_args, const mp_obj_t *args) {
if (TelnetTaskHandle) {
thr_info[0] = mp_obj_new_int((int)TelnetTaskHandle);
thr_info[1] = mp_obj_new_int(THREAD_TYPE_SERVICE);
- thr_info[2] = mp_obj_new_str("Telnet", 6, false);
+ thr_info[2] = mp_obj_new_str("Telnet", 6);
thr_info[3] = mp_obj_new_int(0);
thr_info[4] = mp_obj_new_int(TELNET_STACK_LEN);
thr_info[5] = mp_obj_new_int(TELNET_STACK_LEN - uxTaskGetStackHighWaterMark(TelnetTaskHandle));
@@ -499,7 +505,7 @@ STATIC mp_obj_t mod_thread_list(mp_uint_t n_args, const mp_obj_t *args) {
if (FtpTaskHandle) {
thr_info[0] = mp_obj_new_int((int)FtpTaskHandle);
thr_info[1] = mp_obj_new_int(THREAD_TYPE_SERVICE);
- thr_info[2] = mp_obj_new_str("Ftp", 3, false);
+ thr_info[2] = mp_obj_new_str("Ftp", 3);
thr_info[3] = mp_obj_new_int(0);
thr_info[4] = mp_obj_new_int(FTP_STACK_LEN);
thr_info[5] = mp_obj_new_int(FTP_STACK_LEN - uxTaskGetStackHighWaterMark(FtpTaskHandle));
diff --git a/MicroPython_BUILD/components/micropython/py/mpconfig.h b/MicroPython_BUILD/components/micropython/py/mpconfig.h
index 4727e6e..edb6fa6 100644
--- a/MicroPython_BUILD/components/micropython/py/mpconfig.h
+++ b/MicroPython_BUILD/components/micropython/py/mpconfig.h
@@ -79,7 +79,7 @@
// - seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff 64-bit fp, e != 0x7ff
// - s1111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000 +/- inf
// - 01111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000 normalised nan
-// - 01111111 11111101 00000000 00000000 iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int
+// - 01111111 11111101 iiiiiiii iiiiiiii iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int
// - 01111111 11111110 00000000 00000000 qqqqqqqq qqqqqqqq qqqqqqqq qqqqqqq1 str
// - 01111111 11111100 00000000 00000000 pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment)
// Stored as O = R + 0x8004000000000000, retrieved as R = O - 0x8004000000000000.
@@ -347,7 +347,7 @@
#endif
// Whether to enable optimisation of: a, b, c = d, e, f
-// Cost 156 bytes (Thumb2)
+// Requires MICROPY_COMP_DOUBLE_TUPLE_ASSIGN and costs 68 bytes (Thumb2)
#ifndef MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0)
#endif
@@ -405,6 +405,13 @@
/*****************************************************************************/
/* Python internal features */
+// Whether to enable import of external modules
+// When disabled, only importing of built-in modules is supported
+// When enabled, a port must implement mp_import_stat (among other things)
+#ifndef MICROPY_ENABLE_EXTERNAL_IMPORT
+#define MICROPY_ENABLE_EXTERNAL_IMPORT (1)
+#endif
+
// Whether to use the POSIX reader for importing files
#ifndef MICROPY_READER_POSIX
#define MICROPY_READER_POSIX (0)
@@ -441,6 +448,17 @@
#define MICROPY_ENABLE_FINALISER (0)
#endif
+// Whether to enable a separate allocator for the Python stack.
+// If enabled then the code must call mp_pystack_init before mp_init.
+#ifndef MICROPY_ENABLE_PYSTACK
+#define MICROPY_ENABLE_PYSTACK (0)
+#endif
+
+// Number of bytes that memory returned by mp_pystack_alloc will be aligned by.
+#ifndef MICROPY_PYSTACK_ALIGN
+#define MICROPY_PYSTACK_ALIGN (8)
+#endif
+
// Whether to check C stack usage. C stack used for calling Python functions,
// etc. Not checking means segfault on overflow.
#ifndef MICROPY_STACK_CHECK
@@ -666,6 +684,13 @@ typedef double mp_float_t;
/*****************************************************************************/
/* Fine control over Python builtins, classes, modules, etc */
+// Whether to support multiple inheritance of Python classes. Multiple
+// inheritance makes some C functions inherently recursive, and adds a bit of
+// code overhead.
+#ifndef MICROPY_MULTIPLE_INHERITANCE
+#define MICROPY_MULTIPLE_INHERITANCE (1)
+#endif
+
// Whether to implement attributes on functions
#ifndef MICROPY_PY_FUNCTION_ATTRS
#define MICROPY_PY_FUNCTION_ATTRS (0)
@@ -688,6 +713,15 @@ typedef double mp_float_t;
#define MICROPY_PY_ASYNC_AWAIT (1)
#endif
+// Non-standard .pend_throw() method for generators, allowing for
+// Future-like behavior with respect to exception handling: an
+// exception set with .pend_throw() will activate on the next call
+// to generator's .send() or .__next__(). (This is useful to implement
+// async schedulers.)
+#ifndef MICROPY_PY_GENERATOR_PEND_THROW
+#define MICROPY_PY_GENERATOR_PEND_THROW (1)
+#endif
+
// Issue a warning when comparing str and bytes objects
#ifndef MICROPY_PY_STR_BYTES_CMP_WARN
#define MICROPY_PY_STR_BYTES_CMP_WARN (0)
@@ -760,6 +794,14 @@ typedef double mp_float_t;
#define MICROPY_PY_BUILTINS_RANGE_ATTRS (1)
#endif
+// Whether to support binary ops [only (in)equality is defined] between range
+// objects. With this option disabled all range objects that are not exactly
+// 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)
+#endif
+
// Whether to support timeout exceptions (like socket.timeout)
#ifndef MICROPY_PY_BUILTINS_TIMEOUTERROR
#define MICROPY_PY_BUILTINS_TIMEOUTERROR (0)
@@ -865,6 +907,11 @@ typedef double mp_float_t;
#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)
#endif
+// Whether to provide "micropython.stack_use" function
+#ifndef MICROPY_PY_MICROPYTHON_STACK_USE
+#define MICROPY_PY_MICROPYTHON_STACK_USE (MICROPY_PY_MICROPYTHON_MEM_INFO)
+#endif
+
// Whether to provide "array" module. Note that large chunk of the
// underlying code is shared with "bytearray" builtin type, so to
// get real savings, it should be disabled too.
@@ -889,11 +936,21 @@ typedef double mp_float_t;
#define MICROPY_PY_COLLECTIONS (1)
#endif
+// Whether to provide "ucollections.deque" type
+#ifndef MICROPY_PY_COLLECTIONS_DEQUE
+#define MICROPY_PY_COLLECTIONS_DEQUE (0)
+#endif
+
// Whether to provide "collections.OrderedDict" type
#ifndef MICROPY_PY_COLLECTIONS_ORDEREDDICT
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0)
#endif
+// Whether to provide the _asdict function for namedtuple
+#ifndef MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT
+#define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (0)
+#endif
+
// Whether to provide "math" module
#ifndef MICROPY_PY_MATH
#define MICROPY_PY_MATH (1)
@@ -926,7 +983,11 @@ typedef double mp_float_t;
// Whether to provide "uio.resource_stream()" function with
// the semantics of CPython's pkg_resources.resource_stream()
-// (allows to access resources in frozen packages).
+// (allows to access binary resources in frozen source packages).
+// Note that the same functionality can be achieved in "pure
+// Python" by prepocessing binary resources into Python source
+// and bytecode-freezing it (with a simple helper module available
+// e.g. in micropython-lib).
#ifndef MICROPY_PY_IO_RESOURCE_STREAM
#define MICROPY_PY_IO_RESOURCE_STREAM (0)
#endif
@@ -1294,4 +1355,24 @@ typedef double mp_float_t;
#define MP_UNLIKELY(x) __builtin_expect((x), 0)
#endif
+#ifndef MP_HTOBE16
+#if MP_ENDIANNESS_LITTLE
+# define MP_HTOBE16(x) ((uint16_t)( (((x) & 0xff) << 8) | (((x) >> 8) & 0xff) ))
+# define MP_BE16TOH(x) MP_HTOBE16(x)
+#else
+# define MP_HTOBE16(x) (x)
+# define MP_BE16TOH(x) (x)
+#endif
+#endif
+
+#ifndef MP_HTOBE32
+#if MP_ENDIANNESS_LITTLE
+# define MP_HTOBE32(x) ((uint32_t)( (((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) >> 8) & 0xff00) | (((x) >> 24) & 0xff) ))
+# define MP_BE32TOH(x) MP_HTOBE32(x)
+#else
+# define MP_HTOBE32(x) (x)
+# define MP_BE32TOH(x) (x)
+#endif
+#endif
+
#endif // MICROPY_INCLUDED_PY_MPCONFIG_H
diff --git a/MicroPython_BUILD/components/micropython/py/mpprint.c b/MicroPython_BUILD/components/micropython/py/mpprint.c
index a569ef7..c2e6530 100644
--- a/MicroPython_BUILD/components/micropython/py/mpprint.c
+++ b/MicroPython_BUILD/components/micropython/py/mpprint.c
@@ -446,11 +446,16 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
}
}
- // parse long specifiers (current not used)
- //bool long_arg = false;
+ // parse long specifiers (only for LP64 model where they make a difference)
+ #ifndef __LP64__
+ const
+ #endif
+ bool long_arg = false;
if (*fmt == 'l') {
++fmt;
- //long_arg = true;
+ #ifdef __LP64__
+ long_arg = true;
+ #endif
}
if (*fmt == '\0') {
@@ -505,14 +510,21 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
chrs += mp_print_int(print, va_arg(args, int), 1, 10, 'a', flags, fill, width);
break;
case 'x':
- chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 16, 'a', flags, fill, width);
- break;
- case 'X':
- chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 16, 'A', flags, fill, width);
+ case 'X': {
+ char fmt_c = *fmt - 'X' + 'A';
+ mp_uint_t val;
+ if (long_arg) {
+ val = va_arg(args, unsigned long int);
+ } else {
+ val = va_arg(args, unsigned int);
+ }
+ chrs += mp_print_int(print, val, 0, 16, fmt_c, flags, fill, width);
break;
+ }
case 'p':
case 'P': // don't bother to handle upcase for 'P'
- chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 16, 'a', flags, fill, width);
+ // Use unsigned long int to work on both ILP32 and LP64 systems
+ chrs += mp_print_int(print, va_arg(args, unsigned long int), 0, 16, 'a', flags, fill, width);
break;
#if MICROPY_PY_BUILTINS_FLOAT
case 'e':
diff --git a/MicroPython_BUILD/components/micropython/py/mpstate.h b/MicroPython_BUILD/components/micropython/py/mpstate.h
index 826f453..4df202e 100644
--- a/MicroPython_BUILD/components/micropython/py/mpstate.h
+++ b/MicroPython_BUILD/components/micropython/py/mpstate.h
@@ -169,6 +169,10 @@ typedef struct _mp_state_vm_t {
// 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];
mp_obj_t dupterm_arr_obj;
@@ -218,7 +222,6 @@ typedef struct _mp_state_thread_t {
mp_obj_dict_t *dict_locals;
mp_obj_dict_t *dict_globals;
- // Note: nlr asm code has the offset of this hard-coded
nlr_buf_t *nlr_top; // ROOT POINTER
// Stack top at the start of program
@@ -227,6 +230,12 @@ typedef struct _mp_state_thread_t {
#if MICROPY_STACK_CHECK
size_t stack_limit;
#endif
+
+ #if MICROPY_ENABLE_PYSTACK
+ uint8_t *pystack_start;
+ uint8_t *pystack_end;
+ uint8_t *pystack_cur;
+ #endif
} mp_state_thread_t;
// This structure combines the above 3 structures.
diff --git a/MicroPython_BUILD/components/micropython/py/mpthread.h b/MicroPython_BUILD/components/micropython/py/mpthread.h
index 8f84e4a..aaeabf4 100644
--- a/MicroPython_BUILD/components/micropython/py/mpthread.h
+++ b/MicroPython_BUILD/components/micropython/py/mpthread.h
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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/MicroPython_BUILD/components/micropython/py/mpz.c b/MicroPython_BUILD/components/micropython/py/mpz.c
index 45ffee4..24c8f27 100644
--- a/MicroPython_BUILD/components/micropython/py/mpz.c
+++ b/MicroPython_BUILD/components/micropython/py/mpz.c
@@ -538,83 +538,57 @@ STATIC void mpn_div(mpz_dig_t *num_dig, size_t *num_len, const mpz_dig_t *den_di
// not to overflow the borrow variable. And the shifting of
// borrow needs some special logic (it's a shift right with
// round up).
-
- if (DIG_SIZE < 8 * sizeof(mpz_dbl_dig_t) / 2) {
- const mpz_dig_t *d = den_dig;
- mpz_dbl_dig_t d_norm = 0;
- mpz_dbl_dig_signed_t borrow = 0;
-
- for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
- d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
- borrow += (mpz_dbl_dig_t)*n - (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK); // will overflow if DIG_SIZE >= 8*sizeof(mpz_dbl_dig_t)/2
- *n = borrow & DIG_MASK;
- borrow >>= DIG_SIZE;
- }
- borrow += *num_dig; // will overflow if DIG_SIZE >= 8*sizeof(mpz_dbl_dig_t)/2
- *num_dig = borrow & DIG_MASK;
- borrow >>= DIG_SIZE;
-
- // adjust quotient if it is too big
- for (; borrow != 0; --quo) {
- d = den_dig;
- d_norm = 0;
- mpz_dbl_dig_t carry = 0;
- for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
- d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
- carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK);
- *n = carry & DIG_MASK;
- carry >>= DIG_SIZE;
- }
- carry += *num_dig;
- *num_dig = carry & DIG_MASK;
- carry >>= DIG_SIZE;
-
- borrow += carry;
- }
- } else { // DIG_SIZE == 8 * sizeof(mpz_dbl_dig_t) / 2
- const mpz_dig_t *d = den_dig;
- mpz_dbl_dig_t d_norm = 0;
- mpz_dbl_dig_t borrow = 0;
-
- for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
- d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
- mpz_dbl_dig_t x = (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK);
- if (x >= *n || *n - x <= borrow) {
- borrow += (mpz_dbl_dig_t)x - (mpz_dbl_dig_t)*n;
- *n = (-borrow) & DIG_MASK;
- borrow = (borrow >> DIG_SIZE) + ((borrow & DIG_MASK) == 0 ? 0 : 1); // shift-right with round-up
- } else {
- *n = ((mpz_dbl_dig_t)*n - (mpz_dbl_dig_t)x - (mpz_dbl_dig_t)borrow) & DIG_MASK;
- borrow = 0;
- }
- }
- if (borrow >= *num_dig) {
- borrow -= (mpz_dbl_dig_t)*num_dig;
- *num_dig = (-borrow) & DIG_MASK;
+ //
+ const mpz_dig_t *d = den_dig;
+ mpz_dbl_dig_t d_norm = 0;
+ mpz_dbl_dig_t borrow = 0;
+ for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
+ d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
+ mpz_dbl_dig_t x = (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK);
+ #if DIG_SIZE < MPZ_DBL_DIG_SIZE / 2
+ borrow += (mpz_dbl_dig_t)*n - x; // will overflow if DIG_SIZE >= MPZ_DBL_DIG_SIZE/2
+ *n = borrow & DIG_MASK;
+ borrow = (mpz_dbl_dig_signed_t)borrow >> DIG_SIZE;
+ #else // DIG_SIZE == MPZ_DBL_DIG_SIZE / 2
+ if (x >= *n || *n - x <= borrow) {
+ borrow += x - (mpz_dbl_dig_t)*n;
+ *n = (-borrow) & DIG_MASK;
borrow = (borrow >> DIG_SIZE) + ((borrow & DIG_MASK) == 0 ? 0 : 1); // shift-right with round-up
} else {
- *num_dig = (*num_dig - borrow) & DIG_MASK;
+ *n = ((mpz_dbl_dig_t)*n - x - borrow) & DIG_MASK;
borrow = 0;
}
+ #endif
+ }
- // adjust quotient if it is too big
- for (; borrow != 0; --quo) {
- d = den_dig;
- d_norm = 0;
- mpz_dbl_dig_t carry = 0;
- for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
- d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
- carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK);
- *n = carry & DIG_MASK;
- carry >>= DIG_SIZE;
- }
- carry += (mpz_dbl_dig_t)*num_dig;
- *num_dig = carry & DIG_MASK;
+ #if DIG_SIZE < MPZ_DBL_DIG_SIZE / 2
+ // Borrow was negative in the above for-loop, make it positive for next if-block.
+ borrow = -borrow;
+ #endif
+
+ // At this point we have either:
+ //
+ // 1. quo was the correct value and the most-sig-digit of num is exactly
+ // cancelled by borrow (borrow == *num_dig). In this case there is
+ // nothing more to do.
+ //
+ // 2. quo was too large, we subtracted too many den from num, and the
+ // most-sig-digit of num is 1 less than borrow (borrow == *num_dig + 1).
+ // In this case we must reduce quo and add back den to num until the
+ // carry from this operation cancels out the borrow.
+ //
+ borrow -= *num_dig;
+ for (; borrow != 0; --quo) {
+ d = den_dig;
+ d_norm = 0;
+ mpz_dbl_dig_t carry = 0;
+ for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
+ d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
+ carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK);
+ *n = carry & DIG_MASK;
carry >>= DIG_SIZE;
-
- //assert(borrow >= carry); // enable this to check the logic
- borrow -= carry;
}
+ borrow -= carry;
}
// store this digit of the quotient
@@ -732,17 +706,14 @@ STATIC void mpz_need_dig(mpz_t *z, size_t need) {
}
STATIC mpz_t *mpz_clone(const mpz_t *src) {
+ assert(src->alloc != 0);
mpz_t *z = m_new_obj(mpz_t);
z->neg = src->neg;
z->fixed_dig = 0;
z->alloc = src->alloc;
z->len = src->len;
- if (src->dig == NULL) {
- z->dig = NULL;
- } else {
- z->dig = m_new(mpz_dig_t, z->alloc);
- memcpy(z->dig, src->dig, src->alloc * sizeof(mpz_dig_t));
- }
+ z->dig = m_new(mpz_dig_t, z->alloc);
+ memcpy(z->dig, src->dig, src->alloc * sizeof(mpz_dig_t));
return z;
}
@@ -1010,6 +981,7 @@ these functions are unused
/* returns abs(z)
*/
mpz_t *mpz_abs(const mpz_t *z) {
+ // TODO: handle case of z->alloc=0
mpz_t *z2 = mpz_clone(z);
z2->neg = 0;
return z2;
@@ -1018,6 +990,7 @@ mpz_t *mpz_abs(const mpz_t *z) {
/* returns -z
*/
mpz_t *mpz_neg(const mpz_t *z) {
+ // TODO: handle case of z->alloc=0
mpz_t *z2 = mpz_clone(z);
z2->neg = 1 - z2->neg;
return z2;
@@ -1391,13 +1364,14 @@ void mpz_pow_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {
can have dest, lhs, rhs the same; mod can't be the same as dest
*/
void mpz_pow3_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs, const mpz_t *mod) {
- if (lhs->len == 0 || rhs->neg != 0) {
+ if (lhs->len == 0 || rhs->neg != 0 || (mod->len == 1 && mod->dig[0] == 1)) {
mpz_set_from_int(dest, 0);
return;
}
+ mpz_set_from_int(dest, 1);
+
if (rhs->len == 0) {
- mpz_set_from_int(dest, 1);
return;
}
@@ -1405,8 +1379,6 @@ void mpz_pow3_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs, const mpz_t
mpz_t *n = mpz_clone(rhs);
mpz_t quo; mpz_init_zero(&quo);
- mpz_set_from_int(dest, 1);
-
while (n->len > 0) {
if ((n->dig[0] & 1) != 0) {
mpz_mul_inpl(dest, dest, x);
@@ -1436,6 +1408,7 @@ these functions are unused
*/
mpz_t *mpz_gcd(const mpz_t *z1, const mpz_t *z2) {
if (z1->len == 0) {
+ // TODO: handle case of z2->alloc=0
mpz_t *a = mpz_clone(z2);
a->neg = 0;
return a;
@@ -1716,16 +1689,12 @@ char *mpz_as_str(const mpz_t *i, unsigned int base) {
}
#endif
-// assumes enough space as calculated by mp_int_format_size
+// assumes enough space in str as calculated by mp_int_format_size
+// base must be between 2 and 32 inclusive
// returns length of string, not including null byte
size_t mpz_as_str_inpl(const mpz_t *i, unsigned int base, const char *prefix, char base_char, char comma, char *str) {
- if (str == NULL) {
- return 0;
- }
- if (base < 2 || base > 32) {
- str[0] = 0;
- return 0;
- }
+ assert(str != NULL);
+ assert(2 <= base && base <= 32);
size_t ilen = i->len;
diff --git a/MicroPython_BUILD/components/micropython/py/mpz.h b/MicroPython_BUILD/components/micropython/py/mpz.h
index 7053829..7e73741 100644
--- a/MicroPython_BUILD/components/micropython/py/mpz.h
+++ b/MicroPython_BUILD/components/micropython/py/mpz.h
@@ -56,18 +56,22 @@
#endif
#if MPZ_DIG_SIZE > 16
+#define MPZ_DBL_DIG_SIZE (64)
typedef uint32_t mpz_dig_t;
typedef uint64_t mpz_dbl_dig_t;
typedef int64_t mpz_dbl_dig_signed_t;
#elif MPZ_DIG_SIZE > 8
+#define MPZ_DBL_DIG_SIZE (32)
typedef uint16_t mpz_dig_t;
typedef uint32_t mpz_dbl_dig_t;
typedef int32_t mpz_dbl_dig_signed_t;
#elif MPZ_DIG_SIZE > 4
+#define MPZ_DBL_DIG_SIZE (16)
typedef uint8_t mpz_dig_t;
typedef uint16_t mpz_dbl_dig_t;
typedef int16_t mpz_dbl_dig_signed_t;
#else
+#define MPZ_DBL_DIG_SIZE (8)
typedef uint8_t mpz_dig_t;
typedef uint8_t mpz_dbl_dig_t;
typedef int8_t mpz_dbl_dig_signed_t;
diff --git a/MicroPython_BUILD/components/micropython/py/nlr.c b/MicroPython_BUILD/components/micropython/py/nlr.c
new file mode 100644
index 0000000..03d0157
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/py/nlr.c
@@ -0,0 +1,51 @@
+/*
+ * 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 !MICROPY_NLR_SETJMP
+// When not using setjmp, nlr_push_tail is called from inline asm so needs special care
+#if MICROPY_NLR_X86 && MICROPY_NLR_OS_WINDOWS
+// On these 32-bit platforms make sure nlr_push_tail doesn't have a leading underscore
+unsigned int nlr_push_tail(nlr_buf_t *nlr) asm("nlr_push_tail");
+#else
+// LTO can't see inside inline asm functions so explicitly mark nlr_push_tail as used
+__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);
+#endif
+#endif
+
+unsigned int nlr_push_tail(nlr_buf_t *nlr) {
+ nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
+ nlr->prev = *top;
+ MP_NLR_SAVE_PYSTACK(nlr);
+ *top = nlr;
+ return 0; // normal return
+}
+
+void nlr_pop(void) {
+ nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
+ *top = (*top)->prev;
+}
diff --git a/MicroPython_BUILD/components/micropython/py/nlr.h b/MicroPython_BUILD/components/micropython/py/nlr.h
index 63fe392..90595a1 100644
--- a/MicroPython_BUILD/components/micropython/py/nlr.h
+++ b/MicroPython_BUILD/components/micropython/py/nlr.h
@@ -30,29 +30,34 @@
// exception handling, basically a stack of setjmp/longjmp buffers
#include
-#include
#include
#include "py/mpconfig.h"
-typedef struct _nlr_buf_t nlr_buf_t;
-struct _nlr_buf_t {
- // the entries here must all be machine word size
- nlr_buf_t *prev;
- void *ret_val; // always a concrete object (an exception instance)
-#if !defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP
+// If MICROPY_NLR_SETJMP is not enabled then auto-detect the machine arch
+#if !MICROPY_NLR_SETJMP
+// A lot of nlr-related things need different treatment on Windows
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define MICROPY_NLR_OS_WINDOWS 1
+#else
+#define MICROPY_NLR_OS_WINDOWS 0
+#endif
#if defined(__i386__)
- void *regs[6];
+ #define MICROPY_NLR_X86 (1)
+ #define MICROPY_NLR_NUM_REGS (6)
#elif defined(__x86_64__)
- #if defined(__CYGWIN__)
- void *regs[12];
- #else
- void *regs[8];
- #endif
+ #define MICROPY_NLR_X64 (1)
+ #if MICROPY_NLR_OS_WINDOWS
+ #define MICROPY_NLR_NUM_REGS (10)
+ #else
+ #define MICROPY_NLR_NUM_REGS (8)
+ #endif
#elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__)
- void *regs[10];
+ #define MICROPY_NLR_THUMB (1)
+ #define MICROPY_NLR_NUM_REGS (10)
#elif defined(__xtensa__)
- void *regs[10];
+ #define MICROPY_NLR_XTENSA (1)
+ #define MICROPY_NLR_NUM_REGS (10)
#else
#define MICROPY_NLR_SETJMP (1)
//#warning "No native NLR support for this arch, using setjmp implementation"
@@ -60,24 +65,58 @@ struct _nlr_buf_t {
#endif
#if MICROPY_NLR_SETJMP
- jmp_buf jmpbuf;
+#include
#endif
+
+typedef struct _nlr_buf_t nlr_buf_t;
+struct _nlr_buf_t {
+ // the entries here must all be machine word size
+ nlr_buf_t *prev;
+ void *ret_val; // always a concrete object (an exception instance)
+
+ #if MICROPY_NLR_SETJMP
+ jmp_buf jmpbuf;
+ #else
+ void *regs[MICROPY_NLR_NUM_REGS];
+ #endif
+
+ #if MICROPY_ENABLE_PYSTACK
+ void *pystack;
+ #endif
};
-#if MICROPY_NLR_SETJMP
-#include "py/mpstate.h"
+// Helper macros to save/restore the pystack state
+#if MICROPY_ENABLE_PYSTACK
+#define MP_NLR_SAVE_PYSTACK(nlr_buf) (nlr_buf)->pystack = MP_STATE_THREAD(pystack_cur)
+#define MP_NLR_RESTORE_PYSTACK(nlr_buf) MP_STATE_THREAD(pystack_cur) = (nlr_buf)->pystack
+#else
+#define MP_NLR_SAVE_PYSTACK(nlr_buf) (void)nlr_buf
+#define MP_NLR_RESTORE_PYSTACK(nlr_buf) (void)nlr_buf
+#endif
-NORETURN void nlr_setjmp_jump(void *val);
+// Helper macro to use at the start of a specific nlr_jump implementation
+#define MP_NLR_JUMP_HEAD(val, top) \
+ nlr_buf_t **_top_ptr = &MP_STATE_THREAD(nlr_top); \
+ nlr_buf_t *top = *_top_ptr; \
+ if (top == NULL) { \
+ nlr_jump_fail(val); \
+ } \
+ top->ret_val = val; \
+ MP_NLR_RESTORE_PYSTACK(top); \
+ *_top_ptr = top->prev; \
+
+#if MICROPY_NLR_SETJMP
// nlr_push() must be defined as a macro, because "The stack context will be
// invalidated if the function which called setjmp() returns."
-#define nlr_push(buf) ((buf)->prev = MP_STATE_THREAD(nlr_top), MP_STATE_THREAD(nlr_top) = (buf), setjmp((buf)->jmpbuf))
-#define nlr_pop() { MP_STATE_THREAD(nlr_top) = MP_STATE_THREAD(nlr_top)->prev; }
-#define nlr_jump(val) nlr_setjmp_jump(val)
+// For this case it is safe to call nlr_push_tail() first.
+#define nlr_push(buf) (nlr_push_tail(buf), setjmp((buf)->jmpbuf))
#else
unsigned int nlr_push(nlr_buf_t *);
+#endif
+
+unsigned int nlr_push_tail(nlr_buf_t *top);
void nlr_pop(void);
NORETURN void nlr_jump(void *val);
-#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
@@ -106,7 +145,6 @@ NORETURN void nlr_jump_fail(void *val);
/*
#define nlr_push(val) \
printf("nlr_push: before: nlr_top=%p, val=%p\n", MP_STATE_THREAD(nlr_top), val),assert(MP_STATE_THREAD(nlr_top) != val),nlr_push(val)
-#endif
*/
#endif
diff --git a/MicroPython_BUILD/components/micropython/py/nlrsetjmp.c b/MicroPython_BUILD/components/micropython/py/nlrsetjmp.c
index 1fb4594..960dd86 100644
--- a/MicroPython_BUILD/components/micropython/py/nlrsetjmp.c
+++ b/MicroPython_BUILD/components/micropython/py/nlrsetjmp.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * 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
@@ -24,17 +24,18 @@
* THE SOFTWARE.
*/
-#include "py/nlr.h"
+#include "py/mpstate.h"
#if MICROPY_NLR_SETJMP
-void nlr_setjmp_jump(void *val) {
+void nlr_jump(void *val) {
nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
nlr_buf_t *top = *top_ptr;
if (top == NULL) {
nlr_jump_fail(val);
}
top->ret_val = val;
+ MP_NLR_RESTORE_PYSTACK(top);
*top_ptr = top->prev;
longjmp(top->jmpbuf, 1);
}
diff --git a/MicroPython_BUILD/components/micropython/py/nlrthumb.c b/MicroPython_BUILD/components/micropython/py/nlrthumb.c
index 6e7d717..7dbeac1 100644
--- a/MicroPython_BUILD/components/micropython/py/nlrthumb.c
+++ b/MicroPython_BUILD/components/micropython/py/nlrthumb.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013-2016 Damien P. George
+ * 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
@@ -26,7 +26,7 @@
#include "py/mpstate.h"
-#if (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__))
+#if MICROPY_NLR_THUMB
#undef nlr_push
@@ -76,30 +76,14 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) {
#endif
);
- return 0; // needed to silence compiler warning
+ #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
+ // Older versions of gcc give an error when naked functions don't return a value
+ return 0;
+ #endif
}
-__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- nlr->prev = *top;
- *top = nlr;
- return 0; // normal return
-}
-
-void nlr_pop(void) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- *top = (*top)->prev;
-}
-
-NORETURN __attribute__((naked)) void nlr_jump(void *val) {
- nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
- nlr_buf_t *top = *top_ptr;
- if (top == NULL) {
- nlr_jump_fail(val);
- }
-
- top->ret_val = val;
- *top_ptr = top->prev;
+NORETURN void nlr_jump(void *val) {
+ MP_NLR_JUMP_HEAD(val, top)
__asm volatile (
"mov r0, %0 \n" // r0 points to nlr_buf
@@ -136,7 +120,11 @@ NORETURN __attribute__((naked)) void nlr_jump(void *val) {
: // clobbered registers
);
+ #if defined(__GNUC__)
+ __builtin_unreachable();
+ #else
for (;;); // needed to silence compiler warning
+ #endif
}
-#endif // (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__))
+#endif // MICROPY_NLR_THUMB
diff --git a/MicroPython_BUILD/components/micropython/py/nlrx64.c b/MicroPython_BUILD/components/micropython/py/nlrx64.c
index 847d103..a3a1cf3 100644
--- a/MicroPython_BUILD/components/micropython/py/nlrx64.c
+++ b/MicroPython_BUILD/components/micropython/py/nlrx64.c
@@ -26,25 +26,19 @@
#include "py/mpstate.h"
-#if !MICROPY_NLR_SETJMP && defined(__x86_64__)
+#if MICROPY_NLR_X64
#undef nlr_push
// x86-64 callee-save registers are:
// rbx, rbp, rsp, r12, r13, r14, r15
-#if defined(_WIN32) || defined(__CYGWIN__)
-#define NLR_OS_WINDOWS 1
-#else
-#define NLR_OS_WINDOWS 0
-#endif
-
__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);
unsigned int nlr_push(nlr_buf_t *nlr) {
(void)nlr;
- #if NLR_OS_WINDOWS
+ #if MICROPY_NLR_OS_WINDOWS
__asm volatile (
"movq (%rsp), %rax \n" // load return %rip
@@ -88,31 +82,12 @@ unsigned int nlr_push(nlr_buf_t *nlr) {
return 0; // needed to silence compiler warning
}
-__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- nlr->prev = *top;
- *top = nlr;
- return 0; // normal return
-}
-
-void nlr_pop(void) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- *top = (*top)->prev;
-}
-
NORETURN void nlr_jump(void *val) {
- nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
- nlr_buf_t *top = *top_ptr;
- if (top == NULL) {
- nlr_jump_fail(val);
- }
-
- top->ret_val = val;
- *top_ptr = top->prev;
+ MP_NLR_JUMP_HEAD(val, top)
__asm volatile (
"movq %0, %%rcx \n" // %rcx points to nlr_buf
- #if NLR_OS_WINDOWS
+ #if MICROPY_NLR_OS_WINDOWS
"movq 88(%%rcx), %%rsi \n" // load saved %rsi
"movq 80(%%rcx), %%rdi \n" // load saved %rdr
#endif
@@ -136,4 +111,4 @@ NORETURN void nlr_jump(void *val) {
for (;;); // needed to silence compiler warning
}
-#endif // !MICROPY_NLR_SETJMP && defined(__x86_64__)
+#endif // MICROPY_NLR_X64
diff --git a/MicroPython_BUILD/components/micropython/py/nlrx86.c b/MicroPython_BUILD/components/micropython/py/nlrx86.c
index 094dea3..23882cc 100644
--- a/MicroPython_BUILD/components/micropython/py/nlrx86.c
+++ b/MicroPython_BUILD/components/micropython/py/nlrx86.c
@@ -26,20 +26,14 @@
#include "py/mpstate.h"
-#if !MICROPY_NLR_SETJMP && defined(__i386__)
+#if MICROPY_NLR_X86
#undef nlr_push
// For reference, x86 callee save regs are:
// ebx, esi, edi, ebp, esp, eip
-#if defined(_WIN32) || defined(__CYGWIN__)
-#define NLR_OS_WINDOWS 1
-#else
-#define NLR_OS_WINDOWS 0
-#endif
-
-#if NLR_OS_WINDOWS
+#if MICROPY_NLR_OS_WINDOWS
unsigned int nlr_push_tail(nlr_buf_t *nlr) asm("nlr_push_tail");
#else
__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);
@@ -70,27 +64,8 @@ unsigned int nlr_push(nlr_buf_t *nlr) {
return 0; // needed to silence compiler warning
}
-__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- nlr->prev = *top;
- *top = nlr;
- return 0; // normal return
-}
-
-void nlr_pop(void) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- *top = (*top)->prev;
-}
-
NORETURN void nlr_jump(void *val) {
- nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
- nlr_buf_t *top = *top_ptr;
- if (top == NULL) {
- nlr_jump_fail(val);
- }
-
- top->ret_val = val;
- *top_ptr = top->prev;
+ MP_NLR_JUMP_HEAD(val, top)
__asm volatile (
"mov %0, %%edx \n" // %edx points to nlr_buf
@@ -112,4 +87,4 @@ NORETURN void nlr_jump(void *val) {
for (;;); // needed to silence compiler warning
}
-#endif // !MICROPY_NLR_SETJMP && defined(__i386__)
+#endif // MICROPY_NLR_X86
diff --git a/MicroPython_BUILD/components/micropython/py/nlrxtensa.c b/MicroPython_BUILD/components/micropython/py/nlrxtensa.c
index 4520e7e..cd3dee3 100644
--- a/MicroPython_BUILD/components/micropython/py/nlrxtensa.c
+++ b/MicroPython_BUILD/components/micropython/py/nlrxtensa.c
@@ -26,7 +26,7 @@
#include "py/mpstate.h"
-#if !MICROPY_NLR_SETJMP && defined(__xtensa__)
+#if MICROPY_NLR_XTENSA
#undef nlr_push
@@ -55,27 +55,8 @@ unsigned int nlr_push(nlr_buf_t *nlr) {
return 0; // needed to silence compiler warning
}
-__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- nlr->prev = *top;
- *top = nlr;
- return 0; // normal return
-}
-
-void nlr_pop(void) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- *top = (*top)->prev;
-}
-
NORETURN void nlr_jump(void *val) {
- nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
- nlr_buf_t *top = *top_ptr;
- if (top == NULL) {
- nlr_jump_fail(val);
- }
-
- top->ret_val = val;
- *top_ptr = top->prev;
+ MP_NLR_JUMP_HEAD(val, top)
__asm volatile (
"mov.n a2, %0 \n" // a2 points to nlr_buf
@@ -99,4 +80,4 @@ NORETURN void nlr_jump(void *val) {
for (;;); // needed to silence compiler warning
}
-#endif // !MICROPY_NLR_SETJMP && defined(__xtensa__)
+#endif // MICROPY_NLR_XTENSA
diff --git a/MicroPython_BUILD/components/micropython/py/obj.h b/MicroPython_BUILD/components/micropython/py/obj.h
index dd00343..39f9fd5 100644
--- a/MicroPython_BUILD/components/micropython/py/obj.h
+++ b/MicroPython_BUILD/components/micropython/py/obj.h
@@ -171,8 +171,8 @@ static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)
static inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o)
{ return ((((mp_int_t)(o)) & 0xffff000000000000) == 0x0001000000000000); }
-#define MP_OBJ_SMALL_INT_VALUE(o) (((intptr_t)(o)) >> 1)
-#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)(((uintptr_t)(small_int)) << 1) | 0x0001000000000001)
+#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 inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o)
{ return ((((mp_int_t)(o)) & 0xffff000000000000) == 0x0002000000000000); }
@@ -251,6 +251,8 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t;
// The macros below are derived from the ones above and are used to
// 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 == (t))) // this does not work for checking int, str or fun; use below macros for that
#define MP_OBJ_IS_INT(o) (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int))
@@ -259,17 +261,6 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t;
#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))
#define MP_OBJ_IS_METH(o) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_bound_method))
-// Note: inline functions sometimes use much more code space than the
-// equivalent macros, depending on the compiler.
-//static inline bool MP_OBJ_IS_TYPE(mp_const_obj_t o, const mp_obj_type_t *t) { return (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)(o))->type == (t))); } // this does not work for checking a string, use below macro for that
-//static inline bool MP_OBJ_IS_INT(mp_const_obj_t o) { return (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int)); } // returns true if o is a small int or long int
-// Need to forward declare these for the inline function to compile.
-extern const mp_obj_type_t mp_type_int;
-extern const mp_obj_type_t mp_type_bool;
-static inline bool mp_obj_is_integer(mp_const_obj_t o) { return MP_OBJ_IS_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_bool); } // returns true if o is bool, small int or long int
-//static inline bool MP_OBJ_IS_STR(mp_const_obj_t o) { return (MP_OBJ_IS_QSTR(o) || MP_OBJ_IS_TYPE(o, &mp_type_str)); }
-
-
// These macros are used to declare and define constant function objects
// You can put "static" in front of the definitions to make them local
@@ -555,6 +546,7 @@ extern const mp_obj_type_t mp_type_list;
extern const mp_obj_type_t mp_type_map; // map (the python builtin, not the dict implementation detail)
extern const mp_obj_type_t mp_type_enumerate;
extern const mp_obj_type_t mp_type_filter;
+extern const mp_obj_type_t mp_type_deque;
extern const mp_obj_type_t mp_type_dict;
extern const mp_obj_type_t mp_type_ordereddict;
extern const mp_obj_type_t mp_type_range;
@@ -626,7 +618,6 @@ 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_singleton_t mp_const_ellipsis_obj;
extern const struct _mp_obj_singleton_t mp_const_notimplemented_obj;
-extern const struct _mp_obj_exception_t mp_const_MemoryError_obj;
extern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj;
// General API for objects
@@ -639,7 +630,8 @@ 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, bool make_qstr_if_not_already);
+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_bytes(const byte* data, size_t len);
mp_obj_t mp_obj_new_bytearray(size_t n, void *items);
@@ -682,6 +674,7 @@ bool mp_obj_is_true(mp_obj_t arg);
bool mp_obj_is_callable(mp_obj_t o_in);
bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2);
+static inline bool mp_obj_is_integer(mp_const_obj_t o) { return MP_OBJ_IS_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_bool); } // returns true if o is bool, small int or long int
mp_int_t mp_obj_get_int(mp_const_obj_t arg);
uint64_t mp_obj_get_int64(mp_const_obj_t arg);
mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg);
@@ -731,6 +724,7 @@ qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway conve
const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated
const char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len);
mp_obj_t mp_obj_str_intern(mp_obj_t str);
+mp_obj_t mp_obj_str_intern_checked(mp_obj_t obj);
void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t str_len, bool is_bytes);
#if MICROPY_PY_BUILTINS_FLOAT
diff --git a/MicroPython_BUILD/components/micropython/py/objarray.c b/MicroPython_BUILD/components/micropython/py/objarray.c
index 7003ec9..a355394 100644
--- a/MicroPython_BUILD/components/micropython/py/objarray.c
+++ b/MicroPython_BUILD/components/micropython/py/objarray.c
@@ -269,8 +269,7 @@ STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs
return lhs_in;
}
- case MP_BINARY_OP_IN: {
- /* NOTE `a in b` is `b.__contains__(a)` */
+ case MP_BINARY_OP_CONTAINS: {
mp_buffer_info_t lhs_bufinfo;
mp_buffer_info_t rhs_bufinfo;
diff --git a/MicroPython_BUILD/components/micropython/py/objboundmeth.c b/MicroPython_BUILD/components/micropython/py/objboundmeth.c
index 890f8b1..b0df6a6 100644
--- a/MicroPython_BUILD/components/micropython/py/objboundmeth.c
+++ b/MicroPython_BUILD/components/micropython/py/objboundmeth.c
@@ -51,6 +51,9 @@ mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, s
// need to insert self before all other args and then call meth
size_t n_total = n_args + 2 * n_kw;
mp_obj_t *args2 = NULL;
+ #if MICROPY_ENABLE_PYSTACK
+ args2 = mp_pystack_alloc(sizeof(mp_obj_t) * (1 + n_total));
+ #else
mp_obj_t *free_args2 = NULL;
if (n_total > 4) {
// try to use heap to allocate temporary args array
@@ -61,12 +64,17 @@ mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, s
// (fallback to) use stack to allocate temporary args array
args2 = alloca(sizeof(mp_obj_t) * (1 + n_total));
}
+ #endif
args2[0] = self;
memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t));
mp_obj_t res = mp_call_function_n_kw(meth, n_args + 1, n_kw, args2);
+ #if MICROPY_ENABLE_PYSTACK
+ mp_pystack_free(args2);
+ #else
if (free_args2 != NULL) {
m_del(mp_obj_t, free_args2, 1 + n_total);
}
+ #endif
return res;
}
diff --git a/MicroPython_BUILD/components/micropython/py/objdeque.c b/MicroPython_BUILD/components/micropython/py/objdeque.c
new file mode 100644
index 0000000..bbb0781
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/py/objdeque.c
@@ -0,0 +1,166 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 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
+ * 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
+
+#include "py/mpconfig.h"
+#if MICROPY_PY_COLLECTIONS_DEQUE
+
+#include "py/runtime.h"
+
+typedef struct _mp_obj_deque_t {
+ mp_obj_base_t base;
+ size_t alloc;
+ size_t i_get;
+ size_t i_put;
+ mp_obj_t *items;
+ uint32_t flags;
+ #define FLAG_CHECK_OVERFLOW 1
+} mp_obj_deque_t;
+
+STATIC mp_obj_t deque_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 2, 3, false);
+
+ /* Initialization from existing sequence is not supported, so an empty
+ tuple must be passed as such. */
+ if (args[0] != mp_const_empty_tuple) {
+ mp_raise_ValueError(NULL);
+ }
+
+ // Protect against -1 leading to zero-length allocation and bad array access
+ mp_int_t maxlen = mp_obj_get_int(args[1]);
+ if (maxlen < 0) {
+ mp_raise_ValueError(NULL);
+ }
+
+ mp_obj_deque_t *o = m_new_obj(mp_obj_deque_t);
+ o->base.type = type;
+ o->alloc = maxlen + 1;
+ o->i_get = o->i_put = 0;
+ o->items = m_new0(mp_obj_t, o->alloc);
+
+ if (n_args > 2) {
+ o->flags = mp_obj_get_int(args[2]);
+ }
+
+ return MP_OBJ_FROM_PTR(o);
+}
+
+STATIC mp_obj_t deque_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
+ mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in);
+ switch (op) {
+ case MP_UNARY_OP_BOOL:
+ return mp_obj_new_bool(self->i_get != self->i_put);
+ case MP_UNARY_OP_LEN: {
+ mp_int_t len = self->i_put - self->i_get;
+ if (len < 0) {
+ len += self->alloc;
+ }
+ return MP_OBJ_NEW_SMALL_INT(len);
+ }
+ #if MICROPY_PY_SYS_GETSIZEOF
+ case MP_UNARY_OP_SIZEOF: {
+ size_t sz = sizeof(*self) + sizeof(mp_obj_t) * self->alloc;
+ return MP_OBJ_NEW_SMALL_INT(sz);
+ }
+ #endif
+ default:
+ return MP_OBJ_NULL; // op not supported
+ }
+}
+
+STATIC mp_obj_t mp_obj_deque_append(mp_obj_t self_in, mp_obj_t arg) {
+ mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in);
+
+ size_t new_i_put = self->i_put + 1;
+ if (new_i_put == self->alloc) {
+ new_i_put = 0;
+ }
+
+ if (self->flags & FLAG_CHECK_OVERFLOW && new_i_put == self->i_get) {
+ mp_raise_msg(&mp_type_IndexError, "full");
+ }
+
+ self->items[self->i_put] = arg;
+ self->i_put = new_i_put;
+
+ if (self->i_get == new_i_put) {
+ if (++self->i_get == self->alloc) {
+ self->i_get = 0;
+ }
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(deque_append_obj, mp_obj_deque_append);
+
+STATIC mp_obj_t deque_popleft(mp_obj_t self_in) {
+ mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (self->i_get == self->i_put) {
+ mp_raise_msg(&mp_type_IndexError, "empty");
+ }
+
+ mp_obj_t ret = self->items[self->i_get];
+ self->items[self->i_get] = MP_OBJ_NULL;
+
+ if (++self->i_get == self->alloc) {
+ self->i_get = 0;
+ }
+
+ return ret;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(deque_popleft_obj, deque_popleft);
+
+#if 0
+STATIC mp_obj_t deque_clear(mp_obj_t self_in) {
+ mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in);
+ self->i_get = self->i_put = 0;
+ mp_seq_clear(self->items, 0, self->alloc, sizeof(*self->items));
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(deque_clear_obj, deque_clear);
+#endif
+
+STATIC const mp_rom_map_elem_t deque_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&deque_append_obj) },
+ #if 0
+ { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&deque_clear_obj) },
+ #endif
+ { MP_ROM_QSTR(MP_QSTR_popleft), MP_ROM_PTR(&deque_popleft_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(deque_locals_dict, deque_locals_dict_table);
+
+const mp_obj_type_t mp_type_deque = {
+ { &mp_type_type },
+ .name = MP_QSTR_deque,
+ .make_new = deque_make_new,
+ .unary_op = deque_unary_op,
+ .locals_dict = (mp_obj_dict_t*)&deque_locals_dict,
+};
+
+#endif // MICROPY_PY_COLLECTIONS_DEQUE
diff --git a/MicroPython_BUILD/components/micropython/py/objdict.c b/MicroPython_BUILD/components/micropython/py/objdict.c
index 1553a83..c064706 100644
--- a/MicroPython_BUILD/components/micropython/py/objdict.c
+++ b/MicroPython_BUILD/components/micropython/py/objdict.c
@@ -115,7 +115,7 @@ STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_dict_t *o = MP_OBJ_TO_PTR(lhs_in);
switch (op) {
- case MP_BINARY_OP_IN: {
+ case MP_BINARY_OP_CONTAINS: {
mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
return mp_obj_new_bool(elem != NULL);
}
@@ -193,42 +193,18 @@ STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
}
/******************************************************************************/
-/* dict iterator */
+/* dict methods */
-typedef struct _mp_obj_dict_it_t {
- mp_obj_base_t base;
- mp_fun_1_t iternext;
- mp_obj_t dict;
- size_t cur;
-} mp_obj_dict_it_t;
-
-STATIC mp_obj_t dict_it_iternext(mp_obj_t self_in) {
- mp_obj_dict_it_t *self = MP_OBJ_TO_PTR(self_in);
- mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur);
-
- if (next == NULL) {
- return MP_OBJ_STOP_ITERATION;
- } else {
- return next->key;
+STATIC void mp_ensure_not_fixed(const mp_obj_dict_t *dict) {
+ if (dict->map.is_fixed) {
+ mp_raise_TypeError(NULL);
}
}
-STATIC mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
- assert(sizeof(mp_obj_dict_it_t) <= sizeof(mp_obj_iter_buf_t));
- mp_obj_dict_it_t *o = (mp_obj_dict_it_t*)iter_buf;
- o->base.type = &mp_type_polymorph_iter;
- o->iternext = dict_it_iternext;
- o->dict = self_in;
- o->cur = 0;
- return MP_OBJ_FROM_PTR(o);
-}
-
-/******************************************************************************/
-/* dict methods */
-
STATIC mp_obj_t dict_clear(mp_obj_t self_in) {
mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_ensure_not_fixed(self);
mp_map_clear(&self->map);
@@ -284,6 +260,9 @@ STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, MP_ROM_PTR(&dict_fromk
STATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) {
mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0]));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
+ if (lookup_kind != MP_MAP_LOOKUP) {
+ mp_ensure_not_fixed(self);
+ }
mp_map_elem_t *elem = mp_map_lookup(&self->map, args[1], lookup_kind);
mp_obj_t value;
if (elem == NULL || elem->value == MP_OBJ_NULL) {
@@ -326,6 +305,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setde
STATIC mp_obj_t dict_popitem(mp_obj_t self_in) {
mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_ensure_not_fixed(self);
size_t cur = 0;
mp_map_elem_t *next = dict_iter_next(self, &cur);
if (next == NULL) {
@@ -344,6 +324,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem);
STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0]));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
+ mp_ensure_not_fixed(self);
mp_arg_check_num(n_args, kwargs->used, 1, 2, true);
@@ -485,7 +466,7 @@ STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t
if (o->kind != MP_DICT_VIEW_KEYS) {
return MP_OBJ_NULL; // op not supported
}
- if (op != MP_BINARY_OP_IN) {
+ if (op != MP_BINARY_OP_CONTAINS) {
return MP_OBJ_NULL; // op not supported
}
return dict_binary_op(op, o->dict, rhs_in);
@@ -527,6 +508,20 @@ STATIC mp_obj_t dict_values(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values);
+/******************************************************************************/
+/* dict iterator */
+
+STATIC mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
+ assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t));
+ mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
+ mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t*)iter_buf;
+ o->base.type = &dict_view_it_type;
+ o->kind = MP_DICT_VIEW_KEYS;
+ o->dict = self_in;
+ o->cur = 0;
+ return MP_OBJ_FROM_PTR(o);
+}
+
/******************************************************************************/
/* dict constructors & public C API */
@@ -595,6 +590,7 @@ size_t mp_obj_dict_len(mp_obj_t self_in) {
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_TYPE(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_ensure_not_fixed(self);
mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
return self_in;
}
diff --git a/MicroPython_BUILD/components/micropython/py/objexcept.c b/MicroPython_BUILD/components/micropython/py/objexcept.c
index b87609a..1e746bc 100644
--- a/MicroPython_BUILD/components/micropython/py/objexcept.c
+++ b/MicroPython_BUILD/components/micropython/py/objexcept.c
@@ -43,9 +43,6 @@
// Number of traceback entries to reserve in the emergency exception buffer
#define EMG_TRACEBACK_ALLOC (2 * TRACEBACK_ENTRY_LEN)
-// Instance of MemoryError exception - needed by mp_malloc_fail
-const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj};
-
// Optionally allocated buffer for storing the first argument of an exception
// allocated when the heap is locked.
#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
@@ -96,7 +93,7 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) {
// definition module-private so far, have it here.
const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj};
-STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
+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;
bool is_subclass = kind & PRINT_EXC_SUBCLASS;
@@ -118,7 +115,7 @@ STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr
if (o->base.type == &mp_type_OSError && MP_OBJ_IS_SMALL_INT(o->args->items[0])) {
qstr qst = mp_errno_to_str(o->args->items[0]);
if (qst != MP_QSTR_NULL) {
- mp_printf(print, "[Errno %d] %q", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), qst);
+ mp_printf(print, "[Errno " INT_FMT "] %q", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), qst);
return;
}
}
@@ -189,7 +186,7 @@ mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in) {
}
}
-STATIC void exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
+void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in);
if (dest[0] != MP_OBJ_NULL) {
// store/delete attribute
@@ -212,37 +209,12 @@ STATIC void exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
}
}
-STATIC mp_obj_t exc___init__(size_t n_args, const mp_obj_t *args) {
- mp_obj_exception_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_obj_t argst = mp_obj_new_tuple(n_args - 1, args + 1);
- self->args = MP_OBJ_TO_PTR(argst);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(exc___init___obj, 1, MP_OBJ_FUN_ARGS_MAX, exc___init__);
-
-STATIC const mp_rom_map_elem_t exc_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&exc___init___obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(exc_locals_dict, exc_locals_dict_table);
-
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 = exception_attr,
- .locals_dict = (mp_obj_dict_t*)&exc_locals_dict,
-};
-
-#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 = exception_attr, \
- .parent = &mp_type_ ## base_name, \
+ .attr = mp_obj_exception_attr,
};
// List of all exceptions, arranged as in the table at:
diff --git a/MicroPython_BUILD/components/micropython/py/objexcept.h b/MicroPython_BUILD/components/micropython/py/objexcept.h
index f67651a..7c30762 100644
--- a/MicroPython_BUILD/components/micropython/py/objexcept.h
+++ b/MicroPython_BUILD/components/micropython/py/objexcept.h
@@ -37,4 +37,17 @@ typedef struct _mp_obj_exception_t {
mp_obj_tuple_t *args;
} mp_obj_exception_t;
+void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind);
+void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest);
+
+#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, \
+};
+
#endif // MICROPY_INCLUDED_PY_OBJEXCEPT_H
diff --git a/MicroPython_BUILD/components/micropython/py/objfloat.c b/MicroPython_BUILD/components/micropython/py/objfloat.c
index 743287b..e4d5a65 100644
--- a/MicroPython_BUILD/components/micropython/py/objfloat.c
+++ b/MicroPython_BUILD/components/micropython/py/objfloat.c
@@ -137,12 +137,11 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size
return mp_obj_new_float(0);
case 1:
- default:
- if (MP_OBJ_IS_STR(args[0])) {
- // 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, false, false, NULL);
+ default: {
+ 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);
} else if (mp_obj_is_float(args[0])) {
// a float, just return it
return args[0];
@@ -150,6 +149,7 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size
// something else, try to cast it to a float
return mp_obj_new_float(mp_obj_get_float(args[0]));
}
+ }
}
}
@@ -293,7 +293,7 @@ mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t
break;
case MP_BINARY_OP_POWER:
case MP_BINARY_OP_INPLACE_POWER:
- if (lhs_val == 0 && rhs_val < 0) {
+ if (lhs_val == 0 && rhs_val < 0 && !isinf(rhs_val)) {
goto zero_division_error;
}
if (lhs_val < 0 && rhs_val != MICROPY_FLOAT_C_FUN(floor)(rhs_val)) {
diff --git a/MicroPython_BUILD/components/micropython/py/objfun.c b/MicroPython_BUILD/components/micropython/py/objfun.c
index 030b3f7..e6d33d2 100644
--- a/MicroPython_BUILD/components/micropython/py/objfun.c
+++ b/MicroPython_BUILD/components/micropython/py/objfun.c
@@ -195,32 +195,53 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) {
// than this will try to use the heap, with fallback to stack allocation.
#define VM_MAX_STATE_ON_STACK (11 * sizeof(mp_uint_t))
-// Set this to enable a simple stack overflow check.
+// Set this to 1 to enable a simple stack overflow check.
#define VM_DETECT_STACK_OVERFLOW (0)
+#define DECODE_CODESTATE_SIZE(bytecode, n_state_out_var, state_size_out_var) \
+ { \
+ /* bytecode prelude: state size and exception stack size */ \
+ n_state_out_var = mp_decode_uint_value(bytecode); \
+ size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(bytecode)); \
+ \
+ n_state += VM_DETECT_STACK_OVERFLOW; \
+ \
+ /* state size in bytes */ \
+ state_size_out_var = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); \
+ }
+
+#define INIT_CODESTATE(code_state, _fun_bc, n_args, n_kw, args) \
+ code_state->fun_bc = _fun_bc; \
+ code_state->ip = 0; \
+ mp_setup_code_state(code_state, n_args, n_kw, args); \
+ code_state->old_globals = mp_globals_get();
+
#if MICROPY_STACKLESS
mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
MP_STACK_CHECK();
mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);
- // bytecode prelude: state size and exception stack size
- size_t n_state = mp_decode_uint_value(self->bytecode);
- size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode));
+ size_t n_state, state_size;
+ DECODE_CODESTATE_SIZE(self->bytecode, n_state, state_size);
- // allocate state for locals and stack
- size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
mp_code_state_t *code_state;
+ #if MICROPY_ENABLE_PYSTACK
+ code_state = mp_pystack_alloc(sizeof(mp_code_state_t) + state_size);
+ #else
+ // If we use m_new_obj_var(), then on no memory, MemoryError will be
+ // raised. But this is not correct exception for a function call,
+ // RuntimeError should be raised instead. So, we use m_new_obj_var_maybe(),
+ // return NULL, then vm.c takes the needed action (either raise
+ // RuntimeError or fallback to stack allocation).
code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);
if (!code_state) {
return NULL;
}
+ #endif
- code_state->fun_bc = self;
- code_state->ip = 0;
- mp_setup_code_state(code_state, n_args, n_kw, args);
+ INIT_CODESTATE(code_state, self, n_args, n_kw, args);
// execute the byte code with the correct globals context
- code_state->old_globals = mp_globals_get();
mp_globals_set(self->globals);
return code_state;
@@ -238,17 +259,14 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);
DEBUG_printf("Func n_def_args: %d\n", self->n_def_args);
- // bytecode prelude: state size and exception stack size
- size_t n_state = mp_decode_uint_value(self->bytecode);
- size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode));
-
-#if VM_DETECT_STACK_OVERFLOW
- n_state += 1;
-#endif
+ size_t n_state, state_size;
+ DECODE_CODESTATE_SIZE(self->bytecode, n_state, state_size);
// allocate state for locals and stack
- size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
mp_code_state_t *code_state = NULL;
+ #if MICROPY_ENABLE_PYSTACK
+ code_state = mp_pystack_alloc(sizeof(mp_code_state_t) + state_size);
+ #else
if (state_size > VM_MAX_STATE_ON_STACK) {
code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);
}
@@ -256,13 +274,11 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
code_state = alloca(sizeof(mp_code_state_t) + state_size);
state_size = 0; // indicate that we allocated using alloca
}
+ #endif
- code_state->fun_bc = self;
- code_state->ip = 0;
- mp_setup_code_state(code_state, n_args, n_kw, args);
+ INIT_CODESTATE(code_state, self, n_args, n_kw, args);
// execute the byte code with the correct globals context
- code_state->old_globals = mp_globals_get();
mp_globals_set(self->globals);
mp_vm_return_kind_t vm_return_kind = mp_execute_bytecode(code_state, MP_OBJ_NULL);
mp_globals_set(code_state->old_globals);
@@ -304,10 +320,14 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
result = code_state->state[n_state - 1];
}
+ #if MICROPY_ENABLE_PYSTACK
+ mp_pystack_free(code_state);
+ #else
// free the state if it was allocated on the heap
if (state_size != 0) {
m_del_var(mp_code_state_t, byte, state_size, code_state);
}
+ #endif
if (vm_return_kind == MP_VM_RETURN_NORMAL) {
return result;
diff --git a/MicroPython_BUILD/components/micropython/py/objgenerator.c b/MicroPython_BUILD/components/micropython/py/objgenerator.c
index bf0bbb0..8c1260b 100644
--- a/MicroPython_BUILD/components/micropython/py/objgenerator.c
+++ b/MicroPython_BUILD/components/micropython/py/objgenerator.c
@@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
- * Copyright (c) 2014 Paul Sokolovsky
+ * 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
@@ -104,7 +104,16 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
mp_raise_TypeError("can't send non-None value to a just-started generator");
}
} else {
- *self->code_state.sp = send_value;
+ #if MICROPY_PY_GENERATOR_PEND_THROW
+ // If exception is pending (set using .pend_throw()), process it now.
+ if (*self->code_state.sp != mp_const_none) {
+ throw_value = *self->code_state.sp;
+ *self->code_state.sp = MP_OBJ_NULL;
+ } else
+ #endif
+ {
+ *self->code_state.sp = send_value;
+ }
}
mp_obj_dict_t *old_globals = mp_globals_get();
mp_globals_set(self->globals);
@@ -125,9 +134,9 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
case MP_VM_RETURN_YIELD:
*ret_val = *self->code_state.sp;
- if (*ret_val == MP_OBJ_STOP_ITERATION) {
- self->code_state.ip = 0;
- }
+ #if MICROPY_PY_GENERATOR_PEND_THROW
+ *self->code_state.sp = mp_const_none;
+ #endif
break;
case MP_VM_RETURN_EXCEPTION: {
@@ -222,10 +231,24 @@ STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(gen_instance_close_obj, gen_instance_close);
+STATIC mp_obj_t gen_instance_pend_throw(mp_obj_t self_in, mp_obj_t exc_in) {
+ mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->code_state.sp == self->code_state.state - 1) {
+ mp_raise_TypeError("can't pend throw to just-started generator");
+ }
+ mp_obj_t prev = *self->code_state.sp;
+ *self->code_state.sp = exc_in;
+ return prev;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_pend_throw_obj, gen_instance_pend_throw);
+
STATIC const mp_rom_map_elem_t gen_instance_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&gen_instance_close_obj) },
{ MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&gen_instance_send_obj) },
{ MP_ROM_QSTR(MP_QSTR_throw), MP_ROM_PTR(&gen_instance_throw_obj) },
+ #if MICROPY_PY_GENERATOR_PEND_THROW
+ { MP_ROM_QSTR(MP_QSTR_pend_throw), MP_ROM_PTR(&gen_instance_pend_throw_obj) },
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_table);
diff --git a/MicroPython_BUILD/components/micropython/py/objint.c b/MicroPython_BUILD/components/micropython/py/objint.c
index 4f2e610..270e169 100644
--- a/MicroPython_BUILD/components/micropython/py/objint.c
+++ b/MicroPython_BUILD/components/micropython/py/objint.c
@@ -222,27 +222,26 @@ size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char co
char *mp_obj_int_formatted(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) {
fmt_int_t num;
+ #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
+ // Only have small ints; get the integer value to format.
+ num = MP_OBJ_SMALL_INT_VALUE(self_in);
+ #else
if (MP_OBJ_IS_SMALL_INT(self_in)) {
// A small int; get the integer value to format.
num = MP_OBJ_SMALL_INT_VALUE(self_in);
-#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
- } else if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {
+ } else {
+ assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
// Not a small int.
-#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
+ #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
const mp_obj_int_t *self = self_in;
// Get the value to format; mp_obj_get_int truncates to mp_int_t.
num = self->val;
-#else
+ #else
// Delegate to the implementation for the long int.
return mp_obj_int_formatted_impl(buf, buf_size, fmt_size, self_in, base, prefix, base_char, comma);
-#endif
-#endif
- } else {
- // Not an int.
- **buf = '\0';
- *fmt_size = 0;
- return *buf;
+ #endif
}
+ #endif
char sign = '\0';
if (num < 0) {
@@ -378,7 +377,7 @@ mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp
// true acts as 0
return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(1));
} else if (op == MP_BINARY_OP_MULTIPLY) {
- if (MP_OBJ_IS_STR(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_bytes) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) {
+ if (MP_OBJ_IS_STR_OR_BYTES(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) {
// multiply is commutative for these types, so delegate to them
return mp_binary_op(op, rhs_in, lhs_in);
}
diff --git a/MicroPython_BUILD/components/micropython/py/objint_longlong.c b/MicroPython_BUILD/components/micropython/py/objint_longlong.c
index 2e567c5..3e5ebad 100644
--- a/MicroPython_BUILD/components/micropython/py/objint_longlong.c
+++ b/MicroPython_BUILD/components/micropython/py/objint_longlong.c
@@ -151,9 +151,15 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i
return mp_obj_new_int_from_ll(lhs_val * rhs_val);
case MP_BINARY_OP_FLOOR_DIVIDE:
case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:
+ if (rhs_val == 0) {
+ goto zero_division;
+ }
return mp_obj_new_int_from_ll(lhs_val / rhs_val);
case MP_BINARY_OP_MODULO:
case MP_BINARY_OP_INPLACE_MODULO:
+ if (rhs_val == 0) {
+ goto zero_division;
+ }
return mp_obj_new_int_from_ll(lhs_val % rhs_val);
case MP_BINARY_OP_AND:
@@ -210,6 +216,9 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i
default:
return MP_OBJ_NULL; // op not supported
}
+
+zero_division:
+ mp_raise_msg(&mp_type_ZeroDivisionError, "division by zero");
}
mp_obj_t mp_obj_new_int(mp_int_t value) {
diff --git a/MicroPython_BUILD/components/micropython/py/objint_mpz.c b/MicroPython_BUILD/components/micropython/py/objint_mpz.c
index d02311b..ccf5e0b 100644
--- a/MicroPython_BUILD/components/micropython/py/objint_mpz.c
+++ b/MicroPython_BUILD/components/micropython/py/objint_mpz.c
@@ -208,7 +208,7 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i
return mp_obj_new_float(flhs / frhs);
#endif
- } else if (op >= MP_BINARY_OP_INPLACE_OR) {
+ } else if (op >= MP_BINARY_OP_INPLACE_OR && op < MP_BINARY_OP_CONTAINS) {
mp_obj_int_t *res = mp_obj_int_new_mpz();
switch (op) {
diff --git a/MicroPython_BUILD/components/micropython/py/objlist.h b/MicroPython_BUILD/components/micropython/py/objlist.h
index 28b5495..a43663d 100644
--- a/MicroPython_BUILD/components/micropython/py/objlist.h
+++ b/MicroPython_BUILD/components/micropython/py/objlist.h
@@ -35,4 +35,6 @@ typedef struct _mp_obj_list_t {
mp_obj_t *items;
} mp_obj_list_t;
+void mp_obj_list_init(mp_obj_list_t *o, size_t n);
+
#endif // MICROPY_INCLUDED_PY_OBJLIST_H
diff --git a/MicroPython_BUILD/components/micropython/py/objmodule.c b/MicroPython_BUILD/components/micropython/py/objmodule.c
index f9363e3..c4aba3a 100644
--- a/MicroPython_BUILD/components/micropython/py/objmodule.c
+++ b/MicroPython_BUILD/components/micropython/py/objmodule.c
@@ -247,17 +247,7 @@ mp_obj_t mp_module_get(qstr module_name) {
if (el == NULL) {
return MP_OBJ_NULL;
}
-
- if (MICROPY_MODULE_BUILTIN_INIT) {
- // look for __init__ and call it if it exists
- mp_obj_t dest[2];
- mp_load_method_maybe(el->value, MP_QSTR___init__, dest);
- if (dest[0] != MP_OBJ_NULL) {
- mp_call_method_n_kw(0, 0, dest);
- // register module so __init__ is not called again
- mp_module_register(module_name, el->value);
- }
- }
+ mp_module_call_init(module_name, el->value);
}
// module found, return it
@@ -268,3 +258,19 @@ void mp_module_register(qstr qst, mp_obj_t module) {
mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map;
mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module;
}
+
+#if MICROPY_MODULE_BUILTIN_INIT
+void mp_module_call_init(qstr module_name, mp_obj_t module_obj) {
+ // Look for __init__ and call it if it exists
+ mp_obj_t dest[2];
+ mp_load_method_maybe(module_obj, MP_QSTR___init__, dest);
+ if (dest[0] != MP_OBJ_NULL) {
+ mp_call_method_n_kw(0, 0, dest);
+ // Register module so __init__ is not called again.
+ // If a module can be referenced by more than one name (eg due to weak links)
+ // then __init__ will still be called for each distinct import, and it's then
+ // up to the particular module to make sure it's __init__ code only runs once.
+ mp_module_register(module_name, module_obj);
+ }
+}
+#endif
diff --git a/MicroPython_BUILD/components/micropython/py/objmodule.h b/MicroPython_BUILD/components/micropython/py/objmodule.h
index b5c07dc..b7702ec 100644
--- a/MicroPython_BUILD/components/micropython/py/objmodule.h
+++ b/MicroPython_BUILD/components/micropython/py/objmodule.h
@@ -34,4 +34,13 @@ extern const mp_map_t mp_builtin_module_weak_links_map;
mp_obj_t mp_module_get(qstr module_name);
void mp_module_register(qstr qstr, mp_obj_t module);
+#if MICROPY_MODULE_BUILTIN_INIT
+void mp_module_call_init(qstr module_name, mp_obj_t module_obj);
+#else
+static inline void mp_module_call_init(qstr module_name, mp_obj_t module_obj) {
+ (void)module_name;
+ (void)module_obj;
+}
+#endif
+
#endif // MICROPY_INCLUDED_PY_OBJMODULE_H
diff --git a/MicroPython_BUILD/components/micropython/py/objnamedtuple.c b/MicroPython_BUILD/components/micropython/py/objnamedtuple.c
index 38daccd..e7de899 100644
--- a/MicroPython_BUILD/components/micropython/py/objnamedtuple.c
+++ b/MicroPython_BUILD/components/micropython/py/objnamedtuple.c
@@ -30,20 +30,11 @@
#include "py/objtuple.h"
#include "py/runtime.h"
#include "py/objstr.h"
+#include "py/objnamedtuple.h"
#if MICROPY_PY_COLLECTIONS
-typedef struct _mp_obj_namedtuple_type_t {
- mp_obj_type_t base;
- size_t n_fields;
- qstr fields[];
-} mp_obj_namedtuple_type_t;
-
-typedef struct _mp_obj_namedtuple_t {
- mp_obj_tuple_t tuple;
-} mp_obj_namedtuple_t;
-
-STATIC size_t namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name) {
+size_t mp_obj_namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name) {
for (size_t i = 0; i < type->n_fields; i++) {
if (type->fields[i] == name) {
return i;
@@ -52,6 +43,23 @@ STATIC size_t namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr n
return (size_t)-1;
}
+#if MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT
+STATIC mp_obj_t namedtuple_asdict(mp_obj_t self_in) {
+ mp_obj_namedtuple_t *self = MP_OBJ_TO_PTR(self_in);
+ const qstr *fields = ((mp_obj_namedtuple_type_t*)self->tuple.base.type)->fields;
+ mp_obj_t dict = mp_obj_new_dict(self->tuple.len);
+ //make it an OrderedDict
+ mp_obj_dict_t *dictObj = MP_OBJ_TO_PTR(dict);
+ dictObj->base.type = &mp_type_ordereddict;
+ dictObj->map.is_ordered = 1;
+ for (size_t i = 0; i < self->tuple.len; ++i) {
+ mp_obj_dict_store(dict, MP_OBJ_NEW_QSTR(fields[i]), self->tuple.items[i]);
+ }
+ return dict;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(namedtuple_asdict_obj, namedtuple_asdict);
+#endif
+
STATIC void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_namedtuple_t *o = MP_OBJ_TO_PTR(o_in);
@@ -64,7 +72,14 @@ STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
if (dest[0] == MP_OBJ_NULL) {
// load attribute
mp_obj_namedtuple_t *self = MP_OBJ_TO_PTR(self_in);
- size_t id = namedtuple_find_field((mp_obj_namedtuple_type_t*)self->tuple.base.type, attr);
+ #if MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT
+ if (attr == MP_QSTR__asdict) {
+ dest[0] = MP_OBJ_FROM_PTR(&namedtuple_asdict_obj);
+ dest[1] = self_in;
+ return;
+ }
+ #endif
+ size_t id = mp_obj_namedtuple_find_field((mp_obj_namedtuple_type_t*)self->tuple.base.type, attr);
if (id == (size_t)-1) {
return;
}
@@ -104,7 +119,7 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args,
memset(&tuple->items[n_args], 0, sizeof(mp_obj_t) * n_kw);
for (size_t i = n_args; i < n_args + 2 * n_kw; i += 2) {
qstr kw = mp_obj_str_get_qstr(args[i]);
- size_t id = namedtuple_find_field(type, kw);
+ size_t id = mp_obj_namedtuple_find_field(type, kw);
if (id == (size_t)-1) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
mp_arg_error_terse_mismatch();
@@ -127,9 +142,18 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args,
return MP_OBJ_FROM_PTR(tuple);
}
-STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) {
+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));
+ o->n_fields = n_fields;
+ for (size_t i = 0; i < n_fields; i++) {
+ o->fields[i] = mp_obj_str_get_qstr(fields[i]);
+ }
+ return o;
+}
+
+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.name = name;
o->base.print = namedtuple_print;
@@ -140,10 +164,6 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t
o->base.subscr = mp_obj_tuple_subscr;
o->base.getiter = mp_obj_tuple_getiter;
o->base.parent = &mp_type_tuple;
- o->n_fields = n_fields;
- for (size_t i = 0; i < n_fields; i++) {
- o->fields[i] = mp_obj_str_get_qstr(fields[i]);
- }
return MP_OBJ_FROM_PTR(o);
}
diff --git a/MicroPython_BUILD/components/micropython/py/objnamedtuple.h b/MicroPython_BUILD/components/micropython/py/objnamedtuple.h
new file mode 100644
index 0000000..d32af35
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/py/objnamedtuple.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * 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
+ * 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_PY_OBJNAMEDTUPLE_H
+#define MICROPY_INCLUDED_PY_OBJNAMEDTUPLE_H
+
+#include "py/objtuple.h"
+
+typedef struct _mp_obj_namedtuple_type_t {
+ mp_obj_type_t base;
+ size_t n_fields;
+ qstr fields[];
+} mp_obj_namedtuple_type_t;
+
+typedef struct _mp_obj_namedtuple_t {
+ mp_obj_tuple_t tuple;
+} mp_obj_namedtuple_t;
+
+size_t mp_obj_namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name);
+mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t *fields);
+
+#endif // MICROPY_INCLUDED_PY_OBJNAMEDTUPLE_H
diff --git a/MicroPython_BUILD/components/micropython/py/objobject.c b/MicroPython_BUILD/components/micropython/py/objobject.c
index 49d2ec6..265fcfb 100644
--- a/MicroPython_BUILD/components/micropython/py/objobject.c
+++ b/MicroPython_BUILD/components/micropython/py/objobject.c
@@ -52,9 +52,12 @@ STATIC mp_obj_t object___new__(mp_obj_t cls) {
if (!MP_OBJ_IS_TYPE(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)MP_OBJ_TO_PTR(cls))) {
mp_raise_TypeError("__new__ arg must be a user-type");
}
- mp_obj_t o = MP_OBJ_SENTINEL;
- mp_obj_t res = mp_obj_instance_make_new(MP_OBJ_TO_PTR(cls), 1, 0, &o);
- return res;
+ // This executes only "__new__" part of instance creation.
+ // TODO: This won't work well for classes with native bases.
+ // TODO: This is a hack, should be resolved along the lines of
+ // https://github.com/micropython/micropython/issues/606#issuecomment-43685883
+ const mp_obj_type_t *native_base;
+ return MP_OBJ_FROM_PTR(mp_obj_new_instance(MP_OBJ_TO_PTR(cls), &native_base));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___new___fun_obj, object___new__);
STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(object___new___obj, MP_ROM_PTR(&object___new___fun_obj));
diff --git a/MicroPython_BUILD/components/micropython/py/objrange.c b/MicroPython_BUILD/components/micropython/py/objrange.c
index 3874adb..86aa0cc 100644
--- a/MicroPython_BUILD/components/micropython/py/objrange.c
+++ b/MicroPython_BUILD/components/micropython/py/objrange.c
@@ -138,6 +138,24 @@ STATIC mp_obj_t range_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
}
}
+#if MICROPY_PY_BUILTINS_RANGE_BINOP
+STATIC mp_obj_t range_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+ if (!MP_OBJ_IS_TYPE(rhs_in, &mp_type_range) || op != MP_BINARY_OP_EQUAL) {
+ return MP_OBJ_NULL; // op not supported
+ }
+ mp_obj_range_t *lhs = MP_OBJ_TO_PTR(lhs_in);
+ mp_obj_range_t *rhs = MP_OBJ_TO_PTR(rhs_in);
+ mp_int_t lhs_len = range_len(lhs);
+ mp_int_t rhs_len = range_len(rhs);
+ return mp_obj_new_bool(
+ lhs_len == rhs_len
+ && (lhs_len == 0
+ || (lhs->start == rhs->start
+ && (lhs_len == 1 || lhs->step == rhs->step)))
+ );
+}
+#endif
+
STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
if (value == MP_OBJ_SENTINEL) {
// load
@@ -195,6 +213,9 @@ const mp_obj_type_t mp_type_range = {
.print = range_print,
.make_new = range_make_new,
.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_ATTRS
diff --git a/MicroPython_BUILD/components/micropython/py/objset.c b/MicroPython_BUILD/components/micropython/py/objset.c
index 6ed15c7..799ba9d 100644
--- a/MicroPython_BUILD/components/micropython/py/objset.c
+++ b/MicroPython_BUILD/components/micropython/py/objset.c
@@ -351,11 +351,9 @@ STATIC mp_obj_t set_issuperset_proper(mp_obj_t self_in, mp_obj_t other_in) {
}
STATIC mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) {
+ assert(is_set_or_frozenset(other_in));
check_set_or_frozenset(self_in);
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
- if (!is_set_or_frozenset(other_in)) {
- return mp_const_false;
- }
mp_obj_set_t *other = MP_OBJ_TO_PTR(other_in);
if (self->set.used != other->set.used) {
return mp_const_false;
@@ -461,7 +459,7 @@ STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
#else
bool update = true;
#endif
- if (op != MP_BINARY_OP_IN && !is_set_or_frozenset(rhs)) {
+ if (op != MP_BINARY_OP_CONTAINS && !is_set_or_frozenset(rhs)) {
// For all ops except containment the RHS must be a set/frozenset
return MP_OBJ_NULL;
}
@@ -507,7 +505,7 @@ STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
return set_issubset(lhs, rhs);
case MP_BINARY_OP_MORE_EQUAL:
return set_issuperset(lhs, rhs);
- case MP_BINARY_OP_IN: {
+ case MP_BINARY_OP_CONTAINS: {
mp_obj_set_t *o = MP_OBJ_TO_PTR(lhs);
mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP);
return mp_obj_new_bool(elem != MP_OBJ_NULL);
diff --git a/MicroPython_BUILD/components/micropython/py/objstr.c b/MicroPython_BUILD/components/micropython/py/objstr.c
index 51da7a4..0b11533 100644
--- a/MicroPython_BUILD/components/micropython/py/objstr.c
+++ b/MicroPython_BUILD/components/micropython/py/objstr.c
@@ -164,7 +164,14 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
mp_raise_msg(&mp_type_UnicodeError, NULL);
}
#endif
- mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(type, NULL, str_len));
+
+ // Check if a qstr with this data already exists
+ qstr q = qstr_find_strn((const char*)str_data, str_len);
+ if (q != MP_QSTR_NULL) {
+ return MP_OBJ_NEW_QSTR(q);
+ }
+
+ mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_copy(type, NULL, str_len));
o->data = str_data;
o->hash = str_hash;
return MP_OBJ_FROM_PTR(o);
@@ -176,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_raise_msg(&mp_type_UnicodeError, NULL);
}
#endif
- return mp_obj_new_str(bufinfo.buf, bufinfo.len, false);
+ return mp_obj_new_str(bufinfo.buf, bufinfo.len);
}
}
}
@@ -205,7 +212,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size
if (str_hash == 0) {
str_hash = qstr_compute_hash(str_data, str_len);
}
- mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(&mp_type_bytes, NULL, str_len));
+ mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_copy(&mp_type_bytes, NULL, str_len));
o->data = str_data;
o->hash = str_hash;
return MP_OBJ_FROM_PTR(o);
@@ -216,7 +223,10 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size
}
if (MP_OBJ_IS_SMALL_INT(args[0])) {
- uint len = MP_OBJ_SMALL_INT_VALUE(args[0]);
+ mp_int_t len = MP_OBJ_SMALL_INT_VALUE(args[0]);
+ if (len < 0) {
+ mp_raise_ValueError(NULL);
+ }
vstr_t vstr;
vstr_init_len(&vstr, len);
memset(vstr.buf, 0, len);
@@ -226,7 +236,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size
// check if argument has the buffer protocol
mp_buffer_info_t bufinfo;
if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) {
- return mp_obj_new_str_of_type(&mp_type_bytes, bufinfo.buf, bufinfo.len);
+ return mp_obj_new_bytes(bufinfo.buf, bufinfo.len);
}
vstr_t vstr;
@@ -377,8 +387,7 @@ 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_obj_new_str_from_vstr(lhs_type, &vstr);
}
- case MP_BINARY_OP_IN:
- /* NOTE `a in b` is `b.__contains__(a)` */
+ case MP_BINARY_OP_CONTAINS:
return mp_obj_new_bool(find_subbytes(lhs_data, lhs_len, rhs_data, rhs_len, 1) != NULL);
//case MP_BINARY_OP_NOT_EQUAL: // This is never passed here
@@ -423,7 +432,7 @@ STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
if (MICROPY_PY_BUILTINS_STR_UNICODE || type == &mp_type_bytes) {
return MP_OBJ_NEW_SMALL_INT(self_data[index_val]);
} else {
- return mp_obj_new_str((char*)&self_data[index_val], 1, true);
+ return mp_obj_new_str_via_qstr((char*)&self_data[index_val], 1);
}
} else {
return MP_OBJ_NULL; // op not supported
@@ -654,9 +663,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) {
}
res->items[idx--] = mp_obj_new_str_of_type(self_type, s + sep_len, last - s - sep_len);
last = s;
- if (splits > 0) {
- splits--;
- }
+ splits--;
}
if (idx != 0) {
// We split less parts than split limit, now go cleanup surplus
@@ -1046,7 +1053,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
} else {
const char *lookup;
for (lookup = field_name; lookup < field_name_top && *lookup != '.' && *lookup != '['; lookup++);
- mp_obj_t field_q = mp_obj_new_str(field_name, lookup - field_name, true/*?*/);
+ mp_obj_t field_q = mp_obj_new_str_via_qstr(field_name, lookup - field_name); // should it be via qstr?
field_name = lookup;
mp_map_elem_t *key_elem = mp_map_lookup(kwargs, field_q, MP_MAP_LOOKUP);
if (key_elem == NULL) {
@@ -1413,7 +1420,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_
}
++str;
}
- mp_obj_t k_obj = mp_obj_new_str((const char*)key, str - key, true);
+ mp_obj_t k_obj = mp_obj_new_str_via_qstr((const char*)key, str - key);
arg = mp_obj_dict_get(dict, k_obj);
str++;
}
@@ -1698,7 +1705,7 @@ STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) {
// if needle_len is zero then we count each gap between characters as an occurrence
if (needle_len == 0) {
- return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char*)start, end - start) + 1);
+ return MP_OBJ_NEW_SMALL_INT(utf8_charlen(start, end - start) + 1);
}
// count the occurrences
@@ -1977,8 +1984,9 @@ const mp_obj_type_t mp_type_bytes = {
const mp_obj_str_t mp_const_empty_bytes_obj = {{&mp_type_bytes}, 0, 0, (const byte*)""};
// Create a str/bytes object using the given data. New memory is allocated and
-// the data is copied across.
-mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len) {
+// the data is copied across. This function should only be used if the type is bytes,
+// or if the type is str and the string data is known to be not interned.
+mp_obj_t mp_obj_new_str_copy(const mp_obj_type_t *type, const byte* data, size_t len) {
mp_obj_str_t *o = m_new_obj(mp_obj_str_t);
o->base.type = type;
o->len = len;
@@ -1992,6 +2000,22 @@ mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, siz
return MP_OBJ_FROM_PTR(o);
}
+// Create a str/bytes object using the given data. If the type is str and the string
+// data is already interned, then a qstr object is returned. Otherwise new memory is
+// allocated for the object and the data is copied across.
+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);
+ } else {
+ return mp_obj_new_bytes(data, len);
+ }
+}
+
+// Create a str using a qstr to store the data; may use existing or new qstr.
+mp_obj_t mp_obj_new_str_via_qstr(const char* data, size_t len) {
+ return MP_OBJ_NEW_QSTR(qstr_from_strn(data, 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.
@@ -2022,29 +2046,30 @@ mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) {
return MP_OBJ_FROM_PTR(o);
}
-mp_obj_t mp_obj_new_str(const char* data, size_t len, bool make_qstr_if_not_already) {
- if (make_qstr_if_not_already) {
- // use existing, or make a new qstr
- return MP_OBJ_NEW_QSTR(qstr_from_strn(data, len));
+mp_obj_t mp_obj_new_str(const char* data, size_t len) {
+ qstr q = qstr_find_strn(data, len);
+ if (q != MP_QSTR_NULL) {
+ // qstr with this data already exists
+ return MP_OBJ_NEW_QSTR(q);
} else {
- qstr q = qstr_find_strn(data, len);
- if (q != MP_QSTR_NULL) {
- // qstr with this data already exists
- return MP_OBJ_NEW_QSTR(q);
- } else {
- // no existing qstr, don't make one
- return mp_obj_new_str_of_type(&mp_type_str, (const byte*)data, len);
- }
+ // no existing qstr, don't make one
+ return mp_obj_new_str_copy(&mp_type_str, (const byte*)data, len);
}
}
mp_obj_t mp_obj_str_intern(mp_obj_t str) {
GET_STR_DATA_LEN(str, data, len);
- return MP_OBJ_NEW_QSTR(qstr_from_strn((const char*)data, len));
+ return mp_obj_new_str_via_qstr((const char*)data, len);
+}
+
+mp_obj_t mp_obj_str_intern_checked(mp_obj_t obj) {
+ size_t len;
+ const char *data = mp_obj_str_get_data(obj, &len);
+ return mp_obj_new_str_via_qstr((const char*)data, len);
}
mp_obj_t mp_obj_new_bytes(const byte* data, size_t len) {
- return mp_obj_new_str_of_type(&mp_type_bytes, data, len);
+ return mp_obj_new_str_copy(&mp_type_bytes, data, len);
}
bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) {
@@ -2066,7 +2091,7 @@ bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) {
}
}
-STATIC void bad_implicit_conversion(mp_obj_t self_in) {
+STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
mp_raise_TypeError("can't convert to str implicitly");
} else {
@@ -2138,7 +2163,7 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
mp_obj_str8_it_t *self = MP_OBJ_TO_PTR(self_in);
GET_STR_DATA_LEN(self->str, str, len);
if (self->cur < len) {
- mp_obj_t o_out = mp_obj_new_str((const char*)str + self->cur, 1, true);
+ mp_obj_t o_out = mp_obj_new_str_via_qstr((const char*)str + self->cur, 1);
self->cur += 1;
return o_out;
} else {
diff --git a/MicroPython_BUILD/components/micropython/py/objstr.h b/MicroPython_BUILD/components/micropython/py/objstr.h
index 82501a7..4e55cad 100644
--- a/MicroPython_BUILD/components/micropython/py/objstr.h
+++ b/MicroPython_BUILD/components/micropython/py/objstr.h
@@ -65,6 +65,7 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t
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_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);
diff --git a/MicroPython_BUILD/components/micropython/py/objstrunicode.c b/MicroPython_BUILD/components/micropython/py/objstrunicode.c
index 29f7695..badb569 100644
--- a/MicroPython_BUILD/components/micropython/py/objstrunicode.c
+++ b/MicroPython_BUILD/components/micropython/py/objstrunicode.c
@@ -104,7 +104,7 @@ STATIC mp_obj_t uni_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
case MP_UNARY_OP_BOOL:
return mp_obj_new_bool(str_len != 0);
case MP_UNARY_OP_LEN:
- return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char *)str_data, str_len));
+ return MP_OBJ_NEW_SMALL_INT(utf8_charlen(str_data, str_len));
default:
return MP_OBJ_NULL; // op not supported
}
@@ -216,7 +216,7 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
++len;
}
}
- return mp_obj_new_str((const char*)s, len, true); // This will create a one-character string
+ return mp_obj_new_str_via_qstr((const char*)s, len); // This will create a one-character string
} else {
return MP_OBJ_NULL; // op not supported
}
@@ -291,7 +291,7 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
if (self->cur < len) {
const byte *cur = str + self->cur;
const byte *end = utf8_next_char(str + self->cur);
- mp_obj_t o_out = mp_obj_new_str((const char*)cur, end - cur, true);
+ mp_obj_t o_out = mp_obj_new_str_via_qstr((const char*)cur, end - cur);
self->cur += end - cur;
return o_out;
} else {
diff --git a/MicroPython_BUILD/components/micropython/py/objtype.c b/MicroPython_BUILD/components/micropython/py/objtype.c
index 6e2ab6c..7df349c 100644
--- a/MicroPython_BUILD/components/micropython/py/objtype.c
+++ b/MicroPython_BUILD/components/micropython/py/objtype.c
@@ -46,14 +46,6 @@ STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_
/******************************************************************************/
// instance object
-STATIC mp_obj_t mp_obj_new_instance(const mp_obj_type_t *class, size_t subobjs) {
- mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, subobjs);
- o->base.type = class;
- mp_map_init(&o->members, 0);
- mp_seq_clear(o->subobj, 0, subobjs, sizeof(*o->subobj));
- return MP_OBJ_FROM_PTR(o);
-}
-
STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {
int count = 0;
for (;;) {
@@ -67,6 +59,7 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t
} else if (type->parent == NULL) {
// No parents so end search here.
return count;
+ #if MICROPY_MULTIPLE_INHERITANCE
} else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {
// Multiple parents, search through them all recursively.
const mp_obj_tuple_t *parent_tuple = type->parent;
@@ -78,6 +71,7 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t
count += instance_count_native_bases(bt, last_native_base);
}
return count;
+ #endif
} else {
// A single parent, use iteration to continue the search.
type = type->parent;
@@ -85,6 +79,35 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t
}
}
+// This wrapper function is allows a subclass of a native type to call the
+// __init__() method (corresponding to type->make_new) of the native type.
+STATIC mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *args) {
+ mp_obj_instance_t *self = MP_OBJ_TO_PTR(args[0]);
+ const mp_obj_type_t *native_base = NULL;
+ instance_count_native_bases(self->base.type, &native_base);
+ self->subobj[0] = native_base->make_new(native_base, n_args - 1, 0, args + 1);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(native_base_init_wrapper_obj, 1, MP_OBJ_FUN_ARGS_MAX, native_base_init_wrapper);
+
+#if !MICROPY_CPYTHON_COMPAT
+STATIC
+#endif
+mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *class, const mp_obj_type_t **native_base) {
+ size_t num_native_bases = instance_count_native_bases(class, native_base);
+ assert(num_native_bases < 2);
+ mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, num_native_bases);
+ o->base.type = class;
+ mp_map_init(&o->members, 0);
+ // Initialise the native base-class slot (should be 1 at most) with a valid
+ // object. It doesn't matter which object, so long as it can be uniquely
+ // distinguished from a native class that is initialised.
+ if (num_native_bases != 0) {
+ o->subobj[0] = MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj);
+ }
+ return o;
+}
+
// TODO
// This implements depth-first left-to-right MRO, which is not compliant with Python3 MRO
// http://python-history.blogspot.com/2010/06/method-resolution-order.html
@@ -172,6 +195,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
if (type->parent == NULL) {
DEBUG_printf("mp_obj_class_lookup: No more parents\n");
return;
+ #if MICROPY_MULTIPLE_INHERITANCE
} else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {
const mp_obj_tuple_t *parent_tuple = type->parent;
const mp_obj_t *item = parent_tuple->items;
@@ -192,6 +216,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
// 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);
+ #endif
} else {
type = type->parent;
}
@@ -247,20 +272,6 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
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));
- const mp_obj_type_t *native_base;
- size_t num_native_bases = instance_count_native_bases(self, &native_base);
- assert(num_native_bases < 2);
-
- mp_obj_instance_t *o = MP_OBJ_TO_PTR(mp_obj_new_instance(self, num_native_bases));
-
- // This executes only "__new__" part of instance creation.
- // TODO: This won't work well for classes with native bases.
- // TODO: This is a hack, should be resolved along the lines of
- // https://github.com/micropython/micropython/issues/606#issuecomment-43685883
- if (n_args == 1 && *args == MP_OBJ_SENTINEL) {
- return MP_OBJ_FROM_PTR(o);
- }
-
// look for __new__ function
mp_obj_t init_fn[2] = {MP_OBJ_NULL};
struct class_lookup_data lookup = {
@@ -272,13 +283,22 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size
};
mp_obj_class_lookup(&lookup, self);
- mp_obj_t new_ret = MP_OBJ_FROM_PTR(o);
- if (init_fn[0] == MP_OBJ_SENTINEL) {
- // Native type's constructor is what wins - it gets all our arguments,
- // and none Python classes are initialized at all.
- o->subobj[0] = native_base->make_new(native_base, n_args, n_kw, args);
- } else if (init_fn[0] != MP_OBJ_NULL) {
- // now call Python class __new__ function with all args
+ const mp_obj_type_t *native_base = NULL;
+ mp_obj_instance_t *o;
+ if (init_fn[0] == MP_OBJ_NULL || init_fn[0] == MP_OBJ_SENTINEL) {
+ // Either there is no __new__() method defined or there is a native
+ // constructor. In both cases create a blank instance.
+ o = mp_obj_new_instance(self, &native_base);
+
+ // Since type->make_new() implements both __new__() and __init__() in
+ // one go, of which the latter may be overridden by the Python subclass,
+ // we defer (see the end of this function) the call of the native
+ // constructor to give a chance for the Python __init__() method to call
+ // said native constructor.
+
+ } else {
+ // Call Python class __new__ function with all args to create an instance
+ mp_obj_t new_ret;
if (n_args == 0 && n_kw == 0) {
mp_obj_t args2[1] = {MP_OBJ_FROM_PTR(self)};
new_ret = mp_call_function_n_kw(init_fn[0], 1, 0, args2);
@@ -290,17 +310,20 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size
m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw);
}
- }
+ // https://docs.python.org/3.4/reference/datamodel.html#object.__new__
+ // "If __new__() does not return an instance of cls, then the new
+ // instance's __init__() method will not be invoked."
+ if (mp_obj_get_type(new_ret) != self) {
+ return new_ret;
+ }
- // https://docs.python.org/3.4/reference/datamodel.html#object.__new__
- // "If __new__() does not return an instance of cls, then the new instance's __init__() method will not be invoked."
- if (mp_obj_get_type(new_ret) != self) {
- return new_ret;
+ // The instance returned by __new__() becomes the new object
+ o = MP_OBJ_TO_PTR(new_ret);
}
- o = MP_OBJ_TO_PTR(new_ret);
-
// now call Python class __init__ function with all args
+ // This method has a chance to call super().__init__() to construct a
+ // possible native base class.
init_fn[0] = init_fn[1] = MP_OBJ_NULL;
lookup.obj = o;
lookup.attr = MP_QSTR___init__;
@@ -329,6 +352,12 @@ 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);
+ }
+
return MP_OBJ_FROM_PTR(o);
}
@@ -420,7 +449,7 @@ const byte mp_binary_op_method_name[MP_BINARY_OP_NUM_RUNTIME] = {
[MP_BINARY_OP_LESS_EQUAL] = MP_QSTR___le__,
[MP_BINARY_OP_MORE_EQUAL] = MP_QSTR___ge__,
// MP_BINARY_OP_NOT_EQUAL, // a != b calls a == b and inverts result
- [MP_BINARY_OP_IN] = MP_QSTR___contains__,
+ [MP_BINARY_OP_CONTAINS] = MP_QSTR___contains__,
// All inplace methods are optional, and normal methods will be used
// as a fallback.
@@ -946,21 +975,21 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
if (self->locals_dict != NULL) {
assert(self->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now
mp_map_t *locals_map = &self->locals_dict->map;
+ if (locals_map->is_fixed) {
+ // can't apply delete/store to a fixed map
+ return;
+ }
if (dest[1] == MP_OBJ_NULL) {
// delete attribute
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
- // note that locals_map may be in ROM, so remove will fail in that case
if (elem != NULL) {
dest[0] = MP_OBJ_NULL; // indicate success
}
} else {
// store attribute
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
- // note that locals_map may be in ROM, so add will fail in that case
- if (elem != NULL) {
- elem->value = dest[1];
- dest[0] = MP_OBJ_NULL; // indicate success
- }
+ elem->value = dest[1];
+ dest[0] = MP_OBJ_NULL; // indicate success
}
}
}
@@ -983,12 +1012,12 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
// TODO might need to make a copy of locals_dict; at least that's how CPython does it
// Basic validation of base classes
- size_t len;
- mp_obj_t *items;
- mp_obj_tuple_get(bases_tuple, &len, &items);
- for (size_t i = 0; i < len; i++) {
- assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
- mp_obj_type_t *t = MP_OBJ_TO_PTR(items[i]);
+ 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++) {
+ assert(MP_OBJ_IS_TYPE(bases_items[i], &mp_type_type));
+ 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 (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
@@ -1014,17 +1043,21 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
//o->iternext = ; not implemented
o->buffer_p.get_buffer = instance_get_buffer;
- if (len > 0) {
+ 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->protocol = ((mp_obj_type_t*)MP_OBJ_TO_PTR(items[0]))->protocol;
+ o->protocol = ((mp_obj_type_t*)MP_OBJ_TO_PTR(bases_items[0]))->protocol;
- if (len >= 2) {
+ if (bases_len >= 2) {
+ #if MICROPY_MULTIPLE_INHERITANCE
o->parent = MP_OBJ_TO_PTR(bases_tuple);
+ #else
+ mp_raise_NotImplementedError("multiple inheritance not supported");
+ #endif
} else {
- o->parent = MP_OBJ_TO_PTR(items[0]);
+ o->parent = MP_OBJ_TO_PTR(bases_items[0]);
}
}
@@ -1099,26 +1132,48 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
.is_type = false,
};
+ // 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);
+ }
+
if (type->parent == NULL) {
// no parents, do nothing
+ #if MICROPY_MULTIPLE_INHERITANCE
} else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {
const mp_obj_tuple_t *parent_tuple = type->parent;
size_t len = parent_tuple->len;
const mp_obj_t *items = parent_tuple->items;
for (size_t i = 0; i < len; i++) {
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
+ if (MP_OBJ_TO_PTR(items[i]) == &mp_type_object) {
+ // The "object" type will be searched at the end of this function,
+ // 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) {
- return;
+ break;
}
}
- } else {
+ #endif
+ } else if (type->parent != &mp_type_object) {
mp_obj_class_lookup(&lookup, type->parent);
- if (dest[0] != MP_OBJ_NULL) {
- return;
- }
}
+ if (dest[0] != MP_OBJ_NULL) {
+ if (dest[0] == MP_OBJ_SENTINEL) {
+ // Looked up native __init__ so defer to it
+ dest[0] = MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj);
+ dest[1] = self->obj;
+ }
+ return;
+ }
+
+ // Reset meth_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;
+
mp_obj_class_lookup(&lookup, &mp_type_object);
}
@@ -1158,6 +1213,7 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
if (self->parent == NULL) {
// type has no parents
return false;
+ #if MICROPY_MULTIPLE_INHERITANCE
} else if (((mp_obj_base_t*)self->parent)->type == &mp_type_tuple) {
// get the base objects (they should be type objects)
const mp_obj_tuple_t *parent_tuple = self->parent;
@@ -1173,6 +1229,7 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
// search last base (simple tail recursion elimination)
object = *item;
+ #endif
} else {
// type has 1 parent
object = MP_OBJ_FROM_PTR(self->parent);
diff --git a/MicroPython_BUILD/components/micropython/py/objtype.h b/MicroPython_BUILD/components/micropython/py/objtype.h
index 52419f3..1f43130 100644
--- a/MicroPython_BUILD/components/micropython/py/objtype.h
+++ b/MicroPython_BUILD/components/micropython/py/objtype.h
@@ -37,6 +37,11 @@ typedef struct _mp_obj_instance_t {
// TODO maybe cache __getattr__ and __setattr__ for efficient lookup of them
} mp_obj_instance_t;
+#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);
+#endif
+
// this needs to be exposed for MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE to work
void mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest);
diff --git a/MicroPython_BUILD/components/micropython/py/opmethods.c b/MicroPython_BUILD/components/micropython/py/opmethods.c
index 1200ba3..247fa5b 100644
--- a/MicroPython_BUILD/components/micropython/py/opmethods.c
+++ b/MicroPython_BUILD/components/micropython/py/opmethods.c
@@ -24,7 +24,7 @@
* THE SOFTWARE.
*/
-#include "py/runtime0.h"
+#include "py/obj.h"
#include "py/builtin.h"
STATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) {
@@ -47,6 +47,6 @@ 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) {
mp_obj_type_t *type = mp_obj_get_type(lhs_in);
- return type->binary_op(MP_BINARY_OP_IN, lhs_in, rhs_in);
+ return 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/MicroPython_BUILD/components/micropython/py/parse.c b/MicroPython_BUILD/components/micropython/py/parse.c
index 8c51b03..8c12864 100644
--- a/MicroPython_BUILD/components/micropython/py/parse.c
+++ b/MicroPython_BUILD/components/micropython/py/parse.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013-2015 Damien P. George
+ * 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
@@ -58,15 +58,6 @@
// (un)comment to use rule names; for debugging
//#define USE_RULE_NAME (1)
-typedef struct _rule_t {
- byte rule_id;
- byte act;
-#ifdef USE_RULE_NAME
- const char *rule_name;
-#endif
- uint16_t arg[];
-} rule_t;
-
enum {
// define rules with a compile function
#define DEF_RULE(rule, comp, kind, ...) RULE_##rule,
@@ -84,6 +75,8 @@ enum {
#undef DEF_RULE_NC
};
+// Define an array of actions corresponding to each rule
+STATIC const uint8_t rule_act_table[] = {
#define or(n) (RULE_ACT_OR | n)
#define and(n) (RULE_ACT_AND | n)
#define and_ident(n) (RULE_ACT_AND | n | RULE_ACT_ALLOW_IDENT)
@@ -91,45 +84,129 @@ enum {
#define one_or_more (RULE_ACT_LIST | 2)
#define list (RULE_ACT_LIST | 1)
#define list_with_end (RULE_ACT_LIST | 3)
-#define tok(t) (RULE_ARG_TOK | MP_TOKEN_##t)
-#define rule(r) (RULE_ARG_RULE | RULE_##r)
-#define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r)
-#ifdef USE_RULE_NAME
-#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };
-#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };
-#else
-#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };
-#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };
-#endif
-#include "py/grammar.h"
-#undef or
-#undef and
-#undef list
-#undef list_with_end
-#undef tok
-#undef rule
-#undef opt_rule
-#undef one_or_more
-#undef DEF_RULE
-#undef DEF_RULE_NC
-STATIC const rule_t *const rules[] = {
-// define rules with a compile function
-#define DEF_RULE(rule, comp, kind, ...) &rule_##rule,
+#define DEF_RULE(rule, comp, kind, ...) kind,
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
- NULL, // RULE_const_object
-// define rules without a compile function
+ 0, // RULE_const_object
+
#define DEF_RULE(rule, comp, kind, ...)
-#define DEF_RULE_NC(rule, kind, ...) &rule_##rule,
+#define DEF_RULE_NC(rule, kind, ...) kind,
+#include "py/grammar.h"
+#undef DEF_RULE
+#undef DEF_RULE_NC
+
+#undef or
+#undef and
+#undef and_ident
+#undef and_blank
+#undef one_or_more
+#undef list
+#undef list_with_end
+};
+
+// Define the argument data for each rule, as a combined array
+STATIC const uint16_t rule_arg_combined_table[] = {
+#define tok(t) (RULE_ARG_TOK | MP_TOKEN_##t)
+#define rule(r) (RULE_ARG_RULE | RULE_##r)
+#define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r)
+
+#define DEF_RULE(rule, comp, kind, ...) __VA_ARGS__,
+#define DEF_RULE_NC(rule, kind, ...)
+#include "py/grammar.h"
+#undef DEF_RULE
+#undef DEF_RULE_NC
+
+#define DEF_RULE(rule, comp, kind, ...)
+#define DEF_RULE_NC(rule, kind, ...) __VA_ARGS__,
+#include "py/grammar.h"
+#undef DEF_RULE
+#undef DEF_RULE_NC
+
+#undef tok
+#undef rule
+#undef opt_rule
+};
+
+// Macro to create a list of N identifiers where N is the number of variable arguments to the macro
+#define RULE_EXPAND(x) x
+#define RULE_PADDING(rule, ...) RULE_PADDING2(rule, __VA_ARGS__, RULE_PADDING_IDS(rule))
+#define RULE_PADDING2(rule, ...) RULE_EXPAND(RULE_PADDING3(rule, __VA_ARGS__))
+#define RULE_PADDING3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, ...) __VA_ARGS__
+#define RULE_PADDING_IDS(r) PAD12_##r, PAD11_##r, PAD10_##r, PAD9_##r, PAD8_##r, PAD7_##r, PAD6_##r, PAD5_##r, PAD4_##r, PAD3_##r, PAD2_##r, PAD1_##r,
+
+// Use an enum to create constants specifying how much room a rule takes in rule_arg_combined_table
+enum {
+#define DEF_RULE(rule, comp, kind, ...) RULE_PADDING(rule, __VA_ARGS__)
+#define DEF_RULE_NC(rule, kind, ...)
+#include "py/grammar.h"
+#undef DEF_RULE
+#undef DEF_RULE_NC
+#define DEF_RULE(rule, comp, kind, ...)
+#define DEF_RULE_NC(rule, kind, ...) RULE_PADDING(rule, __VA_ARGS__)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
};
+// Macro to compute the start of a rule in rule_arg_combined_table
+#define RULE_ARG_OFFSET(rule, ...) RULE_ARG_OFFSET2(rule, __VA_ARGS__, RULE_ARG_OFFSET_IDS(rule))
+#define RULE_ARG_OFFSET2(rule, ...) RULE_EXPAND(RULE_ARG_OFFSET3(rule, __VA_ARGS__))
+#define RULE_ARG_OFFSET3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) _13
+#define RULE_ARG_OFFSET_IDS(r) PAD12_##r, PAD11_##r, PAD10_##r, PAD9_##r, PAD8_##r, PAD7_##r, PAD6_##r, PAD5_##r, PAD4_##r, PAD3_##r, PAD2_##r, PAD1_##r, PAD0_##r,
+
+// Use the above enum values to create a table of offsets for each rule's arg
+// data, which indexes rule_arg_combined_table. The offsets require 9 bits of
+// storage but only the lower 8 bits are stored here. The 9th bit is computed
+// in get_rule_arg using the FIRST_RULE_WITH_OFFSET_ABOVE_255 constant.
+STATIC const uint8_t rule_arg_offset_table[] = {
+#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) & 0xff,
+#define DEF_RULE_NC(rule, kind, ...)
+#include "py/grammar.h"
+#undef DEF_RULE
+#undef DEF_RULE_NC
+ 0, // RULE_const_object
+#define DEF_RULE(rule, comp, kind, ...)
+#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) & 0xff,
+#include "py/grammar.h"
+#undef DEF_RULE
+#undef DEF_RULE_NC
+};
+
+// Define a constant that's used to determine the 9th bit of the values in rule_arg_offset_table
+static const size_t FIRST_RULE_WITH_OFFSET_ABOVE_255 =
+#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) >= 0x100 ? RULE_##rule :
+#define DEF_RULE_NC(rule, kind, ...)
+#include "py/grammar.h"
+#undef DEF_RULE
+#undef DEF_RULE_NC
+#define DEF_RULE(rule, comp, kind, ...)
+#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) >= 0x100 ? RULE_##rule :
+#include "py/grammar.h"
+#undef DEF_RULE
+#undef DEF_RULE_NC
+0;
+
+#if USE_RULE_NAME
+// Define an array of rule names corresponding to each rule
+STATIC const char *const rule_name_table[] = {
+#define DEF_RULE(rule, comp, kind, ...) #rule,
+#define DEF_RULE_NC(rule, kind, ...)
+#include "py/grammar.h"
+#undef DEF_RULE
+#undef DEF_RULE_NC
+ "", // RULE_const_object
+#define DEF_RULE(rule, comp, kind, ...)
+#define DEF_RULE_NC(rule, kind, ...) #rule,
+#include "py/grammar.h"
+#undef DEF_RULE
+#undef DEF_RULE_NC
+};
+#endif
+
typedef struct _rule_stack_t {
size_t src_line : 8 * sizeof(size_t) - 8; // maximum bits storing source line number
size_t rule_id : 8; // this must be large enough to fit largest rule number
@@ -164,6 +241,14 @@ typedef struct _parser_t {
#endif
} parser_t;
+STATIC const uint16_t *get_rule_arg(uint8_t r_id) {
+ size_t off = rule_arg_offset_table[r_id];
+ if (r_id >= FIRST_RULE_WITH_OFFSET_ABOVE_255) {
+ off |= 0x100;
+ }
+ return &rule_arg_combined_table[off];
+}
+
STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) {
// use a custom memory allocator to store parse nodes sequentially in large chunks
@@ -205,7 +290,7 @@ STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) {
return ret;
}
-STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) {
+STATIC void push_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t arg_i) {
if (parser->rule_stack_top >= parser->rule_stack_alloc) {
rule_stack_t *rs = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC);
parser->rule_stack = rs;
@@ -213,21 +298,22 @@ STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, siz
}
rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++];
rs->src_line = src_line;
- rs->rule_id = rule->rule_id;
+ rs->rule_id = rule_id;
rs->arg_i = arg_i;
}
STATIC void push_rule_from_arg(parser_t *parser, size_t arg) {
assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE);
size_t rule_id = arg & RULE_ARG_ARG_MASK;
- push_rule(parser, parser->lexer->tok_line, rules[rule_id], 0);
+ push_rule(parser, parser->lexer->tok_line, rule_id, 0);
}
-STATIC void pop_rule(parser_t *parser, const rule_t **rule, size_t *arg_i, size_t *src_line) {
+STATIC uint8_t pop_rule(parser_t *parser, size_t *arg_i, size_t *src_line) {
parser->rule_stack_top -= 1;
- *rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];
+ uint8_t rule_id = parser->rule_stack[parser->rule_stack_top].rule_id;
*arg_i = parser->rule_stack[parser->rule_stack_top].arg_i;
*src_line = parser->rule_stack[parser->rule_stack_top].src_line;
+ return rule_id;
}
bool mp_parse_node_is_const_false(mp_parse_node_t pn) {
@@ -313,11 +399,11 @@ void mp_parse_node_print(mp_parse_node_t pn, size_t indent) {
#endif
} else {
size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
-#ifdef USE_RULE_NAME
- printf("%s(%u) (n=%u)\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns)]->rule_name, (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n);
-#else
+ #if USE_RULE_NAME
+ printf("%s(%u) (n=%u)\n", rule_name_table[MP_PARSE_NODE_STRUCT_KIND(pns)], (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n);
+ #else
printf("rule(%u) (n=%u)\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n);
-#endif
+ #endif
for (size_t i = 0; i < n; i++) {
mp_parse_node_print(pns->nodes[i], indent + 2);
}
@@ -369,7 +455,19 @@ STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line,
return (mp_parse_node_t)pn;
}
-STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
+STATIC mp_parse_node_t mp_parse_node_new_small_int_checked(parser_t *parser, mp_obj_t o_val) {
+ (void)parser;
+ mp_int_t val = MP_OBJ_SMALL_INT_VALUE(o_val);
+ #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
+ // A parse node is only 32-bits and the small-int value must fit in 31-bits
+ if (((val ^ (val << 1)) & 0xffffffff80000000) != 0) {
+ return make_node_const_object(parser, 0, o_val);
+ }
+ #endif
+ return mp_parse_node_new_small_int(val);
+}
+
+STATIC void push_result_token(parser_t *parser, uint8_t rule_id) {
mp_parse_node_t pn;
mp_lexer_t *lex = parser->lexer;
if (lex->tok_kind == MP_TOKEN_NAME) {
@@ -377,10 +475,10 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
#if MICROPY_COMP_CONST
// if name is a standalone identifier, look it up in the table of dynamic constants
mp_map_elem_t *elem;
- if (rule->rule_id == RULE_atom
+ if (rule_id == RULE_atom
&& (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) {
if (MP_OBJ_IS_SMALL_INT(elem->value)) {
- pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value));
+ pn = mp_parse_node_new_small_int_checked(parser, elem->value);
} else {
pn = make_node_const_object(parser, lex->tok_line, elem->value);
}
@@ -388,13 +486,13 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);
}
#else
- (void)rule;
+ (void)rule_id;
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);
#endif
} else if (lex->tok_kind == MP_TOKEN_INTEGER) {
mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex);
if (MP_OBJ_IS_SMALL_INT(o)) {
- pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(o));
+ pn = mp_parse_node_new_small_int_checked(parser, o);
} else {
pn = make_node_const_object(parser, lex->tok_line, o);
}
@@ -417,7 +515,7 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst);
} else {
// not interned, make a node holding a pointer to the string/bytes object
- mp_obj_t o = mp_obj_new_str_of_type(
+ mp_obj_t o = mp_obj_new_str_copy(
lex->tok_kind == MP_TOKEN_STRING ? &mp_type_str : &mp_type_bytes,
(const byte*)lex->vstr.buf, lex->vstr.len);
pn = make_node_const_object(parser, lex->tok_line, o);
@@ -442,12 +540,12 @@ STATIC const mp_rom_map_elem_t mp_constants_table[] = {
STATIC MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table);
#endif
-STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t num_args);
+STATIC void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args);
#if MICROPY_COMP_CONST_FOLDING
-STATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t *num_args) {
- if (rule->rule_id == RULE_or_test
- || rule->rule_id == RULE_and_test) {
+STATIC bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *num_args) {
+ if (rule_id == RULE_or_test
+ || rule_id == RULE_and_test) {
// folding for binary logical ops: or and
size_t copy_to = *num_args;
for (size_t i = copy_to; i > 0;) {
@@ -457,7 +555,7 @@ STATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t
// always need to keep the last value
break;
}
- if (rule->rule_id == RULE_or_test) {
+ if (rule_id == RULE_or_test) {
if (mp_parse_node_is_const_true(pn)) {
//
break;
@@ -484,7 +582,7 @@ STATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t
// we did a complete folding if there's only 1 arg left
return *num_args == 1;
- } else if (rule->rule_id == RULE_not_test_2) {
+ } else if (rule_id == RULE_not_test_2) {
// folding for unary logical op: not
mp_parse_node_t pn = peek_result(parser, 0);
if (mp_parse_node_is_const_false(pn)) {
@@ -502,23 +600,23 @@ STATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t
return false;
}
-STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args) {
+STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
// this code does folding of arbitrary integer expressions, eg 1 + 2 * 3 + 4
// it does not do partial folding, eg 1 + 2 + x -> 3 + x
mp_obj_t arg0;
- if (rule->rule_id == RULE_expr
- || rule->rule_id == RULE_xor_expr
- || rule->rule_id == RULE_and_expr) {
+ if (rule_id == RULE_expr
+ || rule_id == RULE_xor_expr
+ || rule_id == RULE_and_expr) {
// folding for binary ops: | ^ &
mp_parse_node_t pn = peek_result(parser, num_args - 1);
if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
return false;
}
mp_binary_op_t op;
- if (rule->rule_id == RULE_expr) {
+ if (rule_id == RULE_expr) {
op = MP_BINARY_OP_OR;
- } else if (rule->rule_id == RULE_xor_expr) {
+ } else if (rule_id == RULE_xor_expr) {
op = MP_BINARY_OP_XOR;
} else {
op = MP_BINARY_OP_AND;
@@ -531,9 +629,9 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
}
arg0 = mp_binary_op(op, arg0, arg1);
}
- } else if (rule->rule_id == RULE_shift_expr
- || rule->rule_id == RULE_arith_expr
- || rule->rule_id == RULE_term) {
+ } else if (rule_id == RULE_shift_expr
+ || rule_id == RULE_arith_expr
+ || rule_id == RULE_term) {
// folding for binary ops: << >> + - * / % //
mp_parse_node_t pn = peek_result(parser, num_args - 1);
if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
@@ -577,7 +675,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
}
arg0 = mp_binary_op(op, arg0, arg1);
}
- } else if (rule->rule_id == RULE_factor_2) {
+ } else if (rule_id == RULE_factor_2) {
// folding for unary ops: + - ~
mp_parse_node_t pn = peek_result(parser, 0);
if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
@@ -596,7 +694,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
arg0 = mp_unary_op(op, arg0);
#if MICROPY_COMP_CONST
- } else if (rule->rule_id == RULE_expr_stmt) {
+ } else if (rule_id == RULE_expr_stmt) {
mp_parse_node_t pn1 = peek_result(parser, 0);
if (!MP_PARSE_NODE_IS_NULL(pn1)
&& !(MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_augassign)
@@ -635,7 +733,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
if (qstr_str(id)[0] == '_') {
pop_result(parser); // pop const(value)
pop_result(parser); // pop id
- push_result_rule(parser, 0, rules[RULE_pass_stmt], 0); // replace with "pass"
+ push_result_rule(parser, 0, RULE_pass_stmt, 0); // replace with "pass"
return true;
}
@@ -651,7 +749,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
#endif
#if MICROPY_COMP_MODULE_CONST
- } else if (rule->rule_id == RULE_atom_expr_normal) {
+ } else if (rule_id == RULE_atom_expr_normal) {
mp_parse_node_t pn0 = peek_result(parser, 1);
mp_parse_node_t pn1 = peek_result(parser, 0);
if (!(MP_PARSE_NODE_IS_ID(pn0)
@@ -686,7 +784,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
pop_result(parser);
}
if (MP_OBJ_IS_SMALL_INT(arg0)) {
- push_result_node(parser, mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(arg0)));
+ push_result_node(parser, mp_parse_node_new_small_int_checked(parser, arg0));
} else {
// TODO reuse memory for parse node struct?
push_result_node(parser, make_node_const_object(parser, 0, arg0));
@@ -696,9 +794,9 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
}
#endif
-STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t num_args) {
+STATIC void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args) {
// optimise away parenthesis around an expression if possible
- if (rule->rule_id == RULE_atom_paren) {
+ if (rule_id == RULE_atom_paren) {
// there should be just 1 arg for this rule
mp_parse_node_t pn = peek_result(parser, 0);
if (MP_PARSE_NODE_IS_NULL(pn)) {
@@ -712,11 +810,11 @@ STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *ru
}
#if MICROPY_COMP_CONST_FOLDING
- if (fold_logical_constants(parser, rule, &num_args)) {
+ if (fold_logical_constants(parser, rule_id, &num_args)) {
// we folded this rule so return straight away
return;
}
- if (fold_constants(parser, rule, num_args)) {
+ if (fold_constants(parser, rule_id, num_args)) {
// we folded this rule so return straight away
return;
}
@@ -724,7 +822,7 @@ STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *ru
mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * num_args);
pn->source_line = src_line;
- pn->kind_num_nodes = (rule->rule_id & 0xff) | (num_args << 8);
+ pn->kind_num_nodes = (rule_id & 0xff) | (num_args << 8);
for (size_t i = num_args; i > 0; i--) {
pn->nodes[i - 1] = pop_result(parser);
}
@@ -761,14 +859,11 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;
default: top_level_rule = RULE_file_input;
}
- push_rule(&parser, lex->tok_line, rules[top_level_rule], 0);
+ push_rule(&parser, lex->tok_line, top_level_rule, 0);
// parse!
- size_t n, i; // state for the current rule
- size_t rule_src_line; // source line for the first token matched by the current rule
bool backtrack = false;
- const rule_t *rule = NULL;
for (;;) {
next_rule:
@@ -776,19 +871,24 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
break;
}
- pop_rule(&parser, &rule, &i, &rule_src_line);
- n = rule->act & RULE_ACT_ARG_MASK;
+ // Pop the next rule to process it
+ size_t i; // state for the current rule
+ size_t rule_src_line; // source line for the first token matched by the current rule
+ uint8_t rule_id = pop_rule(&parser, &i, &rule_src_line);
+ uint8_t rule_act = rule_act_table[rule_id];
+ const uint16_t *rule_arg = get_rule_arg(rule_id);
+ size_t n = rule_act & RULE_ACT_ARG_MASK;
- /*
+ #if 0
// debugging
- printf("depth=%d ", parser.rule_stack_top);
+ printf("depth=" UINT_FMT " ", parser.rule_stack_top);
for (int j = 0; j < parser.rule_stack_top; ++j) {
printf(" ");
}
- printf("%s n=%d i=%d bt=%d\n", rule->rule_name, n, i, backtrack);
- */
+ printf("%s n=" UINT_FMT " i=" UINT_FMT " bt=%d\n", rule_name_table[rule_id], n, i, backtrack);
+ #endif
- switch (rule->act & RULE_ACT_KIND_MASK) {
+ switch (rule_act & RULE_ACT_KIND_MASK) {
case RULE_ACT_OR:
if (i > 0 && !backtrack) {
goto next_rule;
@@ -796,19 +896,19 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
backtrack = false;
}
for (; i < n; ++i) {
- uint16_t kind = rule->arg[i] & RULE_ARG_KIND_MASK;
+ uint16_t kind = rule_arg[i] & RULE_ARG_KIND_MASK;
if (kind == RULE_ARG_TOK) {
- if (lex->tok_kind == (rule->arg[i] & RULE_ARG_ARG_MASK)) {
- push_result_token(&parser, rule);
+ if (lex->tok_kind == (rule_arg[i] & RULE_ARG_ARG_MASK)) {
+ push_result_token(&parser, rule_id);
mp_lexer_to_next(lex);
goto next_rule;
}
} else {
assert(kind == RULE_ARG_RULE);
if (i + 1 < n) {
- push_rule(&parser, rule_src_line, rule, i + 1); // save this or-rule
+ push_rule(&parser, rule_src_line, rule_id, i + 1); // save this or-rule
}
- push_rule_from_arg(&parser, rule->arg[i]); // push child of or-rule
+ push_rule_from_arg(&parser, rule_arg[i]); // push child of or-rule
goto next_rule;
}
}
@@ -820,7 +920,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
// failed, backtrack if we can, else syntax error
if (backtrack) {
assert(i > 0);
- if ((rule->arg[i - 1] & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE) {
+ if ((rule_arg[i - 1] & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE) {
// an optional rule that failed, so continue with next arg
push_result_node(&parser, MP_PARSE_NODE_NULL);
backtrack = false;
@@ -837,13 +937,13 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
// progress through the rule
for (; i < n; ++i) {
- if ((rule->arg[i] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
+ if ((rule_arg[i] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
// need to match a token
- mp_token_kind_t tok_kind = rule->arg[i] & RULE_ARG_ARG_MASK;
+ mp_token_kind_t tok_kind = rule_arg[i] & RULE_ARG_ARG_MASK;
if (lex->tok_kind == tok_kind) {
// matched token
if (tok_kind == MP_TOKEN_NAME) {
- push_result_token(&parser, rule);
+ push_result_token(&parser, rule_id);
}
mp_lexer_to_next(lex);
} else {
@@ -858,8 +958,8 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
}
}
} else {
- push_rule(&parser, rule_src_line, rule, i + 1); // save this and-rule
- push_rule_from_arg(&parser, rule->arg[i]); // push child of and-rule
+ push_rule(&parser, rule_src_line, rule_id, i + 1); // save this and-rule
+ push_rule_from_arg(&parser, rule_arg[i]); // push child of and-rule
goto next_rule;
}
}
@@ -870,7 +970,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
#if !MICROPY_ENABLE_DOC_STRING
// this code discards lonely statements, such as doc strings
- if (input_kind != MP_PARSE_SINGLE_INPUT && rule->rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) {
+ if (input_kind != MP_PARSE_SINGLE_INPUT && rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) {
mp_parse_node_t p = peek_result(&parser, 1);
if ((MP_PARSE_NODE_IS_LEAF(p) && !MP_PARSE_NODE_IS_ID(p))
|| MP_PARSE_NODE_IS_STRUCT_KIND(p, RULE_const_object)) {
@@ -879,7 +979,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
// Pushing the "pass" rule here will overwrite any RULE_const_object
// entry that was on the result stack, allowing the GC to reclaim
// the memory from the const object when needed.
- push_result_rule(&parser, rule_src_line, rules[RULE_pass_stmt], 0);
+ push_result_rule(&parser, rule_src_line, RULE_pass_stmt, 0);
break;
}
}
@@ -890,8 +990,8 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
size_t num_not_nil = 0;
for (size_t x = n; x > 0;) {
--x;
- if ((rule->arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
- mp_token_kind_t tok_kind = rule->arg[x] & RULE_ARG_ARG_MASK;
+ if ((rule_arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
+ mp_token_kind_t tok_kind = rule_arg[x] & RULE_ARG_ARG_MASK;
if (tok_kind == MP_TOKEN_NAME) {
// only tokens which were names are pushed to stack
i += 1;
@@ -906,7 +1006,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
}
}
- if (num_not_nil == 1 && (rule->act & RULE_ACT_ALLOW_IDENT)) {
+ if (num_not_nil == 1 && (rule_act & RULE_ACT_ALLOW_IDENT)) {
// this rule has only 1 argument and should not be emitted
mp_parse_node_t pn = MP_PARSE_NODE_NULL;
for (size_t x = 0; x < i; ++x) {
@@ -919,19 +1019,19 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
} else {
// this rule must be emitted
- if (rule->act & RULE_ACT_ADD_BLANK) {
+ if (rule_act & RULE_ACT_ADD_BLANK) {
// and add an extra blank node at the end (used by the compiler to store data)
push_result_node(&parser, MP_PARSE_NODE_NULL);
i += 1;
}
- push_result_rule(&parser, rule_src_line, rule, i);
+ push_result_rule(&parser, rule_src_line, rule_id, i);
}
break;
}
default: {
- assert((rule->act & RULE_ACT_KIND_MASK) == RULE_ACT_LIST);
+ assert((rule_act & RULE_ACT_KIND_MASK) == RULE_ACT_LIST);
// n=2 is: item item*
// n=1 is: item (sep item)*
@@ -969,13 +1069,13 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
}
} else {
for (;;) {
- size_t arg = rule->arg[i & 1 & n];
+ size_t arg = rule_arg[i & 1 & n];
if ((arg & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
if (lex->tok_kind == (arg & RULE_ARG_ARG_MASK)) {
if (i & 1 & n) {
// separators which are tokens are not pushed to result stack
} else {
- push_result_token(&parser, rule);
+ push_result_token(&parser, rule_id);
}
mp_lexer_to_next(lex);
// got element of list, so continue parsing list
@@ -988,7 +1088,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
}
} else {
assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE);
- push_rule(&parser, rule_src_line, rule, i + 1); // save this list-rule
+ push_rule(&parser, rule_src_line, rule_id, i + 1); // save this list-rule
push_rule_from_arg(&parser, arg); // push child of list-rule
goto next_rule;
}
@@ -998,7 +1098,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
// compute number of elements in list, result in i
i -= 1;
- if ((n & 1) && (rule->arg[1] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
+ if ((n & 1) && (rule_arg[1] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
// don't count separators when they are tokens
i = (i + 1) / 2;
}
@@ -1007,12 +1107,12 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
// list matched single item
if (had_trailing_sep) {
// if there was a trailing separator, make a list of a single item
- push_result_rule(&parser, rule_src_line, rule, i);
+ push_result_rule(&parser, rule_src_line, rule_id, i);
} else {
// just leave single item on stack (ie don't wrap in a list)
}
} else {
- push_result_rule(&parser, rule_src_line, rule, i);
+ push_result_rule(&parser, rule_src_line, rule_id, i);
}
break;
}
diff --git a/MicroPython_BUILD/components/micropython/py/parsenum.c b/MicroPython_BUILD/components/micropython/py/parsenum.c
index b62029f..124489c 100644
--- a/MicroPython_BUILD/components/micropython/py/parsenum.c
+++ b/MicroPython_BUILD/components/micropython/py/parsenum.c
@@ -170,6 +170,19 @@ typedef enum {
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
+
+// 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
+#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
+#define DEC_VAL_MAX 1e20F
+#define SMALL_NORMAL_VAL (1e-37F)
+#define SMALL_NORMAL_EXP (-37)
+#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
+#define DEC_VAL_MAX 1e200
+#define SMALL_NORMAL_VAL (1e-307)
+#define SMALL_NORMAL_EXP (-307)
+#endif
+
const char *top = str + len;
mp_float_t dec_val = 0;
bool dec_neg = false;
@@ -214,8 +227,8 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool
// string should be a decimal number
parse_dec_in_t in = PARSE_DEC_IN_INTG;
bool exp_neg = false;
- mp_float_t frac_mult = 0.1;
mp_int_t exp_val = 0;
+ mp_int_t exp_extra = 0;
while (str < top) {
mp_uint_t dig = *str++;
if ('0' <= dig && dig <= '9') {
@@ -223,11 +236,18 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool
if (in == PARSE_DEC_IN_EXP) {
exp_val = 10 * exp_val + dig;
} else {
- if (in == PARSE_DEC_IN_FRAC) {
- dec_val += dig * frac_mult;
- frac_mult *= MICROPY_FLOAT_CONST(0.1);
- } 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;
+ }
+ } 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;
+ }
}
}
} else if (in == PARSE_DEC_IN_INTG && dig == '.') {
@@ -260,7 +280,12 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool
exp_val = -exp_val;
}
- // apply the exponent
+ // apply the exponent, making sure it's not a subnormal value
+ exp_val += exp_extra;
+ if (exp_val < SMALL_NORMAL_EXP) {
+ exp_val -= SMALL_NORMAL_EXP;
+ dec_val *= SMALL_NORMAL_VAL;
+ }
dec_val *= MICROPY_FLOAT_C_FUN(pow)(10, exp_val);
}
diff --git a/MicroPython_BUILD/components/micropython/py/persistentcode.c b/MicroPython_BUILD/components/micropython/py/persistentcode.c
index e0bb8f1..7113b0d 100644
--- a/MicroPython_BUILD/components/micropython/py/persistentcode.c
+++ b/MicroPython_BUILD/components/micropython/py/persistentcode.c
@@ -200,7 +200,11 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) {
// create raw_code and return it
mp_raw_code_t *rc = mp_emit_glue_new_raw_code();
- mp_emit_glue_assign_bytecode(rc, bytecode, bc_len, const_table,
+ mp_emit_glue_assign_bytecode(rc, bytecode,
+ #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
+ bc_len,
+ #endif
+ const_table,
#if MICROPY_PERSISTENT_CODE_SAVE
n_obj, n_raw_code,
#endif
diff --git a/MicroPython_BUILD/components/micropython/py/py.mk b/MicroPython_BUILD/components/micropython/py/py.mk
index e69618b..902e2fd 100644
--- a/MicroPython_BUILD/components/micropython/py/py.mk
+++ b/MicroPython_BUILD/components/micropython/py/py.mk
@@ -62,6 +62,7 @@ endif
# py object files
PY_O_BASENAME = \
mpstate.o \
+ nlr.o \
nlrx86.o \
nlrx64.o \
nlrthumb.o \
@@ -69,6 +70,7 @@ PY_O_BASENAME = \
nlrsetjmp.o \
malloc.o \
gc.o \
+ pystack.o \
qstr.o \
vstr.o \
mpprint.o \
@@ -115,6 +117,7 @@ PY_O_BASENAME = \
objcell.o \
objclosure.o \
objcomplex.o \
+ objdeque.o \
objdict.o \
objenumerate.o \
objexcept.o \
diff --git a/MicroPython_BUILD/components/micropython/py/pystack.c b/MicroPython_BUILD/components/micropython/py/pystack.c
new file mode 100644
index 0000000..552e59d
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/py/pystack.c
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 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
+
+#include "py/runtime.h"
+
+#if MICROPY_ENABLE_PYSTACK
+
+void mp_pystack_init(void *start, void *end) {
+ MP_STATE_THREAD(pystack_start) = start;
+ MP_STATE_THREAD(pystack_end) = end;
+ MP_STATE_THREAD(pystack_cur) = start;
+}
+
+void *mp_pystack_alloc(size_t n_bytes) {
+ n_bytes = (n_bytes + (MICROPY_PYSTACK_ALIGN - 1)) & ~(MICROPY_PYSTACK_ALIGN - 1);
+ #if MP_PYSTACK_DEBUG
+ n_bytes += MICROPY_PYSTACK_ALIGN;
+ #endif
+ if (MP_STATE_THREAD(pystack_cur) + n_bytes > MP_STATE_THREAD(pystack_end)) {
+ // out of memory in the pystack
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError,
+ MP_OBJ_NEW_QSTR(MP_QSTR_pystack_space_exhausted)));
+ }
+ void *ptr = MP_STATE_THREAD(pystack_cur);
+ MP_STATE_THREAD(pystack_cur) += n_bytes;
+ #if MP_PYSTACK_DEBUG
+ *(size_t*)(MP_STATE_THREAD(pystack_cur) - MICROPY_PYSTACK_ALIGN) = n_bytes;
+ #endif
+ return ptr;
+}
+
+#endif
diff --git a/MicroPython_BUILD/components/micropython/py/pystack.h b/MicroPython_BUILD/components/micropython/py/pystack.h
new file mode 100644
index 0000000..82ac374
--- /dev/null
+++ b/MicroPython_BUILD/components/micropython/py/pystack.h
@@ -0,0 +1,123 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 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.
+ */
+#ifndef MICROPY_INCLUDED_PY_PYSTACK_H
+#define MICROPY_INCLUDED_PY_PYSTACK_H
+
+#include "py/mpstate.h"
+
+// Enable this debugging option to check that the amount of memory freed is
+// consistent with amounts that were previously allocated.
+#define MP_PYSTACK_DEBUG (0)
+
+#if MICROPY_ENABLE_PYSTACK
+
+void mp_pystack_init(void *start, void *end);
+void *mp_pystack_alloc(size_t n_bytes);
+
+// This function can free multiple continuous blocks at once: just pass the
+// pointer to the block that was allocated first and it and all subsequently
+// allocated blocks will be freed.
+static inline void mp_pystack_free(void *ptr) {
+ assert((uint8_t*)ptr >= MP_STATE_THREAD(pystack_start));
+ assert((uint8_t*)ptr <= MP_STATE_THREAD(pystack_cur));
+ #if MP_PYSTACK_DEBUG
+ size_t n_bytes_to_free = MP_STATE_THREAD(pystack_cur) - (uint8_t*)ptr;
+ size_t n_bytes = *(size_t*)(MP_STATE_THREAD(pystack_cur) - MICROPY_PYSTACK_ALIGN);
+ while (n_bytes < n_bytes_to_free) {
+ n_bytes += *(size_t*)(MP_STATE_THREAD(pystack_cur) - n_bytes - MICROPY_PYSTACK_ALIGN);
+ }
+ if (n_bytes != n_bytes_to_free) {
+ mp_printf(&mp_plat_print, "mp_pystack_free() failed: %u != %u\n", (uint)n_bytes_to_free,
+ (uint)*(size_t*)(MP_STATE_THREAD(pystack_cur) - MICROPY_PYSTACK_ALIGN));
+ assert(0);
+ }
+ #endif
+ MP_STATE_THREAD(pystack_cur) = (uint8_t*)ptr;
+}
+
+static inline void mp_pystack_realloc(void *ptr, size_t n_bytes) {
+ mp_pystack_free(ptr);
+ mp_pystack_alloc(n_bytes);
+}
+
+static inline size_t mp_pystack_usage(void) {
+ return MP_STATE_THREAD(pystack_cur) - MP_STATE_THREAD(pystack_start);
+}
+
+static inline size_t mp_pystack_limit(void) {
+ return MP_STATE_THREAD(pystack_end) - MP_STATE_THREAD(pystack_start);
+}
+
+#endif
+
+#if !MICROPY_ENABLE_PYSTACK
+
+#define mp_local_alloc(n_bytes) alloca(n_bytes)
+
+static inline void mp_local_free(void *ptr) {
+ (void)ptr;
+}
+
+static inline void *mp_nonlocal_alloc(size_t n_bytes) {
+ return m_new(uint8_t, n_bytes);
+}
+
+static inline void *mp_nonlocal_realloc(void *ptr, size_t old_n_bytes, size_t new_n_bytes) {
+ return m_renew(uint8_t, ptr, old_n_bytes, new_n_bytes);
+}
+
+static inline void mp_nonlocal_free(void *ptr, size_t n_bytes) {
+ m_del(uint8_t, ptr, n_bytes);
+}
+
+#else
+
+static inline void *mp_local_alloc(size_t n_bytes) {
+ return mp_pystack_alloc(n_bytes);
+}
+
+static inline void mp_local_free(void *ptr) {
+ mp_pystack_free(ptr);
+}
+
+static inline void *mp_nonlocal_alloc(size_t n_bytes) {
+ return mp_pystack_alloc(n_bytes);
+}
+
+static inline void *mp_nonlocal_realloc(void *ptr, size_t old_n_bytes, size_t new_n_bytes) {
+ (void)old_n_bytes;
+ mp_pystack_realloc(ptr, new_n_bytes);
+ return ptr;
+}
+
+static inline void mp_nonlocal_free(void *ptr, size_t n_bytes) {
+ (void)n_bytes;
+ mp_pystack_free(ptr);
+}
+
+#endif
+
+#endif // MICROPY_INCLUDED_PY_PYSTACK_H
diff --git a/MicroPython_BUILD/components/micropython/py/qstr.c b/MicroPython_BUILD/components/micropython/py/qstr.c
index 95c9b68..08c3e25 100644
--- a/MicroPython_BUILD/components/micropython/py/qstr.c
+++ b/MicroPython_BUILD/components/micropython/py/qstr.c
@@ -127,14 +127,12 @@ void qstr_init(void) {
STATIC const byte *find_qstr(qstr q) {
// search pool for this qstr
- for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL; pool = pool->prev) {
- if (q >= pool->total_prev_len) {
- return pool->qstrs[q - pool->total_prev_len];
- }
+ // total_prev_len==0 in the final pool, so the loop will always terminate
+ qstr_pool_t *pool = MP_STATE_VM(last_pool);
+ while (q < pool->total_prev_len) {
+ pool = pool->prev;
}
-
- // not found
- return 0;
+ return pool->qstrs[q - pool->total_prev_len];
}
// qstr_mutex must be taken while in this function
@@ -243,29 +241,6 @@ qstr qstr_from_strn(const char *str, size_t len) {
return q;
}
-byte *qstr_build_start(size_t len, byte **q_ptr) {
- assert(len < (1 << (8 * MICROPY_QSTR_BYTES_IN_LEN)));
- *q_ptr = m_new(byte, MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len + 1);
- Q_SET_LENGTH(*q_ptr, len);
- return Q_GET_DATA(*q_ptr);
-}
-
-qstr qstr_build_end(byte *q_ptr) {
- QSTR_ENTER();
- qstr q = qstr_find_strn((const char*)Q_GET_DATA(q_ptr), Q_GET_LENGTH(q_ptr));
- if (q == 0) {
- size_t len = Q_GET_LENGTH(q_ptr);
- mp_uint_t hash = qstr_compute_hash(Q_GET_DATA(q_ptr), len);
- Q_SET_HASH(q_ptr, hash);
- q_ptr[MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len] = '\0';
- q = qstr_add(q_ptr);
- } else {
- m_del(byte, q_ptr, Q_GET_ALLOC(q_ptr));
- }
- QSTR_EXIT();
- return q;
-}
-
mp_uint_t qstr_hash(qstr q) {
return Q_GET_HASH(find_qstr(q));
}
diff --git a/MicroPython_BUILD/components/micropython/py/qstr.h b/MicroPython_BUILD/components/micropython/py/qstr.h
index e2bdcc3..f4375ee 100644
--- a/MicroPython_BUILD/components/micropython/py/qstr.h
+++ b/MicroPython_BUILD/components/micropython/py/qstr.h
@@ -56,6 +56,7 @@ typedef struct _qstr_pool_t {
} qstr_pool_t;
#define QSTR_FROM_STR_STATIC(s) (qstr_from_strn((s), strlen(s)))
+#define QSTR_TOTAL() (MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len)
void qstr_init(void);
@@ -65,9 +66,6 @@ qstr qstr_find_strn(const char *str, size_t str_len); // returns MP_QSTR_NULL if
qstr qstr_from_str(const char *str);
qstr qstr_from_strn(const char *str, size_t len);
-byte *qstr_build_start(size_t len, byte **q_ptr);
-qstr qstr_build_end(byte *q_ptr);
-
mp_uint_t qstr_hash(qstr q);
const char *qstr_str(qstr q);
size_t qstr_len(qstr q);
diff --git a/MicroPython_BUILD/components/micropython/py/qstrdefs.h b/MicroPython_BUILD/components/micropython/py/qstrdefs.h
index 4ded5be..a609058 100644
--- a/MicroPython_BUILD/components/micropython/py/qstrdefs.h
+++ b/MicroPython_BUILD/components/micropython/py/qstrdefs.h
@@ -40,6 +40,7 @@ Q(/)
Q(%#o)
Q(%#x)
Q({:#b})
+Q( )
Q(\n)
Q(maximum recursion depth exceeded)
Q()
@@ -51,3 +52,7 @@ Q()
Q()
Q()
Q(utf-8)
+
+#if MICROPY_ENABLE_PYSTACK
+Q(pystack exhausted)
+#endif
diff --git a/MicroPython_BUILD/components/micropython/py/repl.c b/MicroPython_BUILD/components/micropython/py/repl.c
index 7e8922e..61ae2c1 100644
--- a/MicroPython_BUILD/components/micropython/py/repl.c
+++ b/MicroPython_BUILD/components/micropython/py/repl.c
@@ -27,6 +27,7 @@
#include
#include "py/obj.h"
#include "py/runtime.h"
+#include "py/builtin.h"
#include "py/repl.h"
#if MICROPY_HELPER_REPL
@@ -136,8 +137,11 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print
}
}
- // begin search in locals dict
- mp_obj_dict_t *dict = mp_locals_get();
+ size_t nqstr = QSTR_TOTAL();
+
+ // begin search in outer global dict which is accessed from __main__
+ mp_obj_t obj = MP_OBJ_FROM_PTR(&mp_module___main__);
+ mp_obj_t dest[2];
for (;;) {
// get next word in string to complete
@@ -148,43 +152,20 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print
size_t s_len = str - s_start;
if (str < top) {
- // a complete word, lookup in current dict
-
- mp_obj_t obj = MP_OBJ_NULL;
- for (size_t i = 0; i < dict->map.alloc; i++) {
- if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
- size_t d_len;
- const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
- if (s_len == d_len && strncmp(s_start, d_str, d_len) == 0) {
- obj = dict->map.table[i].value;
- break;
- }
- }
+ // a complete word, lookup in current object
+ qstr q = qstr_find_strn(s_start, s_len);
+ if (q == MP_QSTR_NULL) {
+ // lookup will fail
+ return 0;
}
+ mp_load_method_maybe(obj, q, dest);
+ obj = dest[0]; // attribute, method, or MP_OBJ_NULL if nothing found
if (obj == MP_OBJ_NULL) {
// lookup failed
return 0;
}
- // found an object of this name; try to get its dict
- if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) {
- dict = mp_obj_module_get_globals(obj);
- } else {
- mp_obj_type_t *type;
- if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) {
- type = MP_OBJ_TO_PTR(obj);
- } else {
- type = mp_obj_get_type(obj);
- }
- if (type->locals_dict != NULL && type->locals_dict->base.type == &mp_type_dict) {
- dict = type->locals_dict;
- } else {
- // obj has no dict
- return 0;
- }
- }
-
// skip '.' to move to next word
++str;
@@ -192,14 +173,15 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print
// end of string, do completion on this partial name
// look for matches
- int n_found = 0;
const char *match_str = NULL;
size_t match_len = 0;
- for (size_t i = 0; i < dict->map.alloc; i++) {
- if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
- size_t d_len;
- const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
- if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {
+ qstr q_first = 0, q_last;
+ for (qstr q = 1; q < nqstr; ++q) {
+ size_t d_len;
+ const char *d_str = (const char*)qstr_data(q, &d_len);
+ if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {
+ mp_load_method_maybe(obj, q, dest);
+ if (dest[0] != MP_OBJ_NULL) {
if (match_str == NULL) {
match_str = d_str;
match_len = d_len;
@@ -213,13 +195,16 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print
}
}
}
- ++n_found;
+ if (q_first == 0) {
+ q_first = q;
+ }
+ q_last = q;
}
}
}
// nothing found
- if (n_found == 0) {
+ if (q_first == 0) {
// If there're no better alternatives, and if it's first word
// in the line, try to complete "import".
if (s_start == org_str) {
@@ -234,7 +219,7 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print
}
// 1 match found, or multiple matches with a common prefix
- if (n_found == 1 || match_len > s_len) {
+ if (q_first == q_last || match_len > s_len) {
*compl_str = match_str + s_len;
return match_len - s_len;
}
@@ -245,11 +230,12 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print
#define MAX_LINE_LEN (4 * WORD_SLOT_LEN)
int line_len = MAX_LINE_LEN; // force a newline for first word
- for (size_t i = 0; i < dict->map.alloc; i++) {
- if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
- size_t d_len;
- const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
- if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {
+ for (qstr q = q_first; q <= q_last; ++q) {
+ size_t d_len;
+ const char *d_str = (const char*)qstr_data(q, &d_len);
+ if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {
+ mp_load_method_maybe(obj, q, dest);
+ if (dest[0] != MP_OBJ_NULL) {
int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len;
if (gap < 2) {
gap += WORD_SLOT_LEN;
diff --git a/MicroPython_BUILD/components/micropython/py/ringbuf.h b/MicroPython_BUILD/components/micropython/py/ringbuf.h
index 399849b..b9b40aa 100644
--- a/MicroPython_BUILD/components/micropython/py/ringbuf.h
+++ b/MicroPython_BUILD/components/micropython/py/ringbuf.h
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
+ * Copyright (c) 2018 LoBo (https://github.com/loboris)
*
* 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/MicroPython_BUILD/components/micropython/py/runtime.c b/MicroPython_BUILD/components/micropython/py/runtime.c
index 0599f80..219ec22 100644
--- a/MicroPython_BUILD/components/micropython/py/runtime.c
+++ b/MicroPython_BUILD/components/micropython/py/runtime.c
@@ -122,7 +122,6 @@ void mp_init(void) {
#if MICROPY_PY_THREAD_GIL
mp_thread_mutex_init(&MP_STATE_VM(gil_mutex));
- MP_STATE_VM(thread_lock) = 0;
#endif
MP_THREAD_GIL_ENTER();
@@ -215,7 +214,7 @@ void mp_delete_global(qstr qst) {
}
mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) {
- DEBUG_OP_printf("unary " UINT_FMT " %p\n", op, arg);
+ DEBUG_OP_printf("unary " UINT_FMT " %q %p\n", op, mp_unary_op_method_name[op], arg);
if (op == MP_UNARY_OP_NOT) {
// "not x" is the negative of whether "x" is true per Python semantics
@@ -276,7 +275,7 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) {
}
mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
- DEBUG_OP_printf("binary " UINT_FMT " %p %p\n", op, lhs, rhs);
+ DEBUG_OP_printf("binary " UINT_FMT " %q %p %p\n", op, mp_binary_op_method_name[op], lhs, rhs);
// TODO correctly distinguish inplace operators for mutable objects
// lookup logic that CPython uses for +=:
@@ -414,7 +413,6 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
// use standard precision
return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val);
}
- break;
}
case MP_BINARY_OP_FLOOR_DIVIDE:
case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:
@@ -489,10 +487,10 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
return MP_OBJ_FROM_PTR(tuple);
}
- case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val); break;
- case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val); break;
- case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val); break;
- case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val); break;
+ case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val);
+ case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val);
+ case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val);
+ case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val);
default:
goto unsupported_op;
@@ -524,38 +522,12 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
}
}
- /* deal with `in`
- *
- * NOTE `a in b` is `b.__contains__(a)`, hence why the generic dispatch
- * needs to go below with swapped arguments
- */
+ // Convert MP_BINARY_OP_IN to MP_BINARY_OP_CONTAINS with swapped args.
if (op == MP_BINARY_OP_IN) {
- mp_obj_type_t *type = mp_obj_get_type(rhs);
- if (type->binary_op != NULL) {
- mp_obj_t res = type->binary_op(op, rhs, lhs);
- if (res != MP_OBJ_NULL) {
- return res;
- }
- }
- if (type->getiter != NULL) {
- /* second attempt, walk the iterator */
- mp_obj_iter_buf_t iter_buf;
- mp_obj_t iter = mp_getiter(rhs, &iter_buf);
- mp_obj_t next;
- while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
- if (mp_obj_equal(next, lhs)) {
- return mp_const_true;
- }
- }
- return mp_const_false;
- }
-
- if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_TypeError("object not iterable");
- } else {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
- "'%s' object is not iterable", mp_obj_get_type_str(rhs)));
- }
+ op = MP_BINARY_OP_CONTAINS;
+ mp_obj_t temp = lhs;
+ lhs = rhs;
+ rhs = temp;
}
// generic binary_op supplied by type
@@ -584,6 +556,20 @@ generic_binary_op:
}
#endif
+ if (op == MP_BINARY_OP_CONTAINS) {
+ // If type didn't support containment then explicitly walk the iterator.
+ // mp_getiter will raise the appropriate exception if lhs is not iterable.
+ mp_obj_iter_buf_t iter_buf;
+ mp_obj_t iter = mp_getiter(lhs, &iter_buf);
+ mp_obj_t next;
+ while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
+ if (mp_obj_equal(next, rhs)) {
+ return mp_const_true;
+ }
+ }
+ return mp_const_false;
+ }
+
unsupported_op:
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
mp_raise_TypeError("unsupported type for operator");
@@ -682,7 +668,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
// allocate memory for the new array of args
args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len);
- args2 = m_new(mp_obj_t, args2_alloc);
+ args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t));
// copy the self
if (self != MP_OBJ_NULL) {
@@ -703,7 +689,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
// allocate memory for the new array of args
args2_alloc = 1 + n_args + len + 2 * (n_kw + kw_dict_len);
- args2 = m_new(mp_obj_t, args2_alloc);
+ args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t));
// copy the self
if (self != MP_OBJ_NULL) {
@@ -719,7 +705,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
// allocate memory for the new array of args
args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len) + 3;
- args2 = m_new(mp_obj_t, args2_alloc);
+ args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t));
// copy the self
if (self != MP_OBJ_NULL) {
@@ -736,7 +722,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if (args2_len >= args2_alloc) {
- args2 = m_renew(mp_obj_t, args2, args2_alloc, args2_alloc * 2);
+ args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t), args2_alloc * 2 * sizeof(mp_obj_t));
args2_alloc *= 2;
}
args2[args2_len++] = item;
@@ -762,8 +748,8 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
if (MP_MAP_SLOT_IS_FILLED(map, i)) {
// the key must be a qstr, so intern it if it's a string
mp_obj_t key = map->table[i].key;
- if (MP_OBJ_IS_TYPE(key, &mp_type_str)) {
- key = mp_obj_str_intern(key);
+ if (!MP_OBJ_IS_QSTR(key)) {
+ key = mp_obj_str_intern_checked(key);
}
args2[args2_len++] = key;
args2[args2_len++] = map->table[i].value;
@@ -787,13 +773,13 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
if (new_alloc < 4) {
new_alloc = 4;
}
- args2 = m_renew(mp_obj_t, args2, args2_alloc, new_alloc);
+ args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t), new_alloc * sizeof(mp_obj_t));
args2_alloc = new_alloc;
}
// the key must be a qstr, so intern it if it's a string
- if (MP_OBJ_IS_TYPE(key, &mp_type_str)) {
- key = mp_obj_str_intern(key);
+ if (!MP_OBJ_IS_QSTR(key)) {
+ key = mp_obj_str_intern_checked(key);
}
// get the value corresponding to the key
@@ -819,7 +805,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ob
mp_call_prepare_args_n_kw_var(have_self, n_args_n_kw, args, &out_args);
mp_obj_t res = mp_call_function_n_kw(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args);
- m_del(mp_obj_t, out_args.args, out_args.n_alloc);
+ mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t));
return res;
}
@@ -1229,13 +1215,12 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th
if (type->iternext != NULL && send_value == mp_const_none) {
mp_obj_t ret = type->iternext(self_in);
+ *ret_val = ret;
if (ret != MP_OBJ_STOP_ITERATION) {
- *ret_val = ret;
return MP_VM_RETURN_YIELD;
} else {
// Emulate raise StopIteration()
// Special case, handled in vm.c
- *ret_val = MP_OBJ_NULL;
return MP_VM_RETURN_NORMAL;
}
}
@@ -1297,7 +1282,7 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th
// will be propagated up. This behavior is approved by test_pep380.py
// test_delegation_of_close_to_non_generator(),
// test_delegating_throw_to_non_generator()
- *ret_val = throw_value;
+ *ret_val = mp_make_raise_obj(throw_value);
return MP_VM_RETURN_EXCEPTION;
}
}
@@ -1351,6 +1336,8 @@ import_error:
return dest[0];
}
+ #if MICROPY_ENABLE_EXTERNAL_IMPORT
+
// See if it's a package, then can try FS import
if (!mp_obj_is_package(module)) {
goto import_error;
@@ -1361,11 +1348,12 @@ import_error:
const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len);
const uint dot_name_len = pkg_name_len + 1 + qstr_len(name);
- char *dot_name = alloca(dot_name_len);
+ char *dot_name = mp_local_alloc(dot_name_len);
memcpy(dot_name, pkg_name, pkg_name_len);
dot_name[pkg_name_len] = '.';
memcpy(dot_name + pkg_name_len + 1, qstr_str(name), qstr_len(name));
qstr dot_name_q = qstr_from_strn(dot_name, dot_name_len);
+ mp_local_free(dot_name);
mp_obj_t args[5];
args[0] = MP_OBJ_NEW_QSTR(dot_name_q);
@@ -1376,6 +1364,13 @@ import_error:
// TODO lookup __import__ and call that instead of going straight to builtin implementation
return mp_builtin___import__(5, args);
+
+ #else
+
+ // Package import not supported with external imports disabled
+ goto import_error;
+
+ #endif
}
void mp_import_all(mp_obj_t module) {
@@ -1469,3 +1464,10 @@ NORETURN void mp_raise_OSError(int errno_) {
NORETURN void mp_raise_NotImplementedError(const char *msg) {
mp_raise_msg(&mp_type_NotImplementedError, msg);
}
+
+#if MICROPY_STACK_CHECK || MICROPY_ENABLE_PYSTACK
+NORETURN void mp_raise_recursion_depth(void) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError,
+ MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded)));
+}
+#endif
diff --git a/MicroPython_BUILD/components/micropython/py/runtime.h b/MicroPython_BUILD/components/micropython/py/runtime.h
index 7e47646..3fe5be9 100644
--- a/MicroPython_BUILD/components/micropython/py/runtime.h
+++ b/MicroPython_BUILD/components/micropython/py/runtime.h
@@ -28,6 +28,7 @@
#define MICROPY_INCLUDED_PY_RUNTIME_H
#include "py/mpstate.h"
+#include "py/pystack.h"
typedef enum {
MP_VM_RETURN_NORMAL,
@@ -149,8 +150,9 @@ mp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args);
mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args);
mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, size_t n_kw, const mp_obj_t *args);
// Call function and catch/dump exception - for Python callbacks from C code
-void mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg);
-void mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);
+// (return MP_OBJ_NULL in case of exception).
+mp_obj_t mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg);
+mp_obj_t mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);
typedef struct _mp_call_args_t {
mp_obj_t fun;
@@ -193,7 +195,7 @@ NORETURN void mp_raise_ValueError(const char *msg);
NORETURN void mp_raise_TypeError(const char *msg);
NORETURN void mp_raise_NotImplementedError(const char *msg);
NORETURN void mp_raise_OSError(int errno_);
-NORETURN void mp_exc_recursion_depth(void);
+NORETURN void mp_raise_recursion_depth(void);
#if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
#undef mp_check_self
diff --git a/MicroPython_BUILD/components/micropython/py/runtime0.h b/MicroPython_BUILD/components/micropython/py/runtime0.h
index a72b7fe..960532d 100644
--- a/MicroPython_BUILD/components/micropython/py/runtime0.h
+++ b/MicroPython_BUILD/components/micropython/py/runtime0.h
@@ -131,6 +131,10 @@ typedef enum {
#endif
,
+ // The runtime will convert MP_BINARY_OP_IN to this operator with swapped args.
+ // A type should implement this containment operator instead of MP_BINARY_OP_IN.
+ MP_BINARY_OP_CONTAINS,
+
MP_BINARY_OP_NUM_RUNTIME,
// These 2 are not supported by the runtime and must be synthesised by the emitter
diff --git a/MicroPython_BUILD/components/micropython/py/runtime_utils.c b/MicroPython_BUILD/components/micropython/py/runtime_utils.c
index a5c5403..b92c6bd 100644
--- a/MicroPython_BUILD/components/micropython/py/runtime_utils.c
+++ b/MicroPython_BUILD/components/micropython/py/runtime_utils.c
@@ -27,22 +27,26 @@
#include "py/runtime.h"
-void mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg) {
+mp_obj_t mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
- mp_call_function_1(fun, arg);
+ mp_obj_t ret = mp_call_function_1(fun, arg);
nlr_pop();
+ return ret;
} else {
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
+ return MP_OBJ_NULL;
}
}
-void mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) {
+mp_obj_t mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
- mp_call_function_2(fun, arg1, arg2);
+ mp_obj_t ret = mp_call_function_2(fun, arg1, arg2);
nlr_pop();
+ return ret;
} else {
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
+ return MP_OBJ_NULL;
}
}
diff --git a/MicroPython_BUILD/components/micropython/py/scheduler.c b/MicroPython_BUILD/components/micropython/py/scheduler.c
index d4cbd3b..aba5c26 100644
--- a/MicroPython_BUILD/components/micropython/py/scheduler.c
+++ b/MicroPython_BUILD/components/micropython/py/scheduler.c
@@ -139,28 +139,28 @@ static mp_obj_t make_arg_from_carg(mp_sched_carg_t *carg, int level)
for (int i = 0; i < carg->n; i++) {
mp_sched_carg_entry_t *entry = (mp_sched_carg_entry_t *)carg->entry[i];
if (entry->type == MP_SCHED_ENTRY_TYPE_INT) {
- mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false),
+ mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key)),
mp_obj_new_int(entry->ival));
}
else if (entry->type == MP_SCHED_ENTRY_TYPE_BOOL) {
- mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false),
+ mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key)),
mp_obj_new_bool(entry->ival));
}
else if (entry->type == MP_SCHED_ENTRY_TYPE_FLOAT) {
- mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false),
+ mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key)),
mp_obj_new_float(entry->fval));
}
else if (entry->type == MP_SCHED_ENTRY_TYPE_STR) {
- mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false),
- mp_obj_new_str((const char*)entry->sval, entry->ival, false));
+ mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key)),
+ mp_obj_new_str((const char*)entry->sval, entry->ival));
}
else if (entry->type == MP_SCHED_ENTRY_TYPE_BYTES) {
- mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false),
+ mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key)),
mp_obj_new_bytes((const byte*)entry->sval, entry->ival));
}
else if ((level == 0) && (entry->type == MP_SCHED_ENTRY_TYPE_CARG) && (strlen(entry->key) > 0) && (entry->carg)) {
mp_obj_t darg = make_arg_from_carg(entry->carg, 1);
- mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false), darg);
+ mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key)), darg);
}
}
arg = dct;
@@ -180,7 +180,7 @@ static mp_obj_t make_arg_from_carg(mp_sched_carg_t *carg, int level)
tuple[i] = mp_obj_new_float(entry->fval);
}
else if (entry->type == MP_SCHED_ENTRY_TYPE_STR) {
- tuple[i] = mp_obj_new_str((const char*)entry->sval, entry->ival, false);
+ tuple[i] = mp_obj_new_str((const char*)entry->sval, entry->ival);
}
else if (entry->type == MP_SCHED_ENTRY_TYPE_BYTES) {
tuple[i] = mp_obj_new_bytes((const byte*)entry->sval, entry->ival);
@@ -205,7 +205,7 @@ static mp_obj_t make_arg_from_carg(mp_sched_carg_t *carg, int level)
arg = mp_obj_new_float(entry->fval);
}
else if (entry->type == MP_SCHED_ENTRY_TYPE_STR) {
- arg = mp_obj_new_str((const char*)entry->sval, entry->ival, false);
+ arg = mp_obj_new_str((const char*)entry->sval, entry->ival);
}
else if (entry->type == MP_SCHED_ENTRY_TYPE_BYTES) {
arg = mp_obj_new_bytes((const byte*)entry->sval, entry->ival);
diff --git a/MicroPython_BUILD/components/micropython/py/smallint.h b/MicroPython_BUILD/components/micropython/py/smallint.h
index 42679a7..6a3c752 100644
--- a/MicroPython_BUILD/components/micropython/py/smallint.h
+++ b/MicroPython_BUILD/components/micropython/py/smallint.h
@@ -50,10 +50,10 @@
#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
-#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)0xffffffff80000000) >> 1))
-#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & 0xffffffff80000000) == 0)
+#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)0xffff800000000000) >> 1))
+#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & 0xffff800000000000) == 0)
// Mask to truncate mp_int_t to positive value
-#define MP_SMALL_INT_POSITIVE_MASK ~(0xffffffff80000000 | (0xffffffff80000000 >> 1))
+#define MP_SMALL_INT_POSITIVE_MASK ~(0xffff800000000000 | (0xffff800000000000 >> 1))
#endif
diff --git a/MicroPython_BUILD/components/micropython/py/stackctrl.c b/MicroPython_BUILD/components/micropython/py/stackctrl.c
index 7cd35fe..5c07796 100644
--- a/MicroPython_BUILD/components/micropython/py/stackctrl.c
+++ b/MicroPython_BUILD/components/micropython/py/stackctrl.c
@@ -48,14 +48,9 @@ void mp_stack_set_limit(mp_uint_t limit) {
MP_STATE_THREAD(stack_limit) = limit;
}
-void mp_exc_recursion_depth(void) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError,
- MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded)));
-}
-
void mp_stack_check(void) {
if (mp_stack_usage() >= MP_STATE_THREAD(stack_limit)) {
- mp_exc_recursion_depth();
+ mp_raise_recursion_depth();
}
}
diff --git a/MicroPython_BUILD/components/micropython/py/unicode.c b/MicroPython_BUILD/components/micropython/py/unicode.c
index 140b7ba..935dc90 100644
--- a/MicroPython_BUILD/components/micropython/py/unicode.c
+++ b/MicroPython_BUILD/components/micropython/py/unicode.c
@@ -67,9 +67,9 @@ STATIC const uint8_t attr[] = {
AT_LO, AT_LO, AT_LO, AT_PR, AT_PR, AT_PR, AT_PR, 0
};
-// TODO: Rename to str_get_char
-unichar utf8_get_char(const byte *s) {
#if MICROPY_PY_BUILTINS_STR_UNICODE
+
+unichar utf8_get_char(const byte *s) {
unichar ord = *s++;
if (!UTF8_IS_NONASCII(ord)) return ord;
ord &= 0x7F;
@@ -80,22 +80,14 @@ unichar utf8_get_char(const byte *s) {
ord = (ord << 6) | (*s++ & 0x3F);
}
return ord;
-#else
- return *s;
-#endif
}
-// TODO: Rename to str_next_char
const byte *utf8_next_char(const byte *s) {
-#if MICROPY_PY_BUILTINS_STR_UNICODE
++s;
while (UTF8_IS_CONT(*s)) {
++s;
}
return s;
-#else
- return s + 1;
-#endif
}
mp_uint_t utf8_ptr_to_index(const byte *s, const byte *ptr) {
@@ -109,21 +101,18 @@ mp_uint_t utf8_ptr_to_index(const byte *s, const byte *ptr) {
return i;
}
-// TODO: Rename to str_charlen
-mp_uint_t unichar_charlen(const char *str, mp_uint_t len) {
-#if MICROPY_PY_BUILTINS_STR_UNICODE
- mp_uint_t charlen = 0;
- for (const char *top = str + len; str < top; ++str) {
+size_t utf8_charlen(const byte *str, size_t len) {
+ size_t charlen = 0;
+ for (const byte *top = str + len; str < top; ++str) {
if (!UTF8_IS_CONT(*str)) {
++charlen;
}
}
return charlen;
-#else
- return len;
-#endif
}
+#endif
+
// Be aware: These unichar_is* functions are actually ASCII-only!
bool unichar_isspace(unichar c) {
return c < 128 && (attr[c] & FL_SPACE) != 0;
@@ -183,6 +172,8 @@ mp_uint_t unichar_xdigit_value(unichar c) {
return n;
}
+#if MICROPY_PY_BUILTINS_STR_UNICODE
+
bool utf8_check(const byte *p, size_t len) {
uint8_t need = 0;
const byte *end = p + len;
@@ -210,3 +201,5 @@ bool utf8_check(const byte *p, size_t len) {
}
return need == 0; // no pending fragments allowed
}
+
+#endif
diff --git a/MicroPython_BUILD/components/micropython/py/vm.c b/MicroPython_BUILD/components/micropython/py/vm.c
index debf86d..d913f20 100644
--- a/MicroPython_BUILD/components/micropython/py/vm.c
+++ b/MicroPython_BUILD/components/micropython/py/vm.c
@@ -5,8 +5,8 @@
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2014 Paul Sokolovsky
- * Copyright (c) 2018 LoBo (https://github.com/loboris)
- *
+* Copyright (c) 2018 LoBo (https://github.com/loboris)
+ *
* 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
@@ -50,14 +50,6 @@
// top element.
// Exception stack also grows up, top element is also pointed at.
-// Exception stack unwind reasons (WHY_* in CPython-speak)
-// TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds
-// left to do encoded in the JUMP number
-typedef enum {
- UNWIND_RETURN = 1,
- UNWIND_JUMP,
-} mp_unwind_reason_t;
-
#define DECODE_UINT \
mp_uint_t unum = 0; \
do { \
@@ -128,7 +120,6 @@ typedef enum {
// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) {
mp_hal_set_wdt_tmo(); // LoBo
-
#define SELECTIVE_EXC_IP (0)
#if SELECTIVE_EXC_IP
#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */
@@ -617,29 +608,18 @@ dispatch_loop:
mp_call_method_n_kw(3, 0, sp);
SET_TOP(mp_const_none);
} else if (MP_OBJ_IS_SMALL_INT(TOP())) {
- mp_int_t cause_val = MP_OBJ_SMALL_INT_VALUE(TOP());
- if (cause_val == UNWIND_RETURN) {
- // stack: (..., __exit__, ctx_mgr, ret_val, UNWIND_RETURN)
- mp_obj_t ret_val = sp[-1];
- sp[-1] = mp_const_none;
- sp[0] = mp_const_none;
- sp[1] = mp_const_none;
- mp_call_method_n_kw(3, 0, sp - 3);
- sp[-3] = ret_val;
- sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN);
- } else {
- assert(cause_val == UNWIND_JUMP);
- // stack: (..., __exit__, ctx_mgr, dest_ip, num_exc, UNWIND_JUMP)
- mp_obj_t dest_ip = sp[-2];
- mp_obj_t num_exc = sp[-1];
- sp[-2] = mp_const_none;
- sp[-1] = mp_const_none;
- sp[0] = mp_const_none;
- mp_call_method_n_kw(3, 0, sp - 4);
- sp[-4] = dest_ip;
- sp[-3] = num_exc;
- sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP);
- }
+ // Getting here there are two distinct cases:
+ // - unwind return, stack: (..., __exit__, ctx_mgr, ret_val, SMALL_INT(-1))
+ // - unwind jump, stack: (..., __exit__, ctx_mgr, dest_ip, SMALL_INT(num_exc))
+ // For both cases we do exactly the same thing.
+ mp_obj_t data = sp[-1];
+ mp_obj_t cause = sp[0];
+ sp[-1] = mp_const_none;
+ sp[0] = mp_const_none;
+ sp[1] = mp_const_none;
+ mp_call_method_n_kw(3, 0, sp - 3);
+ sp[-3] = data;
+ sp[-2] = cause;
sp -= 2; // we removed (__exit__, ctx_mgr)
} else {
assert(mp_obj_is_exception_instance(TOP()));
@@ -684,10 +664,11 @@ unwind_jump:;
// of a "with" block contains the context manager info.
// We're going to run "finally" code as a coroutine
// (not calling it recursively). Set up a sentinel
- // on a stack so it can return back to us when it is
+ // on the stack so it can return back to us when it is
// done (when WITH_CLEANUP or END_FINALLY reached).
- PUSH((mp_obj_t)unum); // push number of exception handlers left to unwind
- PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
+ // The sentinel is the number of exception handlers left to
+ // unwind, which is a non-negative integer.
+ PUSH(MP_OBJ_NEW_SMALL_INT(unum));
ip = exc_sp->handler; // get exception handler byte code address
exc_sp--; // pop exception handler
goto dispatch_loop; // run the exception handler
@@ -724,11 +705,14 @@ unwind_jump:;
} else if (MP_OBJ_IS_SMALL_INT(TOP())) {
// We finished "finally" coroutine and now dispatch back
// to our caller, based on TOS value
- mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
- if (reason == UNWIND_RETURN) {
+ mp_int_t cause = MP_OBJ_SMALL_INT_VALUE(POP());
+ if (cause < 0) {
+ // A negative cause indicates unwind return
goto unwind_return;
} else {
- assert(reason == UNWIND_JUMP);
+ // Otherwise it's an unwind jump and we must push as a raw
+ // number the number of exception handlers to unwind
+ PUSH((mp_obj_t)cause);
goto unwind_jump;
}
} else {
@@ -939,8 +923,11 @@ unwind_jump:;
#if MICROPY_STACKLESS_STRICT
else {
deep_recursion_error:
- mp_exc_recursion_depth();
+ mp_raise_recursion_depth();
}
+ #else
+ // If we couldn't allocate codestate on heap, in
+ // non non-strict case fall thru to stack allocation.
#endif
}
#endif
@@ -967,7 +954,11 @@ unwind_jump:;
mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
out_args.n_args, out_args.n_kw, out_args.args);
- m_del(mp_obj_t, out_args.args, out_args.n_alloc);
+ #if !MICROPY_ENABLE_PYSTACK
+ // Freeing args at this point does not follow a LIFO order so only do it if
+ // pystack is not enabled. For pystack, they are freed when code_state is.
+ mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t));
+ #endif
if (new_state) {
new_state->prev = code_state;
code_state = new_state;
@@ -978,6 +969,9 @@ unwind_jump:;
else {
goto deep_recursion_error;
}
+ #else
+ // If we couldn't allocate codestate on heap, in
+ // non non-strict case fall thru to stack allocation.
#endif
}
#endif
@@ -1012,6 +1006,9 @@ unwind_jump:;
else {
goto deep_recursion_error;
}
+ #else
+ // If we couldn't allocate codestate on heap, in
+ // non non-strict case fall thru to stack allocation.
#endif
}
#endif
@@ -1038,7 +1035,11 @@ unwind_jump:;
mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
out_args.n_args, out_args.n_kw, out_args.args);
- m_del(mp_obj_t, out_args.args, out_args.n_alloc);
+ #if !MICROPY_ENABLE_PYSTACK
+ // Freeing args at this point does not follow a LIFO order so only do it if
+ // pystack is not enabled. For pystack, they are freed when code_state is.
+ mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t));
+ #endif
if (new_state) {
new_state->prev = code_state;
code_state = new_state;
@@ -1049,6 +1050,9 @@ unwind_jump:;
else {
goto deep_recursion_error;
}
+ #else
+ // If we couldn't allocate codestate on heap, in
+ // non non-strict case fall thru to stack allocation.
#endif
}
#endif
@@ -1085,7 +1089,7 @@ unwind_return:
// (not calling it recursively). Set up a sentinel
// on a stack so it can return back to us when it is
// done (when WITH_CLEANUP or END_FINALLY reached).
- PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
+ PUSH(MP_OBJ_NEW_SMALL_INT(-1));
ip = exc_sp->handler;
exc_sp--;
goto dispatch_loop;
@@ -1100,7 +1104,15 @@ unwind_return:
if (code_state->prev != NULL) {
mp_obj_t res = *sp;
mp_globals_set(code_state->old_globals);
- code_state = code_state->prev;
+ mp_code_state_t *new_code_state = code_state->prev;
+ #if MICROPY_ENABLE_PYSTACK
+ // Free code_state, and args allocated by mp_call_prepare_args_n_kw_var
+ // (The latter is implicitly freed when using pystack due to its LIFO nature.)
+ // The sizeof in the following statement does not include the size of the variable
+ // part of the struct. This arg is anyway not used if pystack is enabled.
+ mp_nonlocal_free(code_state, sizeof(mp_code_state_t));
+ #endif
+ code_state = new_code_state;
*code_state->sp = res;
goto run_code_state;
}
@@ -1153,6 +1165,7 @@ yield:
mp_obj_t send_value = POP();
mp_obj_t t_exc = MP_OBJ_NULL;
mp_obj_t ret_value;
+ code_state->sp = sp; // Save sp because it's needed if mp_resume raises StopIteration
if (inject_exc != MP_OBJ_NULL) {
t_exc = inject_exc;
inject_exc = MP_OBJ_NULL;
@@ -1168,8 +1181,7 @@ yield:
} else if (ret_kind == MP_VM_RETURN_NORMAL) {
// Pop exhausted gen
sp--;
- // TODO: When ret_value can be MP_OBJ_NULL here??
- if (ret_value == MP_OBJ_NULL || ret_value == MP_OBJ_STOP_ITERATION) {
+ if (ret_value == MP_OBJ_STOP_ITERATION) {
// Optimize StopIteration
// TODO: get StopIteration's value
PUSH(mp_const_none);
@@ -1316,16 +1328,15 @@ pending_exception_check:
#endif
#if MICROPY_ENABLE_SCHEDULER
// can only switch threads if the scheduler is unlocked
- if ((MP_STATE_VM(sched_state) == MP_SCHED_IDLE) && !MP_STATE_VM(thread_lock))
+ if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE)
#endif
{
- mp_hal_reset_wdt();// LoBo
- // *** Switch threads ***
- MP_THREAD_GIL_EXIT();
- MP_THREAD_GIL_ENTER();
+ mp_hal_reset_wdt();// LoBo
+ MP_THREAD_GIL_EXIT();
+ MP_THREAD_GIL_ENTER();
}
}
- #endif // MICROPY_PY_THREAD_GIL
+ #endif
} // for loop
@@ -1354,7 +1365,8 @@ exception_handler:
} 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
- *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
+ // (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
}
@@ -1367,8 +1379,7 @@ unwind_loop:
// set file and line number that the exception occurred at
// TODO: don't set traceback for exceptions re-raised by END_FINALLY.
// But consider how to handle nested exceptions.
- // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
- if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
+ if (nlr.ret_val != &mp_const_GeneratorExit_obj) {
const byte *ip = code_state->fun_bc->bytecode;
ip = mp_decode_uint_skip(ip); // skip n_state
ip = mp_decode_uint_skip(ip); // skip n_exc_stack
@@ -1444,7 +1455,15 @@ unwind_loop:
#if MICROPY_STACKLESS
} else if (code_state->prev != NULL) {
mp_globals_set(code_state->old_globals);
- code_state = code_state->prev;
+ mp_code_state_t *new_code_state = code_state->prev;
+ #if MICROPY_ENABLE_PYSTACK
+ // Free code_state, and args allocated by mp_call_prepare_args_n_kw_var
+ // (The latter is implicitly freed when using pystack due to its LIFO nature.)
+ // The sizeof in the following statement does not include the size of the variable
+ // part of the struct. This arg is anyway not used if pystack is enabled.
+ mp_nonlocal_free(code_state, sizeof(mp_code_state_t));
+ #endif
+ code_state = new_code_state;
size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode);
fastn = &code_state->state[n_state - 1];
exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);
diff --git a/MicroPython_BUILD/components/micropython/tools/mpy-tool.py b/MicroPython_BUILD/components/micropython/tools/mpy-tool.py
index ac7b2c1..eeb760a 100755
--- a/MicroPython_BUILD/components/micropython/tools/mpy-tool.py
+++ b/MicroPython_BUILD/components/micropython/tools/mpy-tool.py
@@ -287,7 +287,9 @@ class RawCode:
# generate constant objects
for i, obj in enumerate(self.objs):
obj_name = 'const_obj_%s_%u' % (self.escaped_name, i)
- if is_str_type(obj) or is_bytes_type(obj):
+ if obj is Ellipsis:
+ print('#define %s mp_const_ellipsis_obj' % obj_name)
+ elif is_str_type(obj) or is_bytes_type(obj):
if is_str_type(obj):
obj = bytes_cons(obj, 'utf8')
obj_type = 'mp_type_str'
@@ -328,7 +330,6 @@ class RawCode:
print('STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};'
% (obj_name, obj.real, obj.imag))
else:
- # TODO
raise FreezeError(self, 'freezing of object %r is not implemented' % (obj,))
# generate constant table, if it has any entries
diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip
index 046b4cf..5a3746c 100644
Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip differ
diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip
index a56abe7..be7dc00 100644
Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip differ
diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip
index 4e3e261..fe70ef6 100644
Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip differ
diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip
index c1065b4..e46b653 100644
Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip differ
diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip
index 0830410..1bf0867 100644
Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip differ
diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip
index fa273ba..6791a69 100644
Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip differ
diff --git a/MicroPython_BUILD/firmware/esp32/sdkconfig b/MicroPython_BUILD/firmware/esp32/sdkconfig
index df09967..6559673 100644
--- a/MicroPython_BUILD/firmware/esp32/sdkconfig
+++ b/MicroPython_BUILD/firmware/esp32/sdkconfig
@@ -228,6 +228,11 @@ CONFIG_BT_ENABLED=
CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0
CONFIG_BT_RESERVE_DRAM=0
+#
+# ADC configuration
+#
+CONFIG_ADC_FORCE_XPD_FSM=
+
#
# ESP32-specific
#
@@ -296,6 +301,7 @@ CONFIG_ESP32_TIME_SYSCALL_USE_NONE=
CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL=
CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
+CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES=100
CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
CONFIG_ESP32_XTAL_FREQ_40=
CONFIG_ESP32_XTAL_FREQ_26=
@@ -305,6 +311,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE=
CONFIG_NO_BLOBS=
CONFIG_ESP_TIMER_PROFILING=
CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS=
+CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
#
# Wi-Fi
@@ -379,6 +386,9 @@ CONFIG_FATFS_LFN_NONE=
CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_LFN_STACK=
CONFIG_FATFS_MAX_LFN=127
+CONFIG_FATFS_API_ENCODING_ANSI_OEM=y
+CONFIG_FATFS_API_ENCODING_UTF_16=
+CONFIG_FATFS_API_ENCODING_UTF_8=
CONFIG_FATFS_FS_LOCK=0
CONFIG_FATFS_TIMEOUT_MS=10000
CONFIG_FATFS_PER_FILE_CACHE=
diff --git a/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin
index a41eeba..7e3f652 100644
Binary files a/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin differ
diff --git a/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin
index 6a15f97..4230aea 100644
Binary files a/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin differ
diff --git a/MicroPython_BUILD/firmware/esp32_all/sdkconfig b/MicroPython_BUILD/firmware/esp32_all/sdkconfig
index 7d8e9ed..b4ae80b 100644
--- a/MicroPython_BUILD/firmware/esp32_all/sdkconfig
+++ b/MicroPython_BUILD/firmware/esp32_all/sdkconfig
@@ -219,6 +219,11 @@ CONFIG_BT_ENABLED=
CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0
CONFIG_BT_RESERVE_DRAM=0
+#
+# ADC configuration
+#
+CONFIG_ADC_FORCE_XPD_FSM=
+
#
# ESP32-specific
#
@@ -287,6 +292,7 @@ CONFIG_ESP32_TIME_SYSCALL_USE_NONE=
CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL=
CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
+CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES=100
CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
CONFIG_ESP32_XTAL_FREQ_40=
CONFIG_ESP32_XTAL_FREQ_26=
@@ -296,6 +302,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE=
CONFIG_NO_BLOBS=
CONFIG_ESP_TIMER_PROFILING=
CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS=
+CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
#
# Wi-Fi
@@ -370,6 +377,9 @@ CONFIG_FATFS_LFN_NONE=
CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_LFN_STACK=
CONFIG_FATFS_MAX_LFN=127
+CONFIG_FATFS_API_ENCODING_ANSI_OEM=y
+CONFIG_FATFS_API_ENCODING_UTF_16=
+CONFIG_FATFS_API_ENCODING_UTF_8=
CONFIG_FATFS_FS_LOCK=0
CONFIG_FATFS_TIMEOUT_MS=10000
CONFIG_FATFS_PER_FILE_CACHE=
diff --git a/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin
index 672846c..acac28c 100644
Binary files a/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin differ
diff --git a/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin
index 4961abd..9ec4f57 100644
Binary files a/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin differ
diff --git a/MicroPython_BUILD/firmware/esp32_ota/sdkconfig b/MicroPython_BUILD/firmware/esp32_ota/sdkconfig
index 733e21e..25af91f 100644
--- a/MicroPython_BUILD/firmware/esp32_ota/sdkconfig
+++ b/MicroPython_BUILD/firmware/esp32_ota/sdkconfig
@@ -218,6 +218,11 @@ CONFIG_BT_ENABLED=
CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0
CONFIG_BT_RESERVE_DRAM=0
+#
+# ADC configuration
+#
+CONFIG_ADC_FORCE_XPD_FSM=
+
#
# ESP32-specific
#
@@ -286,6 +291,7 @@ CONFIG_ESP32_TIME_SYSCALL_USE_NONE=
CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL=
CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
+CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES=100
CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
CONFIG_ESP32_XTAL_FREQ_40=
CONFIG_ESP32_XTAL_FREQ_26=
@@ -295,6 +301,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE=
CONFIG_NO_BLOBS=
CONFIG_ESP_TIMER_PROFILING=
CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS=
+CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
#
# Wi-Fi
@@ -369,6 +376,9 @@ CONFIG_FATFS_LFN_NONE=
CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_LFN_STACK=
CONFIG_FATFS_MAX_LFN=127
+CONFIG_FATFS_API_ENCODING_ANSI_OEM=y
+CONFIG_FATFS_API_ENCODING_UTF_16=
+CONFIG_FATFS_API_ENCODING_UTF_8=
CONFIG_FATFS_FS_LOCK=0
CONFIG_FATFS_TIMEOUT_MS=10000
CONFIG_FATFS_PER_FILE_CACHE=
diff --git a/MicroPython_BUILD/firmware/esp32_psram/sdkconfig b/MicroPython_BUILD/firmware/esp32_psram/sdkconfig
index 1732cb3..7ec4b31 100644
--- a/MicroPython_BUILD/firmware/esp32_psram/sdkconfig
+++ b/MicroPython_BUILD/firmware/esp32_psram/sdkconfig
@@ -228,6 +228,11 @@ CONFIG_BT_ENABLED=
CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0
CONFIG_BT_RESERVE_DRAM=0
+#
+# ADC configuration
+#
+CONFIG_ADC_FORCE_XPD_FSM=
+
#
# ESP32-specific
#
@@ -311,6 +316,7 @@ CONFIG_ESP32_TIME_SYSCALL_USE_NONE=
CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL=
CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
+CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES=100
CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
CONFIG_ESP32_XTAL_FREQ_40=
CONFIG_ESP32_XTAL_FREQ_26=
@@ -320,6 +326,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE=
CONFIG_NO_BLOBS=
CONFIG_ESP_TIMER_PROFILING=
CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS=
+CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
#
# Wi-Fi
@@ -394,6 +401,9 @@ CONFIG_FATFS_LFN_NONE=
CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_LFN_STACK=
CONFIG_FATFS_MAX_LFN=127
+CONFIG_FATFS_API_ENCODING_ANSI_OEM=y
+CONFIG_FATFS_API_ENCODING_UTF_16=
+CONFIG_FATFS_API_ENCODING_UTF_8=
CONFIG_FATFS_FS_LOCK=0
CONFIG_FATFS_TIMEOUT_MS=10000
CONFIG_FATFS_PER_FILE_CACHE=
diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin
index 4698776..6127e16 100644
Binary files a/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin differ
diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin
index f9a8a58..91aab6f 100644
Binary files a/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin differ
diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/sdkconfig b/MicroPython_BUILD/firmware/esp32_psram_all/sdkconfig
index b65669f..65e9e0a 100644
--- a/MicroPython_BUILD/firmware/esp32_psram_all/sdkconfig
+++ b/MicroPython_BUILD/firmware/esp32_psram_all/sdkconfig
@@ -219,6 +219,11 @@ CONFIG_BT_ENABLED=
CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0
CONFIG_BT_RESERVE_DRAM=0
+#
+# ADC configuration
+#
+CONFIG_ADC_FORCE_XPD_FSM=
+
#
# ESP32-specific
#
@@ -302,6 +307,7 @@ CONFIG_ESP32_TIME_SYSCALL_USE_NONE=
CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL=
CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
+CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES=100
CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
CONFIG_ESP32_XTAL_FREQ_40=
CONFIG_ESP32_XTAL_FREQ_26=
@@ -311,6 +317,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE=
CONFIG_NO_BLOBS=
CONFIG_ESP_TIMER_PROFILING=
CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS=
+CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
#
# Wi-Fi
@@ -385,6 +392,9 @@ CONFIG_FATFS_LFN_NONE=
CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_LFN_STACK=
CONFIG_FATFS_MAX_LFN=127
+CONFIG_FATFS_API_ENCODING_ANSI_OEM=y
+CONFIG_FATFS_API_ENCODING_UTF_16=
+CONFIG_FATFS_API_ENCODING_UTF_8=
CONFIG_FATFS_FS_LOCK=0
CONFIG_FATFS_TIMEOUT_MS=10000
CONFIG_FATFS_PER_FILE_CACHE=
diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin
index cb425f0..1f1e065 100644
Binary files a/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin differ
diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin
index 0f3a8f1..f070e00 100644
Binary files a/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin differ
diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/sdkconfig b/MicroPython_BUILD/firmware/esp32_psram_ota/sdkconfig
index 891ff6b..a6ea0cd 100644
--- a/MicroPython_BUILD/firmware/esp32_psram_ota/sdkconfig
+++ b/MicroPython_BUILD/firmware/esp32_psram_ota/sdkconfig
@@ -218,6 +218,11 @@ CONFIG_BT_ENABLED=
CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0
CONFIG_BT_RESERVE_DRAM=0
+#
+# ADC configuration
+#
+CONFIG_ADC_FORCE_XPD_FSM=
+
#
# ESP32-specific
#
@@ -301,6 +306,7 @@ CONFIG_ESP32_TIME_SYSCALL_USE_NONE=
CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL=
CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
+CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES=100
CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
CONFIG_ESP32_XTAL_FREQ_40=
CONFIG_ESP32_XTAL_FREQ_26=
@@ -310,6 +316,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE=
CONFIG_NO_BLOBS=
CONFIG_ESP_TIMER_PROFILING=
CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS=
+CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
#
# Wi-Fi
@@ -384,6 +391,9 @@ CONFIG_FATFS_LFN_NONE=
CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_LFN_STACK=
CONFIG_FATFS_MAX_LFN=127
+CONFIG_FATFS_API_ENCODING_ANSI_OEM=y
+CONFIG_FATFS_API_ENCODING_UTF_16=
+CONFIG_FATFS_API_ENCODING_UTF_8=
CONFIG_FATFS_FS_LOCK=0
CONFIG_FATFS_TIMEOUT_MS=10000
CONFIG_FATFS_PER_FILE_CACHE=
diff --git a/Tools/.gitignore b/Tools/.gitignore
index 2be2b7f..ddcbd81 100644
--- a/Tools/.gitignore
+++ b/Tools/.gitignore
@@ -4,3 +4,5 @@ xtensa-esp32-elf/
xtensa-esp32-elf_psram/
esp-idf_patches/
*.id
+*_new.tar.xz
+*_old.tar.xz
diff --git a/Tools/esp-idf.tar.xz b/Tools/esp-idf.tar.xz
index 44a8c78..a27d0c2 100644
Binary files a/Tools/esp-idf.tar.xz and b/Tools/esp-idf.tar.xz differ
diff --git a/Tools/esp-idf_github.sha b/Tools/esp-idf_github.sha
new file mode 100644
index 0000000..8f57e2c
--- /dev/null
+++ b/Tools/esp-idf_github.sha
@@ -0,0 +1 @@
+139d49894c473bd34ab6e9515e85d3f6871a30c7