mirror of
https://github.com/micropython/micropython.git
synced 2025-12-29 08:10:12 +01:00
Compare commits
111 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
361909e3ca | ||
|
|
1ee1785bed | ||
|
|
df103462dc | ||
|
|
749575097f | ||
|
|
1570eaf0e3 | ||
|
|
7690b13953 | ||
|
|
e2745b307b | ||
|
|
20236a8a99 | ||
|
|
6b755d827a | ||
|
|
c546b66bab | ||
|
|
83204f3406 | ||
|
|
e37dcaafb4 | ||
|
|
3b74c91684 | ||
|
|
8ab6f90674 | ||
|
|
343266ea51 | ||
|
|
c55a4d82cf | ||
|
|
7fdb8d78a4 | ||
|
|
f3a1d673de | ||
|
|
90cd6cd987 | ||
|
|
9c658b6afc | ||
|
|
a37656c132 | ||
|
|
74eb44c392 | ||
|
|
81836c28b3 | ||
|
|
01039b5bd8 | ||
|
|
584ba6762f | ||
|
|
b063b9b36d | ||
|
|
7b80d908bf | ||
|
|
9b561a7c0d | ||
|
|
4b60b45bfc | ||
|
|
6aaccc484c | ||
|
|
bf19586c53 | ||
|
|
6efa66f125 | ||
|
|
b47ea4eadd | ||
|
|
4fd7c1a2ac | ||
|
|
2870d85a11 | ||
|
|
978f4ca2e1 | ||
|
|
f5efefd5a0 | ||
|
|
6d3ae569cf | ||
|
|
2a3e2b9033 | ||
|
|
8427c5b76c | ||
|
|
f04329e93b | ||
|
|
6936f4626c | ||
|
|
c8b0229bc7 | ||
|
|
5cf7ac7309 | ||
|
|
9d944c7fb2 | ||
|
|
9642846d71 | ||
|
|
0078561303 | ||
|
|
7a4765dbeb | ||
|
|
b62371e8fb | ||
|
|
c0bc3bd736 | ||
|
|
83d27b0f0b | ||
|
|
138562ccd9 | ||
|
|
e181c0dc07 | ||
|
|
7764f163fa | ||
|
|
1ca28bd570 | ||
|
|
dbc7854355 | ||
|
|
f42b3c7599 | ||
|
|
5fba93a26b | ||
|
|
c33ce606cf | ||
|
|
f905145c6d | ||
|
|
184182d14c | ||
|
|
66a6caa307 | ||
|
|
5318cc028a | ||
|
|
7eb2317fa2 | ||
|
|
969a6b37bf | ||
|
|
d51107927d | ||
|
|
4140e19c8a | ||
|
|
e8487ea1be | ||
|
|
6c3fc74656 | ||
|
|
b4fe6e28eb | ||
|
|
78d702c300 | ||
|
|
e6e8ad8ab2 | ||
|
|
706955976c | ||
|
|
5deceb842d | ||
|
|
b66a31c42c | ||
|
|
008251180d | ||
|
|
46c3ab2004 | ||
|
|
d0caaadaee | ||
|
|
1f8a2f6623 | ||
|
|
9de6773237 | ||
|
|
d4f80f58b8 | ||
|
|
be6d8be91e | ||
|
|
451a087075 | ||
|
|
759cc9bcc8 | ||
|
|
a4c52c5a3d | ||
|
|
41c07d5b80 | ||
|
|
adf4c4cea8 | ||
|
|
c0b3d4540b | ||
|
|
29a1ec1bd6 | ||
|
|
d8f239263d | ||
|
|
32ef3a3517 | ||
|
|
3a5352b483 | ||
|
|
cd97a43f8d | ||
|
|
57c70d6073 | ||
|
|
578ea6d4a5 | ||
|
|
d8fd3103fa | ||
|
|
d96a916405 | ||
|
|
7f0699eedf | ||
|
|
6e8ff9cd68 | ||
|
|
17c5ce3727 | ||
|
|
1960475ed7 | ||
|
|
c7ca01ad96 | ||
|
|
d8c2b2a1c4 | ||
|
|
b2e731177e | ||
|
|
19fb1b4dd7 | ||
|
|
b395220ef0 | ||
|
|
7288403b9b | ||
|
|
3b603f29ec | ||
|
|
e636279fe0 | ||
|
|
bfdc205934 | ||
|
|
d96e6b14c9 |
@@ -9,6 +9,7 @@ include ../py/py.mk
|
||||
CROSS_COMPILE = arm-none-eabi-
|
||||
|
||||
INC = -I.
|
||||
INC += -I..
|
||||
INC += -I$(PY_SRC)
|
||||
INC += -I$(BUILD)
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "repl.h"
|
||||
#include "pfenv.h"
|
||||
|
||||
void do_str(const char *src) {
|
||||
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
|
||||
@@ -32,13 +33,13 @@ void do_str(const char *src) {
|
||||
}
|
||||
|
||||
// parse okay
|
||||
qstr source_name = mp_lexer_source_name(lex);
|
||||
qstr source_name = lex->source_name;
|
||||
mp_lexer_free(lex);
|
||||
mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true);
|
||||
|
||||
if (mp_obj_is_exception_instance(module_fun)) {
|
||||
// compile error
|
||||
mp_obj_print_exception(module_fun);
|
||||
mp_obj_print_exception(printf_wrapper, NULL, module_fun);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -48,7 +49,7 @@ void do_str(const char *src) {
|
||||
nlr_pop();
|
||||
} else {
|
||||
// uncaught exception
|
||||
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
|
||||
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ extensions = [
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
#templates_path = ['templates']
|
||||
templates_path = ['templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
@@ -144,7 +144,7 @@ else:
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
#html_static_path = ['static']
|
||||
html_static_path = ['static']
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
|
||||
@@ -46,6 +46,9 @@ The modes are:
|
||||
filesystem to its factory state, then boots in safe mode.
|
||||
|
||||
If your filesystem becomes corrupt, boot into mode 3 to fix it.
|
||||
If resetting the filesystem while plugged into your compute doesn't work,
|
||||
you can try doing the same procedure while the board is plugged into a USB
|
||||
charger, or other USB power supply without data connection.
|
||||
|
||||
Errors: flashing LEDs
|
||||
---------------------
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
.. _hardware_index:
|
||||
|
||||
The pyboard hardware
|
||||
====================
|
||||
|
||||
For the pyboard:
|
||||
|
||||
* `PYBv1.0 schematics and layout <http://micropython.org/resources/PYBv10b.pdf>`_ (2.4MiB PDF)
|
||||
* `PYBv1.0 metric dimensions <http://micropython.org/resources/PYBv10b-metric-dimensions.pdf>`_ (360KiB PDF)
|
||||
* `PYBv1.0 imperial dimensions <http://micropython.org/resources/PYBv10b-imperial-dimensions.pdf>`_ (360KiB PDF)
|
||||
|
||||
For the official skin modules:
|
||||
|
||||
* `LCD32MKv1.0 schematics <http://micropython.org/resources/LCD32MKv10-schematics.pdf>`_ (194KiB PDF)
|
||||
* `AMPv1.0 schematics <http://micropython.org/resources/AMPv10-schematics.pdf>`_ (209KiB PDF)
|
||||
|
||||
Datasheets for the components on the pyboard
|
||||
============================================
|
||||
|
||||
|
||||
@@ -38,9 +38,13 @@ it will fallback to loading the built-in ``ujson`` module.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
usocket.rst
|
||||
ubinascii.rst
|
||||
uhashlib.rst
|
||||
uheapq.rst
|
||||
ujson.rst
|
||||
ure.rst
|
||||
usocket.rst
|
||||
uzlib.rst
|
||||
|
||||
Libraries specific to the pyboard
|
||||
---------------------------------
|
||||
|
||||
@@ -5,27 +5,116 @@
|
||||
.. module:: network
|
||||
:synopsis: network configuration
|
||||
|
||||
This module provides network drivers and routing configuration.
|
||||
This module provides network drivers and routing configuration. Network
|
||||
drivers for specific hardware are available within this module and are
|
||||
used to configure a hardware network interface. Configured interfaces
|
||||
are then available for use via the :mod:`socket` module.
|
||||
|
||||
For example::
|
||||
|
||||
class CC3k
|
||||
# configure a specific network interface
|
||||
# see below for examples of specific drivers
|
||||
import network
|
||||
nic = network.Driver(...)
|
||||
print(nic.ifconfig())
|
||||
|
||||
# now use socket as usual
|
||||
import 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()
|
||||
|
||||
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)
|
||||
.. class:: CC3K(spi, pin_cs, pin_en, pin_irq)
|
||||
|
||||
Initialise the CC3000 using the given SPI bus and pins and return a CC3k object.
|
||||
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 <pyb.SPI>` which is the SPI bus that the CC3000 is
|
||||
connected to (the MOSI, MISO and CLK pins).
|
||||
- ``pin_cs`` is a :ref:`Pin object <pyb.Pin>` which is connected to the CC3000 CS pin.
|
||||
- ``pin_en`` is a :ref:`Pin object <pyb.Pin>` which is connected to the CC3000 VBEN pin.
|
||||
- ``pin_irq`` is a :ref:`Pin object <pyb.Pin>` 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.
|
||||
|
||||
class WIZnet5k
|
||||
.. 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
|
||||
@@ -33,31 +122,56 @@ the W5200 and W5500 chipsets (only W5200 tested).
|
||||
|
||||
Example usage::
|
||||
|
||||
import wiznet5k
|
||||
w = wiznet5k.WIZnet5k()
|
||||
print(w.ipaddr())
|
||||
w.gethostbyname('micropython.org')
|
||||
s = w.socket()
|
||||
s.connect(('192.168.0.2', 8080))
|
||||
s.send('hello')
|
||||
print(s.recv(10))
|
||||
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)
|
||||
.. class:: WIZNET5K(spi, pin_cs, pin_rst)
|
||||
|
||||
Create and return a WIZnet5k object.
|
||||
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 <pyb.SPI>` which is the SPI bus that the WIZnet5x00 is
|
||||
connected to (the MOSI, MISO and SCLK pins).
|
||||
- ``pin_cs`` is a :ref:`Pin object <pyb.Pin>` which is connected to the WIZnet5x00 nSS pin.
|
||||
- ``pin_rst`` is a :ref:`Pin object <pyb.Pin>` 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.ipaddr([(ip, subnet, gateway, dns)])
|
||||
.. 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 WIZnet5k registers.
|
||||
Dump the WIZnet5x00 registers. Useful for debugging.
|
||||
|
||||
@@ -7,15 +7,12 @@ to connect the pyboard to a CAN bus you must use a CAN transceiver
|
||||
to convert the CAN logic signals from the pyboard to the correct
|
||||
voltage levels on the bus.
|
||||
|
||||
Note that this driver does not yet support filter configuration
|
||||
(it defaults to a single filter that lets through all messages),
|
||||
or bus timing configuration (except for setting the prescaler).
|
||||
|
||||
Example usage (works without anything connected)::
|
||||
|
||||
from pyb import CAN
|
||||
can = pyb.CAN(1, pyb.CAN.LOOPBACK)
|
||||
can.send('message!', 123) # send message to id 123
|
||||
can = CAN(1, CAN.LOOPBACK)
|
||||
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126)) # set a filter to receive messages with id=123, 124, 125 and 126
|
||||
can.send('message!', 123) # send a message with id 123
|
||||
can.recv(0) # receive message on FIFO 0
|
||||
|
||||
|
||||
@@ -35,7 +32,17 @@ Constructors
|
||||
- ``CAN(1)`` is on ``YA``: ``(RX, TX) = (Y3, Y4) = (PB8, PB9)``
|
||||
- ``CAN(2)`` is on ``YB``: ``(RX, TX) = (Y5, Y6) = (PB12, PB13)``
|
||||
|
||||
|
||||
Class Methods
|
||||
-------------
|
||||
.. method:: CAN.initfilterbanks(nr)
|
||||
|
||||
Reset and disable all filter banks and assign how many banks should be available for CAN(1).
|
||||
|
||||
STM32F405 has 28 filter banks that are shared between the two available CAN bus controllers.
|
||||
This function configures how many filter banks should be assigned to each. ``nr`` is the number of banks
|
||||
that will be assigned to CAN(1), the rest of the 28 are assigned to CAN(2).
|
||||
At boot, 14 banks are assigned to each controller.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
@@ -75,6 +82,37 @@ Methods
|
||||
|
||||
Turn off the CAN bus.
|
||||
|
||||
.. method:: can.setfilter(bank, mode, fifo, params)
|
||||
|
||||
Configure a filter bank:
|
||||
|
||||
- ``bank`` is the filter bank that is to be configured.
|
||||
- ``mode`` is the mode the filter should operate in.
|
||||
- ``fifo`` is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter.
|
||||
- ``params`` is an array of values the defines the filter. The contents of the array depends on the ``mode`` argument.
|
||||
|
||||
+-----------+---------------------------------------------------------+
|
||||
|``mode`` |contents of parameter array |
|
||||
+===========+=========================================================+
|
||||
|CAN.LIST16 |Four 16 bit ids that will be accepted |
|
||||
+-----------+---------------------------------------------------------+
|
||||
|CAN.LIST32 |Two 32 bit ids that will be accepted |
|
||||
+-----------+---------------------------------------------------------+
|
||||
|CAN.MASK16 |Two 16 bit id/mask pairs. E.g. (1, 3, 4, 4) |
|
||||
| | | The first pair, 1 and 3 will accept all ids |
|
||||
| | | that have bit 0 = 1 and bit 1 = 0. |
|
||||
| | | The second pair, 4 and 4, will accept all ids |
|
||||
| | | that have bit 2 = 1. |
|
||||
+-----------+---------------------------------------------------------+
|
||||
|CAN.MASK32 |As with CAN.MASK16 but with only one 32 bit id/mask pair.|
|
||||
+-----------+---------------------------------------------------------+
|
||||
|
||||
.. method:: can.clearfilter(bank)
|
||||
|
||||
Clear and disables a filter bank:
|
||||
|
||||
- ``bank`` is the filter bank that is to be cleared.
|
||||
|
||||
.. method:: can.any(fifo)
|
||||
|
||||
Return ``True`` if any message waiting on the FIFO, else ``False``.
|
||||
@@ -98,7 +136,6 @@ Methods
|
||||
|
||||
Return value: ``None``.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
@@ -108,3 +145,10 @@ Constants
|
||||
.. data:: CAN.SILENT_LOOPBACK
|
||||
|
||||
the mode of the CAN bus
|
||||
|
||||
.. data:: CAN.LIST16
|
||||
.. data:: CAN.MASK16
|
||||
.. data:: CAN.LIST32
|
||||
.. data:: CAN.MASK32
|
||||
|
||||
the operation mode of a filter
|
||||
|
||||
@@ -31,8 +31,9 @@ Methods
|
||||
|
||||
.. method:: led.on()
|
||||
|
||||
Turn the LED on.
|
||||
Turn the LED on, to maximum intensity.
|
||||
|
||||
.. method:: led.toggle()
|
||||
|
||||
Toggle the LED between on and off.
|
||||
Toggle the LED between on (maximum intensity) and off. If the LED is at
|
||||
non-zero intensity then it is considered "on" and toggle will turn it off.
|
||||
|
||||
@@ -52,12 +52,29 @@ Methods
|
||||
|
||||
Turn off the SPI bus.
|
||||
|
||||
.. method:: spi.init(mode, baudrate=328125, \*, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
|
||||
.. method:: spi.init(mode, baudrate=328125, \*, prescaler, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
|
||||
|
||||
Initialise the SPI bus with the given parameters:
|
||||
|
||||
- ``mode`` must be either ``SPI.MASTER`` or ``SPI.SLAVE``.
|
||||
- ``baudrate`` is the SCK clock rate (only sensible for a master).
|
||||
- ``prescaler`` is the prescaler to use to derive SCK from the APB bus frequency;
|
||||
use of ``prescaler`` overrides ``baudrate``.
|
||||
- ``polarity`` can be 0 or 1, and is the level the idle clock line sits at.
|
||||
- ``phase`` can be 0 or 1 to sample data on the first or second clock edge
|
||||
respectively.
|
||||
- ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``.
|
||||
- ``crc`` can be None for no CRC, or a polynomial specifier.
|
||||
|
||||
Note that the SPI clock frequency will not always be the requested baudrate.
|
||||
The hardware only supports baudrates that are the APB bus frequency
|
||||
(see :meth:`pyb.freq`) divided by a prescaler, which can be 2, 4, 8, 16, 32,
|
||||
64, 128 or 256. SPI(1) is on AHB2, and SPI(2) is on AHB1. For precise
|
||||
control over the SPI clock frequency, specify ``prescaler`` instead of
|
||||
``baudrate``.
|
||||
|
||||
Printing the SPI object will show you the computed baudrate and the chosen
|
||||
prescaler.
|
||||
|
||||
.. method:: spi.recv(recv, \*, timeout=5000)
|
||||
|
||||
|
||||
@@ -17,6 +17,15 @@ Constructors
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: usb_vcp.setinterrupt(chr)
|
||||
|
||||
Set the character which interrupts running Python code. This is set
|
||||
to 3 (CTRL-C) by default, and when a CTRL-C character is received over
|
||||
the USB VCP port, a KeyboardInterrupt exception is raised.
|
||||
|
||||
Set to -1 to disable this interrupt feature. This is useful when you
|
||||
want to send raw bytes over the USB VCP port.
|
||||
|
||||
.. method:: usb_vcp.any()
|
||||
|
||||
Return ``True`` if any characters waiting, else ``False``.
|
||||
|
||||
@@ -93,26 +93,38 @@ Interrupt related functions
|
||||
Power related functions
|
||||
-----------------------
|
||||
|
||||
.. function:: freq([sys_freq])
|
||||
.. function:: freq([sysclk[, hclk[, pclk1[, pclk2]]]])
|
||||
|
||||
If given no arguments, returns a tuple of clock frequencies:
|
||||
(SYSCLK, HCLK, PCLK1, PCLK2).
|
||||
|
||||
If given an argument, sets the system frequency to that value in Hz.
|
||||
Eg freq(120000000) gives 120MHz. Note that not all values are
|
||||
supported and the largest supported frequency not greater than
|
||||
the given sys_freq will be selected.
|
||||
(sysclk, hclk, pclk1, pclk2).
|
||||
These correspond to:
|
||||
- sysclk: frequency of the CPU
|
||||
- hclk: frequency of the AHB bus, core memory and DMA
|
||||
- pclk1: frequency of the APB1 bus
|
||||
- pclk2: frequency of the APB2 bus
|
||||
|
||||
Supported frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48,
|
||||
If given any arguments then the function sets the frequency of the CPU,
|
||||
and the busses if additional arguments are given. Frequencies are given in
|
||||
Hz. Eg freq(120000000) sets sysclk (the CPU frequency) to 120MHz. Note that
|
||||
not all values are supported and the largest supported frequency not greater
|
||||
than the given value will be selected.
|
||||
|
||||
Supported sysclk frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48,
|
||||
54, 56, 60, 64, 72, 84, 96, 108, 120, 144, 168.
|
||||
|
||||
The hclk, pclk1 and pclk2 frequencies are derived from the sysclk frequency
|
||||
using a prescaler (divider). Supported prescalers for hclk are: 1, 2, 4, 8,
|
||||
16, 64, 128, 256, 512. Supported prescalers for pclk1 and pclk2 are: 1, 2,
|
||||
4, 8. A prescaler will be chosen to best match the requested frequency.
|
||||
|
||||
A sysclk frequency of
|
||||
8MHz uses the HSE (external crystal) directly and 16MHz uses the HSI
|
||||
(internal oscillator) directly. The higher frequencies use the HSE to
|
||||
drive the PLL (phase locked loop), and then use the output of the PLL.
|
||||
|
||||
Note that if you change the frequency while the USB is enabled then
|
||||
the USB may become unreliable. It is best to change the frequency
|
||||
in boot.py, before the USB peripheral is started. Also note that
|
||||
in boot.py, before the USB peripheral is started. Also note that sysclk
|
||||
frequencies below 36MHz do not allow the USB to function correctly.
|
||||
|
||||
.. function:: wfi()
|
||||
@@ -142,6 +154,37 @@ Miscellaneous functions
|
||||
|
||||
Print out lots of information about the board.
|
||||
|
||||
.. function:: mount(device, mountpoint, \*, readonly=False, mkfs=False)
|
||||
|
||||
Mount a block device and make it available as part of the filesystem.
|
||||
``device`` must be an object that provides the block protocol:
|
||||
|
||||
- ``readblocks(self, blocknum, buf)``
|
||||
- ``writeblocks(self, blocknum, buf)`` (optional)
|
||||
- ``count(self)``
|
||||
- ``sync(self)`` (optional)
|
||||
|
||||
``readblocks`` and ``writeblocks`` should copy data between ``buf`` and
|
||||
the block device, starting from block number ``blocknum`` on the device.
|
||||
``buf`` will be a bytearray with length a multiple of 512. If
|
||||
``writeblocks`` is not defined then the device is mounted read-only.
|
||||
The return value of these two functions is ignored.
|
||||
|
||||
``count`` should return the number of blocks available on the device.
|
||||
``sync``, if implemented, should sync the data on the device.
|
||||
|
||||
The parameter ``mountpoint`` is the location in the root of the filesystem
|
||||
to mount the device. It must begin with a forward-slash.
|
||||
|
||||
If ``readonly`` is ``True``, then the device is mounted read-only,
|
||||
otherwise it is mounted read-write.
|
||||
|
||||
If ``mkfs`` is ``True``, then a new filesystem is created if one does not
|
||||
already exist.
|
||||
|
||||
To unmount a device, pass ``None`` as the device and the mount location
|
||||
as ``mountpoint``.
|
||||
|
||||
.. function:: repl_uart(uart)
|
||||
|
||||
Get or set the UART object that the REPL is repeated on.
|
||||
|
||||
@@ -12,6 +12,16 @@ Functions
|
||||
Raise a ``SystemExit`` exception. If an argument is given, it is the
|
||||
value given to ``SystemExit``.
|
||||
|
||||
.. function:: print_exception(exc, [file])
|
||||
|
||||
Print exception with a traceback to a file-like object ``file`` (or
|
||||
``sys.stdout`` by default).
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
This function appears in the ``traceback`` module in CPython.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
@@ -29,7 +39,9 @@ Constants
|
||||
|
||||
.. data:: platform
|
||||
|
||||
the platform that Micro Python is running on
|
||||
The platform that Micro Python is running on. This is "pyboard" on the
|
||||
pyboard and provides a robust way of determining if a script is running
|
||||
on the pyboard or not.
|
||||
|
||||
.. data:: stderr
|
||||
|
||||
|
||||
15
docs/library/ubinascii.rst
Normal file
15
docs/library/ubinascii.rst
Normal file
@@ -0,0 +1,15 @@
|
||||
:mod:`ubinascii` -- binary/ASCII conversions
|
||||
============================================
|
||||
|
||||
.. module:: ubinascii
|
||||
:synopsis: binary/ASCII conversions
|
||||
|
||||
This module implements conversions between binary data and various
|
||||
encodings of it in ASCII form (in both directions).
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: hexlify(data)
|
||||
|
||||
Convert binary data to hexadecimal representation. Return bytes string.
|
||||
37
docs/library/uhashlib.rst
Normal file
37
docs/library/uhashlib.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
:mod:`uhashlib` -- hashing algorithm
|
||||
====================================
|
||||
|
||||
.. module:: uhashlib
|
||||
:synopsis: hashing algorithm
|
||||
|
||||
This module implements binary data hashing algorithms. Currently, it
|
||||
implements SHA256 algorithm. Choosing SHA256 was a deliberate choice,
|
||||
as a modern, cryptographically secure algorithm. This means that a
|
||||
single algorithm can cover both usecases of "any hash algorithm" and
|
||||
security-related usage, and thus save space omitting legacy algorithms
|
||||
like MD5 or SHA1.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: uhashlib.sha256([data])
|
||||
|
||||
Create a hasher object and optionally feed ``data`` into it.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: sha256.update(data)
|
||||
|
||||
Feed more binary data into hash.
|
||||
|
||||
.. method:: sha256.digest()
|
||||
|
||||
Return hash for all data passed thru hash, as a bytes object. After this
|
||||
method is called, more data cannot be fed into hash any longer.
|
||||
|
||||
.. method:: sha256.hexdigest()
|
||||
|
||||
This method is NOT implemented. Use ``ubinascii.hexlify(sha256.digest())``
|
||||
to achieve similar effect.
|
||||
82
docs/library/ure.rst
Normal file
82
docs/library/ure.rst
Normal file
@@ -0,0 +1,82 @@
|
||||
:mod:`ure` -- regular expressions
|
||||
=================================
|
||||
|
||||
.. module:: ure
|
||||
:synopsis: regular expressions
|
||||
|
||||
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.
|
||||
|
||||
``'^'``
|
||||
|
||||
``'$'``
|
||||
|
||||
``'?'``
|
||||
|
||||
``'*'``
|
||||
|
||||
``'+'``
|
||||
|
||||
``'??'``
|
||||
|
||||
``'*?'``
|
||||
|
||||
``'+?'``
|
||||
|
||||
Counted repetitions (``{m,n}``), more advanced assertions, names groups,
|
||||
etc. are not supported.
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: compile(regex)
|
||||
|
||||
Compile regular expression, return ``regex`` object.
|
||||
|
||||
.. function:: match(regex, string)
|
||||
|
||||
Match ``regex`` against ``string``. Match always happens from starting
|
||||
position in a string.
|
||||
|
||||
.. function:: search(regex, string)
|
||||
|
||||
Search ``regex`` 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.
|
||||
|
||||
|
||||
Regex objects
|
||||
-------------
|
||||
|
||||
Compiled regular expression. Instances of this class are created using
|
||||
``ure.compile()``.
|
||||
|
||||
.. method:: regex.match(string)
|
||||
|
||||
.. method:: regex.search(string)
|
||||
|
||||
.. method:: regex.split(string, max_split=-1)
|
||||
|
||||
|
||||
Match objects
|
||||
-------------
|
||||
|
||||
Match objects as returned by ``match()`` and ``search()`` methods.
|
||||
|
||||
.. method:: match.group([index])
|
||||
|
||||
Only numeric groups are supported.
|
||||
16
docs/library/uzlib.rst
Normal file
16
docs/library/uzlib.rst
Normal file
@@ -0,0 +1,16 @@
|
||||
:mod:`uzlib` -- zlib decompression
|
||||
==================================
|
||||
|
||||
.. module:: uzlib
|
||||
:synopsis: zlib decompression
|
||||
|
||||
This modules 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)
|
||||
|
||||
Return decompressed data as bytes.
|
||||
9
docs/readthedocs/settings/local_settings.py
Normal file
9
docs/readthedocs/settings/local_settings.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import os
|
||||
|
||||
# Directory that the project lives in, aka ../..
|
||||
SITE_ROOT = '/'.join(os.path.dirname(__file__).split('/')[0:-2])
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
"%s/templates/" % SITE_ROOT, # Your custom template directory, before the RTD one to override it.
|
||||
"%s/readthedocs/templates/" % SITE_ROOT, # Default RTD template dir
|
||||
)
|
||||
10
docs/static/customstyle.css
vendored
Normal file
10
docs/static/customstyle.css
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/* custom CSS for Micro Python docs
|
||||
*/
|
||||
|
||||
.admonition-difference-to-cpython {
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.admonition-difference-to-cpython .admonition-title {
|
||||
margin: 4px;
|
||||
}
|
||||
2
docs/templates/layout.html
vendored
Normal file
2
docs/templates/layout.html
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
{% extends "!layout.html" %}
|
||||
{% set css_files = css_files + ["_static/customstyle.css"] %}
|
||||
@@ -17,6 +17,8 @@ The following video shows how to solder the headers, microphone and speaker onto
|
||||
|
||||
<iframe style="margin-left:3em;" width="560" height="315" src="http://www.youtube.com/embed/fjB1DuZRveo?rel=0" frameborder="0" allowfullscreen></iframe>
|
||||
|
||||
For circuit schematics and datasheets for the components on the skin see :ref:`hardware_index`.
|
||||
|
||||
Example code
|
||||
------------
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ At the end of the video, it shows you how to correctly connect the LCD skin to t
|
||||
|
||||
<iframe style="margin-left:3em;" width="560" height="315" src="http://www.youtube.com/embed/PowCzdLYbFM?rel=0" frameborder="0" allowfullscreen></iframe>
|
||||
|
||||
For circuit schematics and datasheets for the components on the skin see :ref:`hardware_index`.
|
||||
|
||||
Using the LCD
|
||||
-------------
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ Next we will set up an infinite loop that cycles through each of the LEDs turnin
|
||||
leds[n].toggle()
|
||||
pyb.delay(50)
|
||||
|
||||
Here, n keeps track of the current LED and every time the loop is executed we cycle to the next n (the % sign is a modulus operator that keeps n between 0 and 4.) Then we access the nth LED and toggle it. If you run this you should see each of the LEDs turning on then all turning off again in sequence.
|
||||
Here, n keeps track of the current LED and every time the loop is executed we cycle to the next n (the % sign is a modulus operator that keeps n between 0 and 3.) Then we access the nth LED and toggle it. If you run this you should see each of the LEDs turning on then all turning off again in sequence.
|
||||
|
||||
One problem you might find is that if you stop the script and then start it again that the LEDs are stuck on from the previous run, ruining our carefully choreographed disco. We can fix this by turning all the LEDs off when we initialise the script and then using a try/finally block. When you press CTRL-C, Micro Python generates a VCPInterrupt exception. Exceptions normally mean something has gone wrong and you can use a try: command to "catch" an exception. In this case it is just the user interrupting the script, so we don't need to catch the error but just tell Micro Python what to do when we exit. The finally block does this, and we use it to make sure all the LEDs are off. The full code is::
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ It's as simple as::
|
||||
import select
|
||||
|
||||
def pass_through(usb, uart):
|
||||
usb.setinterrupt(-1)
|
||||
while True:
|
||||
select.select([usb, uart], [], [])
|
||||
if usb.any():
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""NRF24L01 driver for Micro Python"""
|
||||
"""NRF24L01 driver for Micro Python
|
||||
"""
|
||||
|
||||
import pyb
|
||||
|
||||
@@ -10,7 +11,6 @@ SETUP_RETR = const(0x04)
|
||||
RF_CH = const(0x05)
|
||||
RF_SETUP = const(0x06)
|
||||
STATUS = const(0x07)
|
||||
OBSERVE_TX = const(0x08)
|
||||
RX_ADDR_P0 = const(0x0a)
|
||||
TX_ADDR = const(0x10)
|
||||
RX_PW_P0 = const(0x11)
|
||||
@@ -69,8 +69,10 @@ class NRF24L01:
|
||||
self.pipe0_read_addr = None
|
||||
pyb.delay(5)
|
||||
|
||||
# set address width to 5 bytes
|
||||
# set address width to 5 bytes and check for device present
|
||||
self.reg_write(SETUP_AW, 0b11)
|
||||
if self.reg_read(SETUP_AW) != 0b11:
|
||||
raise OSError("nRF24L01+ Hardware not responding")
|
||||
|
||||
# disable dynamic payloads
|
||||
self.reg_write(DYNPD, 0)
|
||||
@@ -80,7 +82,7 @@ class NRF24L01:
|
||||
self.reg_write(SETUP_RETR, (6 << 4) | 8)
|
||||
|
||||
# set rf power and speed
|
||||
self.set_power_speed(POWER_3, SPEED_1M)
|
||||
self.set_power_speed(POWER_3, SPEED_250K) # Best for point to point links
|
||||
|
||||
# init CRC
|
||||
self.set_crc(2)
|
||||
@@ -102,13 +104,6 @@ class NRF24L01:
|
||||
self.cs.high()
|
||||
return buf[0]
|
||||
|
||||
def reg_read_ret_status(self, reg):
|
||||
self.cs.low()
|
||||
status = self.spi.send_recv(reg)[0]
|
||||
buf = self.spi.recv(1)
|
||||
self.cs.high()
|
||||
return status
|
||||
|
||||
def reg_write(self, reg, buf):
|
||||
self.cs.low()
|
||||
status = self.spi.send_recv(0x20 | reg)[0]
|
||||
@@ -143,7 +138,7 @@ class NRF24L01:
|
||||
self.reg_write(CONFIG, config)
|
||||
|
||||
def set_channel(self, channel):
|
||||
self.reg_write(RF_CH, min(channel, 127))
|
||||
self.reg_write(RF_CH, min(channel, 125))
|
||||
|
||||
# address should be a bytes object 5 bytes long
|
||||
def open_tx_pipe(self, address):
|
||||
@@ -194,17 +189,26 @@ class NRF24L01:
|
||||
self.spi.send(R_RX_PAYLOAD)
|
||||
buf = self.spi.recv(self.payload_size)
|
||||
self.cs.high()
|
||||
|
||||
# clear RX ready flag
|
||||
self.reg_write(STATUS, RX_DR)
|
||||
|
||||
return buf
|
||||
|
||||
# blocking wait for tx complete
|
||||
def send(self, buf, timeout=500):
|
||||
send_nonblock = self.send_start(buf)
|
||||
start = pyb.millis()
|
||||
result = None
|
||||
while result is None and pyb.elapsed_millis(start) < timeout:
|
||||
result = self.send_done() # 1 == success, 2 == fail
|
||||
if result == 2:
|
||||
raise OSError("send failed")
|
||||
|
||||
# non-blocking tx
|
||||
def send_start(self, buf):
|
||||
# power up
|
||||
self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX)
|
||||
pyb.udelay(150)
|
||||
|
||||
# send the data
|
||||
self.cs.low()
|
||||
self.spi.send(W_TX_PAYLOAD)
|
||||
@@ -218,17 +222,12 @@ class NRF24L01:
|
||||
pyb.udelay(15) # needs to be >10us
|
||||
self.ce.low()
|
||||
|
||||
# blocking wait for tx complete
|
||||
start = pyb.millis()
|
||||
while pyb.millis() - start < timeout:
|
||||
status = self.reg_read_ret_status(OBSERVE_TX)
|
||||
if status & (TX_DS | MAX_RT):
|
||||
break
|
||||
# returns None if send still in progress, 1 for success, 2 for fail
|
||||
def send_done(self):
|
||||
if not (self.reg_read(STATUS) & (TX_DS | MAX_RT)):
|
||||
return None # tx not finished
|
||||
|
||||
# get and clear all status flags
|
||||
# either finished or failed: get and clear status flags, power down
|
||||
status = self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
|
||||
if not (status & TX_DS):
|
||||
raise OSError("send failed")
|
||||
|
||||
# power down
|
||||
self.reg_write(CONFIG, self.reg_read(CONFIG) & ~PWR_UP)
|
||||
return 1 if status & TX_DS else 2
|
||||
|
||||
202
drivers/sdcard/sdcard.py
Normal file
202
drivers/sdcard/sdcard.py
Normal file
@@ -0,0 +1,202 @@
|
||||
"""
|
||||
Micro Python driver for SD cards using SPI bus.
|
||||
|
||||
Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
|
||||
methods so the device can be mounted as a filesystem.
|
||||
|
||||
Example usage:
|
||||
|
||||
import pyb, sdcard, os
|
||||
sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
|
||||
pyb.mount(sd, '/sd2')
|
||||
os.listdir('/')
|
||||
|
||||
"""
|
||||
|
||||
import pyb
|
||||
|
||||
class SDCard:
|
||||
CMD_TIMEOUT = const(100)
|
||||
|
||||
R1_IDLE_STATE = const(1 << 0)
|
||||
#R1_ERASE_RESET = const(1 << 1)
|
||||
R1_ILLEGAL_COMMAND = const(1 << 2)
|
||||
#R1_COM_CRC_ERROR = const(1 << 3)
|
||||
#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
|
||||
#R1_ADDRESS_ERROR = const(1 << 5)
|
||||
#R1_PARAMETER_ERROR = const(1 << 6)
|
||||
|
||||
def __init__(self, spi, cs):
|
||||
self.spi = spi
|
||||
self.cs = cs
|
||||
|
||||
self.cmdbuf = bytearray(6)
|
||||
self.dummybuf = bytearray(512)
|
||||
for i in range(512):
|
||||
self.dummybuf[i] = 0xff
|
||||
self.dummybuf_memoryview = memoryview(self.dummybuf)
|
||||
|
||||
# initialise the card
|
||||
self.init_card()
|
||||
|
||||
def init_card(self):
|
||||
# init CS pin
|
||||
self.cs.high()
|
||||
self.cs.init(self.cs.OUT_PP)
|
||||
|
||||
# init SPI bus; use low data rate for initialisation
|
||||
self.spi.init(self.spi.MASTER, baudrate=100000, phase=0, polarity=0)
|
||||
|
||||
# clock card at least 100 cycles with cs high
|
||||
for i in range(16):
|
||||
self.spi.send(0xff)
|
||||
|
||||
# CMD0: init card; should return R1_IDLE_STATE (allow 2 attempts)
|
||||
if self.cmd(0, 0, 0x95) != R1_IDLE_STATE:
|
||||
if self.cmd(0, 0, 0x95) != R1_IDLE_STATE:
|
||||
raise OSError("no SD card")
|
||||
|
||||
# CMD8: determine card version
|
||||
r = self.cmd(8, 0x01aa, 0x87, 4)
|
||||
if r == R1_IDLE_STATE:
|
||||
self.init_card_v2()
|
||||
elif r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND):
|
||||
self.init_card_v1()
|
||||
else:
|
||||
raise OSError("couldn't determine SD card version")
|
||||
|
||||
# get the number of sectors
|
||||
# CMD9: response R2 (R1 byte + 16-byte block read)
|
||||
if self.cmd(9, 0, 0, 0, False) != 0:
|
||||
raise OSError("no response from SD card")
|
||||
csd = bytearray(16)
|
||||
self.readinto(csd)
|
||||
if csd[0] & 0xc0 != 0x40:
|
||||
raise OSError("SD card CSD format not supported")
|
||||
self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 2014
|
||||
#print('sectors', self.sectors)
|
||||
|
||||
# CMD16: set block length to 512 bytes
|
||||
if self.cmd(16, 512, 0) != 0:
|
||||
raise OSError("can't set 512 block size")
|
||||
|
||||
# set to high data rate now that it's initialised
|
||||
self.spi.init(self.spi.MASTER, baudrate=1320000, phase=0, polarity=0)
|
||||
|
||||
def init_card_v1(self):
|
||||
for i in range(CMD_TIMEOUT):
|
||||
self.cmd(55, 0, 0)
|
||||
if self.cmd(41, 0, 0) == 0:
|
||||
self.cdv = 512
|
||||
#print("[SDCard] v1 card")
|
||||
return
|
||||
raise OSError("timeout waiting for v1 card")
|
||||
|
||||
def init_card_v2(self):
|
||||
for i in range(CMD_TIMEOUT):
|
||||
pyb.delay(50)
|
||||
self.cmd(58, 0, 0, 4)
|
||||
self.cmd(55, 0, 0)
|
||||
if self.cmd(41, 0x40000000, 0) == 0:
|
||||
self.cmd(58, 0, 0, 4)
|
||||
self.cdv = 1
|
||||
#print("[SDCard] v2 card")
|
||||
return
|
||||
raise OSError("timeout waiting for v2 card")
|
||||
|
||||
def cmd(self, cmd, arg, crc, final=0, release=True):
|
||||
self.cs.low()
|
||||
|
||||
# create and send the command
|
||||
buf = self.cmdbuf
|
||||
buf[0] = 0x40 | cmd
|
||||
buf[1] = arg >> 24
|
||||
buf[2] = arg >> 16
|
||||
buf[3] = arg >> 8
|
||||
buf[4] = arg
|
||||
buf[5] = crc
|
||||
self.spi.send(buf)
|
||||
|
||||
# wait for the repsonse (response[7] == 0)
|
||||
for i in range(CMD_TIMEOUT):
|
||||
response = self.spi.send_recv(0xff)[0]
|
||||
if not (response & 0x80):
|
||||
# this could be a big-endian integer that we are getting here
|
||||
for j in range(final):
|
||||
self.spi.send(0xff)
|
||||
if release:
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
return response
|
||||
|
||||
# timeout
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
return -1
|
||||
|
||||
def readinto(self, buf):
|
||||
self.cs.low()
|
||||
|
||||
# read until start byte (0xff)
|
||||
while self.spi.send_recv(0xff)[0] != 0xfe:
|
||||
pass
|
||||
|
||||
# read data
|
||||
mv = self.dummybuf_memoryview[:len(buf)]
|
||||
self.spi.send_recv(mv, recv=buf)
|
||||
|
||||
# read checksum
|
||||
self.spi.send(0xff)
|
||||
self.spi.send(0xff)
|
||||
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
|
||||
def write(self, buf):
|
||||
self.cs.low()
|
||||
|
||||
# send: start of block, data, checksum
|
||||
self.spi.send(0xfe)
|
||||
self.spi.send(buf)
|
||||
self.spi.send(0xff)
|
||||
self.spi.send(0xff)
|
||||
|
||||
# check the response
|
||||
if (self.spi.send_recv(0xff)[0] & 0x1f) != 0x05:
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
return
|
||||
|
||||
# wait for write to finish
|
||||
while self.spi.send_recv(0xff)[0] == 0:
|
||||
pass
|
||||
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
|
||||
def count(self):
|
||||
return self.sectors
|
||||
|
||||
def readblocks(self, block_num, buf):
|
||||
# TODO support multiple block reads
|
||||
assert len(buf) == 512
|
||||
|
||||
# CMD17: set read address for single block
|
||||
if self.cmd(17, block_num * self.cdv, 0) != 0:
|
||||
return 1
|
||||
|
||||
# receive the data
|
||||
self.readinto(buf)
|
||||
return 0
|
||||
|
||||
def writeblocks(self, block_num, buf):
|
||||
# TODO support multiple block writes
|
||||
assert len(buf) == 512
|
||||
|
||||
# CMD24: set write address for single block
|
||||
if self.cmd(24, block_num * self.cdv, 0) != 0:
|
||||
return 1
|
||||
|
||||
# send the data
|
||||
self.write(buf)
|
||||
return 0
|
||||
@@ -49,6 +49,9 @@
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "socket.h"
|
||||
|
||||
extern void HAL_Delay(uint32_t);
|
||||
@@ -85,7 +88,19 @@ static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
|
||||
if(len == 0) return SOCKERR_DATALEN; \
|
||||
}while(0); \
|
||||
|
||||
void WIZCHIP_EXPORT(socket_reset)(void) {
|
||||
sock_any_port = SOCK_ANY_PORT_NUM;
|
||||
sock_io_mode = 0;
|
||||
sock_is_sending = 0;
|
||||
/*
|
||||
memset(sock_remained_size, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
|
||||
memset(sock_pack_info, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint8_t));
|
||||
*/
|
||||
|
||||
#if _WIZCHIP_ == 5200
|
||||
memset(sock_next_rd, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
|
||||
{
|
||||
@@ -336,8 +351,13 @@ int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len)
|
||||
if(recvsize != 0) break;
|
||||
else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
|
||||
{
|
||||
// dpgeorge: Getting here seems to be an orderly shutdown of the
|
||||
// socket, and trying to get POSIX behaviour we return 0 because:
|
||||
// "If no messages are available to be received and the peer has per‐
|
||||
// formed an orderly shutdown, recv() shall return 0".
|
||||
// TODO this return value clashes with SOCK_BUSY in non-blocking mode.
|
||||
WIZCHIP_EXPORT(close)(sn);
|
||||
return SOCKERR_SOCKSTATUS;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -133,6 +133,9 @@
|
||||
#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received.
|
||||
#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet.
|
||||
|
||||
// resets all global state associated with the socket interface
|
||||
void WIZCHIP_EXPORT(socket_reset)(void);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Open a socket.
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
//
|
||||
|
||||
#include "wizchip_conf.h"
|
||||
#include "socket.h"
|
||||
|
||||
/**
|
||||
* @brief Default function to enable interrupt.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
@@ -328,6 +330,9 @@ int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize)
|
||||
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||
setSn_RXBUF_SIZE(i, rxsize[i]);
|
||||
}
|
||||
|
||||
WIZCHIP_EXPORT(socket_reset)();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ include ../py/py.mk
|
||||
|
||||
PORT = /dev/ttyACM0
|
||||
CROSS_COMPILE = xtensa-lx106-elf-
|
||||
ESP_SDK = $(shell $(CC) -print-sysroot)/..
|
||||
ESP_SDK = $(shell $(CC) -print-sysroot)/usr
|
||||
|
||||
INC = -I.
|
||||
INC += -I$(PY_SRC)
|
||||
|
||||
51
esp8266/README.md
Normal file
51
esp8266/README.md
Normal file
@@ -0,0 +1,51 @@
|
||||
Micro Python port to ESP8266
|
||||
============================
|
||||
|
||||
This is a port of Micro Python to the Espressif ESP8266 wifi module.
|
||||
|
||||
Currently implemented features include:
|
||||
- REPL (Python prompt) over UART0.
|
||||
- 24k heap RAM available for Python code.
|
||||
- Garbage collector, exceptions.
|
||||
- Unicode support.
|
||||
- Builtin modules: gc, array, collections, io, struct, sys.
|
||||
- C long-long type used as bignum implementation (gives 64 signed ints).
|
||||
|
||||
Note that floating-point numbers are not supported.
|
||||
|
||||
On the TODO list:
|
||||
- Wifi support.
|
||||
- GPIO support.
|
||||
- Internal filesystem using the flash.
|
||||
- ...
|
||||
|
||||
Build instructions
|
||||
------------------
|
||||
|
||||
The tool chain required for the build is the OpenSource ESP SDK, which can be
|
||||
found at <https://github.com/pfalcon/esp-open-sdk>. Clone this repository and
|
||||
run `make` in its directory to build and install the SDK locally.
|
||||
|
||||
Then, to build Micro Python for the ESP8266, just run:
|
||||
```bash
|
||||
$ make
|
||||
```
|
||||
This should produce binary images in the `build/` subdirectory. To flash them
|
||||
to your ESP8266, use:
|
||||
```bash
|
||||
$ make deploy
|
||||
```
|
||||
This will use the `esptool.py` script to download the images. You must have
|
||||
your ESP module in the bootloader, and connected to a serial port on your PC.
|
||||
The default serial port is `/dev/ttyACM0`. To specify another, use, eg:
|
||||
```bash
|
||||
$ make PORT=/dev/ttyUSB0 deploy
|
||||
```
|
||||
|
||||
The images that are built are:
|
||||
- `firmware.elf-0x00000.bin`: to be flashed at 0x00000
|
||||
- `firmware.elf-0x10000.bin`: to be flashed at 0x10000
|
||||
|
||||
There is also a combined image, made up of the above 2 binary files with the
|
||||
appropriate padding:
|
||||
- `firmware-combined.bin`: to be flashed at 0x00000
|
||||
@@ -73,9 +73,23 @@ SECTIONS
|
||||
{
|
||||
_irom0_text_start = ABSOLUTE(.);
|
||||
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
|
||||
*py*.o*(.literal* .text*)
|
||||
*gccollect.o*(.literal* .text*)
|
||||
*gchelper.o*(.literal* .text*)
|
||||
|
||||
/* we put some specific text in this section */
|
||||
*py/*.o*(.literal* .text*)
|
||||
*pyexec.o(.literal*, .text*)
|
||||
*readline.o(.literal*, .text*)
|
||||
*pybstdio.o(.literal*, .text*)
|
||||
*modpyb.o(.literal*, .text*)
|
||||
*gccollect.o(.literal* .text*)
|
||||
*gchelper.o(.literal* .text*)
|
||||
|
||||
/* we put as much rodata as possible in this section */
|
||||
/* note that only rodata accessed as a machine word is allowed here */
|
||||
*py/qstr.o(.rodata.const_pool)
|
||||
*py/*.o(.rodata.mp_type_*) /* catches type: mp_obj_type_t */
|
||||
*py/*.o(.rodata.*_locals_dict*) /* catches types: mp_obj_dict_t, mp_map_elem_t */
|
||||
*py/*.o(.rodata.mp_module_*) /* catches types: mp_obj_module_t, mp_obj_dict_t, mp_map_elem_t */
|
||||
|
||||
_irom0_text_end = ABSOLUTE(.);
|
||||
} >irom0_0_seg :irom0_0_phdr
|
||||
|
||||
@@ -90,13 +104,6 @@ SECTIONS
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
*qstr.o(.rodata.const_pool)
|
||||
*.o(.rodata.mp_type_*)
|
||||
/*
|
||||
can't put these here for some reason...
|
||||
*builtin.o(.rodata.mp_builtin_*_obj)
|
||||
*parse.o(.rodata.rule_*)
|
||||
*/
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} >iram1_0_seg :iram1_0_phdr
|
||||
|
||||
@@ -155,16 +155,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&pyb_sync_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t pyb_module_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(pyb_module_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(pyb_module_globals_table),
|
||||
.table = (mp_map_elem_t*)pyb_module_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_module_globals, pyb_module_globals_table);
|
||||
|
||||
const mp_obj_module_t pyb_module = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
79
extmod/modubinascii.c
Normal file
79
extmod/modubinascii.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 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 <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime.h"
|
||||
#include "binary.h"
|
||||
|
||||
#if MICROPY_PY_UBINASCII
|
||||
|
||||
STATIC mp_obj_t mod_binascii_hexlify(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
byte *in = bufinfo.buf, *out;
|
||||
mp_obj_t o = mp_obj_str_builder_start(&mp_type_bytes, bufinfo.len * 2, &out);
|
||||
for (mp_uint_t i = bufinfo.len; i--;) {
|
||||
byte d = (*in >> 4);
|
||||
if (d > 9) {
|
||||
d += 'a' - '9' - 1;
|
||||
}
|
||||
*out++ = d + '0';
|
||||
d = (*in++ & 0xf);
|
||||
if (d > 9) {
|
||||
d += 'a' - '9' - 1;
|
||||
}
|
||||
*out++ = d + '0';
|
||||
}
|
||||
return mp_obj_str_builder_end(o);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj, 1, 2, mod_binascii_hexlify);
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_binascii_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ubinascii) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_hexlify), (mp_obj_t)&mod_binascii_hexlify_obj },
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR_unhexlify), (mp_obj_t)&mod_binascii_unhexlify_obj },
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR_a2b_base64), (mp_obj_t)&mod_binascii_a2b_base64_obj },
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR_b2a_base64), (mp_obj_t)&mod_binascii_b2a_base64_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_ubinascii = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_ubinascii,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_binascii_globals,
|
||||
};
|
||||
|
||||
#endif //MICROPY_PY_UBINASCII
|
||||
@@ -559,7 +559,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
|
||||
/// \function addressof()
|
||||
/// Return address of object's data (applies to object providing buffer
|
||||
/// interface).
|
||||
mp_obj_t uctypes_struct_addressof(mp_obj_t buf) {
|
||||
STATIC mp_obj_t uctypes_struct_addressof(mp_obj_t buf) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
|
||||
return mp_obj_new_int((mp_int_t)bufinfo.buf);
|
||||
@@ -570,8 +570,8 @@ MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_addressof_obj, uctypes_struct_addressof
|
||||
/// Capture memory at given address of given size as bytearray. Memory is
|
||||
/// captured by reference (and thus memory pointed by bytearray may change
|
||||
/// or become invalid at later time). Use bytes_at() to capture by value.
|
||||
mp_obj_t uctypes_struct_bytearray_at(mp_obj_t ptr, mp_obj_t size) {
|
||||
return mp_obj_new_bytearray_by_ref(mp_obj_int_get(size), (void*)mp_obj_int_get(ptr));
|
||||
STATIC mp_obj_t uctypes_struct_bytearray_at(mp_obj_t ptr, mp_obj_t size) {
|
||||
return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void*)mp_obj_int_get_truncated(ptr));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytearray_at_obj, uctypes_struct_bytearray_at);
|
||||
|
||||
@@ -579,8 +579,8 @@ MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytearray_at_obj, uctypes_struct_bytear
|
||||
/// Capture memory at given address of given size as bytes. Memory is
|
||||
/// captured by value, i.e. copied. Use bytearray_at() to capture by reference
|
||||
/// ("zero copy").
|
||||
mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) {
|
||||
return mp_obj_new_bytes((void*)mp_obj_int_get(ptr), mp_obj_int_get(size));
|
||||
STATIC mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) {
|
||||
return mp_obj_new_bytes((void*)mp_obj_int_get_truncated(ptr), mp_obj_int_get_truncated(size));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at);
|
||||
|
||||
@@ -649,16 +649,7 @@ STATIC const mp_map_elem_t mp_module_uctypes_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ARRAY), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(ARRAY, AGG_TYPE_BITS)) },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_uctypes_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_uctypes_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_uctypes_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_uctypes_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_uctypes_globals, mp_module_uctypes_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uctypes = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
@@ -105,16 +105,7 @@ STATIC const mp_map_elem_t mp_module_hashlib_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sha256), (mp_obj_t)&sha256_type },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_hashlib_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_hashlib_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_hashlib_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_hashlib_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uhashlib = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
@@ -118,16 +118,7 @@ STATIC const mp_map_elem_t mp_module_uheapq_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_heapify), (mp_obj_t)&mod_uheapq_heapify_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_uheapq_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_uheapq_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_uheapq_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_uheapq_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_uheapq_globals, mp_module_uheapq_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uheapq = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
@@ -259,16 +259,7 @@ STATIC const mp_map_elem_t mp_module_ujson_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_loads), (mp_obj_t)&mod_ujson_loads_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_ujson_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_ujson_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_ujson_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_ujson_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_ujson_globals, mp_module_ujson_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_ujson = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
@@ -62,7 +62,7 @@ STATIC void match_print(void (*print)(void *env, const char *fmt, ...), void *en
|
||||
|
||||
STATIC mp_obj_t match_group(mp_obj_t self_in, mp_obj_t no_in) {
|
||||
mp_obj_match_t *self = self_in;
|
||||
mp_int_t no = mp_obj_int_get(no_in);
|
||||
mp_int_t no = mp_obj_int_get_truncated(no_in);
|
||||
if (no < 0 || no >= self->num_matches / 2) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_IndexError, no_in));
|
||||
}
|
||||
@@ -130,7 +130,7 @@ STATIC mp_obj_t re_split(uint n_args, const mp_obj_t *args) {
|
||||
|
||||
int maxsplit = 0;
|
||||
if (n_args > 2) {
|
||||
maxsplit = mp_obj_int_get(args[2]);
|
||||
maxsplit = mp_obj_int_get_truncated(args[2]);
|
||||
}
|
||||
|
||||
mp_obj_t retval = mp_obj_new_list(0, NULL);
|
||||
@@ -175,7 +175,7 @@ STATIC const mp_obj_type_t re_type = {
|
||||
.locals_dict = (mp_obj_t)&re_locals_dict,
|
||||
};
|
||||
|
||||
mp_obj_t mod_re_compile(uint n_args, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t mod_re_compile(uint n_args, const mp_obj_t *args) {
|
||||
const char *re_str = mp_obj_str_get_str(args[0]);
|
||||
int size = re1_5_sizecode(re_str);
|
||||
mp_obj_re_t *o = m_new_obj_var(mp_obj_re_t, char, size);
|
||||
@@ -221,16 +221,7 @@ STATIC const mp_map_elem_t mp_module_re_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_DEBUG), MP_OBJ_NEW_SMALL_INT(FLAG_DEBUG) },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_re_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_re_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_re_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_re_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_re_globals, mp_module_re_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_ure = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
@@ -87,16 +87,7 @@ STATIC const mp_map_elem_t mp_module_uzlib_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_decompress), (mp_obj_t)&mod_uzlib_decompress_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_uzlib_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_uzlib_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_uzlib_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_uzlib_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_uzlib_globals, mp_module_uzlib_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uzlib = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FatFs Module Source Files R0.10 (C)ChaN, 2013
|
||||
FatFs Module Source Files R0.10c (C)ChaN, 2014
|
||||
|
||||
|
||||
FILES
|
||||
@@ -24,7 +24,7 @@ AGREEMENTS
|
||||
small embedded systems. This is a free software and is opened for education,
|
||||
research and commercial developments under license policy of following trems.
|
||||
|
||||
Copyright (C) 2013, ChaN, all right reserved.
|
||||
Copyright (C) 2014, ChaN, all right reserved.
|
||||
|
||||
* The FatFs module is a free software and there is NO WARRANTY.
|
||||
* No restriction on use. You can use, modify and redistribute it for
|
||||
@@ -134,7 +134,7 @@ REVISION HISTORY
|
||||
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
|
||||
Changed option name _FS_SHARE to _FS_LOCK.
|
||||
|
||||
Jan 23,'13 R0.09b Added f_getlabel() and f_setlabel(). (_USE_LABEL == 1)
|
||||
Jan 23,'13 R0.09b Added f_getlabel() and f_setlabel(). (_USE_LABEL)
|
||||
|
||||
Oct 02,'13 R0.10 Added selection of character encoding on the file. (_STRF_ENCODE)
|
||||
Added f_closedir().
|
||||
@@ -145,3 +145,19 @@ REVISION HISTORY
|
||||
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
|
||||
Fixed f_write() can be truncated when the file size is close to 4GB.
|
||||
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect error code.
|
||||
|
||||
Jan 15,'14 R0.10a Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
|
||||
Added a configuration option of minimum sector size. (_MIN_SS)
|
||||
2nd argument of f_rename() can have a drive number and it will be ignored.
|
||||
Fixed f_mount() with forced mount fails when drive number is >= 1.
|
||||
Fixed f_close() invalidates the file object without volume lock.
|
||||
Fixed f_closedir() returns but the volume lock is left acquired.
|
||||
Fixed creation of an entry with LFN fails on too many SFN collisions.
|
||||
|
||||
Mar 19,'14 R0.10b Fixed a hard error in the disk I/O layer can collapse the directory entry.
|
||||
Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN.
|
||||
|
||||
Nov 09,'14 R0.10c Added a configuration option for the platforms without RTC. (_FS_NORTC)
|
||||
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel().
|
||||
Fixed a potential problem of FAT access that can appear on disk error.
|
||||
Fixed null pointer dereference on attempting to delete the root direcotry.
|
||||
230
lib/fatfs/diskio.c
Normal file
230
lib/fatfs/diskio.c
Normal file
@@ -0,0 +1,230 @@
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2014 */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* If a working storage control module is available, it should be */
|
||||
/* attached to the FatFs via a glue function rather than modifying it. */
|
||||
/* This is an example of glue functions to attach various exsisting */
|
||||
/* storage control modules to the FatFs module with a defined API. */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#include "diskio.h" /* FatFs lower layer API */
|
||||
#include "usbdisk.h" /* Example: USB drive control */
|
||||
#include "atadrive.h" /* Example: ATA drive control */
|
||||
#include "sdcard.h" /* Example: MMC/SDC contorl */
|
||||
|
||||
/* Definitions of physical drive number for each drive */
|
||||
#define ATA 0 /* Example: Map ATA drive to drive number 0 */
|
||||
#define MMC 1 /* Example: Map MMC/SD card to drive number 1 */
|
||||
#define USB 2 /* Example: Map USB drive to drive number 2 */
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Get Drive Status */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_status (
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
DSTATUS stat;
|
||||
int result;
|
||||
|
||||
switch (pdrv) {
|
||||
case ATA :
|
||||
result = ATA_disk_status();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
|
||||
case MMC :
|
||||
result = MMC_disk_status();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
|
||||
case USB :
|
||||
result = USB_disk_status();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
}
|
||||
return STA_NOINIT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Inidialize a Drive */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_initialize (
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
DSTATUS stat;
|
||||
int result;
|
||||
|
||||
switch (pdrv) {
|
||||
case ATA :
|
||||
result = ATA_disk_initialize();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
|
||||
case MMC :
|
||||
result = MMC_disk_initialize();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
|
||||
case USB :
|
||||
result = USB_disk_initialize();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
}
|
||||
return STA_NOINIT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Read Sector(s) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DRESULT disk_read (
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
BYTE *buff, /* Data buffer to store read data */
|
||||
DWORD sector, /* Sector address in LBA */
|
||||
UINT count /* Number of sectors to read */
|
||||
)
|
||||
{
|
||||
DRESULT res;
|
||||
int result;
|
||||
|
||||
switch (pdrv) {
|
||||
case ATA :
|
||||
// translate the arguments here
|
||||
|
||||
result = ATA_disk_read(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
|
||||
case MMC :
|
||||
// translate the arguments here
|
||||
|
||||
result = MMC_disk_read(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
|
||||
case USB :
|
||||
// translate the arguments here
|
||||
|
||||
result = USB_disk_read(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Write Sector(s) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#if _USE_WRITE
|
||||
DRESULT disk_write (
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
const BYTE *buff, /* Data to be written */
|
||||
DWORD sector, /* Sector address in LBA */
|
||||
UINT count /* Number of sectors to write */
|
||||
)
|
||||
{
|
||||
DRESULT res;
|
||||
int result;
|
||||
|
||||
switch (pdrv) {
|
||||
case ATA :
|
||||
// translate the arguments here
|
||||
|
||||
result = ATA_disk_write(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
|
||||
case MMC :
|
||||
// translate the arguments here
|
||||
|
||||
result = MMC_disk_write(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
|
||||
case USB :
|
||||
// translate the arguments here
|
||||
|
||||
result = USB_disk_write(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return RES_PARERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Miscellaneous Functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#if _USE_IOCTL
|
||||
DRESULT disk_ioctl (
|
||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||
BYTE cmd, /* Control code */
|
||||
void *buff /* Buffer to send/receive control data */
|
||||
)
|
||||
{
|
||||
DRESULT res;
|
||||
int result;
|
||||
|
||||
switch (pdrv) {
|
||||
case ATA :
|
||||
|
||||
// Process of the command for the ATA drive
|
||||
|
||||
return res;
|
||||
|
||||
case MMC :
|
||||
|
||||
// Process of the command for the MMC/SD card
|
||||
|
||||
return res;
|
||||
|
||||
case USB :
|
||||
|
||||
// Process of the command the USB drive
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return RES_PARERR;
|
||||
}
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
/ Low level disk interface modlue include file (C)ChaN, 2013
|
||||
/*-----------------------------------------------------------------------/
|
||||
/ Low level disk interface modlue include file (C)ChaN, 2014 /
|
||||
/-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _DISKIO_DEFINED
|
||||
@@ -34,12 +34,13 @@ typedef enum {
|
||||
|
||||
DSTATUS disk_initialize (BYTE pdrv);
|
||||
DSTATUS disk_status (BYTE pdrv);
|
||||
DRESULT disk_read (BYTE pdrv, BYTE*buff, DWORD sector, BYTE count);
|
||||
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, BYTE count);
|
||||
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
|
||||
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
|
||||
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||
|
||||
|
||||
/* Disk Status Bits (DSTATUS) */
|
||||
|
||||
#define STA_NOINIT 0x01 /* Drive not initialized */
|
||||
#define STA_NODISK 0x02 /* No medium in the drive */
|
||||
#define STA_PROTECT 0x04 /* Write protected */
|
||||
@@ -47,14 +48,14 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||
|
||||
/* Command code for disk_ioctrl fucntion */
|
||||
|
||||
/* Generic command (used by FatFs) */
|
||||
#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */
|
||||
#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */
|
||||
#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */
|
||||
#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */
|
||||
#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */
|
||||
/* Generic command (Used by FatFs) */
|
||||
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
|
||||
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
|
||||
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
|
||||
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
|
||||
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
|
||||
|
||||
/* Generic command (not used by FatFs) */
|
||||
/* Generic command (Not used by FatFs) */
|
||||
#define CTRL_POWER 5 /* Get/Set power status */
|
||||
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
|
||||
#define CTRL_EJECT 7 /* Eject media */
|
||||
@@ -72,18 +73,8 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||
#define ATA_GET_MODEL 21 /* Get model name */
|
||||
#define ATA_GET_SN 22 /* Get serial number */
|
||||
|
||||
|
||||
/* MMC card type flags (MMC_GET_TYPE) */
|
||||
#define CT_MMC 0x01 /* MMC ver 3 */
|
||||
#define CT_SD1 0x02 /* SD ver 1 */
|
||||
#define CT_SD2 0x04 /* SD ver 2 */
|
||||
#define CT_SDC (CT_SD1|CT_SD2) /* SD */
|
||||
#define CT_BLOCK 0x08 /* Block addressing */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module include file R0.10 (C)ChaN, 2013
|
||||
/ FatFs - FAT file system module include file R0.10c (C)ChaN, 2014
|
||||
/----------------------------------------------------------------------------/
|
||||
/ FatFs module is a generic FAT file system module for small embedded systems.
|
||||
/ This is a free software that opened for education, research and commercial
|
||||
/ developments under license policy of following terms.
|
||||
/
|
||||
/ Copyright (C) 2013, ChaN, all right reserved.
|
||||
/ Copyright (C) 2014, ChaN, all right reserved.
|
||||
/
|
||||
/ * The FatFs module is a free software and there is NO WARRANTY.
|
||||
/ * No restriction on use. You can use, modify and redistribute it for
|
||||
@@ -15,7 +15,7 @@
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _FATFS
|
||||
#define _FATFS 80960 /* Revision ID */
|
||||
#define _FATFS 80376 /* Revision ID */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -23,7 +23,6 @@ extern "C" {
|
||||
|
||||
#include "integer.h" /* Basic integer types */
|
||||
#include "ffconf.h" /* FatFs configuration options */
|
||||
|
||||
#if _FATFS != _FFCONF
|
||||
#error Wrong configuration file (ffconf.h).
|
||||
#endif
|
||||
@@ -53,7 +52,7 @@ extern const PARTITION VolToPart[]; /* Volume - Partition resolution table */
|
||||
|
||||
#if _LFN_UNICODE /* Unicode string */
|
||||
#if !_USE_LFN
|
||||
#error _LFN_UNICODE must be 0 in non-LFN cfg.
|
||||
#error _LFN_UNICODE must be 0 at non-LFN cfg.
|
||||
#endif
|
||||
#ifndef _INC_TCHAR
|
||||
typedef WCHAR TCHAR;
|
||||
@@ -75,10 +74,6 @@ typedef char TCHAR;
|
||||
/* File system object structure (FATFS) */
|
||||
|
||||
typedef struct {
|
||||
union{
|
||||
UINT d32[_MAX_SS/4]; /* Force 32bits alignement */
|
||||
BYTE d8[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||
}win;
|
||||
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
|
||||
BYTE drv; /* Physical drive number */
|
||||
BYTE csize; /* Sectors per cluster (1,2,4...128) */
|
||||
@@ -87,7 +82,7 @@ typedef struct {
|
||||
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
||||
WORD id; /* File system mount ID */
|
||||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||
#if _MAX_SS != 512
|
||||
#if _MAX_SS != _MIN_SS
|
||||
WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
|
||||
#endif
|
||||
#if _FS_REENTRANT
|
||||
@@ -100,14 +95,14 @@ typedef struct {
|
||||
#if _FS_RPATH
|
||||
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||
#endif
|
||||
DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */
|
||||
DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */
|
||||
DWORD fsize; /* Sectors per FAT */
|
||||
DWORD volbase; /* Volume start sector */
|
||||
DWORD fatbase; /* FAT start sector */
|
||||
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
|
||||
DWORD database; /* Data start sector */
|
||||
DWORD winsect; /* Current sector appearing in the win[] */
|
||||
|
||||
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||
} FATFS;
|
||||
|
||||
|
||||
@@ -115,30 +110,27 @@ typedef struct {
|
||||
/* File object structure (FIL) */
|
||||
|
||||
typedef struct {
|
||||
#if !_FS_TINY
|
||||
union{
|
||||
UINT d32[_MAX_SS/4]; /* Force 32bits alignement */
|
||||
BYTE d8[_MAX_SS]; /* File data read/write buffer */
|
||||
}buf;
|
||||
#endif
|
||||
FATFS* fs; /* Pointer to the related file system object (**do not change order**) */
|
||||
WORD id; /* Owner file system mount ID (**do not change order**) */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE flag; /* Status flags */
|
||||
BYTE err; /* Abort flag (error code) */
|
||||
DWORD fptr; /* File read/write pointer (Zeroed on file open) */
|
||||
DWORD fsize; /* File size */
|
||||
DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */
|
||||
DWORD clust; /* Current cluster of fpter */
|
||||
DWORD dsect; /* Current data sector of fpter */
|
||||
DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */
|
||||
DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
|
||||
DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */
|
||||
#if !_FS_READONLY
|
||||
DWORD dir_sect; /* Sector containing the directory entry */
|
||||
BYTE* dir_ptr; /* Pointer to the directory entry in the window */
|
||||
DWORD dir_sect; /* Sector number containing the directory entry */
|
||||
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
|
||||
#endif
|
||||
#if _USE_FASTSEEK
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
|
||||
#endif
|
||||
#if _FS_LOCK
|
||||
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
|
||||
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
||||
#endif
|
||||
#if !_FS_TINY
|
||||
BYTE buf[_MAX_SS]; /* File private data read/write window */
|
||||
#endif
|
||||
} FIL;
|
||||
|
||||
@@ -147,12 +139,6 @@ typedef struct {
|
||||
/* Directory object structure (DIR) */
|
||||
|
||||
typedef struct {
|
||||
#if !_FS_TINY
|
||||
union{
|
||||
UINT d32[_MAX_SS/4]; /* Force 32bits alignement */
|
||||
BYTE d8[_MAX_SS]; /* File data read/write buffer */
|
||||
}buf;
|
||||
#endif
|
||||
FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */
|
||||
WORD id; /* Owner file system mount ID (**do not change order**) */
|
||||
WORD index; /* Current read/write index number */
|
||||
@@ -239,7 +225,7 @@ FRESULT f_chdir (const TCHAR* path); /* Change current directory */
|
||||
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
|
||||
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
|
||||
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
|
||||
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* sn); /* Get volume label */
|
||||
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
|
||||
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
||||
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
|
||||
FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */
|
||||
@@ -249,7 +235,7 @@ int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
|
||||
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
|
||||
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
|
||||
|
||||
#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
|
||||
#define f_eof(fp) ((int)((fp)->fptr == (fp)->fsize))
|
||||
#define f_error(fp) ((fp)->err)
|
||||
#define f_tell(fp) ((fp)->fptr)
|
||||
#define f_size(fp) ((fp)->fsize)
|
||||
@@ -265,7 +251,7 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil
|
||||
/* Additional user defined functions */
|
||||
|
||||
/* RTC function */
|
||||
#if !_FS_READONLY
|
||||
#if !_FS_READONLY && !_FS_NORTC
|
||||
DWORD get_fattime (void);
|
||||
#endif
|
||||
|
||||
@@ -287,10 +273,16 @@ void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
|
||||
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
|
||||
#endif
|
||||
|
||||
// dpgeorge: added the following 3 declarations to support our volume names
|
||||
|
||||
/* Returns logical drive number (-1:invalid drive) */
|
||||
// Current drive
|
||||
extern BYTE ff_CurrVol;
|
||||
|
||||
// Returns logical drive number (-1:invalid drive)
|
||||
int ff_get_ldnumber(const TCHAR** path);
|
||||
|
||||
// Store the volume name into dest, and advance the pointer
|
||||
void ff_get_volname(BYTE vol, TCHAR **dest);
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Flags and offset address */
|
||||
@@ -355,4 +347,3 @@ int ff_get_ldnumber(const TCHAR** path);
|
||||
#endif
|
||||
|
||||
#endif /* _FATFS */
|
||||
|
||||
270
lib/fatfs/ffconf_template.h
Normal file
270
lib/fatfs/ffconf_template.h
Normal file
@@ -0,0 +1,270 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module configuration file R0.10c (C)ChaN, 2014
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _FFCONF 80376 /* Revision ID */
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Functions and Buffer Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _FS_TINY 0
|
||||
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
||||
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS
|
||||
/ bytes. Instead of private sector buffer eliminated from the file object,
|
||||
/ common sector buffer in the file system object (FATFS) is used for the file
|
||||
/ data transfer. */
|
||||
|
||||
|
||||
#define _FS_READONLY 0
|
||||
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
|
||||
/ Read-only configuration removes basic writing API functions, f_write(),
|
||||
/ f_sync(), f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(),
|
||||
/ f_getfree() and optional writing functions as well. */
|
||||
|
||||
|
||||
#define _FS_MINIMIZE 0
|
||||
/* This option defines minimization level to remove some API functions.
|
||||
/
|
||||
/ 0: All basic functions are enabled.
|
||||
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(),
|
||||
/ f_truncate() and f_rename() function are removed.
|
||||
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
|
||||
/ 3: f_lseek() function is removed in addition to 2. */
|
||||
|
||||
|
||||
#define _USE_STRFUNC 0
|
||||
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
|
||||
/ f_printf().
|
||||
/
|
||||
/ 0: Disable string functions.
|
||||
/ 1: Enable without LF-CRLF conversion.
|
||||
/ 2: Enable with LF-CRLF conversion. */
|
||||
|
||||
|
||||
#define _USE_MKFS 0
|
||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable)
|
||||
/ To enable it, also _FS_READONLY need to be set to 0. */
|
||||
|
||||
|
||||
#define _USE_FASTSEEK 0
|
||||
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define _USE_LABEL 0
|
||||
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
||||
/ (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define _USE_FORWARD 0
|
||||
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
|
||||
/* To enable it, also _FS_TINY need to be set to 1. */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Locale and Namespace Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _CODE_PAGE 932
|
||||
/* This option specifies the OEM code page to be used on the target system.
|
||||
/ Incorrect setting of the code page can cause a file open failure.
|
||||
/
|
||||
/ 932 - Japanese Shift_JIS (DBCS, OEM, Windows)
|
||||
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
|
||||
/ 949 - Korean (DBCS, OEM, Windows)
|
||||
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
|
||||
/ 1250 - Central Europe (Windows)
|
||||
/ 1251 - Cyrillic (Windows)
|
||||
/ 1252 - Latin 1 (Windows)
|
||||
/ 1253 - Greek (Windows)
|
||||
/ 1254 - Turkish (Windows)
|
||||
/ 1255 - Hebrew (Windows)
|
||||
/ 1256 - Arabic (Windows)
|
||||
/ 1257 - Baltic (Windows)
|
||||
/ 1258 - Vietnam (OEM, Windows)
|
||||
/ 437 - U.S. (OEM)
|
||||
/ 720 - Arabic (OEM)
|
||||
/ 737 - Greek (OEM)
|
||||
/ 775 - Baltic (OEM)
|
||||
/ 850 - Multilingual Latin 1 (OEM)
|
||||
/ 858 - Multilingual Latin 1 + Euro (OEM)
|
||||
/ 852 - Latin 2 (OEM)
|
||||
/ 855 - Cyrillic (OEM)
|
||||
/ 866 - Russian (OEM)
|
||||
/ 857 - Turkish (OEM)
|
||||
/ 862 - Hebrew (OEM)
|
||||
/ 874 - Thai (OEM, Windows)
|
||||
/ 1 - ASCII (No extended character. Valid for only non-LFN configuration.) */
|
||||
|
||||
|
||||
#define _USE_LFN 0
|
||||
#define _MAX_LFN 255
|
||||
/* The _USE_LFN option switches the LFN feature.
|
||||
/
|
||||
/ 0: Disable LFN feature. _MAX_LFN has no effect.
|
||||
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
|
||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||
/
|
||||
/ When enable the LFN feature, Unicode handling functions (option/unicode.c) must
|
||||
/ be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes.
|
||||
/ When use stack for the working buffer, take care on stack overflow. When use heap
|
||||
/ memory for the working buffer, memory management functions, ff_memalloc() and
|
||||
/ ff_memfree(), must be added to the project. */
|
||||
|
||||
|
||||
#define _LFN_UNICODE 0
|
||||
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode)
|
||||
/ To use Unicode string for the path name, enable LFN feature and set _LFN_UNICODE
|
||||
/ to 1. This option also affects behavior of string I/O functions. */
|
||||
|
||||
|
||||
#define _STRF_ENCODE 3
|
||||
/* When _LFN_UNICODE is 1, this option selects the character encoding on the file to
|
||||
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
|
||||
/
|
||||
/ 0: ANSI/OEM
|
||||
/ 1: UTF-16LE
|
||||
/ 2: UTF-16BE
|
||||
/ 3: UTF-8
|
||||
/
|
||||
/ When _LFN_UNICODE is 0, this option has no effect. */
|
||||
|
||||
|
||||
#define _FS_RPATH 0
|
||||
/* This option configures relative path feature.
|
||||
/
|
||||
/ 0: Disable relative path feature and remove related functions.
|
||||
/ 1: Enable relative path feature. f_chdir() and f_chdrive() are available.
|
||||
/ 2: f_getcwd() function is available in addition to 1.
|
||||
/
|
||||
/ Note that directory items read via f_readdir() are affected by this option. */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Drive/Volume Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _VOLUMES 1
|
||||
/* Number of volumes (logical drives) to be used. */
|
||||
|
||||
|
||||
#define _STR_VOLUME_ID 0
|
||||
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
|
||||
/* _STR_VOLUME_ID option switches string volume ID feature.
|
||||
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
|
||||
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
|
||||
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
|
||||
/ the drive ID strings are: A-Z and 0-9. */
|
||||
|
||||
|
||||
#define _MULTI_PARTITION 0
|
||||
/* This option switches multi-partition feature. By default (0), each logical drive
|
||||
/ number is bound to the same physical drive number and only an FAT volume found on
|
||||
/ the physical drive will be mounted. When multi-partition feature is enabled (1),
|
||||
/ each logical drive number is bound to arbitrary physical drive and partition
|
||||
/ listed in the VolToPart[]. Also f_fdisk() funciton will be enabled. */
|
||||
|
||||
|
||||
#define _MIN_SS 512
|
||||
#define _MAX_SS 512
|
||||
/* These options configure the range of sector size to be supported. (512, 1024,
|
||||
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
|
||||
/ harddisk. But a larger value may be required for on-board flash memory and some
|
||||
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
|
||||
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
|
||||
/ disk_ioctl() function. */
|
||||
|
||||
|
||||
#define _USE_TRIM 0
|
||||
/* This option switches ATA-TRIM feature. (0:Disable or 1:Enable)
|
||||
/ To enable Trim feature, also CTRL_TRIM command should be implemented to the
|
||||
/ disk_ioctl() function. */
|
||||
|
||||
|
||||
#define _FS_NOFSINFO 0
|
||||
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
||||
/ option, and f_getfree() function at first time after volume mount will force
|
||||
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
|
||||
/
|
||||
/ bit0=0: Use free cluster count in the FSINFO if available.
|
||||
/ bit0=1: Do not trust free cluster count in the FSINFO.
|
||||
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
|
||||
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ System Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _FS_NORTC 0
|
||||
#define _NORTC_MON 11
|
||||
#define _NORTC_MDAY 9
|
||||
#define _NORTC_YEAR 2014
|
||||
/* The _FS_NORTC option switches timestamp feature. If the system does not have
|
||||
/ an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable
|
||||
/ the timestamp feature. All objects modified by FatFs will have a fixed timestamp
|
||||
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR.
|
||||
/ When timestamp feature is enabled (_FS_NORTC == 0), get_fattime() function need
|
||||
/ to be added to the project to read current time form RTC. _NORTC_MON,
|
||||
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
|
||||
/ These options have no effect at read-only configuration (_FS_READONLY == 1). */
|
||||
|
||||
|
||||
#define _FS_LOCK 0
|
||||
/* The _FS_LOCK option switches file lock feature to control duplicated file open
|
||||
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
|
||||
/ is 1.
|
||||
/
|
||||
/ 0: Disable file lock feature. To avoid volume corruption, application program
|
||||
/ should avoid illegal open, remove and rename to the open objects.
|
||||
/ >0: Enable file lock feature. The value defines how many files/sub-directories
|
||||
/ can be opened simultaneously under file lock control. Note that the file
|
||||
/ lock feature is independent of re-entrancy. */
|
||||
|
||||
|
||||
#define _FS_REENTRANT 0
|
||||
#define _FS_TIMEOUT 1000
|
||||
#define _SYNC_t HANDLE
|
||||
/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs
|
||||
/ module itself. Note that regardless of this option, file access to different
|
||||
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
|
||||
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
|
||||
/ to the same volume is under control of this feature.
|
||||
/
|
||||
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
|
||||
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
||||
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
|
||||
/ function, must be added to the project. Samples are available in
|
||||
/ option/syscall.c.
|
||||
/
|
||||
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
|
||||
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
|
||||
/ SemaphoreHandle_t and etc.. */
|
||||
|
||||
|
||||
#define _WORD_ACCESS 0
|
||||
/* The _WORD_ACCESS option is an only platform dependent option. It defines
|
||||
/ which access method is used to the word data on the FAT volume.
|
||||
/
|
||||
/ 0: Byte-by-byte access. Always compatible with all platforms.
|
||||
/ 1: Word access. Do not choose this unless under both the following conditions.
|
||||
/
|
||||
/ * Address misaligned memory access is always allowed to ALL instructions.
|
||||
/ * Byte order on the memory is little-endian.
|
||||
/
|
||||
/ If it is the case, _WORD_ACCESS can also be set to 1 to reduce code size.
|
||||
/ Following table shows allowable settings of some processor types.
|
||||
/
|
||||
/ ARM7TDMI 0 ColdFire 0 V850E 0
|
||||
/ Cortex-M3 0 Z80 0/1 V850ES 0/1
|
||||
/ Cortex-M0 0 x86 0/1 TLCS-870 0/1
|
||||
/ AVR 0/1 RX600(LE) 0/1 TLCS-900 0/1
|
||||
/ AVR32 0 RL78 0 R32C 0
|
||||
/ PIC18 0/1 SH-2 0 M16C 0/1
|
||||
/ PIC24 0 H8S 0 MSP430 0
|
||||
/ PIC32 0 H8/300H 0 8051 0/1
|
||||
*/
|
||||
|
||||
@@ -31,4 +31,3 @@ typedef unsigned long DWORD;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3739,10 +3739,10 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */
|
||||
#if !_TINY_TABLE
|
||||
if (dir) { /* OEMCP to unicode */
|
||||
p = sjis2uni;
|
||||
hi = sizeof(sjis2uni) / 4 - 1;
|
||||
hi = sizeof sjis2uni / 4 - 1;
|
||||
} else { /* Unicode to OEMCP */
|
||||
p = uni2sjis;
|
||||
hi = sizeof(uni2sjis) / 4 - 1;
|
||||
hi = sizeof uni2sjis / 4 - 1;
|
||||
}
|
||||
li = 0;
|
||||
for (n = 16; n; n--) {
|
||||
@@ -3764,7 +3764,7 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */
|
||||
p -= 3;
|
||||
c = *p;
|
||||
} else { /* Unicode to OEMCP */
|
||||
li = 0; hi = sizeof(uni2sjis) / 4 - 1;
|
||||
li = 0; hi = sizeof uni2sjis / 4 - 1;
|
||||
for (n = 16; n; n--) {
|
||||
i = li + (hi - li) / 2;
|
||||
if (chr == uni2sjis[i * 2]) break;
|
||||
@@ -10936,10 +10936,10 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */
|
||||
} else {
|
||||
if (dir) { /* OEMCP to unicode */
|
||||
p = oem2uni;
|
||||
hi = sizeof(oem2uni) / 4 - 1;
|
||||
hi = sizeof oem2uni / 4 - 1;
|
||||
} else { /* Unicode to OEMCP */
|
||||
p = uni2oem;
|
||||
hi = sizeof(uni2oem) / 4 - 1;
|
||||
hi = sizeof uni2oem / 4 - 1;
|
||||
}
|
||||
li = 0;
|
||||
for (n = 16; n; n--) {
|
||||
@@ -8565,10 +8565,10 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */
|
||||
} else {
|
||||
if (dir) { /* OEMCP to unicode */
|
||||
p = oem2uni;
|
||||
hi = sizeof(oem2uni) / 4 - 1;
|
||||
hi = sizeof oem2uni / 4 - 1;
|
||||
} else { /* Unicode to OEMCP */
|
||||
p = uni2oem;
|
||||
hi = sizeof(uni2oem) / 4 - 1;
|
||||
hi = sizeof uni2oem / 4 - 1;
|
||||
}
|
||||
li = 0;
|
||||
for (n = 16; n; n--) {
|
||||
@@ -6791,10 +6791,10 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */
|
||||
} else {
|
||||
if (dir) { /* OEMCP to unicode */
|
||||
p = oem2uni;
|
||||
hi = sizeof(oem2uni) / 4 - 1;
|
||||
hi = sizeof oem2uni / 4 - 1;
|
||||
} else { /* Unicode to OEMCP */
|
||||
p = uni2oem;
|
||||
hi = sizeof(uni2oem) / 4 - 1;
|
||||
hi = sizeof uni2oem / 4 - 1;
|
||||
}
|
||||
li = 0;
|
||||
for (n = 16; n; n--) {
|
||||
151
lib/fatfs/option/syscall.c
Normal file
151
lib/fatfs/option/syscall.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Sample code of OS dependent controls for FatFs */
|
||||
/* (C)ChaN, 2014 */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "../ff.h"
|
||||
|
||||
|
||||
#if _FS_REENTRANT
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Create a Synchronization Object
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called in f_mount() function to create a new
|
||||
/ synchronization object, such as semaphore and mutex. When a 0 is returned,
|
||||
/ the f_mount() function fails with FR_INT_ERR.
|
||||
*/
|
||||
|
||||
int ff_cre_syncobj ( /* !=0:Function succeeded, ==0:Could not create due to any error */
|
||||
BYTE vol, /* Corresponding logical drive being processed */
|
||||
_SYNC_t *sobj /* Pointer to return the created sync object */
|
||||
)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
*sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */
|
||||
ret = (int)(*sobj != INVALID_HANDLE_VALUE);
|
||||
|
||||
// *sobj = SyncObjects[vol]; /* uITRON (give a static created sync object) */
|
||||
// ret = 1; /* The initial value of the semaphore must be 1. */
|
||||
|
||||
// *sobj = OSMutexCreate(0, &err); /* uC/OS-II */
|
||||
// ret = (int)(err == OS_NO_ERR);
|
||||
|
||||
// *sobj = xSemaphoreCreateMutex(); /* FreeRTOS */
|
||||
// ret = (int)(*sobj != NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Delete a Synchronization Object */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called in f_mount() function to delete a synchronization
|
||||
/ object that created with ff_cre_syncobj function. When a 0 is returned,
|
||||
/ the f_mount() function fails with FR_INT_ERR.
|
||||
*/
|
||||
|
||||
int ff_del_syncobj ( /* !=0:Function succeeded, ==0:Could not delete due to any error */
|
||||
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
|
||||
)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
ret = CloseHandle(sobj); /* Win32 */
|
||||
|
||||
// ret = 1; /* uITRON (nothing to do) */
|
||||
|
||||
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); /* uC/OS-II */
|
||||
// ret = (int)(err == OS_NO_ERR);
|
||||
|
||||
// vSemaphoreDelete(sobj); /* FreeRTOS */
|
||||
// ret = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Request Grant to Access the Volume */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called on entering file functions to lock the volume.
|
||||
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
|
||||
*/
|
||||
|
||||
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
|
||||
_SYNC_t sobj /* Sync object to wait */
|
||||
)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = (int)(WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0); /* Win32 */
|
||||
|
||||
// ret = (int)(wai_sem(sobj) == E_OK); /* uITRON */
|
||||
|
||||
// OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */
|
||||
// ret = (int)(err == OS_NO_ERR);
|
||||
|
||||
// ret = (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE); /* FreeRTOS */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Release Grant to Access the Volume */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called on leaving file functions to unlock the volume.
|
||||
*/
|
||||
|
||||
void ff_rel_grant (
|
||||
_SYNC_t sobj /* Sync object to be signaled */
|
||||
)
|
||||
{
|
||||
ReleaseMutex(sobj); /* Win32 */
|
||||
|
||||
// sig_sem(sobj); /* uITRON */
|
||||
|
||||
// OSMutexPost(sobj); /* uC/OS-II */
|
||||
|
||||
// xSemaphoreGive(sobj); /* FreeRTOS */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Allocate a memory block */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
|
||||
*/
|
||||
|
||||
void* ff_memalloc ( /* Returns pointer to the allocated memory block */
|
||||
UINT msize /* Number of bytes to allocate */
|
||||
)
|
||||
{
|
||||
return malloc(msize); /* Allocate a new memory block with POSIX API */
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Free a memory block */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void ff_memfree (
|
||||
void* mblock /* Pointer to the memory block to free */
|
||||
)
|
||||
{
|
||||
free(mblock); /* Discard the memory block with POSIX API */
|
||||
}
|
||||
|
||||
#endif
|
||||
17
lib/fatfs/option/unicode.c
Normal file
17
lib/fatfs/option/unicode.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "../ff.h"
|
||||
|
||||
#if _USE_LFN != 0
|
||||
|
||||
#if _CODE_PAGE == 932 /* Japanese Shift_JIS */
|
||||
#include "cc932.c"
|
||||
#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
|
||||
#include "cc936.c"
|
||||
#elif _CODE_PAGE == 949 /* Korean */
|
||||
#include "cc949.c"
|
||||
#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
|
||||
#include "cc950.c"
|
||||
#else /* Small character-set */
|
||||
#include "ccsbcs.c"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
32
lib/libm/acoshf.c
Normal file
32
lib/libm/acoshf.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
// acoshf from musl-0.9.15
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "libm.h"
|
||||
|
||||
#if FLT_EVAL_METHOD==2
|
||||
#undef sqrtf
|
||||
#define sqrtf sqrtl
|
||||
#elif FLT_EVAL_METHOD==1
|
||||
#undef sqrtf
|
||||
#define sqrtf sqrt
|
||||
#endif
|
||||
|
||||
/* acosh(x) = log(x + sqrt(x*x-1)) */
|
||||
float acoshf(float x)
|
||||
{
|
||||
union {float f; uint32_t i;} u = {x};
|
||||
uint32_t a = u.i & 0x7fffffff;
|
||||
|
||||
if (a < 0x3f800000+(1<<23))
|
||||
/* |x| < 2, invalid if x < 1 or nan */
|
||||
/* up to 2ulp error in [1,1.125] */
|
||||
return log1pf(x-1 + sqrtf((x-1)*(x-1)+2*(x-1)));
|
||||
if (a < 0x3f800000+(12<<23))
|
||||
/* |x| < 0x1p12 */
|
||||
return logf(2*x - 1/(x+sqrtf(x*x-1)));
|
||||
/* x >= 0x1p12 */
|
||||
return logf(x) + 0.693147180559945309417232121458176568f;
|
||||
}
|
||||
34
lib/libm/asinhf.c
Normal file
34
lib/libm/asinhf.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
// asinhf from musl-0.9.15
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "libm.h"
|
||||
|
||||
/* asinh(x) = sign(x)*log(|x|+sqrt(x*x+1)) ~= x - x^3/6 + o(x^5) */
|
||||
float asinhf(float x)
|
||||
{
|
||||
union {float f; uint32_t i;} u = {.f = x};
|
||||
uint32_t i = u.i & 0x7fffffff;
|
||||
unsigned s = u.i >> 31;
|
||||
|
||||
/* |x| */
|
||||
u.i = i;
|
||||
x = u.f;
|
||||
|
||||
if (i >= 0x3f800000 + (12<<23)) {
|
||||
/* |x| >= 0x1p12 or inf or nan */
|
||||
x = logf(x) + 0.693147180559945309417232121458176568f;
|
||||
} else if (i >= 0x3f800000 + (1<<23)) {
|
||||
/* |x| >= 2 */
|
||||
x = logf(2*x + 1/(sqrtf(x*x+1)+x));
|
||||
} else if (i >= 0x3f800000 - (12<<23)) {
|
||||
/* |x| >= 0x1p-12, up to 1.6ulp error in [0.125,0.5] */
|
||||
x = log1pf(x + x*x/(sqrtf(x*x+1)+1));
|
||||
} else {
|
||||
/* |x| < 0x1p-12, raise inexact if x!=0 */
|
||||
FORCE_EVAL(x + 0x1p120f);
|
||||
}
|
||||
return s ? -x : x;
|
||||
}
|
||||
34
lib/libm/atanhf.c
Normal file
34
lib/libm/atanhf.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
// atanhf from musl-0.9.15
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "libm.h"
|
||||
|
||||
/* atanh(x) = log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2 ~= x + x^3/3 + o(x^5) */
|
||||
float atanhf(float x)
|
||||
{
|
||||
union {float f; uint32_t i;} u = {.f = x};
|
||||
unsigned s = u.i >> 31;
|
||||
float_t y;
|
||||
|
||||
/* |x| */
|
||||
u.i &= 0x7fffffff;
|
||||
y = u.f;
|
||||
|
||||
if (u.i < 0x3f800000 - (1<<23)) {
|
||||
if (u.i < 0x3f800000 - (32<<23)) {
|
||||
/* handle underflow */
|
||||
if (u.i < (1<<23))
|
||||
FORCE_EVAL((float)(y*y));
|
||||
} else {
|
||||
/* |x| < 0.5, up to 1.7ulp error */
|
||||
y = 0.5f*log1pf(2*y + 2*y*y/(1-y));
|
||||
}
|
||||
} else {
|
||||
/* avoid overflow */
|
||||
y = 0.5f*log1pf(2*(y/(1-y)));
|
||||
}
|
||||
return s ? -y : y;
|
||||
}
|
||||
202
lib/libm/ef_rem_pio2.c
Normal file
202
lib/libm/ef_rem_pio2.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* These math functions are taken from newlib-nano-2, the newlib/libm/math
|
||||
* directory, available from https://github.com/32bitmicro/newlib-nano-2.
|
||||
*
|
||||
* Appropriate copyright headers are reproduced below.
|
||||
*/
|
||||
|
||||
/* ef_rem_pio2.c -- float version of e_rem_pio2.c
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*
|
||||
*/
|
||||
|
||||
/* __ieee754_rem_pio2f(x,y)
|
||||
*
|
||||
* return the remainder of x rem pi/2 in y[0]+y[1]
|
||||
* use __kernel_rem_pio2f()
|
||||
*/
|
||||
|
||||
#include "fdlibm.h"
|
||||
|
||||
/*
|
||||
* Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
static const __int32_t two_over_pi[] = {
|
||||
#else
|
||||
static __int32_t two_over_pi[] = {
|
||||
#endif
|
||||
0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC,
|
||||
0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62,
|
||||
0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63,
|
||||
0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A,
|
||||
0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09,
|
||||
0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29,
|
||||
0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44,
|
||||
0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41,
|
||||
0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C,
|
||||
0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8,
|
||||
0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11,
|
||||
0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF,
|
||||
0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E,
|
||||
0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5,
|
||||
0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92,
|
||||
0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08,
|
||||
0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0,
|
||||
0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3,
|
||||
0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85,
|
||||
0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80,
|
||||
0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA,
|
||||
0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B,
|
||||
};
|
||||
|
||||
/* This array is like the one in e_rem_pio2.c, but the numbers are
|
||||
single precision and the last 8 bits are forced to 0. */
|
||||
#ifdef __STDC__
|
||||
static const __int32_t npio2_hw[] = {
|
||||
#else
|
||||
static __int32_t npio2_hw[] = {
|
||||
#endif
|
||||
0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
|
||||
0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
|
||||
0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
|
||||
0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
|
||||
0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
|
||||
0x4242c700, 0x42490f00
|
||||
};
|
||||
|
||||
/*
|
||||
* invpio2: 24 bits of 2/pi
|
||||
* pio2_1: first 17 bit of pi/2
|
||||
* pio2_1t: pi/2 - pio2_1
|
||||
* pio2_2: second 17 bit of pi/2
|
||||
* pio2_2t: pi/2 - (pio2_1+pio2_2)
|
||||
* pio2_3: third 17 bit of pi/2
|
||||
* pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
static const float
|
||||
#else
|
||||
static float
|
||||
#endif
|
||||
zero = 0.0000000000e+00, /* 0x00000000 */
|
||||
half = 5.0000000000e-01, /* 0x3f000000 */
|
||||
two8 = 2.5600000000e+02, /* 0x43800000 */
|
||||
invpio2 = 6.3661980629e-01, /* 0x3f22f984 */
|
||||
pio2_1 = 1.5707855225e+00, /* 0x3fc90f80 */
|
||||
pio2_1t = 1.0804334124e-05, /* 0x37354443 */
|
||||
pio2_2 = 1.0804273188e-05, /* 0x37354400 */
|
||||
pio2_2t = 6.0770999344e-11, /* 0x2e85a308 */
|
||||
pio2_3 = 6.0770943833e-11, /* 0x2e85a300 */
|
||||
pio2_3t = 6.1232342629e-17; /* 0x248d3132 */
|
||||
|
||||
#ifdef __STDC__
|
||||
__int32_t __ieee754_rem_pio2f(float x, float *y)
|
||||
#else
|
||||
__int32_t __ieee754_rem_pio2f(x,y)
|
||||
float x,y[];
|
||||
#endif
|
||||
{
|
||||
float z,w,t,r,fn;
|
||||
float tx[3];
|
||||
__int32_t i,j,n,ix,hx;
|
||||
int e0,nx;
|
||||
|
||||
GET_FLOAT_WORD(hx,x);
|
||||
ix = hx&0x7fffffff;
|
||||
if(ix<=0x3f490fd8) /* |x| ~<= pi/4 , no need for reduction */
|
||||
{y[0] = x; y[1] = 0; return 0;}
|
||||
if(ix<0x4016cbe4) { /* |x| < 3pi/4, special case with n=+-1 */
|
||||
if(hx>0) {
|
||||
z = x - pio2_1;
|
||||
if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
|
||||
y[0] = z - pio2_1t;
|
||||
y[1] = (z-y[0])-pio2_1t;
|
||||
} else { /* near pi/2, use 24+24+24 bit pi */
|
||||
z -= pio2_2;
|
||||
y[0] = z - pio2_2t;
|
||||
y[1] = (z-y[0])-pio2_2t;
|
||||
}
|
||||
return 1;
|
||||
} else { /* negative x */
|
||||
z = x + pio2_1;
|
||||
if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
|
||||
y[0] = z + pio2_1t;
|
||||
y[1] = (z-y[0])+pio2_1t;
|
||||
} else { /* near pi/2, use 24+24+24 bit pi */
|
||||
z += pio2_2;
|
||||
y[0] = z + pio2_2t;
|
||||
y[1] = (z-y[0])+pio2_2t;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */
|
||||
t = fabsf(x);
|
||||
n = (__int32_t) (t*invpio2+half);
|
||||
fn = (float)n;
|
||||
r = t-fn*pio2_1;
|
||||
w = fn*pio2_1t; /* 1st round good to 40 bit */
|
||||
if(n<32&&(ix&0xffffff00)!=npio2_hw[n-1]) {
|
||||
y[0] = r-w; /* quick check no cancellation */
|
||||
} else {
|
||||
__uint32_t high;
|
||||
j = ix>>23;
|
||||
y[0] = r-w;
|
||||
GET_FLOAT_WORD(high,y[0]);
|
||||
i = j-((high>>23)&0xff);
|
||||
if(i>8) { /* 2nd iteration needed, good to 57 */
|
||||
t = r;
|
||||
w = fn*pio2_2;
|
||||
r = t-w;
|
||||
w = fn*pio2_2t-((t-r)-w);
|
||||
y[0] = r-w;
|
||||
GET_FLOAT_WORD(high,y[0]);
|
||||
i = j-((high>>23)&0xff);
|
||||
if(i>25) { /* 3rd iteration need, 74 bits acc */
|
||||
t = r; /* will cover all possible cases */
|
||||
w = fn*pio2_3;
|
||||
r = t-w;
|
||||
w = fn*pio2_3t-((t-r)-w);
|
||||
y[0] = r-w;
|
||||
}
|
||||
}
|
||||
}
|
||||
y[1] = (r-y[0])-w;
|
||||
if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
|
||||
else return n;
|
||||
}
|
||||
/*
|
||||
* all other (large) arguments
|
||||
*/
|
||||
if(!FLT_UWORD_IS_FINITE(ix)) {
|
||||
y[0]=y[1]=x-x; return 0;
|
||||
}
|
||||
/* set z = scalbn(|x|,ilogb(x)-7) */
|
||||
e0 = (int)((ix>>23)-134); /* e0 = ilogb(z)-7; */
|
||||
SET_FLOAT_WORD(z, ix - ((__int32_t)e0<<23));
|
||||
for(i=0;i<2;i++) {
|
||||
tx[i] = (float)((__int32_t)(z));
|
||||
z = (z-tx[i])*two8;
|
||||
}
|
||||
tx[2] = z;
|
||||
nx = 3;
|
||||
while(tx[nx-1]==zero) nx--; /* skip zero term */
|
||||
n = __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi);
|
||||
if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
|
||||
return n;
|
||||
}
|
||||
227
lib/libm/fdlibm.h
Normal file
227
lib/libm/fdlibm.h
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* This file is adapted from from newlib-nano-2, the newlib/libm/common/fdlib.h,
|
||||
* available from https://github.com/32bitmicro/newlib-nano-2. The main change
|
||||
* is removal of anything to do with double precision.
|
||||
*
|
||||
* Appropriate copyright headers are reproduced below.
|
||||
*/
|
||||
|
||||
/* @(#)fdlibm.h 5.1 93/09/24 */
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/* Default to XOPEN_MODE. */
|
||||
#define _XOPEN_MODE
|
||||
|
||||
/* Most routines need to check whether a float is finite, infinite, or not a
|
||||
number, and many need to know whether the result of an operation will
|
||||
overflow. These conditions depend on whether the largest exponent is
|
||||
used for NaNs & infinities, or whether it's used for finite numbers. The
|
||||
macros below wrap up that kind of information:
|
||||
|
||||
FLT_UWORD_IS_FINITE(X)
|
||||
True if a positive float with bitmask X is finite.
|
||||
|
||||
FLT_UWORD_IS_NAN(X)
|
||||
True if a positive float with bitmask X is not a number.
|
||||
|
||||
FLT_UWORD_IS_INFINITE(X)
|
||||
True if a positive float with bitmask X is +infinity.
|
||||
|
||||
FLT_UWORD_MAX
|
||||
The bitmask of FLT_MAX.
|
||||
|
||||
FLT_UWORD_HALF_MAX
|
||||
The bitmask of FLT_MAX/2.
|
||||
|
||||
FLT_UWORD_EXP_MAX
|
||||
The bitmask of the largest finite exponent (129 if the largest
|
||||
exponent is used for finite numbers, 128 otherwise).
|
||||
|
||||
FLT_UWORD_LOG_MAX
|
||||
The bitmask of log(FLT_MAX), rounded down. This value is the largest
|
||||
input that can be passed to exp() without producing overflow.
|
||||
|
||||
FLT_UWORD_LOG_2MAX
|
||||
The bitmask of log(2*FLT_MAX), rounded down. This value is the
|
||||
largest input than can be passed to cosh() without producing
|
||||
overflow.
|
||||
|
||||
FLT_LARGEST_EXP
|
||||
The largest biased exponent that can be used for finite numbers
|
||||
(255 if the largest exponent is used for finite numbers, 254
|
||||
otherwise) */
|
||||
|
||||
#ifdef _FLT_LARGEST_EXPONENT_IS_NORMAL
|
||||
#define FLT_UWORD_IS_FINITE(x) 1
|
||||
#define FLT_UWORD_IS_NAN(x) 0
|
||||
#define FLT_UWORD_IS_INFINITE(x) 0
|
||||
#define FLT_UWORD_MAX 0x7fffffff
|
||||
#define FLT_UWORD_EXP_MAX 0x43010000
|
||||
#define FLT_UWORD_LOG_MAX 0x42b2d4fc
|
||||
#define FLT_UWORD_LOG_2MAX 0x42b437e0
|
||||
#define HUGE ((float)0X1.FFFFFEP128)
|
||||
#else
|
||||
#define FLT_UWORD_IS_FINITE(x) ((x)<0x7f800000L)
|
||||
#define FLT_UWORD_IS_NAN(x) ((x)>0x7f800000L)
|
||||
#define FLT_UWORD_IS_INFINITE(x) ((x)==0x7f800000L)
|
||||
#define FLT_UWORD_MAX 0x7f7fffffL
|
||||
#define FLT_UWORD_EXP_MAX 0x43000000
|
||||
#define FLT_UWORD_LOG_MAX 0x42b17217
|
||||
#define FLT_UWORD_LOG_2MAX 0x42b2d4fc
|
||||
#define HUGE ((float)3.40282346638528860e+38)
|
||||
#endif
|
||||
#define FLT_UWORD_HALF_MAX (FLT_UWORD_MAX-(1L<<23))
|
||||
#define FLT_LARGEST_EXP (FLT_UWORD_MAX>>23)
|
||||
|
||||
/* Many routines check for zero and subnormal numbers. Such things depend
|
||||
on whether the target supports denormals or not:
|
||||
|
||||
FLT_UWORD_IS_ZERO(X)
|
||||
True if a positive float with bitmask X is +0. Without denormals,
|
||||
any float with a zero exponent is a +0 representation. With
|
||||
denormals, the only +0 representation is a 0 bitmask.
|
||||
|
||||
FLT_UWORD_IS_SUBNORMAL(X)
|
||||
True if a non-zero positive float with bitmask X is subnormal.
|
||||
(Routines should check for zeros first.)
|
||||
|
||||
FLT_UWORD_MIN
|
||||
The bitmask of the smallest float above +0. Call this number
|
||||
REAL_FLT_MIN...
|
||||
|
||||
FLT_UWORD_EXP_MIN
|
||||
The bitmask of the float representation of REAL_FLT_MIN's exponent.
|
||||
|
||||
FLT_UWORD_LOG_MIN
|
||||
The bitmask of |log(REAL_FLT_MIN)|, rounding down.
|
||||
|
||||
FLT_SMALLEST_EXP
|
||||
REAL_FLT_MIN's exponent - EXP_BIAS (1 if denormals are not supported,
|
||||
-22 if they are).
|
||||
*/
|
||||
|
||||
#ifdef _FLT_NO_DENORMALS
|
||||
#define FLT_UWORD_IS_ZERO(x) ((x)<0x00800000L)
|
||||
#define FLT_UWORD_IS_SUBNORMAL(x) 0
|
||||
#define FLT_UWORD_MIN 0x00800000
|
||||
#define FLT_UWORD_EXP_MIN 0x42fc0000
|
||||
#define FLT_UWORD_LOG_MIN 0x42aeac50
|
||||
#define FLT_SMALLEST_EXP 1
|
||||
#else
|
||||
#define FLT_UWORD_IS_ZERO(x) ((x)==0)
|
||||
#define FLT_UWORD_IS_SUBNORMAL(x) ((x)<0x00800000L)
|
||||
#define FLT_UWORD_MIN 0x00000001
|
||||
#define FLT_UWORD_EXP_MIN 0x43160000
|
||||
#define FLT_UWORD_LOG_MIN 0x42cff1b5
|
||||
#define FLT_SMALLEST_EXP -22
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
#undef __P
|
||||
#define __P(p) p
|
||||
#else
|
||||
#define __P(p) ()
|
||||
#endif
|
||||
|
||||
/*
|
||||
* set X_TLOSS = pi*2**52, which is possibly defined in <values.h>
|
||||
* (one may replace the following line by "#include <values.h>")
|
||||
*/
|
||||
|
||||
#define X_TLOSS 1.41484755040568800000e+16
|
||||
|
||||
/* Functions that are not documented, and are not in <math.h>. */
|
||||
|
||||
/* Undocumented float functions. */
|
||||
#ifdef _SCALB_INT
|
||||
extern float scalbf __P((float, int));
|
||||
#else
|
||||
extern float scalbf __P((float, float));
|
||||
#endif
|
||||
extern float significandf __P((float));
|
||||
|
||||
/* ieee style elementary float functions */
|
||||
extern float __ieee754_sqrtf __P((float));
|
||||
extern float __ieee754_acosf __P((float));
|
||||
extern float __ieee754_acoshf __P((float));
|
||||
extern float __ieee754_logf __P((float));
|
||||
extern float __ieee754_atanhf __P((float));
|
||||
extern float __ieee754_asinf __P((float));
|
||||
extern float __ieee754_atan2f __P((float,float));
|
||||
extern float __ieee754_expf __P((float));
|
||||
extern float __ieee754_coshf __P((float));
|
||||
extern float __ieee754_fmodf __P((float,float));
|
||||
extern float __ieee754_powf __P((float,float));
|
||||
extern float __ieee754_lgammaf_r __P((float,int *));
|
||||
extern float __ieee754_gammaf_r __P((float,int *));
|
||||
extern float __ieee754_log10f __P((float));
|
||||
extern float __ieee754_sinhf __P((float));
|
||||
extern float __ieee754_hypotf __P((float,float));
|
||||
extern float __ieee754_j0f __P((float));
|
||||
extern float __ieee754_j1f __P((float));
|
||||
extern float __ieee754_y0f __P((float));
|
||||
extern float __ieee754_y1f __P((float));
|
||||
extern float __ieee754_jnf __P((int,float));
|
||||
extern float __ieee754_ynf __P((int,float));
|
||||
extern float __ieee754_remainderf __P((float,float));
|
||||
extern __int32_t __ieee754_rem_pio2f __P((float,float*));
|
||||
#ifdef _SCALB_INT
|
||||
extern float __ieee754_scalbf __P((float,int));
|
||||
#else
|
||||
extern float __ieee754_scalbf __P((float,float));
|
||||
#endif
|
||||
|
||||
/* float versions of fdlibm kernel functions */
|
||||
extern float __kernel_sinf __P((float,float,int));
|
||||
extern float __kernel_cosf __P((float,float));
|
||||
extern float __kernel_tanf __P((float,float,int));
|
||||
extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const __int32_t*));
|
||||
|
||||
/* A union which permits us to convert between a float and a 32 bit
|
||||
int. */
|
||||
|
||||
typedef union
|
||||
{
|
||||
float value;
|
||||
__uint32_t word;
|
||||
} ieee_float_shape_type;
|
||||
|
||||
/* Get a 32 bit int from a float. */
|
||||
|
||||
#define GET_FLOAT_WORD(i,d) \
|
||||
do { \
|
||||
ieee_float_shape_type gf_u; \
|
||||
gf_u.value = (d); \
|
||||
(i) = gf_u.word; \
|
||||
} while (0)
|
||||
|
||||
/* Set a float from a 32 bit int. */
|
||||
|
||||
#define SET_FLOAT_WORD(d,i) \
|
||||
do { \
|
||||
ieee_float_shape_type sf_u; \
|
||||
sf_u.word = (i); \
|
||||
(d) = sf_u.value; \
|
||||
} while (0)
|
||||
|
||||
/* Macros to avoid undefined behaviour that can arise if the amount
|
||||
of a shift is exactly equal to the size of the shifted operand. */
|
||||
|
||||
#define SAFE_LEFT_SHIFT(op,amt) \
|
||||
(((amt) < 8 * sizeof(op)) ? ((op) << (amt)) : 0)
|
||||
|
||||
#define SAFE_RIGHT_SHIFT(op,amt) \
|
||||
(((amt) < 8 * sizeof(op)) ? ((op) >> (amt)) : 0)
|
||||
68
lib/libm/kf_cos.c
Normal file
68
lib/libm/kf_cos.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* These math functions are taken from newlib-nano-2, the newlib/libm/math
|
||||
* directory, available from https://github.com/32bitmicro/newlib-nano-2.
|
||||
*
|
||||
* Appropriate copyright headers are reproduced below.
|
||||
*/
|
||||
|
||||
/* kf_cos.c -- float version of k_cos.c
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#include "fdlibm.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const float
|
||||
#else
|
||||
static float
|
||||
#endif
|
||||
one = 1.0000000000e+00, /* 0x3f800000 */
|
||||
C1 = 4.1666667908e-02, /* 0x3d2aaaab */
|
||||
C2 = -1.3888889225e-03, /* 0xbab60b61 */
|
||||
C3 = 2.4801587642e-05, /* 0x37d00d01 */
|
||||
C4 = -2.7557314297e-07, /* 0xb493f27c */
|
||||
C5 = 2.0875723372e-09, /* 0x310f74f6 */
|
||||
C6 = -1.1359647598e-11; /* 0xad47d74e */
|
||||
|
||||
#ifdef __STDC__
|
||||
float __kernel_cosf(float x, float y)
|
||||
#else
|
||||
float __kernel_cosf(x, y)
|
||||
float x,y;
|
||||
#endif
|
||||
{
|
||||
float a,hz,z,r,qx;
|
||||
__int32_t ix;
|
||||
GET_FLOAT_WORD(ix,x);
|
||||
ix &= 0x7fffffff; /* ix = |x|'s high word*/
|
||||
if(ix<0x32000000) { /* if x < 2**27 */
|
||||
if(((int)x)==0) return one; /* generate inexact */
|
||||
}
|
||||
z = x*x;
|
||||
r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
|
||||
if(ix < 0x3e99999a) /* if |x| < 0.3 */
|
||||
return one - ((float)0.5*z - (z*r - x*y));
|
||||
else {
|
||||
if(ix > 0x3f480000) { /* x > 0.78125 */
|
||||
qx = (float)0.28125;
|
||||
} else {
|
||||
SET_FLOAT_WORD(qx,ix-0x01000000); /* x/4 */
|
||||
}
|
||||
hz = (float)0.5*z-qx;
|
||||
a = one-qx;
|
||||
return a - (hz - (z*r-x*y));
|
||||
}
|
||||
}
|
||||
217
lib/libm/kf_rem_pio2.c
Normal file
217
lib/libm/kf_rem_pio2.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* These math functions are taken from newlib-nano-2, the newlib/libm/math
|
||||
* directory, available from https://github.com/32bitmicro/newlib-nano-2.
|
||||
*
|
||||
* Appropriate copyright headers are reproduced below.
|
||||
*/
|
||||
|
||||
/* kf_rem_pio2.c -- float version of k_rem_pio2.c
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#include "fdlibm.h"
|
||||
|
||||
/* In the float version, the input parameter x contains 8 bit
|
||||
integers, not 24 bit integers. 113 bit precision is not supported. */
|
||||
|
||||
#ifdef __STDC__
|
||||
static const int init_jk[] = {4,7,9}; /* initial value for jk */
|
||||
#else
|
||||
static int init_jk[] = {4,7,9};
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
static const float PIo2[] = {
|
||||
#else
|
||||
static float PIo2[] = {
|
||||
#endif
|
||||
1.5703125000e+00, /* 0x3fc90000 */
|
||||
4.5776367188e-04, /* 0x39f00000 */
|
||||
2.5987625122e-05, /* 0x37da0000 */
|
||||
7.5437128544e-08, /* 0x33a20000 */
|
||||
6.0026650317e-11, /* 0x2e840000 */
|
||||
7.3896444519e-13, /* 0x2b500000 */
|
||||
5.3845816694e-15, /* 0x27c20000 */
|
||||
5.6378512969e-18, /* 0x22d00000 */
|
||||
8.3009228831e-20, /* 0x1fc40000 */
|
||||
3.2756352257e-22, /* 0x1bc60000 */
|
||||
6.3331015649e-25, /* 0x17440000 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
static const float
|
||||
#else
|
||||
static float
|
||||
#endif
|
||||
zero = 0.0,
|
||||
one = 1.0,
|
||||
two8 = 2.5600000000e+02, /* 0x43800000 */
|
||||
twon8 = 3.9062500000e-03; /* 0x3b800000 */
|
||||
|
||||
#ifdef __STDC__
|
||||
int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const __int32_t *ipio2)
|
||||
#else
|
||||
int __kernel_rem_pio2f(x,y,e0,nx,prec,ipio2)
|
||||
float x[], y[]; int e0,nx,prec; __int32_t ipio2[];
|
||||
#endif
|
||||
{
|
||||
__int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
|
||||
float z,fw,f[20],fq[20],q[20];
|
||||
|
||||
/* initialize jk*/
|
||||
jk = init_jk[prec];
|
||||
jp = jk;
|
||||
|
||||
/* determine jx,jv,q0, note that 3>q0 */
|
||||
jx = nx-1;
|
||||
jv = (e0-3)/8; if(jv<0) jv=0;
|
||||
q0 = e0-8*(jv+1);
|
||||
|
||||
/* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
|
||||
j = jv-jx; m = jx+jk;
|
||||
for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j];
|
||||
|
||||
/* compute q[0],q[1],...q[jk] */
|
||||
for (i=0;i<=jk;i++) {
|
||||
for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
|
||||
}
|
||||
|
||||
jz = jk;
|
||||
recompute:
|
||||
/* distill q[] into iq[] reversingly */
|
||||
for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
|
||||
fw = (float)((__int32_t)(twon8* z));
|
||||
iq[i] = (__int32_t)(z-two8*fw);
|
||||
z = q[j-1]+fw;
|
||||
}
|
||||
|
||||
/* compute n */
|
||||
z = scalbnf(z,(int)q0); /* actual value of z */
|
||||
z -= (float)8.0*floorf(z*(float)0.125); /* trim off integer >= 8 */
|
||||
n = (__int32_t) z;
|
||||
z -= (float)n;
|
||||
ih = 0;
|
||||
if(q0>0) { /* need iq[jz-1] to determine n */
|
||||
i = (iq[jz-1]>>(8-q0)); n += i;
|
||||
iq[jz-1] -= i<<(8-q0);
|
||||
ih = iq[jz-1]>>(7-q0);
|
||||
}
|
||||
else if(q0==0) ih = iq[jz-1]>>8;
|
||||
else if(z>=(float)0.5) ih=2;
|
||||
|
||||
if(ih>0) { /* q > 0.5 */
|
||||
n += 1; carry = 0;
|
||||
for(i=0;i<jz ;i++) { /* compute 1-q */
|
||||
j = iq[i];
|
||||
if(carry==0) {
|
||||
if(j!=0) {
|
||||
carry = 1; iq[i] = 0x100- j;
|
||||
}
|
||||
} else iq[i] = 0xff - j;
|
||||
}
|
||||
if(q0>0) { /* rare case: chance is 1 in 12 */
|
||||
switch(q0) {
|
||||
case 1:
|
||||
iq[jz-1] &= 0x7f; break;
|
||||
case 2:
|
||||
iq[jz-1] &= 0x3f; break;
|
||||
}
|
||||
}
|
||||
if(ih==2) {
|
||||
z = one - z;
|
||||
if(carry!=0) z -= scalbnf(one,(int)q0);
|
||||
}
|
||||
}
|
||||
|
||||
/* check if recomputation is needed */
|
||||
if(z==zero) {
|
||||
j = 0;
|
||||
for (i=jz-1;i>=jk;i--) j |= iq[i];
|
||||
if(j==0) { /* need recomputation */
|
||||
for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */
|
||||
|
||||
for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */
|
||||
f[jx+i] = (float) ipio2[jv+i];
|
||||
for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
|
||||
q[i] = fw;
|
||||
}
|
||||
jz += k;
|
||||
goto recompute;
|
||||
}
|
||||
}
|
||||
|
||||
/* chop off zero terms */
|
||||
if(z==(float)0.0) {
|
||||
jz -= 1; q0 -= 8;
|
||||
while(iq[jz]==0) { jz--; q0-=8;}
|
||||
} else { /* break z into 8-bit if necessary */
|
||||
z = scalbnf(z,-(int)q0);
|
||||
if(z>=two8) {
|
||||
fw = (float)((__int32_t)(twon8*z));
|
||||
iq[jz] = (__int32_t)(z-two8*fw);
|
||||
jz += 1; q0 += 8;
|
||||
iq[jz] = (__int32_t) fw;
|
||||
} else iq[jz] = (__int32_t) z ;
|
||||
}
|
||||
|
||||
/* convert integer "bit" chunk to floating-point value */
|
||||
fw = scalbnf(one,(int)q0);
|
||||
for(i=jz;i>=0;i--) {
|
||||
q[i] = fw*(float)iq[i]; fw*=twon8;
|
||||
}
|
||||
|
||||
/* compute PIo2[0,...,jp]*q[jz,...,0] */
|
||||
for(i=jz;i>=0;i--) {
|
||||
for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
|
||||
fq[jz-i] = fw;
|
||||
}
|
||||
|
||||
/* compress fq[] into y[] */
|
||||
switch(prec) {
|
||||
case 0:
|
||||
fw = 0.0;
|
||||
for (i=jz;i>=0;i--) fw += fq[i];
|
||||
y[0] = (ih==0)? fw: -fw;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
fw = 0.0;
|
||||
for (i=jz;i>=0;i--) fw += fq[i];
|
||||
y[0] = (ih==0)? fw: -fw;
|
||||
fw = fq[0]-fw;
|
||||
for (i=1;i<=jz;i++) fw += fq[i];
|
||||
y[1] = (ih==0)? fw: -fw;
|
||||
break;
|
||||
case 3: /* painful */
|
||||
for (i=jz;i>0;i--) {
|
||||
fw = fq[i-1]+fq[i];
|
||||
fq[i] += fq[i-1]-fw;
|
||||
fq[i-1] = fw;
|
||||
}
|
||||
for (i=jz;i>1;i--) {
|
||||
fw = fq[i-1]+fq[i];
|
||||
fq[i] += fq[i-1]-fw;
|
||||
fq[i-1] = fw;
|
||||
}
|
||||
for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
|
||||
if(ih==0) {
|
||||
y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
|
||||
} else {
|
||||
y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
|
||||
}
|
||||
}
|
||||
return n&7;
|
||||
}
|
||||
58
lib/libm/kf_sin.c
Normal file
58
lib/libm/kf_sin.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* These math functions are taken from newlib-nano-2, the newlib/libm/math
|
||||
* directory, available from https://github.com/32bitmicro/newlib-nano-2.
|
||||
*
|
||||
* Appropriate copyright headers are reproduced below.
|
||||
*/
|
||||
|
||||
/* kf_sin.c -- float version of k_sin.c
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#include "fdlibm.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const float
|
||||
#else
|
||||
static float
|
||||
#endif
|
||||
half = 5.0000000000e-01,/* 0x3f000000 */
|
||||
S1 = -1.6666667163e-01, /* 0xbe2aaaab */
|
||||
S2 = 8.3333337680e-03, /* 0x3c088889 */
|
||||
S3 = -1.9841270114e-04, /* 0xb9500d01 */
|
||||
S4 = 2.7557314297e-06, /* 0x3638ef1b */
|
||||
S5 = -2.5050759689e-08, /* 0xb2d72f34 */
|
||||
S6 = 1.5896910177e-10; /* 0x2f2ec9d3 */
|
||||
|
||||
#ifdef __STDC__
|
||||
float __kernel_sinf(float x, float y, int iy)
|
||||
#else
|
||||
float __kernel_sinf(x, y, iy)
|
||||
float x,y; int iy; /* iy=0 if y is zero */
|
||||
#endif
|
||||
{
|
||||
float z,r,v;
|
||||
__int32_t ix;
|
||||
GET_FLOAT_WORD(ix,x);
|
||||
ix &= 0x7fffffff; /* high word of x */
|
||||
if(ix<0x32000000) /* |x| < 2**-27 */
|
||||
{if((int)x==0) return x;} /* generate inexact */
|
||||
z = x*x;
|
||||
v = z*x;
|
||||
r = S2+z*(S3+z*(S4+z*(S5+z*S6)));
|
||||
if(iy==0) return x+v*(S1+z*r);
|
||||
else return x-((z*(half*y-v*r)-y)-v*S1);
|
||||
}
|
||||
105
lib/libm/kf_tan.c
Normal file
105
lib/libm/kf_tan.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* These math functions are taken from newlib-nano-2, the newlib/libm/math
|
||||
* directory, available from https://github.com/32bitmicro/newlib-nano-2.
|
||||
*
|
||||
* Appropriate copyright headers are reproduced below.
|
||||
*/
|
||||
|
||||
/* kf_tan.c -- float version of k_tan.c
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#include "libm.h"
|
||||
#ifdef __STDC__
|
||||
static const float
|
||||
#else
|
||||
static float
|
||||
#endif
|
||||
one = 1.0000000000e+00, /* 0x3f800000 */
|
||||
pio4 = 7.8539812565e-01, /* 0x3f490fda */
|
||||
pio4lo= 3.7748947079e-08, /* 0x33222168 */
|
||||
T[] = {
|
||||
3.3333334327e-01, /* 0x3eaaaaab */
|
||||
1.3333334029e-01, /* 0x3e088889 */
|
||||
5.3968254477e-02, /* 0x3d5d0dd1 */
|
||||
2.1869488060e-02, /* 0x3cb327a4 */
|
||||
8.8632395491e-03, /* 0x3c11371f */
|
||||
3.5920790397e-03, /* 0x3b6b6916 */
|
||||
1.4562094584e-03, /* 0x3abede48 */
|
||||
5.8804126456e-04, /* 0x3a1a26c8 */
|
||||
2.4646313977e-04, /* 0x398137b9 */
|
||||
7.8179444245e-05, /* 0x38a3f445 */
|
||||
7.1407252108e-05, /* 0x3895c07a */
|
||||
-1.8558637748e-05, /* 0xb79bae5f */
|
||||
2.5907305826e-05, /* 0x37d95384 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
float __kernel_tanf(float x, float y, int iy)
|
||||
#else
|
||||
float __kernel_tanf(x, y, iy)
|
||||
float x,y; int iy;
|
||||
#endif
|
||||
{
|
||||
float z,r,v,w,s;
|
||||
__int32_t ix,hx;
|
||||
GET_FLOAT_WORD(hx,x);
|
||||
ix = hx&0x7fffffff; /* high word of |x| */
|
||||
if(ix<0x31800000) /* x < 2**-28 */
|
||||
{if((int)x==0) { /* generate inexact */
|
||||
if((ix|(iy+1))==0) return one/fabsf(x);
|
||||
else return (iy==1)? x: -one/x;
|
||||
}
|
||||
}
|
||||
if(ix>=0x3f2ca140) { /* |x|>=0.6744 */
|
||||
if(hx<0) {x = -x; y = -y;}
|
||||
z = pio4-x;
|
||||
w = pio4lo-y;
|
||||
x = z+w; y = 0.0;
|
||||
}
|
||||
z = x*x;
|
||||
w = z*z;
|
||||
/* Break x^5*(T[1]+x^2*T[2]+...) into
|
||||
* x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
|
||||
* x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
|
||||
*/
|
||||
r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
|
||||
v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
|
||||
s = z*x;
|
||||
r = y + z*(s*(r+v)+y);
|
||||
r += T[0]*s;
|
||||
w = x+r;
|
||||
if(ix>=0x3f2ca140) {
|
||||
v = (float)iy;
|
||||
return (float)(1-((hx>>30)&2))*(v-(float)2.0*(x-(w*w/(w+v)-r)));
|
||||
}
|
||||
if(iy==1) return w;
|
||||
else { /* if allow error up to 2 ulp,
|
||||
simply return -1.0/(x+r) here */
|
||||
/* compute -1.0/(x+r) accurately */
|
||||
float a,t;
|
||||
__int32_t i;
|
||||
z = w;
|
||||
GET_FLOAT_WORD(i,z);
|
||||
SET_FLOAT_WORD(z,i&0xfffff000);
|
||||
v = r-(z - x); /* z+v = r+x */
|
||||
t = a = -(float)1.0/w; /* a = -1.0/w */
|
||||
GET_FLOAT_WORD(i,t);
|
||||
SET_FLOAT_WORD(t,i&0xfffff000);
|
||||
s = (float)1.0+t*z;
|
||||
return t+a*(s+t*v);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#define FLT_EVAL_METHOD 0
|
||||
|
||||
#define FORCE_EVAL(x) do { \
|
||||
if (sizeof(x) == sizeof(float)) { \
|
||||
volatile float __x; \
|
||||
|
||||
83
lib/libm/log1pf.c
Normal file
83
lib/libm/log1pf.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
// log1pf from musl-0.9.15
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_log1pf.c */
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#include "libm.h"
|
||||
|
||||
static const float
|
||||
ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
|
||||
ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
|
||||
/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */
|
||||
Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */
|
||||
Lg2 = 0xccce13.0p-25, /* 0.40000972152 */
|
||||
Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */
|
||||
Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */
|
||||
|
||||
float log1pf(float x)
|
||||
{
|
||||
union {float f; uint32_t i;} u = {x};
|
||||
float_t hfsq,f,c,s,z,R,w,t1,t2,dk;
|
||||
uint32_t ix,iu;
|
||||
int k;
|
||||
|
||||
ix = u.i;
|
||||
k = 1;
|
||||
if (ix < 0x3ed413d0 || ix>>31) { /* 1+x < sqrt(2)+ */
|
||||
if (ix >= 0xbf800000) { /* x <= -1.0 */
|
||||
if (x == -1)
|
||||
return x/0.0f; /* log1p(-1)=+inf */
|
||||
return (x-x)/0.0f; /* log1p(x<-1)=NaN */
|
||||
}
|
||||
if (ix<<1 < 0x33800000<<1) { /* |x| < 2**-24 */
|
||||
/* underflow if subnormal */
|
||||
if ((ix&0x7f800000) == 0)
|
||||
FORCE_EVAL(x*x);
|
||||
return x;
|
||||
}
|
||||
if (ix <= 0xbe95f619) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
|
||||
k = 0;
|
||||
c = 0;
|
||||
f = x;
|
||||
}
|
||||
} else if (ix >= 0x7f800000)
|
||||
return x;
|
||||
if (k) {
|
||||
u.f = 1 + x;
|
||||
iu = u.i;
|
||||
iu += 0x3f800000 - 0x3f3504f3;
|
||||
k = (int)(iu>>23) - 0x7f;
|
||||
/* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
|
||||
if (k < 25) {
|
||||
c = k >= 2 ? 1-(u.f-x) : x-(u.f-1);
|
||||
c /= u.f;
|
||||
} else
|
||||
c = 0;
|
||||
/* reduce u into [sqrt(2)/2, sqrt(2)] */
|
||||
iu = (iu&0x007fffff) + 0x3f3504f3;
|
||||
u.i = iu;
|
||||
f = u.f - 1;
|
||||
}
|
||||
s = f/(2.0f + f);
|
||||
z = s*s;
|
||||
w = z*z;
|
||||
t1= w*(Lg2+w*Lg4);
|
||||
t2= z*(Lg1+w*Lg3);
|
||||
R = t2 + t1;
|
||||
hfsq = 0.5f*f*f;
|
||||
dk = k;
|
||||
return s*(hfsq+R) + (dk*ln2_lo+c) - hfsq + f + dk*ln2_hi;
|
||||
}
|
||||
@@ -113,10 +113,6 @@ float log10f(float x) { return logf(x) / (float)_M_LN10; }
|
||||
float tanhf(float x) { return sinhf(x) / coshf(x); }
|
||||
|
||||
// TODO we need import these functions from some library (eg musl or newlib)
|
||||
float acoshf(float x) { return 0.0; }
|
||||
float asinhf(float x) { return 0.0; }
|
||||
float atanhf(float x) { return 0.0; }
|
||||
float tanf(float x) { return 0.0; }
|
||||
float tgammaf(float x) { return 0.0; }
|
||||
float lgammaf(float x) { return 0.0; }
|
||||
float erff(float x) { return 0.0; }
|
||||
|
||||
@@ -1,627 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* These math functions are taken from newlib 2.1.0, the newlib/libm directory.
|
||||
* Appropriate copyright headers are reproduced below.
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
/* @(#)fdlibm.h 5.1 93/09/24 */
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#define FLT_UWORD_IS_FINITE(x) ((x)<0x7f800000L)
|
||||
|
||||
/* A union which permits us to convert between a float and a 32 bit
|
||||
int. */
|
||||
|
||||
typedef union
|
||||
{
|
||||
float value;
|
||||
__uint32_t word;
|
||||
} ieee_float_shape_type;
|
||||
|
||||
|
||||
/* Get a 32 bit int from a float. */
|
||||
|
||||
#define GET_FLOAT_WORD(i,d) \
|
||||
do { \
|
||||
ieee_float_shape_type gf_u; \
|
||||
gf_u.value = (d); \
|
||||
(i) = gf_u.word; \
|
||||
} while (0)
|
||||
|
||||
/* Set a float from a 32 bit int. */
|
||||
|
||||
#define SET_FLOAT_WORD(d,i) \
|
||||
do { \
|
||||
ieee_float_shape_type sf_u; \
|
||||
sf_u.word = (i); \
|
||||
(d) = sf_u.value; \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
/* kf_rem_pio2.c -- float version of k_rem_pio2.c
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
/* In the float version, the input parameter x contains 8 bit
|
||||
integers, not 24 bit integers. 113 bit precision is not supported. */
|
||||
|
||||
#ifdef __STDC__
|
||||
static const int init_jk[] = {4,7,9}; /* initial value for jk */
|
||||
#else
|
||||
static int init_jk[] = {4,7,9};
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
static const float PIo2[] = {
|
||||
#else
|
||||
static float PIo2[] = {
|
||||
#endif
|
||||
1.5703125000e+00, /* 0x3fc90000 */
|
||||
4.5776367188e-04, /* 0x39f00000 */
|
||||
2.5987625122e-05, /* 0x37da0000 */
|
||||
7.5437128544e-08, /* 0x33a20000 */
|
||||
6.0026650317e-11, /* 0x2e840000 */
|
||||
7.3896444519e-13, /* 0x2b500000 */
|
||||
5.3845816694e-15, /* 0x27c20000 */
|
||||
5.6378512969e-18, /* 0x22d00000 */
|
||||
8.3009228831e-20, /* 0x1fc40000 */
|
||||
3.2756352257e-22, /* 0x1bc60000 */
|
||||
6.3331015649e-25, /* 0x17440000 */
|
||||
};
|
||||
|
||||
static const float
|
||||
zero = 0.0000000000e+00, /* 0x00000000 */
|
||||
one = 1.0000000000e+00, /* 0x3f800000 */
|
||||
two8 = 2.5600000000e+02, /* 0x43800000 */
|
||||
twon8 = 3.9062500000e-03; /* 0x3b800000 */
|
||||
|
||||
int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const __int32_t *ipio2)
|
||||
{
|
||||
__int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
|
||||
float z,fw,f[20],fq[20],q[20];
|
||||
|
||||
/* initialize jk*/
|
||||
jk = init_jk[prec];
|
||||
jp = jk;
|
||||
|
||||
/* determine jx,jv,q0, note that 3>q0 */
|
||||
jx = nx-1;
|
||||
jv = (e0-3)/8; if(jv<0) jv=0;
|
||||
q0 = e0-8*(jv+1);
|
||||
|
||||
/* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
|
||||
j = jv-jx; m = jx+jk;
|
||||
for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j];
|
||||
|
||||
/* compute q[0],q[1],...q[jk] */
|
||||
for (i=0;i<=jk;i++) {
|
||||
for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
|
||||
}
|
||||
|
||||
jz = jk;
|
||||
recompute:
|
||||
/* distill q[] into iq[] reversingly */
|
||||
for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
|
||||
fw = (float)((__int32_t)(twon8* z));
|
||||
iq[i] = (__int32_t)(z-two8*fw);
|
||||
z = q[j-1]+fw;
|
||||
}
|
||||
|
||||
/* compute n */
|
||||
z = scalbnf(z,(int)q0); /* actual value of z */
|
||||
z -= (float)8.0*floorf(z*(float)0.125); /* trim off integer >= 8 */
|
||||
n = (__int32_t) z;
|
||||
z -= (float)n;
|
||||
ih = 0;
|
||||
if(q0>0) { /* need iq[jz-1] to determine n */
|
||||
i = (iq[jz-1]>>(8-q0)); n += i;
|
||||
iq[jz-1] -= i<<(8-q0);
|
||||
ih = iq[jz-1]>>(7-q0);
|
||||
}
|
||||
else if(q0==0) ih = iq[jz-1]>>8;
|
||||
else if(z>=(float)0.5) ih=2;
|
||||
|
||||
if(ih>0) { /* q > 0.5 */
|
||||
n += 1; carry = 0;
|
||||
for(i=0;i<jz ;i++) { /* compute 1-q */
|
||||
j = iq[i];
|
||||
if(carry==0) {
|
||||
if(j!=0) {
|
||||
carry = 1; iq[i] = 0x100- j;
|
||||
}
|
||||
} else iq[i] = 0xff - j;
|
||||
}
|
||||
if(q0>0) { /* rare case: chance is 1 in 12 */
|
||||
switch(q0) {
|
||||
case 1:
|
||||
iq[jz-1] &= 0x7f; break;
|
||||
case 2:
|
||||
iq[jz-1] &= 0x3f; break;
|
||||
}
|
||||
}
|
||||
if(ih==2) {
|
||||
z = one - z;
|
||||
if(carry!=0) z -= scalbnf(one,(int)q0);
|
||||
}
|
||||
}
|
||||
|
||||
/* check if recomputation is needed */
|
||||
if(z==zero) {
|
||||
j = 0;
|
||||
for (i=jz-1;i>=jk;i--) j |= iq[i];
|
||||
if(j==0) { /* need recomputation */
|
||||
for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */
|
||||
|
||||
for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */
|
||||
f[jx+i] = (float) ipio2[jv+i];
|
||||
for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
|
||||
q[i] = fw;
|
||||
}
|
||||
jz += k;
|
||||
goto recompute;
|
||||
}
|
||||
}
|
||||
|
||||
/* chop off zero terms */
|
||||
if(z==(float)0.0) {
|
||||
jz -= 1; q0 -= 8;
|
||||
while(iq[jz]==0) { jz--; q0-=8;}
|
||||
} else { /* break z into 8-bit if necessary */
|
||||
z = scalbnf(z,-(int)q0);
|
||||
if(z>=two8) {
|
||||
fw = (float)((__int32_t)(twon8*z));
|
||||
iq[jz] = (__int32_t)(z-two8*fw);
|
||||
jz += 1; q0 += 8;
|
||||
iq[jz] = (__int32_t) fw;
|
||||
} else iq[jz] = (__int32_t) z ;
|
||||
}
|
||||
|
||||
/* convert integer "bit" chunk to floating-point value */
|
||||
fw = scalbnf(one,(int)q0);
|
||||
for(i=jz;i>=0;i--) {
|
||||
q[i] = fw*(float)iq[i]; fw*=twon8;
|
||||
}
|
||||
|
||||
/* compute PIo2[0,...,jp]*q[jz,...,0] */
|
||||
for(i=jz;i>=0;i--) {
|
||||
for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
|
||||
fq[jz-i] = fw;
|
||||
}
|
||||
|
||||
/* compress fq[] into y[] */
|
||||
switch(prec) {
|
||||
case 0:
|
||||
fw = 0.0;
|
||||
for (i=jz;i>=0;i--) fw += fq[i];
|
||||
y[0] = (ih==0)? fw: -fw;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
fw = 0.0;
|
||||
for (i=jz;i>=0;i--) fw += fq[i];
|
||||
y[0] = (ih==0)? fw: -fw;
|
||||
fw = fq[0]-fw;
|
||||
for (i=1;i<=jz;i++) fw += fq[i];
|
||||
y[1] = (ih==0)? fw: -fw;
|
||||
break;
|
||||
case 3: /* painful */
|
||||
for (i=jz;i>0;i--) {
|
||||
fw = fq[i-1]+fq[i];
|
||||
fq[i] += fq[i-1]-fw;
|
||||
fq[i-1] = fw;
|
||||
}
|
||||
for (i=jz;i>1;i--) {
|
||||
fw = fq[i-1]+fq[i];
|
||||
fq[i] += fq[i-1]-fw;
|
||||
fq[i-1] = fw;
|
||||
}
|
||||
for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
|
||||
if(ih==0) {
|
||||
y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
|
||||
} else {
|
||||
y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
|
||||
}
|
||||
}
|
||||
return n&7;
|
||||
}
|
||||
|
||||
|
||||
/* ef_rem_pio2.c -- float version of e_rem_pio2.c
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*
|
||||
*/
|
||||
|
||||
/* __ieee754_rem_pio2f(x,y)
|
||||
*
|
||||
* return the remainder of x rem pi/2 in y[0]+y[1]
|
||||
* use __kernel_rem_pio2f()
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
|
||||
*/
|
||||
static const __int32_t two_over_pi[] = {
|
||||
0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC,
|
||||
0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62,
|
||||
0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63,
|
||||
0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A,
|
||||
0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09,
|
||||
0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29,
|
||||
0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44,
|
||||
0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41,
|
||||
0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C,
|
||||
0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8,
|
||||
0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11,
|
||||
0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF,
|
||||
0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E,
|
||||
0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5,
|
||||
0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92,
|
||||
0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08,
|
||||
0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0,
|
||||
0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3,
|
||||
0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85,
|
||||
0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80,
|
||||
0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA,
|
||||
0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B,
|
||||
};
|
||||
|
||||
/* This array is like the one in e_rem_pio2.c, but the numbers are
|
||||
single precision and the last 8 bits are forced to 0. */
|
||||
static const __int32_t npio2_hw[] = {
|
||||
0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
|
||||
0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
|
||||
0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
|
||||
0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
|
||||
0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
|
||||
0x4242c700, 0x42490f00
|
||||
};
|
||||
|
||||
/*
|
||||
* invpio2: 24 bits of 2/pi
|
||||
* pio2_1: first 17 bit of pi/2
|
||||
* pio2_1t: pi/2 - pio2_1
|
||||
* pio2_2: second 17 bit of pi/2
|
||||
* pio2_2t: pi/2 - (pio2_1+pio2_2)
|
||||
* pio2_3: third 17 bit of pi/2
|
||||
* pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
|
||||
*/
|
||||
|
||||
static const float
|
||||
half = 5.0000000000e-01, /* 0x3f000000 */
|
||||
invpio2 = 6.3661980629e-01, /* 0x3f22f984 */
|
||||
pio2_1 = 1.5707855225e+00, /* 0x3fc90f80 */
|
||||
pio2_1t = 1.0804334124e-05, /* 0x37354443 */
|
||||
pio2_2 = 1.0804273188e-05, /* 0x37354400 */
|
||||
pio2_2t = 6.0770999344e-11, /* 0x2e85a308 */
|
||||
pio2_3 = 6.0770943833e-11, /* 0x2e85a300 */
|
||||
pio2_3t = 6.1232342629e-17; /* 0x248d3132 */
|
||||
|
||||
__int32_t __ieee754_rem_pio2f(float x, float *y)
|
||||
{
|
||||
float z,w,t,r,fn;
|
||||
float tx[3];
|
||||
__int32_t i,j,n,ix,hx;
|
||||
int e0,nx;
|
||||
|
||||
GET_FLOAT_WORD(hx,x);
|
||||
ix = hx&0x7fffffff;
|
||||
if(ix<=0x3f490fd8) /* |x| ~<= pi/4 , no need for reduction */
|
||||
{y[0] = x; y[1] = 0; return 0;}
|
||||
if(ix<0x4016cbe4) { /* |x| < 3pi/4, special case with n=+-1 */
|
||||
if(hx>0) {
|
||||
z = x - pio2_1;
|
||||
if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
|
||||
y[0] = z - pio2_1t;
|
||||
y[1] = (z-y[0])-pio2_1t;
|
||||
} else { /* near pi/2, use 24+24+24 bit pi */
|
||||
z -= pio2_2;
|
||||
y[0] = z - pio2_2t;
|
||||
y[1] = (z-y[0])-pio2_2t;
|
||||
}
|
||||
return 1;
|
||||
} else { /* negative x */
|
||||
z = x + pio2_1;
|
||||
if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
|
||||
y[0] = z + pio2_1t;
|
||||
y[1] = (z-y[0])+pio2_1t;
|
||||
} else { /* near pi/2, use 24+24+24 bit pi */
|
||||
z += pio2_2;
|
||||
y[0] = z + pio2_2t;
|
||||
y[1] = (z-y[0])+pio2_2t;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */
|
||||
t = fabsf(x);
|
||||
n = (__int32_t) (t*invpio2+half);
|
||||
fn = (float)n;
|
||||
r = t-fn*pio2_1;
|
||||
w = fn*pio2_1t; /* 1st round good to 40 bit */
|
||||
if(n<32&&(ix&0xffffff00)!=npio2_hw[n-1]) {
|
||||
y[0] = r-w; /* quick check no cancellation */
|
||||
} else {
|
||||
__uint32_t high;
|
||||
j = ix>>23;
|
||||
y[0] = r-w;
|
||||
GET_FLOAT_WORD(high,y[0]);
|
||||
i = j-((high>>23)&0xff);
|
||||
if(i>8) { /* 2nd iteration needed, good to 57 */
|
||||
t = r;
|
||||
w = fn*pio2_2;
|
||||
r = t-w;
|
||||
w = fn*pio2_2t-((t-r)-w);
|
||||
y[0] = r-w;
|
||||
GET_FLOAT_WORD(high,y[0]);
|
||||
i = j-((high>>23)&0xff);
|
||||
if(i>25) { /* 3rd iteration need, 74 bits acc */
|
||||
t = r; /* will cover all possible cases */
|
||||
w = fn*pio2_3;
|
||||
r = t-w;
|
||||
w = fn*pio2_3t-((t-r)-w);
|
||||
y[0] = r-w;
|
||||
}
|
||||
}
|
||||
}
|
||||
y[1] = (r-y[0])-w;
|
||||
if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
|
||||
else return n;
|
||||
}
|
||||
/*
|
||||
* all other (large) arguments
|
||||
*/
|
||||
if(!FLT_UWORD_IS_FINITE(ix)) {
|
||||
y[0]=y[1]=x-x; return 0;
|
||||
}
|
||||
/* set z = scalbn(|x|,ilogb(x)-7) */
|
||||
e0 = (int)((ix>>23)-134); /* e0 = ilogb(z)-7; */
|
||||
SET_FLOAT_WORD(z, ix - ((__int32_t)e0<<23));
|
||||
for(i=0;i<2;i++) {
|
||||
tx[i] = (float)((__int32_t)(z));
|
||||
z = (z-tx[i])*two8;
|
||||
}
|
||||
tx[2] = z;
|
||||
nx = 3;
|
||||
while(tx[nx-1]==zero) nx--; /* skip zero term */
|
||||
n = __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi);
|
||||
if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/* kf_sin.c -- float version of k_sin.c
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
|
||||
static const float
|
||||
S1 = -1.6666667163e-01, /* 0xbe2aaaab */
|
||||
S2 = 8.3333337680e-03, /* 0x3c088889 */
|
||||
S3 = -1.9841270114e-04, /* 0xb9500d01 */
|
||||
S4 = 2.7557314297e-06, /* 0x3638ef1b */
|
||||
S5 = -2.5050759689e-08, /* 0xb2d72f34 */
|
||||
S6 = 1.5896910177e-10; /* 0x2f2ec9d3 */
|
||||
|
||||
float __kernel_sinf(float x, float y, int iy) /* iy=0 if y is zero */
|
||||
{
|
||||
float z,r,v;
|
||||
__int32_t ix;
|
||||
GET_FLOAT_WORD(ix,x);
|
||||
ix &= 0x7fffffff; /* high word of x */
|
||||
if(ix<0x32000000) /* |x| < 2**-27 */
|
||||
{if((int)x==0) return x;} /* generate inexact */
|
||||
z = x*x;
|
||||
v = z*x;
|
||||
r = S2+z*(S3+z*(S4+z*(S5+z*S6)));
|
||||
if(iy==0) return x+v*(S1+z*r);
|
||||
else return x-((z*(half*y-v*r)-y)-v*S1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* kf_cos.c -- float version of k_cos.c
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
|
||||
static const float
|
||||
C1 = 4.1666667908e-02, /* 0x3d2aaaab */
|
||||
C2 = -1.3888889225e-03, /* 0xbab60b61 */
|
||||
C3 = 2.4801587642e-05, /* 0x37d00d01 */
|
||||
C4 = -2.7557314297e-07, /* 0xb493f27c */
|
||||
C5 = 2.0875723372e-09, /* 0x310f74f6 */
|
||||
C6 = -1.1359647598e-11; /* 0xad47d74e */
|
||||
|
||||
float __kernel_cosf(float x, float y)
|
||||
{
|
||||
float a,hz,z,r,qx;
|
||||
__int32_t ix;
|
||||
GET_FLOAT_WORD(ix,x);
|
||||
ix &= 0x7fffffff; /* ix = |x|'s high word*/
|
||||
if(ix<0x32000000) { /* if x < 2**27 */
|
||||
if(((int)x)==0) return one; /* generate inexact */
|
||||
}
|
||||
z = x*x;
|
||||
r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
|
||||
if(ix < 0x3e99999a) /* if |x| < 0.3 */
|
||||
return one - ((float)0.5*z - (z*r - x*y));
|
||||
else {
|
||||
if(ix > 0x3f480000) { /* x > 0.78125 */
|
||||
qx = (float)0.28125;
|
||||
} else {
|
||||
SET_FLOAT_WORD(qx,ix-0x01000000); /* x/4 */
|
||||
}
|
||||
hz = (float)0.5*z-qx;
|
||||
a = one-qx;
|
||||
return a - (hz - (z*r-x*y));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* sf_sin.c -- float version of s_sin.c.
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
|
||||
float sinf(float x)
|
||||
{
|
||||
float y[2],z=0.0;
|
||||
__int32_t n,ix;
|
||||
|
||||
GET_FLOAT_WORD(ix,x);
|
||||
|
||||
/* |x| ~< pi/4 */
|
||||
ix &= 0x7fffffff;
|
||||
if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0);
|
||||
|
||||
/* sin(Inf or NaN) is NaN */
|
||||
else if (!FLT_UWORD_IS_FINITE(ix)) return x-x;
|
||||
|
||||
/* argument reduction needed */
|
||||
else {
|
||||
n = __ieee754_rem_pio2f(x,y);
|
||||
switch(n&3) {
|
||||
case 0: return __kernel_sinf(y[0],y[1],1);
|
||||
case 1: return __kernel_cosf(y[0],y[1]);
|
||||
case 2: return -__kernel_sinf(y[0],y[1],1);
|
||||
default:
|
||||
return -__kernel_cosf(y[0],y[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* sf_cos.c -- float version of s_cos.c.
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
|
||||
float cosf(float x)
|
||||
{
|
||||
float y[2],z=0.0;
|
||||
__int32_t n,ix;
|
||||
|
||||
GET_FLOAT_WORD(ix,x);
|
||||
|
||||
/* |x| ~< pi/4 */
|
||||
ix &= 0x7fffffff;
|
||||
if(ix <= 0x3f490fd8) return __kernel_cosf(x,z);
|
||||
|
||||
/* cos(Inf or NaN) is NaN */
|
||||
else if (!FLT_UWORD_IS_FINITE(ix)) return x-x;
|
||||
|
||||
/* argument reduction needed */
|
||||
else {
|
||||
n = __ieee754_rem_pio2f(x,y);
|
||||
switch(n&3) {
|
||||
case 0: return __kernel_cosf(y[0],y[1]);
|
||||
case 1: return -__kernel_sinf(y[0],y[1],1);
|
||||
case 2: return -__kernel_cosf(y[0],y[1]);
|
||||
default:
|
||||
return __kernel_sinf(y[0],y[1],1);
|
||||
}
|
||||
}
|
||||
}
|
||||
77
lib/libm/sf_cos.c
Normal file
77
lib/libm/sf_cos.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* These math functions are taken from newlib-nano-2, the newlib/libm/math
|
||||
* directory, available from https://github.com/32bitmicro/newlib-nano-2.
|
||||
*
|
||||
* Appropriate copyright headers are reproduced below.
|
||||
*/
|
||||
|
||||
/* sf_cos.c -- float version of s_cos.c.
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#include "fdlibm.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const float one=1.0;
|
||||
#else
|
||||
static float one=1.0;
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
float cosf(float x)
|
||||
#else
|
||||
float cosf(x)
|
||||
float x;
|
||||
#endif
|
||||
{
|
||||
float y[2],z=0.0;
|
||||
__int32_t n,ix;
|
||||
|
||||
GET_FLOAT_WORD(ix,x);
|
||||
|
||||
/* |x| ~< pi/4 */
|
||||
ix &= 0x7fffffff;
|
||||
if(ix <= 0x3f490fd8) return __kernel_cosf(x,z);
|
||||
|
||||
/* cos(Inf or NaN) is NaN */
|
||||
else if (!FLT_UWORD_IS_FINITE(ix)) return x-x;
|
||||
|
||||
/* argument reduction needed */
|
||||
else {
|
||||
n = __ieee754_rem_pio2f(x,y);
|
||||
switch(n&3) {
|
||||
case 0: return __kernel_cosf(y[0],y[1]);
|
||||
case 1: return -__kernel_sinf(y[0],y[1],1);
|
||||
case 2: return -__kernel_cosf(y[0],y[1]);
|
||||
default:
|
||||
return __kernel_sinf(y[0],y[1],1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DOUBLE_IS_32BITS
|
||||
|
||||
#ifdef __STDC__
|
||||
double cos(double x)
|
||||
#else
|
||||
double cos(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
return (double) cosf((float) x);
|
||||
}
|
||||
|
||||
#endif /* defined(_DOUBLE_IS_32BITS) */
|
||||
71
lib/libm/sf_sin.c
Normal file
71
lib/libm/sf_sin.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* These math functions are taken from newlib-nano-2, the newlib/libm/math
|
||||
* directory, available from https://github.com/32bitmicro/newlib-nano-2.
|
||||
*
|
||||
* Appropriate copyright headers are reproduced below.
|
||||
*/
|
||||
|
||||
/* sf_sin.c -- float version of s_sin.c.
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#include "fdlibm.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
float sinf(float x)
|
||||
#else
|
||||
float sinf(x)
|
||||
float x;
|
||||
#endif
|
||||
{
|
||||
float y[2],z=0.0;
|
||||
__int32_t n,ix;
|
||||
|
||||
GET_FLOAT_WORD(ix,x);
|
||||
|
||||
/* |x| ~< pi/4 */
|
||||
ix &= 0x7fffffff;
|
||||
if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0);
|
||||
|
||||
/* sin(Inf or NaN) is NaN */
|
||||
else if (!FLT_UWORD_IS_FINITE(ix)) return x-x;
|
||||
|
||||
/* argument reduction needed */
|
||||
else {
|
||||
n = __ieee754_rem_pio2f(x,y);
|
||||
switch(n&3) {
|
||||
case 0: return __kernel_sinf(y[0],y[1],1);
|
||||
case 1: return __kernel_cosf(y[0],y[1]);
|
||||
case 2: return -__kernel_sinf(y[0],y[1],1);
|
||||
default:
|
||||
return -__kernel_cosf(y[0],y[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DOUBLE_IS_32BITS
|
||||
|
||||
#ifdef __STDC__
|
||||
double sin(double x)
|
||||
#else
|
||||
double sin(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
return (double) sinf((float) x);
|
||||
}
|
||||
|
||||
#endif /* defined(_DOUBLE_IS_32BITS) */
|
||||
66
lib/libm/sf_tan.c
Normal file
66
lib/libm/sf_tan.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* These math functions are taken from newlib-nano-2, the newlib/libm/math
|
||||
* directory, available from https://github.com/32bitmicro/newlib-nano-2.
|
||||
*
|
||||
* Appropriate copyright headers are reproduced below.
|
||||
*/
|
||||
|
||||
/* sf_tan.c -- float version of s_tan.c.
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#include "fdlibm.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
float tanf(float x)
|
||||
#else
|
||||
float tanf(x)
|
||||
float x;
|
||||
#endif
|
||||
{
|
||||
float y[2],z=0.0;
|
||||
__int32_t n,ix;
|
||||
|
||||
GET_FLOAT_WORD(ix,x);
|
||||
|
||||
/* |x| ~< pi/4 */
|
||||
ix &= 0x7fffffff;
|
||||
if(ix <= 0x3f490fda) return __kernel_tanf(x,z,1);
|
||||
|
||||
/* tan(Inf or NaN) is NaN */
|
||||
else if (!FLT_UWORD_IS_FINITE(ix)) return x-x; /* NaN */
|
||||
|
||||
/* argument reduction needed */
|
||||
else {
|
||||
n = __ieee754_rem_pio2f(x,y);
|
||||
return __kernel_tanf(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even
|
||||
-1 -- n odd */
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DOUBLE_IS_32BITS
|
||||
|
||||
#ifdef __STDC__
|
||||
double tan(double x)
|
||||
#else
|
||||
double tan(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
return (double) tanf((float) x);
|
||||
}
|
||||
|
||||
#endif /* defined(_DOUBLE_IS_32BITS) */
|
||||
@@ -282,8 +282,9 @@ void asm_arm_mov_reg_i32(asm_arm_t *as, uint rd, int imm) {
|
||||
// TODO: There are more variants of immediate values
|
||||
if ((imm & 0xFF) == imm) {
|
||||
emit_al(as, asm_arm_op_mov_imm(rd, imm));
|
||||
} else if (imm < 0 && ((-imm) & 0xFF) == -imm) {
|
||||
emit_al(as, asm_arm_op_mvn_imm(rd, -imm));
|
||||
} else if (imm < 0 && imm >= -256) {
|
||||
// mvn is "move not", not "move negative"
|
||||
emit_al(as, asm_arm_op_mvn_imm(rd, ~imm));
|
||||
} else {
|
||||
//Insert immediate into code and jump over it
|
||||
emit_al(as, 0x59f0000 | (rd << 12)); // ldr rd, [pc]
|
||||
|
||||
@@ -325,7 +325,7 @@ void asm_x86_add_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) {
|
||||
asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_ADD_R32_TO_RM32);
|
||||
}
|
||||
|
||||
void asm_x86_add_i32_to_r32(asm_x86_t *as, int src_i32, int dest_r32) {
|
||||
STATIC void asm_x86_add_i32_to_r32(asm_x86_t *as, int src_i32, int dest_r32) {
|
||||
if (SIGNED_FIT8(src_i32)) {
|
||||
asm_x86_write_byte_2(as, OPCODE_ADD_I8_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
|
||||
asm_x86_write_byte_1(as, src_i32 & 0xff);
|
||||
|
||||
15
py/bc.h
15
py/bc.h
@@ -28,12 +28,10 @@
|
||||
typedef struct _mp_exc_stack {
|
||||
const byte *handler;
|
||||
// bit 0 is saved currently_in_except_block value
|
||||
// bit 1 is whether the opcode was SETUP_WITH or SETUP_FINALLY
|
||||
mp_obj_t *val_sp;
|
||||
// Saved exception, valid if currently_in_except_block bit is 1
|
||||
mp_obj_t prev_exc;
|
||||
// We might only have 2 interesting cases here: SETUP_EXCEPT & SETUP_FINALLY,
|
||||
// consider storing it in bit 1 of val_sp. TODO: SETUP_WITH?
|
||||
byte opcode;
|
||||
} mp_exc_stack_t;
|
||||
|
||||
typedef struct _mp_code_state {
|
||||
@@ -55,8 +53,11 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
|
||||
void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
|
||||
void mp_bytecode_print(const void *descr, mp_uint_t n_total_args, const byte *code, mp_uint_t len);
|
||||
void mp_bytecode_print2(const byte *code, mp_uint_t len);
|
||||
const byte *mp_bytecode_print_str(const byte *ip);
|
||||
#define mp_bytecode_print_inst(code) mp_bytecode_print2(code, 1)
|
||||
|
||||
// Helper macros to access pointer with least significant bit holding a flag
|
||||
#define MP_TAGPTR_PTR(x) ((void*)((mp_uint_t)(x) & ~((mp_uint_t)1)))
|
||||
#define MP_TAGPTR_TAG(x) ((mp_uint_t)(x) & 1)
|
||||
#define MP_TAGPTR_MAKE(ptr, tag) ((void*)((mp_uint_t)(ptr) | tag))
|
||||
// Helper macros to access pointer with least significant bits holding flags
|
||||
#define MP_TAGPTR_PTR(x) ((void*)((mp_uint_t)(x) & ~((mp_uint_t)3)))
|
||||
#define MP_TAGPTR_TAG0(x) ((mp_uint_t)(x) & 1)
|
||||
#define MP_TAGPTR_TAG1(x) ((mp_uint_t)(x) & 2)
|
||||
#define MP_TAGPTR_MAKE(ptr, tag) ((void*)((mp_uint_t)(ptr) | (tag)))
|
||||
|
||||
@@ -252,7 +252,12 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
|
||||
val = (mp_uint_t)val_in;
|
||||
break;
|
||||
default:
|
||||
val = mp_obj_get_int(val_in);
|
||||
// we handle large ints here by calling the truncated accessor
|
||||
if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) {
|
||||
val = mp_obj_int_get_truncated(val_in);
|
||||
} else {
|
||||
val = mp_obj_get_int(val_in);
|
||||
}
|
||||
}
|
||||
|
||||
mp_binary_set_int(MIN(size, sizeof(val)), struct_type == '>', p, val);
|
||||
|
||||
@@ -41,6 +41,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_dir_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_divmod_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_eval_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_exec_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_execfile_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_getattr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_globals_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hasattr_obj);
|
||||
@@ -73,6 +74,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_op_setitem_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_op_delitem_obj);
|
||||
|
||||
extern const mp_obj_module_t mp_module___main__;
|
||||
extern const mp_obj_module_t mp_module_builtins;
|
||||
extern const mp_obj_module_t mp_module_array;
|
||||
extern const mp_obj_module_t mp_module_collections;
|
||||
extern const mp_obj_module_t mp_module_io;
|
||||
@@ -83,6 +85,9 @@ extern const mp_obj_module_t mp_module_struct;
|
||||
extern const mp_obj_module_t mp_module_sys;
|
||||
extern const mp_obj_module_t mp_module_gc;
|
||||
|
||||
extern const mp_obj_dict_t mp_module_builtins_globals;
|
||||
extern mp_obj_dict_t *mp_module_builtins_override_dict;
|
||||
|
||||
struct _dummy_t;
|
||||
extern struct _dummy_t mp_sys_stdin_obj;
|
||||
extern struct _dummy_t mp_sys_stdout_obj;
|
||||
@@ -95,3 +100,4 @@ extern const mp_obj_module_t mp_module_ujson;
|
||||
extern const mp_obj_module_t mp_module_ure;
|
||||
extern const mp_obj_module_t mp_module_uheapq;
|
||||
extern const mp_obj_module_t mp_module_uhashlib;
|
||||
extern const mp_obj_module_t mp_module_ubinascii;
|
||||
|
||||
@@ -137,7 +137,14 @@ STATIC mp_obj_t eval_exec_helper(mp_uint_t n_args, const mp_obj_t *args, mp_pars
|
||||
const char *str = mp_obj_str_get_data(args[0], &str_len);
|
||||
|
||||
// create the lexer
|
||||
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, str, str_len, 0);
|
||||
// MP_PARSE_SINGLE_INPUT is used to indicate a file input
|
||||
mp_lexer_t *lex;
|
||||
if (MICROPY_PY_BUILTINS_EXECFILE && parse_input_kind == MP_PARSE_SINGLE_INPUT) {
|
||||
lex = mp_lexer_new_from_file(str);
|
||||
parse_input_kind = MP_PARSE_FILE_INPUT;
|
||||
} else {
|
||||
lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, str, str_len, 0);
|
||||
}
|
||||
|
||||
return mp_parse_compile_execute(lex, parse_input_kind, globals, locals);
|
||||
}
|
||||
@@ -151,3 +158,11 @@ STATIC mp_obj_t mp_builtin_exec(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
return eval_exec_helper(n_args, args, MP_PARSE_FILE_INPUT);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj, 1, 3, mp_builtin_exec);
|
||||
|
||||
#if MICROPY_PY_BUILTINS_EXECFILE
|
||||
STATIC mp_obj_t mp_builtin_execfile(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
// MP_PARSE_SINGLE_INPUT is used to indicate a file input
|
||||
return eval_exec_helper(n_args, args, MP_PARSE_SINGLE_INPUT);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_execfile_obj, 1, 3, mp_builtin_execfile);
|
||||
#endif
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "builtin.h"
|
||||
#include "builtintables.h"
|
||||
|
||||
#if 0 // print debugging info
|
||||
#define DEBUG_PRINT (1)
|
||||
@@ -56,6 +55,14 @@
|
||||
|
||||
#define PATH_SEP_CHAR '/'
|
||||
|
||||
#if MICROPY_MODULE_WEAK_LINKS
|
||||
STATIC const mp_map_elem_t mp_builtin_module_weak_links_table[] = {
|
||||
MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_MAP(mp_builtin_module_weak_links_map, mp_builtin_module_weak_links_table);
|
||||
#endif
|
||||
|
||||
bool mp_obj_is_package(mp_obj_t module) {
|
||||
mp_obj_t dest[2];
|
||||
mp_load_method_maybe(module, MP_QSTR___path__, dest);
|
||||
@@ -127,7 +134,7 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
|
||||
}
|
||||
|
||||
#if MICROPY_PY___FILE__
|
||||
qstr source_name = mp_lexer_source_name(lex);
|
||||
qstr source_name = lex->source_name;
|
||||
mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
|
||||
#endif
|
||||
|
||||
@@ -270,7 +277,7 @@ mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
#if MICROPY_MODULE_WEAK_LINKS
|
||||
// check if there is a weak link to this module
|
||||
if (i == mod_len) {
|
||||
mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_dict_obj.map, MP_OBJ_NEW_QSTR(mod_name), MP_MAP_LOOKUP);
|
||||
mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_map, MP_OBJ_NEW_QSTR(mod_name), MP_MAP_LOOKUP);
|
||||
if (el == NULL) {
|
||||
goto no_exist;
|
||||
}
|
||||
|
||||
@@ -1,258 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
#include "builtintables.h"
|
||||
#include "objarray.h"
|
||||
|
||||
STATIC const mp_map_elem_t mp_builtin_object_table[] = {
|
||||
// built-in core functions
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___build_class__), (mp_obj_t)&mp_builtin___build_class___obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___import__), (mp_obj_t)&mp_builtin___import___obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___repl_print__), (mp_obj_t)&mp_builtin___repl_print___obj },
|
||||
|
||||
// built-in types
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bool), (mp_obj_t)&mp_type_bool },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytes), (mp_obj_t)&mp_type_bytes },
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytearray), (mp_obj_t)&mp_type_bytearray },
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_complex), (mp_obj_t)&mp_type_complex },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&mp_type_dict },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_enumerate), (mp_obj_t)&mp_type_enumerate },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_filter), (mp_obj_t)&mp_type_filter },
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_float), (mp_obj_t)&mp_type_float },
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_FROZENSET
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_frozenset), (mp_obj_t)&mp_type_frozenset },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_int), (mp_obj_t)&mp_type_int },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_list), (mp_obj_t)&mp_type_list },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_map), (mp_obj_t)&mp_type_map },
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_memoryview), (mp_obj_t)&mp_type_memoryview },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_object), (mp_obj_t)&mp_type_object },
|
||||
#if MICROPY_PY_BUILTINS_PROPERTY
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_property), (mp_obj_t)&mp_type_property },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_range), (mp_obj_t)&mp_type_range },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_reversed), (mp_obj_t)&mp_type_reversed },
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_set), (mp_obj_t)&mp_type_set },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_str), (mp_obj_t)&mp_type_str },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_super), (mp_obj_t)&mp_type_super },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_tuple), (mp_obj_t)&mp_type_tuple },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_type), (mp_obj_t)&mp_type_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_zip), (mp_obj_t)&mp_type_zip },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_classmethod), (mp_obj_t)&mp_type_classmethod },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_staticmethod), (mp_obj_t)&mp_type_staticmethod },
|
||||
|
||||
// built-in objects
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_Ellipsis), (mp_obj_t)&mp_const_ellipsis_obj },
|
||||
|
||||
// built-in user functions
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_abs), (mp_obj_t)&mp_builtin_abs_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_all), (mp_obj_t)&mp_builtin_all_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&mp_builtin_any_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bin), (mp_obj_t)&mp_builtin_bin_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_callable), (mp_obj_t)&mp_builtin_callable_obj },
|
||||
#if MICROPY_PY_BUILTINS_COMPILE
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_compile), (mp_obj_t)&mp_builtin_compile_obj },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_chr), (mp_obj_t)&mp_builtin_chr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_dir), (mp_obj_t)&mp_builtin_dir_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_divmod), (mp_obj_t)&mp_builtin_divmod_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_eval), (mp_obj_t)&mp_builtin_eval_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_exec), (mp_obj_t)&mp_builtin_exec_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_getattr), (mp_obj_t)&mp_builtin_getattr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_globals), (mp_obj_t)&mp_builtin_globals_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_hasattr), (mp_obj_t)&mp_builtin_hasattr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_hash), (mp_obj_t)&mp_builtin_hash_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_hex), (mp_obj_t)&mp_builtin_hex_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_id), (mp_obj_t)&mp_builtin_id_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_isinstance), (mp_obj_t)&mp_builtin_isinstance_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_issubclass), (mp_obj_t)&mp_builtin_issubclass_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_iter), (mp_obj_t)&mp_builtin_iter_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_len), (mp_obj_t)&mp_builtin_len_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_locals), (mp_obj_t)&mp_builtin_locals_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_max), (mp_obj_t)&mp_builtin_max_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_min), (mp_obj_t)&mp_builtin_min_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_next), (mp_obj_t)&mp_builtin_next_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_oct), (mp_obj_t)&mp_builtin_oct_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ord), (mp_obj_t)&mp_builtin_ord_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_pow), (mp_obj_t)&mp_builtin_pow_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_print), (mp_obj_t)&mp_builtin_print_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_repr), (mp_obj_t)&mp_builtin_repr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_round), (mp_obj_t)&mp_builtin_round_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sorted), (mp_obj_t)&mp_builtin_sorted_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sum), (mp_obj_t)&mp_builtin_sum_obj },
|
||||
|
||||
// built-in exceptions
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BaseException), (mp_obj_t)&mp_type_BaseException },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ArithmeticError), (mp_obj_t)&mp_type_ArithmeticError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_AssertionError), (mp_obj_t)&mp_type_AssertionError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_AttributeError), (mp_obj_t)&mp_type_AttributeError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_EOFError), (mp_obj_t)&mp_type_EOFError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_Exception), (mp_obj_t)&mp_type_Exception },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GeneratorExit), (mp_obj_t)&mp_type_GeneratorExit },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ImportError), (mp_obj_t)&mp_type_ImportError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IndentationError), (mp_obj_t)&mp_type_IndentationError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IndexError), (mp_obj_t)&mp_type_IndexError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_KeyError), (mp_obj_t)&mp_type_KeyError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_LookupError), (mp_obj_t)&mp_type_LookupError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MemoryError), (mp_obj_t)&mp_type_MemoryError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_NameError), (mp_obj_t)&mp_type_NameError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_NotImplementedError), (mp_obj_t)&mp_type_NotImplementedError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_OSError), (mp_obj_t)&mp_type_OSError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_OverflowError), (mp_obj_t)&mp_type_OverflowError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_RuntimeError), (mp_obj_t)&mp_type_RuntimeError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_StopIteration), (mp_obj_t)&mp_type_StopIteration },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SyntaxError), (mp_obj_t)&mp_type_SyntaxError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SystemExit), (mp_obj_t)&mp_type_SystemExit },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_TypeError), (mp_obj_t)&mp_type_TypeError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ValueError), (mp_obj_t)&mp_type_ValueError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ZeroDivisionError), (mp_obj_t)&mp_type_ZeroDivisionError },
|
||||
// Somehow CPython managed to have OverflowError not inherit from ValueError ;-/
|
||||
// TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation
|
||||
|
||||
// Extra builtins as defined by a port
|
||||
MICROPY_PORT_BUILTINS
|
||||
};
|
||||
|
||||
const mp_obj_dict_t mp_builtin_object_dict_obj = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_builtin_object_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_builtin_object_table),
|
||||
.table = (mp_map_elem_t*)mp_builtin_object_table,
|
||||
},
|
||||
};
|
||||
|
||||
STATIC const mp_obj_module_t mp_module_builtins = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_builtins,
|
||||
.globals = (mp_obj_dict_t*)&mp_builtin_object_dict_obj,
|
||||
};
|
||||
|
||||
STATIC const mp_map_elem_t mp_builtin_module_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___main__), (mp_obj_t)&mp_module___main__ },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_builtins), (mp_obj_t)&mp_module_builtins },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_micropython), (mp_obj_t)&mp_module_micropython },
|
||||
|
||||
#if MICROPY_PY_ARRAY
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_array), (mp_obj_t)&mp_module_array },
|
||||
#endif
|
||||
#if MICROPY_PY_IO
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR__io), (mp_obj_t)&mp_module_io },
|
||||
#endif
|
||||
#if MICROPY_PY_COLLECTIONS
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR__collections), (mp_obj_t)&mp_module_collections },
|
||||
#endif
|
||||
#if MICROPY_PY_STRUCT
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_struct },
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
#if MICROPY_PY_MATH
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&mp_module_math },
|
||||
#endif
|
||||
#if MICROPY_PY_CMATH
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_cmath), (mp_obj_t)&mp_module_cmath },
|
||||
#endif
|
||||
#endif
|
||||
#if MICROPY_PY_SYS
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sys), (mp_obj_t)&mp_module_sys },
|
||||
#endif
|
||||
#if MICROPY_PY_GC && MICROPY_ENABLE_GC
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_gc), (mp_obj_t)&mp_module_gc },
|
||||
#endif
|
||||
|
||||
// extmod modules
|
||||
|
||||
#if MICROPY_PY_UCTYPES
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_uctypes), (mp_obj_t)&mp_module_uctypes },
|
||||
#endif
|
||||
#if MICROPY_PY_UZLIB
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_uzlib), (mp_obj_t)&mp_module_uzlib },
|
||||
#endif
|
||||
#if MICROPY_PY_UJSON
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ujson), (mp_obj_t)&mp_module_ujson },
|
||||
#endif
|
||||
#if MICROPY_PY_URE
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ure), (mp_obj_t)&mp_module_ure },
|
||||
#endif
|
||||
#if MICROPY_PY_UHEAPQ
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_uheapq), (mp_obj_t)&mp_module_uheapq },
|
||||
#endif
|
||||
#if MICROPY_PY_UHASHLIB
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib },
|
||||
#endif
|
||||
|
||||
// extra builtin modules as defined by a port
|
||||
MICROPY_PORT_BUILTIN_MODULES
|
||||
};
|
||||
|
||||
const mp_obj_dict_t mp_builtin_module_dict_obj = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_builtin_module_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_builtin_module_table),
|
||||
.table = (mp_map_elem_t*)mp_builtin_module_table,
|
||||
},
|
||||
};
|
||||
|
||||
#if MICROPY_MODULE_WEAK_LINKS
|
||||
STATIC const mp_map_elem_t mp_builtin_module_weak_links_table[] = {
|
||||
MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS
|
||||
};
|
||||
|
||||
const mp_obj_dict_t mp_builtin_module_weak_links_dict_obj = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_builtin_module_weak_links_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_builtin_module_weak_links_table),
|
||||
.table = (mp_map_elem_t*)mp_builtin_module_weak_links_table,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
263
py/compile.c
263
py/compile.c
@@ -49,7 +49,6 @@
|
||||
// TODO need to mangle __attr names
|
||||
|
||||
typedef enum {
|
||||
PN_none = 0,
|
||||
#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
|
||||
#include "grammar.h"
|
||||
#undef DEF_RULE
|
||||
@@ -429,10 +428,7 @@ STATIC int list_get(mp_parse_node_t *pn, int pn_kind, mp_parse_node_t **nodes) {
|
||||
}
|
||||
}
|
||||
|
||||
void compile_do_nothing(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
|
||||
void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
for (int i = 0; i < num_nodes; i++) {
|
||||
compile_node(comp, pns->nodes[i]);
|
||||
@@ -602,7 +598,7 @@ STATIC void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t
|
||||
#endif
|
||||
}
|
||||
|
||||
void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
// a simple tuple expression
|
||||
c_tuple(comp, MP_PARSE_NODE_NULL, pns);
|
||||
}
|
||||
@@ -1100,7 +1096,7 @@ STATIC void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
|
||||
|
||||
// leaves function object on stack
|
||||
// returns function name
|
||||
qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
|
||||
STATIC qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
|
||||
if (comp->pass == MP_PASS_SCOPE) {
|
||||
// create a new scope for this function
|
||||
scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
|
||||
@@ -1149,7 +1145,7 @@ qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint
|
||||
|
||||
// leaves class object on stack
|
||||
// returns class name
|
||||
qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
|
||||
STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
|
||||
if (comp->pass == MP_PASS_SCOPE) {
|
||||
// create a new scope for this class
|
||||
scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
|
||||
@@ -1212,7 +1208,7 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_
|
||||
return true;
|
||||
}
|
||||
|
||||
void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
// get the list of decorators
|
||||
mp_parse_node_t *nodes;
|
||||
int n = list_get(&pns->nodes[0], PN_decorators, &nodes);
|
||||
@@ -1275,7 +1271,7 @@ void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
EMIT_ARG(store_id, body_name);
|
||||
}
|
||||
|
||||
void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
|
||||
// store function object into function name
|
||||
EMIT_ARG(store_id, fname);
|
||||
@@ -1365,11 +1361,11 @@ cannot_delete:
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pn, "can't delete expression");
|
||||
}
|
||||
|
||||
void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
|
||||
}
|
||||
|
||||
void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
if (comp->break_label == 0) {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "'break' outside loop");
|
||||
}
|
||||
@@ -1377,7 +1373,7 @@ void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
|
||||
}
|
||||
|
||||
void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
if (comp->continue_label == 0) {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "'continue' outside loop");
|
||||
}
|
||||
@@ -1385,7 +1381,7 @@ void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
|
||||
}
|
||||
|
||||
void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
if (comp->scope_cur->kind != SCOPE_FUNCTION) {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "'return' outside function");
|
||||
return;
|
||||
@@ -1410,12 +1406,12 @@ void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
EMIT(return_value);
|
||||
}
|
||||
|
||||
void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
compile_node(comp, pns->nodes[0]);
|
||||
EMIT(pop_top);
|
||||
}
|
||||
|
||||
void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
|
||||
// raise
|
||||
EMIT_ARG(raise_varargs, 0);
|
||||
@@ -1503,11 +1499,11 @@ STATIC void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
|
||||
EMIT_ARG(store_id, q_base);
|
||||
}
|
||||
|
||||
void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
|
||||
}
|
||||
|
||||
void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
mp_parse_node_t pn_import_source = pns->nodes[0];
|
||||
|
||||
// extract the preceeding .'s (if any) for a relative import, to compute the import level
|
||||
@@ -1618,35 +1614,63 @@ void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
}
|
||||
|
||||
void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, qstr qst) {
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
|
||||
if (!added) {
|
||||
compile_syntax_error(comp, pn, "identifier already used");
|
||||
return;
|
||||
}
|
||||
id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
|
||||
|
||||
// if the id exists in the global scope, set its kind to EXPLICIT_GLOBAL
|
||||
id_info = scope_find_global(comp->scope_cur, qst);
|
||||
if (id_info != NULL) {
|
||||
id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
if (comp->pass == MP_PASS_SCOPE) {
|
||||
if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
|
||||
scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
|
||||
} else {
|
||||
pns = (mp_parse_node_struct_t*)pns->nodes[0];
|
||||
int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
for (int i = 0; i < num_nodes; i++) {
|
||||
scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
|
||||
}
|
||||
mp_parse_node_t *nodes;
|
||||
int n = list_get(&pns->nodes[0], PN_name_list, &nodes);
|
||||
for (int i = 0; i < n; i++) {
|
||||
compile_declare_global(comp, (mp_parse_node_t)pns, MP_PARSE_NODE_LEAF_ARG(nodes[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, qstr qst) {
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
|
||||
if (!added) {
|
||||
compile_syntax_error(comp, pn, "identifier already used");
|
||||
return;
|
||||
}
|
||||
id_info_t *id_info2 = scope_find_local_in_parent(comp->scope_cur, qst);
|
||||
if (id_info2 == NULL || !(id_info2->kind == ID_INFO_KIND_LOCAL || id_info2->kind == ID_INFO_KIND_CELL || id_info2->kind == ID_INFO_KIND_FREE)) {
|
||||
compile_syntax_error(comp, pn, "no binding for nonlocal found");
|
||||
return;
|
||||
}
|
||||
id_info->kind = ID_INFO_KIND_FREE;
|
||||
scope_close_over_in_parents(comp->scope_cur, qst);
|
||||
}
|
||||
|
||||
STATIC void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
if (comp->pass == MP_PASS_SCOPE) {
|
||||
if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
|
||||
scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
|
||||
} else {
|
||||
pns = (mp_parse_node_struct_t*)pns->nodes[0];
|
||||
int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
for (int i = 0; i < num_nodes; i++) {
|
||||
scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
|
||||
}
|
||||
if (comp->scope_cur->kind == SCOPE_MODULE) {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "can't declare nonlocal in outer code");
|
||||
return;
|
||||
}
|
||||
mp_parse_node_t *nodes;
|
||||
int n = list_get(&pns->nodes[0], PN_name_list, &nodes);
|
||||
for (int i = 0; i < n; i++) {
|
||||
compile_declare_nonlocal(comp, (mp_parse_node_t)pns, MP_PARSE_NODE_LEAF_ARG(nodes[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
uint l_end = comp_next_label(comp);
|
||||
c_if_cond(comp, pns->nodes[0], true, l_end);
|
||||
EMIT_ARG(load_global, MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython
|
||||
@@ -1659,7 +1683,7 @@ void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
EMIT_ARG(label_assign, l_end);
|
||||
}
|
||||
|
||||
void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
// TODO proper and/or short circuiting
|
||||
|
||||
uint l_end = comp_next_label(comp);
|
||||
@@ -1738,7 +1762,7 @@ done:
|
||||
comp->continue_label = old_continue_label; \
|
||||
comp->break_continue_except_level = old_break_continue_except_level;
|
||||
|
||||
void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
START_BREAK_CONTINUE_BLOCK
|
||||
|
||||
// compared to CPython, we have an optimised version of while loops
|
||||
@@ -1779,27 +1803,42 @@ void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
|
||||
#if !MICROPY_EMIT_CPYTHON
|
||||
// TODO preload end and step onto stack if they are not constants
|
||||
// Note that, as per semantics of for .. range, the final failing value should not be stored in the loop variable
|
||||
// And, if the loop never runs, the loop variable should never be assigned
|
||||
// This function compiles an optimised for-loop of the form:
|
||||
// for <var> in range(<start>, <end>, <step>):
|
||||
// <body>
|
||||
// else:
|
||||
// <else>
|
||||
// <var> must be an identifier and <step> must be a small-int.
|
||||
//
|
||||
// Semantics of for-loop require:
|
||||
// - final failing value should not be stored in the loop variable
|
||||
// - if the loop never runs, the loop variable should never be assigned
|
||||
// - assignments to <var>, <end> or <step> in the body do not alter the loop
|
||||
// (<step> is a constant for us, so no need to worry about it changing)
|
||||
//
|
||||
// If <end> is a small-int, then the stack during the for-loop contains just
|
||||
// the current value of <var>. Otherwise, the stack contains <end> then the
|
||||
// current value of <var>.
|
||||
STATIC void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) {
|
||||
START_BREAK_CONTINUE_BLOCK
|
||||
// note that we don't need to pop anything when breaking from an optimise for loop
|
||||
|
||||
uint top_label = comp_next_label(comp);
|
||||
uint entry_label = comp_next_label(comp);
|
||||
|
||||
// compile: start, duplicated on stack
|
||||
// put the end value on the stack if it's not a small-int constant
|
||||
bool end_on_stack = !MP_PARSE_NODE_IS_SMALL_INT(pn_end);
|
||||
if (end_on_stack) {
|
||||
compile_node(comp, pn_end);
|
||||
}
|
||||
|
||||
// compile: start
|
||||
compile_node(comp, pn_start);
|
||||
EMIT(dup_top);
|
||||
|
||||
EMIT_ARG(jump, entry_label);
|
||||
EMIT_ARG(label_assign, top_label);
|
||||
|
||||
// at this point we actually have 1 less element on the stack
|
||||
EMIT_ARG(adjust_stack_size, -1);
|
||||
|
||||
// store next value to var
|
||||
// duplicate next value and store it to var
|
||||
EMIT(dup_top);
|
||||
c_assign(comp, pn_var, ASSIGN_STORE);
|
||||
|
||||
// compile body
|
||||
@@ -1807,16 +1846,20 @@ STATIC void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t p
|
||||
|
||||
EMIT_ARG(label_assign, continue_label);
|
||||
|
||||
// compile: var + step, duplicated on stack
|
||||
compile_node(comp, pn_var);
|
||||
// compile: var + step
|
||||
compile_node(comp, pn_step);
|
||||
EMIT_ARG(binary_op, MP_BINARY_OP_INPLACE_ADD);
|
||||
EMIT(dup_top);
|
||||
|
||||
EMIT_ARG(label_assign, entry_label);
|
||||
|
||||
// compile: if var <cond> end: goto top
|
||||
compile_node(comp, pn_end);
|
||||
if (end_on_stack) {
|
||||
EMIT(dup_top_two);
|
||||
EMIT(rot_two);
|
||||
} else {
|
||||
EMIT(dup_top);
|
||||
compile_node(comp, pn_end);
|
||||
}
|
||||
assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step));
|
||||
if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) {
|
||||
EMIT_ARG(binary_op, MP_BINARY_OP_LESS);
|
||||
@@ -1825,19 +1868,24 @@ STATIC void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t p
|
||||
}
|
||||
EMIT_ARG(pop_jump_if_true, top_label);
|
||||
|
||||
// discard final value of var that failed the loop condition
|
||||
EMIT(pop_top);
|
||||
|
||||
// break/continue apply to outer loop (if any) in the else block
|
||||
END_BREAK_CONTINUE_BLOCK
|
||||
|
||||
compile_node(comp, pn_else);
|
||||
|
||||
EMIT_ARG(label_assign, break_label);
|
||||
|
||||
// discard final value of var that failed the loop condition
|
||||
EMIT(pop_top);
|
||||
|
||||
// discard <end> value if it's on the stack
|
||||
if (end_on_stack) {
|
||||
EMIT(pop_top);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
#if !MICROPY_EMIT_CPYTHON
|
||||
// this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
|
||||
// this is actually slower, but uses no heap memory
|
||||
@@ -2034,7 +2082,7 @@ STATIC void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n
|
||||
EMIT(end_finally);
|
||||
}
|
||||
|
||||
void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
|
||||
mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
|
||||
if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
|
||||
@@ -2094,7 +2142,7 @@ STATIC void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *n
|
||||
}
|
||||
}
|
||||
|
||||
void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
// get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
|
||||
mp_parse_node_t *nodes;
|
||||
int n = list_get(&pns->nodes[0], PN_with_stmt_list, &nodes);
|
||||
@@ -2104,7 +2152,7 @@ void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
|
||||
}
|
||||
|
||||
void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
|
||||
if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
|
||||
// for REPL, evaluate then print the expression
|
||||
@@ -2222,7 +2270,7 @@ STATIC void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, mp_binary
|
||||
}
|
||||
}
|
||||
|
||||
void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
|
||||
mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
|
||||
|
||||
@@ -2237,7 +2285,7 @@ void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
EMIT_ARG(label_assign, l_end);
|
||||
}
|
||||
|
||||
void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
// TODO default params etc for lambda; possibly just use funcdef code
|
||||
//mp_parse_node_t pn_params = pns->nodes[0];
|
||||
//mp_parse_node_t pn_body = pns->nodes[1];
|
||||
@@ -2256,7 +2304,7 @@ void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
close_over_variables_etc(comp, this_scope, 0, 0);
|
||||
}
|
||||
|
||||
void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
uint l_end = comp_next_label(comp);
|
||||
int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
for (int i = 0; i < n; i += 1) {
|
||||
@@ -2268,7 +2316,7 @@ void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
EMIT_ARG(label_assign, l_end);
|
||||
}
|
||||
|
||||
void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
uint l_end = comp_next_label(comp);
|
||||
int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
for (int i = 0; i < n; i += 1) {
|
||||
@@ -2280,12 +2328,12 @@ void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
EMIT_ARG(label_assign, l_end);
|
||||
}
|
||||
|
||||
void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
compile_node(comp, pns->nodes[0]);
|
||||
EMIT_ARG(unary_op, MP_UNARY_OP_NOT);
|
||||
}
|
||||
|
||||
void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
compile_node(comp, pns->nodes[0]);
|
||||
bool multi = (num_nodes > 3);
|
||||
@@ -2346,23 +2394,23 @@ void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
}
|
||||
|
||||
void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "*x must be assignment target");
|
||||
}
|
||||
|
||||
void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
c_binary_op(comp, pns, MP_BINARY_OP_OR);
|
||||
}
|
||||
|
||||
void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
c_binary_op(comp, pns, MP_BINARY_OP_XOR);
|
||||
}
|
||||
|
||||
void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
c_binary_op(comp, pns, MP_BINARY_OP_AND);
|
||||
}
|
||||
|
||||
void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
compile_node(comp, pns->nodes[0]);
|
||||
for (int i = 1; i + 1 < num_nodes; i += 2) {
|
||||
@@ -2378,7 +2426,7 @@ void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
}
|
||||
|
||||
void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
compile_node(comp, pns->nodes[0]);
|
||||
for (int i = 1; i + 1 < num_nodes; i += 2) {
|
||||
@@ -2394,7 +2442,7 @@ void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
}
|
||||
|
||||
void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
compile_node(comp, pns->nodes[0]);
|
||||
for (int i = 1; i + 1 < num_nodes; i += 2) {
|
||||
@@ -2414,7 +2462,7 @@ void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
}
|
||||
|
||||
void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
compile_node(comp, pns->nodes[1]);
|
||||
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
|
||||
EMIT_ARG(unary_op, MP_UNARY_OP_POSITIVE);
|
||||
@@ -2428,7 +2476,7 @@ void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
}
|
||||
|
||||
void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
// this is to handle special super() call
|
||||
comp->func_arg_is_super = MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super;
|
||||
|
||||
@@ -2442,20 +2490,16 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar
|
||||
// this is to handle special super() call
|
||||
if (MP_PARSE_NODE_IS_NULL(pn_arglist) && comp->func_arg_is_super && comp->scope_cur->kind == SCOPE_FUNCTION) {
|
||||
EMIT_ARG(load_id, MP_QSTR___class__);
|
||||
// get first argument to function
|
||||
bool found = false;
|
||||
// look for first argument to function (assumes it's "self")
|
||||
for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
|
||||
if (comp->scope_cur->id_info[i].flags & ID_FLAG_IS_PARAM) {
|
||||
// first argument found; load it and call super
|
||||
EMIT_ARG(load_fast, MP_QSTR_, comp->scope_cur->id_info[i].flags, comp->scope_cur->id_info[i].local_num);
|
||||
found = true;
|
||||
break;
|
||||
EMIT_ARG(call_function, 2, 0, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
printf("TypeError: super() call cannot find self\n");
|
||||
return;
|
||||
}
|
||||
EMIT_ARG(call_function, 2, 0, 0);
|
||||
compile_syntax_error(comp, MP_PARSE_NODE_NULL, "super() call cannot find self"); // really a TypeError
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -2526,7 +2570,7 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar
|
||||
}
|
||||
}
|
||||
|
||||
void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
for (int i = 0; i < num_nodes; i++) {
|
||||
if (i + 1 < num_nodes && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i], PN_trailer_period) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i + 1], PN_trailer_paren)) {
|
||||
@@ -2543,12 +2587,12 @@ void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
}
|
||||
|
||||
void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
compile_node(comp, pns->nodes[0]);
|
||||
EMIT_ARG(binary_op, MP_BINARY_OP_POWER);
|
||||
}
|
||||
|
||||
void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
// a list of strings
|
||||
|
||||
// check type of list (string or bytes) and count total number of bytes
|
||||
@@ -2620,7 +2664,7 @@ STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns,
|
||||
EMIT_ARG(call_function, 1, 0, 0);
|
||||
}
|
||||
|
||||
void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
|
||||
// an empty tuple
|
||||
c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
|
||||
@@ -2654,7 +2698,7 @@ void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
}
|
||||
|
||||
void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
|
||||
// empty list
|
||||
EMIT_ARG(build_list, 0);
|
||||
@@ -2693,7 +2737,7 @@ void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
}
|
||||
|
||||
void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
mp_parse_node_t pn = pns->nodes[0];
|
||||
if (MP_PARSE_NODE_IS_NULL(pn)) {
|
||||
// empty dict
|
||||
@@ -2717,7 +2761,7 @@ void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
|
||||
// first element sets whether it's a dict or set
|
||||
bool is_dict;
|
||||
if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
|
||||
if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
|
||||
// a dictionary
|
||||
EMIT_ARG(build_map, 1 + n);
|
||||
compile_node(comp, pns->nodes[0]);
|
||||
@@ -2748,13 +2792,15 @@ void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
// if it's a set, build it
|
||||
if (!is_dict) {
|
||||
EMIT_ARG(build_set, 1 + n);
|
||||
}
|
||||
#endif
|
||||
} else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {
|
||||
// dict/set comprehension
|
||||
if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
|
||||
if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
|
||||
// a dictionary comprehension
|
||||
compile_comprehension(comp, pns, SCOPE_DICT_COMP);
|
||||
} else {
|
||||
@@ -2772,27 +2818,32 @@ void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
} else {
|
||||
// set with one element
|
||||
set_with_one_element:
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
compile_node(comp, pn);
|
||||
EMIT_ARG(build_set, 1);
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
|
||||
}
|
||||
|
||||
void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
// object who's index we want is on top of stack
|
||||
compile_node(comp, pns->nodes[0]); // the index
|
||||
EMIT(load_subscr);
|
||||
}
|
||||
|
||||
void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
// object who's attribute we want is on top of stack
|
||||
EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
|
||||
}
|
||||
|
||||
void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
STATIC void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
|
||||
mp_parse_node_t pn = pns->nodes[0];
|
||||
if (MP_PARSE_NODE_IS_NULL(pn)) {
|
||||
@@ -2837,30 +2888,31 @@ void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
}
|
||||
}
|
||||
|
||||
void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
compile_node(comp, pns->nodes[0]); // start of slice
|
||||
assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
|
||||
compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
|
||||
}
|
||||
|
||||
void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
|
||||
compile_subscript_3_helper(comp, pns);
|
||||
}
|
||||
#endif // MICROPY_PY_BUILTINS_SLICE
|
||||
|
||||
void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
// if this is called then we are compiling a dict key:value pair
|
||||
compile_node(comp, pns->nodes[1]); // value
|
||||
compile_node(comp, pns->nodes[0]); // key
|
||||
}
|
||||
|
||||
void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
|
||||
// store class object into class name
|
||||
EMIT_ARG(store_id, cname);
|
||||
}
|
||||
|
||||
void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "'yield' outside function");
|
||||
return;
|
||||
@@ -2882,7 +2934,6 @@ void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
|
||||
typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
|
||||
STATIC compile_function_t compile_function[] = {
|
||||
NULL,
|
||||
#define nc NULL
|
||||
#define c(f) compile_##f
|
||||
#define DEF_RULE(rule, comp, kind, ...) comp,
|
||||
@@ -2925,8 +2976,8 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
|
||||
} else {
|
||||
compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
|
||||
if (f == NULL) {
|
||||
printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
|
||||
#if MICROPY_DEBUG_PRINTERS
|
||||
printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
|
||||
mp_parse_node_print(pn, 0);
|
||||
#endif
|
||||
compile_syntax_error(comp, pn, "internal compiler error");
|
||||
@@ -3068,8 +3119,10 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_t pn_iter, m
|
||||
EMIT_ARG(list_append, for_depth + 2);
|
||||
} else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
|
||||
EMIT_ARG(map_add, for_depth + 2);
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
} else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
|
||||
EMIT_ARG(set_add, for_depth + 2);
|
||||
#endif
|
||||
} else {
|
||||
EMIT(yield_value);
|
||||
EMIT(pop_top);
|
||||
@@ -3262,8 +3315,10 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
||||
EMIT_ARG(build_list, 0);
|
||||
} else if (scope->kind == SCOPE_DICT_COMP) {
|
||||
EMIT_ARG(build_map, 0);
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
} else if (scope->kind == SCOPE_SET_COMP) {
|
||||
EMIT_ARG(build_set, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint l_end = comp_next_label(comp);
|
||||
@@ -3330,7 +3385,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
|
||||
comp->next_label = 1;
|
||||
|
||||
if (scope->kind != SCOPE_FUNCTION) {
|
||||
printf("Error: inline assembler must be a function\n");
|
||||
compile_syntax_error(comp, MP_PARSE_NODE_NULL, "inline assembler must be a function");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,12 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __MICROPY_INCLUDED_PY_COMPILE_H__
|
||||
#define __MICROPY_INCLUDED_PY_COMPILE_H__
|
||||
|
||||
#include "py/lexer.h"
|
||||
#include "py/parse.h"
|
||||
#include "py/emitglue.h"
|
||||
|
||||
// These must fit in 8 bits; see scope.h
|
||||
enum {
|
||||
@@ -38,3 +44,5 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is
|
||||
|
||||
// this is implemented in runtime.c
|
||||
mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_input_kind, mp_obj_dict_t *globals, mp_obj_dict_t *locals);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_PY_COMPILE_H__
|
||||
|
||||
10
py/emit.h
10
py/emit.h
@@ -33,6 +33,10 @@
|
||||
* This is problematic for some emitters (x64) since they need to know the maximum
|
||||
* stack size to compile the entry to the function, and this affects code size.
|
||||
*/
|
||||
#ifndef __MICROPY_INCLUDED_PY_EMIT_H__
|
||||
#define __MICROPY_INCLUDED_PY_EMIT_H__
|
||||
|
||||
#include "py/runtime0.h"
|
||||
|
||||
typedef enum {
|
||||
MP_PASS_SCOPE = 1, // work out id's and their kind, and number of labels
|
||||
@@ -124,9 +128,13 @@ typedef struct _emit_method_table_t {
|
||||
void (*build_map)(emit_t *emit, mp_uint_t n_args);
|
||||
void (*store_map)(emit_t *emit);
|
||||
void (*map_add)(emit_t *emit, mp_uint_t map_stack_index);
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
void (*build_set)(emit_t *emit, mp_uint_t n_args);
|
||||
void (*set_add)(emit_t *emit, mp_uint_t set_stack_index);
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
void (*build_slice)(emit_t *emit, mp_uint_t n_args);
|
||||
#endif
|
||||
void (*unpack_sequence)(emit_t *emit, mp_uint_t n_args);
|
||||
void (*unpack_ex)(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right);
|
||||
void (*make_function)(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults);
|
||||
@@ -195,3 +203,5 @@ extern const emit_inline_asm_method_table_t emit_inline_thumb_method_table;
|
||||
|
||||
emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels);
|
||||
void emit_inline_thumb_free(emit_inline_asm_t *emit);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_PY_EMIT_H__
|
||||
|
||||
@@ -782,6 +782,7 @@ STATIC void emit_bc_map_add(emit_t *emit, mp_uint_t map_stack_index) {
|
||||
emit_write_bytecode_byte_uint(emit, MP_BC_MAP_ADD, map_stack_index);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
STATIC void emit_bc_build_set(emit_t *emit, mp_uint_t n_args) {
|
||||
emit_bc_pre(emit, 1 - n_args);
|
||||
emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_SET, n_args);
|
||||
@@ -791,11 +792,14 @@ STATIC void emit_bc_set_add(emit_t *emit, mp_uint_t set_stack_index) {
|
||||
emit_bc_pre(emit, -1);
|
||||
emit_write_bytecode_byte_uint(emit, MP_BC_SET_ADD, set_stack_index);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
STATIC void emit_bc_build_slice(emit_t *emit, mp_uint_t n_args) {
|
||||
emit_bc_pre(emit, 1 - n_args);
|
||||
emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_SLICE, n_args);
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC void emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args) {
|
||||
emit_bc_pre(emit, -1 + n_args);
|
||||
@@ -960,9 +964,13 @@ const emit_method_table_t emit_bc_method_table = {
|
||||
emit_bc_build_map,
|
||||
emit_bc_store_map,
|
||||
emit_bc_map_add,
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
emit_bc_build_set,
|
||||
emit_bc_set_add,
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
emit_bc_build_slice,
|
||||
#endif
|
||||
emit_bc_unpack_sequence,
|
||||
emit_bc_unpack_ex,
|
||||
emit_bc_make_function,
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __MICROPY_INCLUDED_PY_EMITGLUE_H__
|
||||
#define __MICROPY_INCLUDED_PY_EMITGLUE_H__
|
||||
|
||||
// These variables and functions glue the code emitters to the runtime.
|
||||
|
||||
@@ -59,3 +61,5 @@ void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void
|
||||
|
||||
mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args);
|
||||
mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_PY_EMITGLUE_H__
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
#if MICROPY_EMIT_INLINE_THUMB
|
||||
|
||||
typedef enum {
|
||||
PN_none = 0,
|
||||
#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
|
||||
#include "grammar.h"
|
||||
#undef DEF_RULE
|
||||
@@ -61,7 +60,7 @@ struct _emit_inline_asm_t {
|
||||
asm_thumb_t *as;
|
||||
};
|
||||
|
||||
void emit_inline_thumb_error(emit_inline_asm_t *emit, const char *fmt, ...) {
|
||||
STATIC void emit_inline_thumb_error(emit_inline_asm_t *emit, const char *fmt, ...) {
|
||||
printf("SyntaxError: ");
|
||||
emit->success = false;
|
||||
va_list ap;
|
||||
|
||||
@@ -2064,6 +2064,7 @@ STATIC void emit_native_map_add(emit_t *emit, mp_uint_t map_index) {
|
||||
emit_post(emit);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
STATIC void emit_native_build_set(emit_t *emit, mp_uint_t n_args) {
|
||||
emit_native_pre(emit);
|
||||
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
|
||||
@@ -2081,7 +2082,9 @@ STATIC void emit_native_set_add(emit_t *emit, mp_uint_t set_index) {
|
||||
emit_call(emit, MP_F_STORE_SET);
|
||||
emit_post(emit);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
STATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args) {
|
||||
DEBUG_printf("build_slice %d\n", n_args);
|
||||
if (n_args == 2) {
|
||||
@@ -2102,6 +2105,7 @@ STATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args) {
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC void emit_native_unpack_sequence(emit_t *emit, mp_uint_t n_args) {
|
||||
DEBUG_printf("unpack_sequence %d\n", n_args);
|
||||
@@ -2330,9 +2334,13 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
|
||||
emit_native_build_map,
|
||||
emit_native_store_map,
|
||||
emit_native_map_add,
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
emit_native_build_set,
|
||||
emit_native_set_add,
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
emit_native_build_slice,
|
||||
#endif
|
||||
emit_native_unpack_sequence,
|
||||
emit_native_unpack_ex,
|
||||
emit_native_make_function,
|
||||
|
||||
@@ -201,9 +201,13 @@ const emit_method_table_t emit_pass1_method_table = {
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
(void*)emit_pass1_dummy,
|
||||
#endif
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
|
||||
46
py/grammar.h
46
py/grammar.h
@@ -59,16 +59,16 @@ DEF_RULE(decorator, nc, and(4), tok(DEL_AT), rule(dotted_name), opt_rule(trailer
|
||||
DEF_RULE(decorators, nc, one_or_more, rule(decorator))
|
||||
DEF_RULE(decorated, c(decorated), and(2), rule(decorators), rule(decorated_body))
|
||||
DEF_RULE(decorated_body, nc, or(2), rule(classdef), rule(funcdef))
|
||||
DEF_RULE(funcdef, c(funcdef), and(8), tok(KW_DEF), tok(NAME), tok(DEL_PAREN_OPEN), opt_rule(typedargslist), tok(DEL_PAREN_CLOSE), opt_rule(funcdefrettype), tok(DEL_COLON), rule(suite))
|
||||
DEF_RULE(funcdefrettype, nc, and(2), tok(DEL_MINUS_MORE), rule(test))
|
||||
DEF_RULE(funcdef, c(funcdef), blank | and(8), tok(KW_DEF), tok(NAME), tok(DEL_PAREN_OPEN), opt_rule(typedargslist), tok(DEL_PAREN_CLOSE), opt_rule(funcdefrettype), tok(DEL_COLON), rule(suite))
|
||||
DEF_RULE(funcdefrettype, nc, ident | and(2), tok(DEL_MINUS_MORE), rule(test))
|
||||
// TODO typedargslist lets through more than is allowed
|
||||
DEF_RULE(typedargslist, nc, list_with_end, rule(typedargslist_item), tok(DEL_COMMA))
|
||||
DEF_RULE(typedargslist_item, nc, or(3), rule(typedargslist_name), rule(typedargslist_star), rule(typedargslist_dbl_star))
|
||||
DEF_RULE(typedargslist_name, nc, and(3), tok(NAME), opt_rule(typedargslist_colon), opt_rule(typedargslist_equal))
|
||||
DEF_RULE(typedargslist_name, nc, ident | and(3), tok(NAME), opt_rule(typedargslist_colon), opt_rule(typedargslist_equal))
|
||||
DEF_RULE(typedargslist_star, nc, and(2), tok(OP_STAR), opt_rule(tfpdef))
|
||||
DEF_RULE(typedargslist_dbl_star, nc, and(3), tok(OP_DBL_STAR), tok(NAME), opt_rule(typedargslist_colon))
|
||||
DEF_RULE(typedargslist_colon, nc, and(2), tok(DEL_COLON), rule(test))
|
||||
DEF_RULE(typedargslist_equal, nc, and(2), tok(DEL_EQUAL), rule(test))
|
||||
DEF_RULE(typedargslist_colon, nc, ident | and(2), tok(DEL_COLON), rule(test))
|
||||
DEF_RULE(typedargslist_equal, nc, ident | and(2), tok(DEL_EQUAL), rule(test))
|
||||
DEF_RULE(tfpdef, nc, and(2), tok(NAME), opt_rule(typedargslist_colon))
|
||||
// TODO varargslist lets through more than is allowed
|
||||
DEF_RULE(varargslist, nc, list_with_end, rule(varargslist_item), tok(DEL_COMMA))
|
||||
@@ -77,7 +77,7 @@ DEF_RULE(varargslist_name, nc, and(2), tok(NAME), opt_rule(varargslist_equal))
|
||||
DEF_RULE(varargslist_star, nc, and(2), tok(OP_STAR), opt_rule(vfpdef))
|
||||
DEF_RULE(varargslist_dbl_star, nc, and(2), tok(OP_DBL_STAR), tok(NAME))
|
||||
DEF_RULE(varargslist_equal, nc, and(2), tok(DEL_EQUAL), rule(test))
|
||||
DEF_RULE(vfpdef, nc, and(1), tok(NAME))
|
||||
DEF_RULE(vfpdef, nc, ident | and(1), tok(NAME))
|
||||
|
||||
// stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | simple_stmt
|
||||
|
||||
@@ -123,7 +123,7 @@ DEF_RULE(return_stmt, c(return_stmt), and(2), tok(KW_RETURN), opt_rule(testlist)
|
||||
DEF_RULE(yield_stmt, c(yield_stmt), and(1), rule(yield_expr))
|
||||
DEF_RULE(raise_stmt, c(raise_stmt), and(2), tok(KW_RAISE), opt_rule(raise_stmt_arg))
|
||||
DEF_RULE(raise_stmt_arg, nc, and(2), rule(test), opt_rule(raise_stmt_from))
|
||||
DEF_RULE(raise_stmt_from, nc, and(2), tok(KW_FROM), rule(test))
|
||||
DEF_RULE(raise_stmt_from, nc, ident | and(2), tok(KW_FROM), rule(test))
|
||||
|
||||
// import_stmt: import_name | import_from
|
||||
// import_name: 'import' dotted_as_names
|
||||
@@ -143,12 +143,12 @@ DEF_RULE(import_from, c(import_from), and(4), tok(KW_FROM), rule(import_from_2),
|
||||
DEF_RULE(import_from_2, nc, or(2), rule(dotted_name), rule(import_from_2b))
|
||||
DEF_RULE(import_from_2b, nc, and(2), rule(one_or_more_period_or_ellipsis), opt_rule(dotted_name))
|
||||
DEF_RULE(import_from_3, nc, or(3), tok(OP_STAR), rule(import_as_names_paren), rule(import_as_names))
|
||||
DEF_RULE(import_as_names_paren, nc, and(3), tok(DEL_PAREN_OPEN), rule(import_as_names), tok(DEL_PAREN_CLOSE))
|
||||
DEF_RULE(import_as_names_paren, nc, ident | and(3), tok(DEL_PAREN_OPEN), rule(import_as_names), tok(DEL_PAREN_CLOSE))
|
||||
DEF_RULE(one_or_more_period_or_ellipsis, nc, one_or_more, rule(period_or_ellipsis))
|
||||
DEF_RULE(period_or_ellipsis, nc, or(2), tok(DEL_PERIOD), tok(ELLIPSIS))
|
||||
DEF_RULE(import_as_name, nc, and(2), tok(NAME), opt_rule(as_name))
|
||||
DEF_RULE(dotted_as_name, nc, and(2), rule(dotted_name), opt_rule(as_name))
|
||||
DEF_RULE(as_name, nc, and(2), tok(KW_AS), tok(NAME))
|
||||
DEF_RULE(as_name, nc, ident | and(2), tok(KW_AS), tok(NAME))
|
||||
DEF_RULE(import_as_names, nc, list_with_end, rule(import_as_name), tok(DEL_COMMA))
|
||||
DEF_RULE(dotted_as_names, nc, list, rule(dotted_as_name), tok(DEL_COMMA))
|
||||
DEF_RULE(dotted_name, nc, list, tok(NAME), tok(DEL_PERIOD))
|
||||
@@ -156,7 +156,7 @@ DEF_RULE(global_stmt, c(global_stmt), and(2), tok(KW_GLOBAL), rule(name_list))
|
||||
DEF_RULE(nonlocal_stmt, c(nonlocal_stmt), and(2), tok(KW_NONLOCAL), rule(name_list))
|
||||
DEF_RULE(name_list, nc, list, tok(NAME), tok(DEL_COMMA))
|
||||
DEF_RULE(assert_stmt, c(assert_stmt), and(3), tok(KW_ASSERT), rule(test), opt_rule(assert_stmt_extra))
|
||||
DEF_RULE(assert_stmt_extra, nc, and(2), tok(DEL_COMMA), rule(test))
|
||||
DEF_RULE(assert_stmt_extra, nc, ident | and(2), tok(DEL_COMMA), rule(test))
|
||||
|
||||
// compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated
|
||||
// if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
|
||||
@@ -182,11 +182,11 @@ DEF_RULE(try_stmt_except, nc, and(4), tok(KW_EXCEPT), opt_rule(try_stmt_as_name)
|
||||
DEF_RULE(try_stmt_as_name, nc, and(2), rule(test), opt_rule(as_name))
|
||||
DEF_RULE(try_stmt_except_list, nc, one_or_more, rule(try_stmt_except))
|
||||
DEF_RULE(try_stmt_finally, nc, and(3), tok(KW_FINALLY), tok(DEL_COLON), rule(suite))
|
||||
DEF_RULE(else_stmt, nc, and(3), tok(KW_ELSE), tok(DEL_COLON), rule(suite))
|
||||
DEF_RULE(else_stmt, nc, ident | and(3), tok(KW_ELSE), tok(DEL_COLON), rule(suite))
|
||||
DEF_RULE(with_stmt, c(with_stmt), and(4), tok(KW_WITH), rule(with_stmt_list), tok(DEL_COLON), rule(suite))
|
||||
DEF_RULE(with_stmt_list, nc, list, rule(with_item), tok(DEL_COMMA))
|
||||
DEF_RULE(with_item, nc, and(2), rule(test), opt_rule(with_item_as))
|
||||
DEF_RULE(with_item_as, nc, and(2), tok(KW_AS), rule(expr))
|
||||
DEF_RULE(with_item_as, nc, ident | and(2), tok(KW_AS), rule(expr))
|
||||
DEF_RULE(suite, nc, or(2), rule(suite_block), rule(simple_stmt))
|
||||
DEF_RULE(suite_block, nc, and(4), tok(NEWLINE), tok(INDENT), rule(suite_block_stmts), tok(DEDENT))
|
||||
DEF_RULE(suite_block_stmts, c(generic_all_nodes), one_or_more, rule(stmt))
|
||||
@@ -200,8 +200,8 @@ DEF_RULE(test, nc, or(2), rule(lambdef), rule(test_if_expr))
|
||||
DEF_RULE(test_if_expr, c(test_if_expr), and(2), rule(or_test), opt_rule(test_if_else))
|
||||
DEF_RULE(test_if_else, nc, and(4), tok(KW_IF), rule(or_test), tok(KW_ELSE), rule(test))
|
||||
DEF_RULE(test_nocond, nc, or(2), rule(lambdef_nocond), rule(or_test))
|
||||
DEF_RULE(lambdef, c(lambdef), and(4), tok(KW_LAMBDA), opt_rule(varargslist), tok(DEL_COLON), rule(test))
|
||||
DEF_RULE(lambdef_nocond, c(lambdef), and(4), tok(KW_LAMBDA), opt_rule(varargslist), tok(DEL_COLON), rule(test_nocond))
|
||||
DEF_RULE(lambdef, c(lambdef), blank | and(4), tok(KW_LAMBDA), opt_rule(varargslist), tok(DEL_COLON), rule(test))
|
||||
DEF_RULE(lambdef_nocond, c(lambdef), blank | and(4), tok(KW_LAMBDA), opt_rule(varargslist), tok(DEL_COLON), rule(test_nocond))
|
||||
|
||||
// or_test: and_test ('or' and_test)*
|
||||
// and_test: not_test ('and' not_test)*
|
||||
@@ -258,7 +258,7 @@ DEF_RULE(atom_brace, c(atom_brace), and(3), tok(DEL_BRACE_OPEN), opt_rule(dictor
|
||||
DEF_RULE(testlist_comp, nc, and(2), rule(testlist_comp_2), opt_rule(testlist_comp_3))
|
||||
DEF_RULE(testlist_comp_2, nc, or(2), rule(star_expr), rule(test))
|
||||
DEF_RULE(testlist_comp_3, nc, or(2), rule(comp_for), rule(testlist_comp_3b))
|
||||
DEF_RULE(testlist_comp_3b, nc, and(2), tok(DEL_COMMA), opt_rule(testlist_comp_3c))
|
||||
DEF_RULE(testlist_comp_3b, nc, ident | and(2), tok(DEL_COMMA), opt_rule(testlist_comp_3c))
|
||||
DEF_RULE(testlist_comp_3c, nc, list_with_end, rule(testlist_comp_2), tok(DEL_COMMA))
|
||||
DEF_RULE(trailer, nc, or(3), rule(trailer_paren), rule(trailer_bracket), rule(trailer_period))
|
||||
DEF_RULE(trailer_paren, c(trailer_paren), and(3), tok(DEL_PAREN_OPEN), opt_rule(arglist), tok(DEL_PAREN_CLOSE))
|
||||
@@ -269,6 +269,7 @@ DEF_RULE(trailer_period, c(trailer_period), and(2), tok(DEL_PERIOD), tok(NAME))
|
||||
// subscript: test | [test] ':' [test] [sliceop]
|
||||
// sliceop: ':' [test]
|
||||
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
DEF_RULE(subscriptlist, c(generic_tuple), list_with_end, rule(subscript), tok(DEL_COMMA))
|
||||
DEF_RULE(subscript, nc, or(2), rule(subscript_3), rule(subscript_2))
|
||||
DEF_RULE(subscript_2, c(subscript_2), and(2), rule(test), opt_rule(subscript_3))
|
||||
@@ -277,6 +278,9 @@ DEF_RULE(subscript_3b, nc, or(2), rule(subscript_3c), rule(subscript_3d))
|
||||
DEF_RULE(subscript_3c, nc, and(2), tok(DEL_COLON), opt_rule(test))
|
||||
DEF_RULE(subscript_3d, nc, and(2), rule(test), opt_rule(sliceop))
|
||||
DEF_RULE(sliceop, nc, and(2), tok(DEL_COLON), opt_rule(test))
|
||||
#else
|
||||
DEF_RULE(subscriptlist, c(generic_tuple), list_with_end, rule(test), tok(DEL_COMMA))
|
||||
#endif
|
||||
|
||||
// exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
|
||||
// testlist: test (',' test)* [',']
|
||||
@@ -287,16 +291,20 @@ DEF_RULE(exprlist_2, nc, or(2), rule(star_expr), rule(expr))
|
||||
DEF_RULE(testlist, c(generic_tuple), list_with_end, rule(test), tok(DEL_COMMA))
|
||||
// TODO dictorsetmaker lets through more than is allowed
|
||||
DEF_RULE(dictorsetmaker, nc, and(2), rule(dictorsetmaker_item), opt_rule(dictorsetmaker_tail))
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
DEF_RULE(dictorsetmaker_item, c(dictorsetmaker_item), and(2), rule(test), opt_rule(dictorsetmaker_colon))
|
||||
DEF_RULE(dictorsetmaker_colon, nc, and(2), tok(DEL_COLON), rule(test))
|
||||
DEF_RULE(dictorsetmaker_colon, nc, ident | and(2), tok(DEL_COLON), rule(test))
|
||||
#else
|
||||
DEF_RULE(dictorsetmaker_item, c(dictorsetmaker_item), and(3), rule(test), tok(DEL_COLON), rule(test))
|
||||
#endif
|
||||
DEF_RULE(dictorsetmaker_tail, nc, or(2), rule(comp_for), rule(dictorsetmaker_list))
|
||||
DEF_RULE(dictorsetmaker_list, nc, and(2), tok(DEL_COMMA), opt_rule(dictorsetmaker_list2))
|
||||
DEF_RULE(dictorsetmaker_list2, nc, list_with_end, rule(dictorsetmaker_item), tok(DEL_COMMA))
|
||||
|
||||
// classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
|
||||
|
||||
DEF_RULE(classdef, c(classdef), and(5), tok(KW_CLASS), tok(NAME), opt_rule(classdef_2), tok(DEL_COLON), rule(suite))
|
||||
DEF_RULE(classdef_2, nc, and(3), tok(DEL_PAREN_OPEN), opt_rule(arglist), tok(DEL_PAREN_CLOSE))
|
||||
DEF_RULE(classdef, c(classdef), blank | and(5), tok(KW_CLASS), tok(NAME), opt_rule(classdef_2), tok(DEL_COLON), rule(suite))
|
||||
DEF_RULE(classdef_2, nc, ident | and(3), tok(DEL_PAREN_OPEN), opt_rule(arglist), tok(DEL_PAREN_CLOSE))
|
||||
|
||||
// arglist: (argument ',')* (argument [','] | '*' test (',' argument)* [',' '**' test] | '**' test)
|
||||
|
||||
@@ -317,7 +325,7 @@ DEF_RULE(argument, nc, and(2), rule(test), opt_rule(argument_2))
|
||||
DEF_RULE(argument_2, nc, or(2), rule(comp_for), rule(argument_3))
|
||||
DEF_RULE(argument_3, nc, and(2), tok(DEL_EQUAL), rule(test))
|
||||
DEF_RULE(comp_iter, nc, or(2), rule(comp_for), rule(comp_if))
|
||||
DEF_RULE(comp_for, nc, and(5), tok(KW_FOR), rule(exprlist), tok(KW_IN), rule(or_test), opt_rule(comp_iter))
|
||||
DEF_RULE(comp_for, nc, blank | and(5), tok(KW_FOR), rule(exprlist), tok(KW_IN), rule(or_test), opt_rule(comp_iter))
|
||||
DEF_RULE(comp_if, nc, and(3), tok(KW_IF), rule(test_nocond), opt_rule(comp_iter))
|
||||
|
||||
// # not used in grammar, but may appear in "node" passed from Parser to Compiler
|
||||
|
||||
155
py/lexer.c
155
py/lexer.c
@@ -42,32 +42,10 @@
|
||||
// TODO seems that CPython allows NULL byte in the input stream
|
||||
// don't know if that's intentional or not, but we don't allow it
|
||||
|
||||
struct _mp_lexer_t {
|
||||
qstr source_name; // name of source
|
||||
void *stream_data; // data for stream
|
||||
mp_lexer_stream_next_byte_t stream_next_byte; // stream callback to get next byte
|
||||
mp_lexer_stream_close_t stream_close; // stream callback to free
|
||||
|
||||
unichar chr0, chr1, chr2; // current cached characters from source
|
||||
|
||||
mp_uint_t line; // source line
|
||||
mp_uint_t column; // source column
|
||||
|
||||
mp_int_t emit_dent; // non-zero when there are INDENT/DEDENT tokens to emit
|
||||
mp_int_t nested_bracket_level; // >0 when there are nested brackets over multiple lines
|
||||
|
||||
mp_uint_t alloc_indent_level;
|
||||
mp_uint_t num_indent_level;
|
||||
uint16_t *indent_level;
|
||||
|
||||
vstr_t vstr;
|
||||
mp_token_t tok_cur;
|
||||
};
|
||||
|
||||
mp_uint_t mp_optimise_value;
|
||||
|
||||
// TODO replace with a call to a standard function
|
||||
bool str_strn_equal(const char *str, const char *strn, mp_uint_t len) {
|
||||
STATIC bool str_strn_equal(const char *str, const char *strn, mp_uint_t len) {
|
||||
mp_uint_t i = 0;
|
||||
|
||||
while (i < len && *str == *strn) {
|
||||
@@ -79,27 +57,6 @@ bool str_strn_equal(const char *str, const char *strn, mp_uint_t len) {
|
||||
return i == len && *str == 0;
|
||||
}
|
||||
|
||||
#ifdef MICROPY_DEBUG_PRINTERS
|
||||
void mp_token_show(const mp_token_t *tok) {
|
||||
printf("(" UINT_FMT ":" UINT_FMT ") kind:%u str:%p len:" UINT_FMT, tok->src_line, tok->src_column, tok->kind, tok->str, tok->len);
|
||||
if (tok->str != NULL && tok->len > 0) {
|
||||
const byte *i = (const byte *)tok->str;
|
||||
const byte *j = (const byte *)i + tok->len;
|
||||
printf(" ");
|
||||
while (i < j) {
|
||||
unichar c = utf8_get_char(i);
|
||||
i = utf8_next_char(i);
|
||||
if (unichar_isprint(c)) {
|
||||
printf("%c", c);
|
||||
} else {
|
||||
printf("?");
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CUR_CHAR(lex) ((lex)->chr0)
|
||||
|
||||
STATIC bool is_end(mp_lexer_t *lex) {
|
||||
@@ -210,7 +167,7 @@ STATIC void next_char(mp_lexer_t *lex) {
|
||||
}
|
||||
}
|
||||
|
||||
void indent_push(mp_lexer_t *lex, mp_uint_t indent) {
|
||||
STATIC void indent_push(mp_lexer_t *lex, mp_uint_t indent) {
|
||||
if (lex->num_indent_level >= lex->alloc_indent_level) {
|
||||
// TODO use m_renew_maybe and somehow indicate an error if it fails... probably by using MP_TOKEN_MEMORY_ERROR
|
||||
lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level, lex->alloc_indent_level + MICROPY_ALLOC_LEXEL_INDENT_INC);
|
||||
@@ -219,11 +176,11 @@ void indent_push(mp_lexer_t *lex, mp_uint_t indent) {
|
||||
lex->indent_level[lex->num_indent_level++] = indent;
|
||||
}
|
||||
|
||||
mp_uint_t indent_top(mp_lexer_t *lex) {
|
||||
STATIC mp_uint_t indent_top(mp_lexer_t *lex) {
|
||||
return lex->indent_level[lex->num_indent_level - 1];
|
||||
}
|
||||
|
||||
void indent_pop(mp_lexer_t *lex) {
|
||||
STATIC void indent_pop(mp_lexer_t *lex) {
|
||||
lex->num_indent_level -= 1;
|
||||
}
|
||||
|
||||
@@ -335,7 +292,10 @@ STATIC bool get_hex(mp_lexer_t *lex, mp_uint_t num_digits, mp_uint_t *result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool first_token) {
|
||||
STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
|
||||
// start new token text
|
||||
vstr_reset(&lex->vstr);
|
||||
|
||||
// skip white space and comments
|
||||
bool had_physical_newline = false;
|
||||
while (!is_end(lex)) {
|
||||
@@ -355,12 +315,9 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
next_char(lex);
|
||||
if (!is_physical_newline(lex)) {
|
||||
// SyntaxError: unexpected character after line continuation character
|
||||
tok->src_line = lex->line;
|
||||
tok->src_column = lex->column;
|
||||
tok->kind = MP_TOKEN_BAD_LINE_CONTINUATION;
|
||||
vstr_reset(&lex->vstr);
|
||||
tok->str = vstr_str(&lex->vstr);
|
||||
tok->len = 0;
|
||||
lex->tok_line = lex->line;
|
||||
lex->tok_column = lex->column;
|
||||
lex->tok_kind = MP_TOKEN_BAD_LINE_CONTINUATION;
|
||||
return;
|
||||
} else {
|
||||
next_char(lex);
|
||||
@@ -371,29 +328,26 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
}
|
||||
|
||||
// set token source information
|
||||
tok->src_line = lex->line;
|
||||
tok->src_column = lex->column;
|
||||
|
||||
// start new token text
|
||||
vstr_reset(&lex->vstr);
|
||||
lex->tok_line = lex->line;
|
||||
lex->tok_column = lex->column;
|
||||
|
||||
if (first_token && lex->line == 1 && lex->column != 1) {
|
||||
// check that the first token is in the first column
|
||||
// if first token is not on first line, we get a physical newline and
|
||||
// this check is done as part of normal indent/dedent checking below
|
||||
// (done to get equivalence with CPython)
|
||||
tok->kind = MP_TOKEN_INDENT;
|
||||
lex->tok_kind = MP_TOKEN_INDENT;
|
||||
|
||||
} else if (lex->emit_dent < 0) {
|
||||
tok->kind = MP_TOKEN_DEDENT;
|
||||
lex->tok_kind = MP_TOKEN_DEDENT;
|
||||
lex->emit_dent += 1;
|
||||
|
||||
} else if (lex->emit_dent > 0) {
|
||||
tok->kind = MP_TOKEN_INDENT;
|
||||
lex->tok_kind = MP_TOKEN_INDENT;
|
||||
lex->emit_dent -= 1;
|
||||
|
||||
} else if (had_physical_newline && lex->nested_bracket_level == 0) {
|
||||
tok->kind = MP_TOKEN_NEWLINE;
|
||||
lex->tok_kind = MP_TOKEN_NEWLINE;
|
||||
|
||||
mp_uint_t num_spaces = lex->column - 1;
|
||||
lex->emit_dent = 0;
|
||||
@@ -407,20 +361,20 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
lex->emit_dent -= 1;
|
||||
}
|
||||
if (num_spaces != indent_top(lex)) {
|
||||
tok->kind = MP_TOKEN_DEDENT_MISMATCH;
|
||||
lex->tok_kind = MP_TOKEN_DEDENT_MISMATCH;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (is_end(lex)) {
|
||||
if (indent_top(lex) > 0) {
|
||||
tok->kind = MP_TOKEN_NEWLINE;
|
||||
lex->tok_kind = MP_TOKEN_NEWLINE;
|
||||
lex->emit_dent = 0;
|
||||
while (indent_top(lex) > 0) {
|
||||
indent_pop(lex);
|
||||
lex->emit_dent -= 1;
|
||||
}
|
||||
} else {
|
||||
tok->kind = MP_TOKEN_END;
|
||||
lex->tok_kind = MP_TOKEN_END;
|
||||
}
|
||||
|
||||
} else if (is_char_or(lex, '\'', '\"')
|
||||
@@ -451,9 +405,9 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
|
||||
// set token kind
|
||||
if (is_bytes) {
|
||||
tok->kind = MP_TOKEN_BYTES;
|
||||
lex->tok_kind = MP_TOKEN_BYTES;
|
||||
} else {
|
||||
tok->kind = MP_TOKEN_STRING;
|
||||
lex->tok_kind = MP_TOKEN_STRING;
|
||||
}
|
||||
|
||||
// get first quoting character
|
||||
@@ -566,14 +520,14 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
|
||||
// check we got the required end quotes
|
||||
if (n_closing < num_quotes) {
|
||||
tok->kind = MP_TOKEN_LONELY_STRING_OPEN;
|
||||
lex->tok_kind = MP_TOKEN_LONELY_STRING_OPEN;
|
||||
}
|
||||
|
||||
// cut off the end quotes from the token text
|
||||
vstr_cut_tail_bytes(&lex->vstr, n_closing);
|
||||
|
||||
} else if (is_head_of_identifier(lex)) {
|
||||
tok->kind = MP_TOKEN_NAME;
|
||||
lex->tok_kind = MP_TOKEN_NAME;
|
||||
|
||||
// get first char
|
||||
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
|
||||
@@ -586,7 +540,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
}
|
||||
|
||||
} else if (is_digit(lex) || (is_char(lex, '.') && is_following_digit(lex))) {
|
||||
tok->kind = MP_TOKEN_NUMBER;
|
||||
lex->tok_kind = MP_TOKEN_NUMBER;
|
||||
|
||||
// get first char
|
||||
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
|
||||
@@ -621,9 +575,9 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
vstr_add_char(&lex->vstr, '.');
|
||||
next_char(lex);
|
||||
next_char(lex);
|
||||
tok->kind = MP_TOKEN_ELLIPSIS;
|
||||
lex->tok_kind = MP_TOKEN_ELLIPSIS;
|
||||
} else {
|
||||
tok->kind = MP_TOKEN_DEL_PERIOD;
|
||||
lex->tok_kind = MP_TOKEN_DEL_PERIOD;
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -645,7 +599,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
|
||||
if (*t == 0) {
|
||||
// didn't match any delimiter or operator characters
|
||||
tok->kind = MP_TOKEN_INVALID;
|
||||
lex->tok_kind = MP_TOKEN_INVALID;
|
||||
|
||||
} else {
|
||||
// matched a delimiter or operator character
|
||||
@@ -670,7 +624,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
next_char(lex);
|
||||
tok_enc_index = t_index;
|
||||
} else {
|
||||
tok->kind = MP_TOKEN_INVALID;
|
||||
lex->tok_kind = MP_TOKEN_INVALID;
|
||||
goto tok_enc_no_match;
|
||||
}
|
||||
break;
|
||||
@@ -692,37 +646,33 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
}
|
||||
|
||||
// set token kind
|
||||
tok->kind = tok_enc_kind[tok_enc_index];
|
||||
lex->tok_kind = tok_enc_kind[tok_enc_index];
|
||||
|
||||
tok_enc_no_match:
|
||||
|
||||
// compute bracket level for implicit line joining
|
||||
if (tok->kind == MP_TOKEN_DEL_PAREN_OPEN || tok->kind == MP_TOKEN_DEL_BRACKET_OPEN || tok->kind == MP_TOKEN_DEL_BRACE_OPEN) {
|
||||
if (lex->tok_kind == MP_TOKEN_DEL_PAREN_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACKET_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACE_OPEN) {
|
||||
lex->nested_bracket_level += 1;
|
||||
} else if (tok->kind == MP_TOKEN_DEL_PAREN_CLOSE || tok->kind == MP_TOKEN_DEL_BRACKET_CLOSE || tok->kind == MP_TOKEN_DEL_BRACE_CLOSE) {
|
||||
} else if (lex->tok_kind == MP_TOKEN_DEL_PAREN_CLOSE || lex->tok_kind == MP_TOKEN_DEL_BRACKET_CLOSE || lex->tok_kind == MP_TOKEN_DEL_BRACE_CLOSE) {
|
||||
lex->nested_bracket_level -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// point token text to vstr buffer
|
||||
tok->str = vstr_str(&lex->vstr);
|
||||
tok->len = vstr_len(&lex->vstr);
|
||||
|
||||
// check for keywords
|
||||
if (tok->kind == MP_TOKEN_NAME) {
|
||||
if (lex->tok_kind == MP_TOKEN_NAME) {
|
||||
// We check for __debug__ here and convert it to its value. This is so
|
||||
// the parser gives a syntax error on, eg, x.__debug__. Otherwise, we
|
||||
// need to check for this special token in many places in the compiler.
|
||||
// TODO improve speed of these string comparisons
|
||||
//for (mp_int_t i = 0; tok_kw[i] != NULL; i++) {
|
||||
for (mp_int_t i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) {
|
||||
if (str_strn_equal(tok_kw[i], tok->str, tok->len)) {
|
||||
if (str_strn_equal(tok_kw[i], lex->vstr.buf, lex->vstr.len)) {
|
||||
if (i == MP_ARRAY_SIZE(tok_kw) - 1) {
|
||||
// tok_kw[MP_ARRAY_SIZE(tok_kw) - 1] == "__debug__"
|
||||
tok->kind = (mp_optimise_value == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE);
|
||||
lex->tok_kind = (mp_optimise_value == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE);
|
||||
} else {
|
||||
tok->kind = MP_TOKEN_KW_FALSE + i;
|
||||
lex->tok_kind = MP_TOKEN_KW_FALSE + i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -782,7 +732,7 @@ mp_lexer_t *mp_lexer_new(qstr src_name, void *stream_data, mp_lexer_stream_next_
|
||||
}
|
||||
|
||||
// preload first token
|
||||
mp_lexer_next_token_into(lex, &lex->tok_cur, true);
|
||||
mp_lexer_next_token_into(lex, true);
|
||||
|
||||
return lex;
|
||||
}
|
||||
@@ -798,18 +748,27 @@ void mp_lexer_free(mp_lexer_t *lex) {
|
||||
}
|
||||
}
|
||||
|
||||
qstr mp_lexer_source_name(mp_lexer_t *lex) {
|
||||
return lex->source_name;
|
||||
}
|
||||
|
||||
void mp_lexer_to_next(mp_lexer_t *lex) {
|
||||
mp_lexer_next_token_into(lex, &lex->tok_cur, false);
|
||||
mp_lexer_next_token_into(lex, false);
|
||||
}
|
||||
|
||||
const mp_token_t *mp_lexer_cur(const mp_lexer_t *lex) {
|
||||
return &lex->tok_cur;
|
||||
}
|
||||
|
||||
bool mp_lexer_is_kind(mp_lexer_t *lex, mp_token_kind_t kind) {
|
||||
return lex->tok_cur.kind == kind;
|
||||
#if MICROPY_DEBUG_PRINTERS
|
||||
void mp_lexer_show_token(const mp_lexer_t *lex) {
|
||||
printf("(" UINT_FMT ":" UINT_FMT ") kind:%u str:%p len:%zu", lex->tok_line, lex->tok_column, lex->tok_kind, lex->vstr.buf, lex->vstr.len);
|
||||
if (lex->vstr.len > 0) {
|
||||
const byte *i = (const byte *)lex->vstr.buf;
|
||||
const byte *j = (const byte *)i + lex->vstr.len;
|
||||
printf(" ");
|
||||
while (i < j) {
|
||||
unichar c = utf8_get_char(i);
|
||||
i = utf8_next_char(i);
|
||||
if (unichar_isprint(c)) {
|
||||
printf("%c", c);
|
||||
} else {
|
||||
printf("?");
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
46
py/lexer.h
46
py/lexer.h
@@ -23,6 +23,8 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __MICROPY_INCLUDED_PY_LEXER_H__
|
||||
#define __MICROPY_INCLUDED_PY_LEXER_H__
|
||||
|
||||
/* lexer.h -- simple tokeniser for Micro Python
|
||||
*
|
||||
@@ -130,15 +132,6 @@ typedef enum _mp_token_kind_t {
|
||||
MP_TOKEN_DEL_MINUS_MORE,
|
||||
} mp_token_kind_t;
|
||||
|
||||
typedef struct _mp_token_t {
|
||||
mp_uint_t src_line; // source line
|
||||
mp_uint_t src_column; // source column
|
||||
|
||||
mp_token_kind_t kind; // kind of token
|
||||
const char *str; // string of token (valid only while this token is current token)
|
||||
mp_uint_t len; // (byte) length of string of token
|
||||
} mp_token_t;
|
||||
|
||||
// the next-byte function must return the next byte in the stream
|
||||
// it must return MP_LEXER_EOF if end of stream
|
||||
// it can be called again after returning MP_LEXER_EOF, and in that case must return MP_LEXER_EOF
|
||||
@@ -146,21 +139,38 @@ typedef struct _mp_token_t {
|
||||
typedef mp_uint_t (*mp_lexer_stream_next_byte_t)(void*);
|
||||
typedef void (*mp_lexer_stream_close_t)(void*);
|
||||
|
||||
typedef struct _mp_lexer_t mp_lexer_t;
|
||||
// this data structure is exposed for efficiency
|
||||
// public members are: source_name, tok_line, tok_column, tok_kind, vstr
|
||||
typedef struct _mp_lexer_t {
|
||||
qstr source_name; // name of source
|
||||
void *stream_data; // data for stream
|
||||
mp_lexer_stream_next_byte_t stream_next_byte; // stream callback to get next byte
|
||||
mp_lexer_stream_close_t stream_close; // stream callback to free
|
||||
|
||||
void mp_token_show(const mp_token_t *tok);
|
||||
unichar chr0, chr1, chr2; // current cached characters from source
|
||||
|
||||
mp_uint_t line; // current source line
|
||||
mp_uint_t column; // current source column
|
||||
|
||||
mp_int_t emit_dent; // non-zero when there are INDENT/DEDENT tokens to emit
|
||||
mp_int_t nested_bracket_level; // >0 when there are nested brackets over multiple lines
|
||||
|
||||
mp_uint_t alloc_indent_level;
|
||||
mp_uint_t num_indent_level;
|
||||
uint16_t *indent_level;
|
||||
|
||||
mp_uint_t tok_line; // token source line
|
||||
mp_uint_t tok_column; // token source column
|
||||
mp_token_kind_t tok_kind; // token kind
|
||||
vstr_t vstr; // token data
|
||||
} mp_lexer_t;
|
||||
|
||||
mp_lexer_t *mp_lexer_new(qstr src_name, void *stream_data, mp_lexer_stream_next_byte_t stream_next_byte, mp_lexer_stream_close_t stream_close);
|
||||
mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len);
|
||||
|
||||
void mp_lexer_free(mp_lexer_t *lex);
|
||||
qstr mp_lexer_source_name(mp_lexer_t *lex);
|
||||
void mp_lexer_to_next(mp_lexer_t *lex);
|
||||
const mp_token_t *mp_lexer_cur(const mp_lexer_t *lex);
|
||||
bool mp_lexer_is_kind(mp_lexer_t *lex, mp_token_kind_t kind);
|
||||
|
||||
bool mp_lexer_show_error_pythonic_prefix(mp_lexer_t *lex);
|
||||
bool mp_lexer_show_error_pythonic(mp_lexer_t *lex, const char *msg);
|
||||
void mp_lexer_show_token(const mp_lexer_t *lex);
|
||||
|
||||
/******************************************************************/
|
||||
// platform specific import function; must be implemented for a specific port
|
||||
@@ -178,3 +188,5 @@ mp_import_stat_t mp_import_stat(const char *path);
|
||||
mp_lexer_t *mp_lexer_new_from_file(const char *filename);
|
||||
|
||||
extern mp_uint_t mp_optimise_value;
|
||||
|
||||
#endif // __MICROPY_INCLUDED_PY_LEXER_H__
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#if MICROPY_HELPER_LEXER_UNIX
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
4
py/map.c
4
py/map.c
@@ -253,6 +253,8 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
|
||||
/******************************************************************************/
|
||||
/* set */
|
||||
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
|
||||
void mp_set_init(mp_set_t *set, mp_uint_t n) {
|
||||
set->alloc = n;
|
||||
set->used = 0;
|
||||
@@ -368,6 +370,8 @@ void mp_set_clear(mp_set_t *set) {
|
||||
set->table = NULL;
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_BUILTINS_SET
|
||||
|
||||
#if defined(DEBUG_PRINT) && DEBUG_PRINT
|
||||
void mp_map_dump(mp_map_t *map) {
|
||||
for (mp_uint_t i = 0; i < map->alloc; i++) {
|
||||
|
||||
@@ -37,16 +37,7 @@ STATIC const mp_map_elem_t mp_module_array_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_array), (mp_obj_t)&mp_type_array },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_array_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_array_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_array_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_array_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_array_globals, mp_module_array_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_array = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
@@ -561,3 +561,134 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_obj_id);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_len_obj, mp_obj_len);
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_globals_obj, mp_globals_get);
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_locals_obj, mp_locals_get);
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_builtins_globals_table[] = {
|
||||
// built-in core functions
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___build_class__), (mp_obj_t)&mp_builtin___build_class___obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___import__), (mp_obj_t)&mp_builtin___import___obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___repl_print__), (mp_obj_t)&mp_builtin___repl_print___obj },
|
||||
|
||||
// built-in types
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bool), (mp_obj_t)&mp_type_bool },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytes), (mp_obj_t)&mp_type_bytes },
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytearray), (mp_obj_t)&mp_type_bytearray },
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_complex), (mp_obj_t)&mp_type_complex },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&mp_type_dict },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_enumerate), (mp_obj_t)&mp_type_enumerate },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_filter), (mp_obj_t)&mp_type_filter },
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_float), (mp_obj_t)&mp_type_float },
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_SET && MICROPY_PY_BUILTINS_FROZENSET
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_frozenset), (mp_obj_t)&mp_type_frozenset },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_int), (mp_obj_t)&mp_type_int },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_list), (mp_obj_t)&mp_type_list },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_map), (mp_obj_t)&mp_type_map },
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_memoryview), (mp_obj_t)&mp_type_memoryview },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_object), (mp_obj_t)&mp_type_object },
|
||||
#if MICROPY_PY_BUILTINS_PROPERTY
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_property), (mp_obj_t)&mp_type_property },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_range), (mp_obj_t)&mp_type_range },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_reversed), (mp_obj_t)&mp_type_reversed },
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_set), (mp_obj_t)&mp_type_set },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_str), (mp_obj_t)&mp_type_str },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_super), (mp_obj_t)&mp_type_super },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_tuple), (mp_obj_t)&mp_type_tuple },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_type), (mp_obj_t)&mp_type_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_zip), (mp_obj_t)&mp_type_zip },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_classmethod), (mp_obj_t)&mp_type_classmethod },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_staticmethod), (mp_obj_t)&mp_type_staticmethod },
|
||||
|
||||
// built-in objects
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_Ellipsis), (mp_obj_t)&mp_const_ellipsis_obj },
|
||||
|
||||
// built-in user functions
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_abs), (mp_obj_t)&mp_builtin_abs_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_all), (mp_obj_t)&mp_builtin_all_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&mp_builtin_any_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bin), (mp_obj_t)&mp_builtin_bin_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_callable), (mp_obj_t)&mp_builtin_callable_obj },
|
||||
#if MICROPY_PY_BUILTINS_COMPILE
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_compile), (mp_obj_t)&mp_builtin_compile_obj },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_chr), (mp_obj_t)&mp_builtin_chr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_dir), (mp_obj_t)&mp_builtin_dir_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_divmod), (mp_obj_t)&mp_builtin_divmod_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_eval), (mp_obj_t)&mp_builtin_eval_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_exec), (mp_obj_t)&mp_builtin_exec_obj },
|
||||
#if MICROPY_PY_BUILTINS_EXECFILE
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_execfile), (mp_obj_t)&mp_builtin_execfile_obj },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_getattr), (mp_obj_t)&mp_builtin_getattr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_globals), (mp_obj_t)&mp_builtin_globals_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_hasattr), (mp_obj_t)&mp_builtin_hasattr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_hash), (mp_obj_t)&mp_builtin_hash_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_hex), (mp_obj_t)&mp_builtin_hex_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_id), (mp_obj_t)&mp_builtin_id_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_isinstance), (mp_obj_t)&mp_builtin_isinstance_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_issubclass), (mp_obj_t)&mp_builtin_issubclass_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_iter), (mp_obj_t)&mp_builtin_iter_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_len), (mp_obj_t)&mp_builtin_len_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_locals), (mp_obj_t)&mp_builtin_locals_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_max), (mp_obj_t)&mp_builtin_max_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_min), (mp_obj_t)&mp_builtin_min_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_next), (mp_obj_t)&mp_builtin_next_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_oct), (mp_obj_t)&mp_builtin_oct_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ord), (mp_obj_t)&mp_builtin_ord_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_pow), (mp_obj_t)&mp_builtin_pow_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_print), (mp_obj_t)&mp_builtin_print_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_repr), (mp_obj_t)&mp_builtin_repr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_round), (mp_obj_t)&mp_builtin_round_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sorted), (mp_obj_t)&mp_builtin_sorted_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sum), (mp_obj_t)&mp_builtin_sum_obj },
|
||||
|
||||
// built-in exceptions
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BaseException), (mp_obj_t)&mp_type_BaseException },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ArithmeticError), (mp_obj_t)&mp_type_ArithmeticError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_AssertionError), (mp_obj_t)&mp_type_AssertionError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_AttributeError), (mp_obj_t)&mp_type_AttributeError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_EOFError), (mp_obj_t)&mp_type_EOFError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_Exception), (mp_obj_t)&mp_type_Exception },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GeneratorExit), (mp_obj_t)&mp_type_GeneratorExit },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ImportError), (mp_obj_t)&mp_type_ImportError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IndentationError), (mp_obj_t)&mp_type_IndentationError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IndexError), (mp_obj_t)&mp_type_IndexError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_KeyError), (mp_obj_t)&mp_type_KeyError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_LookupError), (mp_obj_t)&mp_type_LookupError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MemoryError), (mp_obj_t)&mp_type_MemoryError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_NameError), (mp_obj_t)&mp_type_NameError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_NotImplementedError), (mp_obj_t)&mp_type_NotImplementedError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_OSError), (mp_obj_t)&mp_type_OSError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_OverflowError), (mp_obj_t)&mp_type_OverflowError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_RuntimeError), (mp_obj_t)&mp_type_RuntimeError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_StopIteration), (mp_obj_t)&mp_type_StopIteration },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SyntaxError), (mp_obj_t)&mp_type_SyntaxError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SystemExit), (mp_obj_t)&mp_type_SystemExit },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_TypeError), (mp_obj_t)&mp_type_TypeError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ValueError), (mp_obj_t)&mp_type_ValueError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ZeroDivisionError), (mp_obj_t)&mp_type_ZeroDivisionError },
|
||||
// Somehow CPython managed to have OverflowError not inherit from ValueError ;-/
|
||||
// TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation
|
||||
|
||||
// Extra builtins as defined by a port
|
||||
MICROPY_PORT_BUILTINS
|
||||
};
|
||||
|
||||
MP_DEFINE_CONST_DICT(mp_module_builtins_globals, mp_module_builtins_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_builtins = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_builtins,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_builtins_globals,
|
||||
};
|
||||
@@ -47,7 +47,7 @@ extern const mp_obj_float_t mp_math_pi_obj;
|
||||
|
||||
/// \function phase(z)
|
||||
/// Returns the phase of the number `z`, in the range (-pi, +pi].
|
||||
mp_obj_t mp_cmath_phase(mp_obj_t z_obj) {
|
||||
STATIC mp_obj_t mp_cmath_phase(mp_obj_t z_obj) {
|
||||
mp_float_t real, imag;
|
||||
mp_obj_get_complex(z_obj, &real, &imag);
|
||||
return mp_obj_new_float(MICROPY_FLOAT_C_FUN(atan2)(imag, real));
|
||||
@@ -56,7 +56,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_phase_obj, mp_cmath_phase);
|
||||
|
||||
/// \function polar(z)
|
||||
/// Returns, as a tuple, the polar form of `z`.
|
||||
mp_obj_t mp_cmath_polar(mp_obj_t z_obj) {
|
||||
STATIC mp_obj_t mp_cmath_polar(mp_obj_t z_obj) {
|
||||
mp_float_t real, imag;
|
||||
mp_obj_get_complex(z_obj, &real, &imag);
|
||||
mp_obj_t tuple[2] = {
|
||||
@@ -69,7 +69,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_polar_obj, mp_cmath_polar);
|
||||
|
||||
/// \function rect(r, phi)
|
||||
/// Returns the complex number with modulus `r` and phase `phi`.
|
||||
mp_obj_t mp_cmath_rect(mp_obj_t r_obj, mp_obj_t phi_obj) {
|
||||
STATIC mp_obj_t mp_cmath_rect(mp_obj_t r_obj, mp_obj_t phi_obj) {
|
||||
mp_float_t r = mp_obj_get_float(r_obj);
|
||||
mp_float_t phi = mp_obj_get_float(phi_obj);
|
||||
return mp_obj_new_complex(r * MICROPY_FLOAT_C_FUN(cos)(phi), r * MICROPY_FLOAT_C_FUN(sin)(phi));
|
||||
@@ -78,7 +78,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_cmath_rect_obj, mp_cmath_rect);
|
||||
|
||||
/// \function exp(z)
|
||||
/// Return the exponential of `z`.
|
||||
mp_obj_t mp_cmath_exp(mp_obj_t z_obj) {
|
||||
STATIC mp_obj_t mp_cmath_exp(mp_obj_t z_obj) {
|
||||
mp_float_t real, imag;
|
||||
mp_obj_get_complex(z_obj, &real, &imag);
|
||||
mp_float_t exp_real = MICROPY_FLOAT_C_FUN(exp)(real);
|
||||
@@ -89,7 +89,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_exp_obj, mp_cmath_exp);
|
||||
/// \function log(z)
|
||||
/// Return the natural logarithm of `z`. The branch cut is along the negative real axis.
|
||||
// TODO can take second argument, being the base
|
||||
mp_obj_t mp_cmath_log(mp_obj_t z_obj) {
|
||||
STATIC mp_obj_t mp_cmath_log(mp_obj_t z_obj) {
|
||||
mp_float_t real, imag;
|
||||
mp_obj_get_complex(z_obj, &real, &imag);
|
||||
return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log)(real*real + imag*imag), MICROPY_FLOAT_C_FUN(atan2)(imag, real));
|
||||
@@ -98,7 +98,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log_obj, mp_cmath_log);
|
||||
|
||||
/// \function log10(z)
|
||||
/// Return the base-10 logarithm of `z`. The branch cut is along the negative real axis.
|
||||
mp_obj_t mp_cmath_log10(mp_obj_t z_obj) {
|
||||
STATIC mp_obj_t mp_cmath_log10(mp_obj_t z_obj) {
|
||||
mp_float_t real, imag;
|
||||
mp_obj_get_complex(z_obj, &real, &imag);
|
||||
return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log10)(real*real + imag*imag), MICROPY_FLOAT_C_FUN(atan2)(imag, real));
|
||||
@@ -107,7 +107,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log10_obj, mp_cmath_log10);
|
||||
|
||||
/// \function sqrt(z)
|
||||
/// Return the square-root of `z`.
|
||||
mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) {
|
||||
STATIC mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) {
|
||||
mp_float_t real, imag;
|
||||
mp_obj_get_complex(z_obj, &real, &imag);
|
||||
mp_float_t sqrt_abs = MICROPY_FLOAT_C_FUN(pow)(real*real + imag*imag, 0.25);
|
||||
@@ -118,7 +118,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sqrt_obj, mp_cmath_sqrt);
|
||||
|
||||
/// \function cos(z)
|
||||
/// Return the cosine of `z`.
|
||||
mp_obj_t mp_cmath_cos(mp_obj_t z_obj) {
|
||||
STATIC mp_obj_t mp_cmath_cos(mp_obj_t z_obj) {
|
||||
mp_float_t real, imag;
|
||||
mp_obj_get_complex(z_obj, &real, &imag);
|
||||
return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), -MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag));
|
||||
@@ -127,7 +127,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_cos_obj, mp_cmath_cos);
|
||||
|
||||
/// \function sin(z)
|
||||
/// Return the sine of `z`.
|
||||
mp_obj_t mp_cmath_sin(mp_obj_t z_obj) {
|
||||
STATIC mp_obj_t mp_cmath_sin(mp_obj_t z_obj) {
|
||||
mp_float_t real, imag;
|
||||
mp_obj_get_complex(z_obj, &real, &imag);
|
||||
return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag));
|
||||
@@ -162,16 +162,7 @@ STATIC const mp_map_elem_t mp_module_cmath_globals_table[] = {
|
||||
//{ MP_OBJ_NEW_QSTR(MP_QSTR_isnan), (mp_obj_t)&mp_cmath_isnan_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_cmath_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_cmath_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_cmath_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_cmath_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_cmath_globals, mp_module_cmath_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_cmath = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
@@ -37,16 +37,7 @@ STATIC const mp_map_elem_t mp_module_collections_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_namedtuple), (mp_obj_t)&mp_namedtuple_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_collections_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_collections_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_collections_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_collections_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_collections_globals, mp_module_collections_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_collections = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
11
py/modgc.c
11
py/modgc.c
@@ -100,16 +100,7 @@ STATIC const mp_map_elem_t mp_module_gc_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_alloc), (mp_obj_t)&gc_mem_alloc_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_gc_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_gc_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_gc_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_gc_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_gc_globals, mp_module_gc_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_gc = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
11
py/modio.c
11
py/modio.c
@@ -52,16 +52,7 @@ STATIC const mp_map_elem_t mp_module_io_globals_table[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_io_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_io_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_io_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_io_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_io_globals, mp_module_io_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_io = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
27
py/modmath.c
27
py/modmath.c
@@ -41,19 +41,19 @@
|
||||
|
||||
//TODO: Change macros to check for overflow and raise OverflowError or RangeError
|
||||
#define MATH_FUN_1(py_name, c_name) \
|
||||
mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
|
||||
STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
|
||||
|
||||
#define MATH_FUN_2(py_name, c_name) \
|
||||
mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_float(y_obj))); } \
|
||||
STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_float(y_obj))); } \
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name);
|
||||
|
||||
#define MATH_FUN_1_TO_BOOL(py_name, c_name) \
|
||||
mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return MP_BOOL(c_name(mp_obj_get_float(x_obj))); } \
|
||||
STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return MP_BOOL(c_name(mp_obj_get_float(x_obj))); } \
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
|
||||
|
||||
#define MATH_FUN_1_TO_INT(py_name, c_name) \
|
||||
mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_int((mp_int_t)MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
|
||||
STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { mp_int_t x = MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj)); return mp_obj_new_int(x); } \
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
|
||||
|
||||
// These are also used by cmath.c
|
||||
@@ -142,7 +142,7 @@ MATH_FUN_1(lgamma, lgamma)
|
||||
|
||||
/// \function frexp(x)
|
||||
/// Converts a floating-point number to fractional and integral components.
|
||||
mp_obj_t mp_math_frexp(mp_obj_t x_obj) {
|
||||
STATIC mp_obj_t mp_math_frexp(mp_obj_t x_obj) {
|
||||
int int_exponent = 0;
|
||||
mp_float_t significand = MICROPY_FLOAT_C_FUN(frexp)(mp_obj_get_float(x_obj), &int_exponent);
|
||||
mp_obj_t tuple[2];
|
||||
@@ -153,7 +153,7 @@ mp_obj_t mp_math_frexp(mp_obj_t x_obj) {
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_frexp_obj, mp_math_frexp);
|
||||
|
||||
/// \function modf(x)
|
||||
mp_obj_t mp_math_modf(mp_obj_t x_obj) {
|
||||
STATIC mp_obj_t mp_math_modf(mp_obj_t x_obj) {
|
||||
mp_float_t int_part = 0.0;
|
||||
mp_float_t fractional_part = MICROPY_FLOAT_C_FUN(modf)(mp_obj_get_float(x_obj), &int_part);
|
||||
mp_obj_t tuple[2];
|
||||
@@ -166,13 +166,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_modf_obj, mp_math_modf);
|
||||
// Angular conversions
|
||||
|
||||
/// \function radians(x)
|
||||
mp_obj_t mp_math_radians(mp_obj_t x_obj) {
|
||||
STATIC mp_obj_t mp_math_radians(mp_obj_t x_obj) {
|
||||
return mp_obj_new_float(mp_obj_get_float(x_obj) * M_PI / 180.0);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_radians_obj, mp_math_radians);
|
||||
|
||||
/// \function degrees(x)
|
||||
mp_obj_t mp_math_degrees(mp_obj_t x_obj) {
|
||||
STATIC mp_obj_t mp_math_degrees(mp_obj_t x_obj) {
|
||||
return mp_obj_new_float(mp_obj_get_float(x_obj) * 180.0 / M_PI);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_degrees_obj, mp_math_degrees);
|
||||
@@ -221,16 +221,7 @@ STATIC const mp_map_elem_t mp_module_math_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_lgamma), (mp_obj_t)&mp_math_lgamma_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_math_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_math_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_math_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_math_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_math_globals, mp_module_math_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_math = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
@@ -24,11 +24,15 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
#include "stackctrl.h"
|
||||
#include "gc.h"
|
||||
|
||||
// Various builtins specific to MicroPython runtime,
|
||||
// living in micropython module
|
||||
@@ -37,18 +41,41 @@
|
||||
STATIC mp_obj_t mp_micropython_mem_total() {
|
||||
return MP_OBJ_NEW_SMALL_INT(m_get_total_bytes_allocated());
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_total_obj, mp_micropython_mem_total);
|
||||
|
||||
STATIC mp_obj_t mp_micropython_mem_current() {
|
||||
return MP_OBJ_NEW_SMALL_INT(m_get_current_bytes_allocated());
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_current_obj, mp_micropython_mem_current);
|
||||
|
||||
STATIC mp_obj_t mp_micropython_mem_peak() {
|
||||
return MP_OBJ_NEW_SMALL_INT(m_get_peak_bytes_allocated());
|
||||
}
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_total_obj, mp_micropython_mem_total);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_current_obj, mp_micropython_mem_current);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_peak_obj, mp_micropython_mem_peak);
|
||||
|
||||
mp_obj_t mp_micropython_mem_info(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
printf("mem: total=" UINT_FMT ", current=" UINT_FMT ", peak=" UINT_FMT "\n",
|
||||
m_get_total_bytes_allocated(), m_get_current_bytes_allocated(), m_get_peak_bytes_allocated());
|
||||
printf("stack: " UINT_FMT "\n", mp_stack_usage());
|
||||
#if MICROPY_ENABLE_GC
|
||||
gc_dump_info();
|
||||
if (n_args == 1) {
|
||||
// arg given means dump gc allocation table
|
||||
gc_dump_alloc_table();
|
||||
}
|
||||
#endif
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_mem_info_obj, 0, 1, mp_micropython_mem_info);
|
||||
|
||||
STATIC mp_obj_t qstr_info(void) {
|
||||
mp_uint_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
|
||||
qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
|
||||
printf("qstr pool: n_pool=" UINT_FMT ", n_qstr=" UINT_FMT ", n_str_data_bytes=" UINT_FMT ", n_total_bytes=" UINT_FMT "\n",
|
||||
n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_qstr_info_obj, qstr_info);
|
||||
#endif
|
||||
|
||||
#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && (MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0)
|
||||
@@ -61,22 +88,15 @@ STATIC const mp_map_elem_t mp_module_micropython_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_total), (mp_obj_t)&mp_micropython_mem_total_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_current), (mp_obj_t)&mp_micropython_mem_current_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_peak), (mp_obj_t)&mp_micropython_mem_peak_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_info), (mp_obj_t)&mp_micropython_mem_info_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_qstr_info), (mp_obj_t)&mp_micropython_qstr_info_obj },
|
||||
#endif
|
||||
#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && (MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0)
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_alloc_emergency_exception_buf), (mp_obj_t)&mp_alloc_emergency_exception_buf_obj },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_micropython_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_micropython_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_micropython_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_micropython_globals_table,
|
||||
},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_micropython_globals, mp_module_micropython_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_micropython = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user