Compare commits

..

111 Commits

Author SHA1 Message Date
Paul Sokolovsky
361909e3ca py: Add MP_LIKELY(), MP_UNLIKELY() macros to help branch prediction. 2014-12-29 00:51:24 +02:00
Paul Sokolovsky
1ee1785bed showbc: Print operation mnemonic in BINARY_OP. 2014-12-28 21:43:44 +02:00
Paul Sokolovsky
df103462dc showbc: Make code object start pointer semi-public.
This allows to pring either absolute addresses or relative offsets in jumps
and code references.
2014-12-28 21:37:17 +02:00
Paul Sokolovsky
749575097f vm: Record exception ip only for instructions where exceptions may happen.
Mirroring ip to a volatile memory variable for each opcode is an expensive
operation. For quite a lot of often executed opcodes like stack manipulation
or jumps, exceptions cannot actually happen. So, record ip only for opcode
where that's possible.
2014-12-28 07:37:04 +02:00
Damien George
1570eaf0e3 drivers: Add SD card driver, controlled via SPI bus. 2014-12-27 20:23:14 +00:00
Damien George
7690b13953 stmhal: Add ability to mount custom block device. 2014-12-27 20:20:51 +00:00
Damien George
e2745b307b lib/fatfs: Allow a smaller minimum sector count for fatfs to be created. 2014-12-27 20:20:08 +00:00
Damien George
20236a8a99 stmhal: Upgrade to latest fatfs driver. 2014-12-27 17:36:16 +00:00
Damien George
6b755d827a lib/fatfs: Support our volume names; make some funcs static. 2014-12-27 17:36:16 +00:00
Damien George
c546b66bab lib/fatfs: Upgrade to new FatFs driver, put in lib/ for common use.
Patches to fatfs for our use will follow.
2014-12-27 17:36:16 +00:00
Damien George
83204f3406 py: Allow to properly disable builtin slice operation.
This patch makes the MICROPY_PY_BUILTINS_SLICE compile-time option
fully disable the builtin slice operation (when set to 0).  This
includes removing the slice sytanx from the grammar.  Now, enabling
slice costs 4228 bytes on unix x64, and 1816 bytes on stmhal.
2014-12-27 17:33:30 +00:00
Damien George
e37dcaafb4 py: Allow to properly disable builtin "set" object.
This patch makes MICROPY_PY_BUILTINS_SET compile-time option fully
disable the builtin set object (when set to 0).  This includes removing
set constructor/comprehension from the grammar, the compiler and the
emitters.  Now, enabling set costs 8168 bytes on unix x64, and 3576
bytes on stmhal.
2014-12-27 17:33:30 +00:00
Paul Sokolovsky
3b74c91684 Makefiles: Support py/*.h includes per #1022. 2014-12-27 16:32:52 +02:00
Paul Sokolovsky
8ab6f90674 py: Move to guarded includes for compile.h and related headers. 2014-12-27 16:12:17 +02:00
Paul Sokolovsky
343266ea51 showbc: Refactor to allow inline instruction printing. 2014-12-27 05:01:21 +02:00
Damien George
c55a4d82cf py: Make bytes objs work with more str methods; add tests. 2014-12-24 20:28:30 +00:00
Paul Sokolovsky
7fdb8d78a4 tests: Add run-tests-exp.py, simple MicroPython-based test runner.
This script is rewrite of run-tests-exp.sh, and tries to achieve self-hosted
testsuite running in environments where neither CPython nor unix shell is
available. As run-tests-exp.sh, it requires complete set of .exp files
pre-generated with ./run-test --write-exp.
2014-12-24 16:34:05 +00:00
Damien George
f3a1d673de stmhal: Enable ubinascii module, weak link to binascii. 2014-12-24 16:24:42 +00:00
Dave Hylands
90cd6cd987 docs: Add mention about using USB charger when resetting the filesystem.
It seems the Mac will happily wipe out at least some of the data on
a freshly reset filesytem, if the filesystem was reset while plugged
into the Mac.
2014-12-23 13:22:32 +00:00
Paul Sokolovsky
9c658b6afc unix, windows: Add _os.system() call.
system() is the basic function to support automation of tasks, so have it
available builtin, for example, for bootstrapping rest of micropython
environment.
2014-12-23 12:56:24 +00:00
Damien George
a37656c132 docs: Make admonition for CPy-difference use "attention" class.
This renders it in yellow/orange box on RTD server.
2014-12-22 13:42:30 +00:00
Damien George
74eb44c392 py: Reduce size of VM exception stack element by 1 machine word.
This optimisation reduces the VM exception stack element (mp_exc_stack_t)
by 1 word, by using bit 1 of a pointer to store whether the opcode was a
FINALLY or WITH opcode.  This optimisation was pending, waiting for
maturity of the exception handling code, which has now proven itself.

Saves 1 machine word RAM for each exception (4->3 words per exception).
Increases stmhal code by 4 bytes, and decreases unix x64 code by 32
bytes.
2014-12-22 12:49:57 +00:00
Damien George
81836c28b3 py: Use str_to_int function in more places to reduce code size. 2014-12-21 21:07:03 +00:00
Damien George
01039b5bd8 py: Remove last uses of printf from compile; use proper SyntaxError. 2014-12-21 17:44:27 +00:00
Damien George
584ba6762f py: Move global/nonlocal decl code to compiler for proper SyntaxError.
This patch gives proper SyntaxError exceptions for bad global/nonlocal
declarations.  It also reduces code size: 304 bytes on unix x64, 132
bytes on stmhal.
2014-12-21 17:26:45 +00:00
Damien George
b063b9b36d py: Fix iteration over map in 2 places. 2014-12-21 16:24:09 +00:00
Damien George
7b80d908bf docs: Add RTD local_settings file, to add custom templates. 2014-12-21 11:21:06 +00:00
Damien George
9b561a7c0d docs: Add custom CSS file, with code for admonition. 2014-12-21 00:22:49 +00:00
Paul Sokolovsky
4b60b45bfc stmhal: gccollect.h is superfluous in many places. 2014-12-21 00:58:06 +02:00
Paul Sokolovsky
6aaccc484c stmhal: Use gc_dump_info() function instead of adhoc code. 2014-12-21 00:26:10 +02:00
Paul Sokolovsky
bf19586c53 stmhal: Include MICROPY_HAL_H only if defined.
Helps other ports.
2014-12-20 20:47:35 +02:00
Damien George
6efa66f125 py: Remove unnecessary RULE_none and PN_none from parser. 2014-12-20 18:41:59 +00:00
Damien George
b47ea4eadd py: Add blank and ident flags to grammar rules to simplify parser.
This saves around 100 bytes code space on stmhal, more on unix.
2014-12-20 18:37:50 +00:00
Damien George
4fd7c1a2ac tools, pyboard.py: Write data to pyboard in chunks of 256 bytes.
This speeds up writes significantly.
2014-12-20 18:09:04 +00:00
Damien George
2870d85a11 py: Save a few code bytes in parser; make vars local where possible. 2014-12-20 18:06:08 +00:00
Paul Sokolovsky
978f4ca2e1 run-tests: Allow to run testuite against Windows build on Linux (using Wine).
Just adjust line-endings of micropython.exe output, the rest should be
handled by Wine (automagically on properly configured distro).

To run:

MICROPY_MICROPYTHON=../windows/micropython.exe ./run-tests
2014-12-20 16:53:46 +02:00
stijn
f5efefd5a0 windows: Correctly interpret skipped tests, enable uhashlib and ubinascii 2014-12-20 16:52:22 +02:00
Damien George
6d3ae569cf docs: Add CPy diff note for print_exception; embellish sys.platform. 2014-12-19 22:10:38 +00:00
Damien George
2a3e2b9033 py: Add execfile function (from Python 2); enable in stmhal port.
Adds just 60 bytes to stmhal binary.  Addresses issue #362.
2014-12-19 13:36:17 +00:00
Paul Sokolovsky
8427c5b76c unix/windows: Make sure that process exit code is portable 8-bit value.
This fixes FORCED_EXIT internal flag leaking into Windows exit code.
2014-12-19 00:01:49 +02:00
Damien George
f04329e93b lib/libm: Add acosh, asinh, atanh, tan; get working with stmhal.
acoshf, asinhf, atanhf were added from musl.  mathsincos.c was
split up into its original, separate files (from newlibe-nano-2).
tan was added.

All of the important missing float functions are now implemented,
and pyboard now passes tests/float/math_fun.py (finally!).
2014-12-18 14:44:02 +00:00
Damien George
6936f4626c tests: Get misc/print_exception and pyb/spi working on pyboard. 2014-12-18 13:37:56 +00:00
Paul Sokolovsky
c8b0229bc7 tests: sha256: skip test if uhashlib module is not available. 2014-12-18 00:32:15 +02:00
Gregory
5cf7ac7309 Fix leds.rst
N (mod 4) is 0..3
2014-12-18 00:06:48 +03:00
Paul Sokolovsky
9d944c7fb2 unix: Rename "time" module to "utime" to allow extensibility.
Name choosen per latest conventions and for compatibiity with stmhal port.
2014-12-17 00:13:32 +02:00
Damien George
9642846d71 docs: Define more clearly the behaviour of LED methods.
Addresses issue #1006.
2014-12-16 11:55:46 +00:00
Paul Sokolovsky
0078561303 modffi: Support void (None) return value for Python callback functions. 2014-12-16 00:28:12 +02:00
Paul Sokolovsky
7a4765dbeb tests: Add testcase for ffi callbacks. 2014-12-15 02:18:54 +02:00
Paul Sokolovsky
b62371e8fb modffi: 64-bit cleanness (fixes actual bug in callback arg handling). 2014-12-15 02:18:49 +02:00
Paul Sokolovsky
c0bc3bd736 asmarm: Fix bug with encoding small negative ints using MVN instruction. 2014-12-14 03:24:17 +02:00
Paul Sokolovsky
83d27b0f0b unix: Enable Thumb2 and ARM emitters by default on corresponding archs. 2014-12-14 03:24:17 +02:00
Paul Sokolovsky
138562ccd9 run-tests: Skip native/viper tests based on prefix.
Otherwise, new tests are forgotten to be added to explicit lists. Issue
found running on Debian/ARM.
2014-12-13 00:51:24 +02:00
Damien George
e181c0dc07 py: Fix optimised for-loop compiler so it follows proper semantics.
You can now assign to the range end variable and the for-loop still
works correctly.  This fully addresses issue #565.

Also fixed a bug with the stack not being fully popped when breaking out
of an optimised for-loop (and it's actually impossible to write a test
for this case!).
2014-12-12 17:19:56 +00:00
Damien George
7764f163fa py: Fix label printing in showbc; print sp in vm trace. 2014-12-12 17:18:56 +00:00
Paul Sokolovsky
1ca28bd570 run-tests: Reset MICROPYPATH, to make sure tests use only builtin modules. 2014-12-12 00:58:07 +02:00
Paul Sokolovsky
dbc7854355 run-tests: PEP8 fix. 2014-12-12 00:58:07 +02:00
Paul Sokolovsky
f42b3c7599 tests: Activate recursive_data.py test, now that io.StringIO is available. 2014-12-12 00:58:07 +02:00
Damien George
5fba93a26b tests: Add test for semantics of for-loop that optimisation can break. 2014-12-11 17:40:41 +00:00
Damien George
c33ce606cf py: Fix a semantic issue with range optimisation.
Now you can assign to the range variable within the for loop and it will
still work.

Partially addresses issue #565.
2014-12-11 17:35:23 +00:00
Damien George
f905145c6d tests: Disable print_exception test when using native emitter. 2014-12-11 17:34:55 +00:00
Damien George
184182d14c tests: Fix print_exception test and re-enable it on Travis CI.
Issue was with uPy: on local machine with micropython-lib installed, io
module is available.  Not the case on Travis CI, where only _io module
is available in uPy.
2014-12-11 17:10:25 +00:00
Paul Sokolovsky
66a6caa307 run-tests: Skip print_exception.py on TravisCI, as it irreproducibly fails.
TODO: Figure out what's wrong on Travis.
2014-12-11 15:03:29 +02:00
Damien George
5318cc028a py: Tidy up a few function declarations. 2014-12-10 22:37:07 +00:00
Damien George
7eb2317fa2 py: Remove static from definition of pfenv_printf.
It's used by stmhal, but not unix.
2014-12-10 22:11:01 +00:00
Damien George
969a6b37bf py: Make functions static where appropriate. 2014-12-10 22:08:14 +00:00
Nikita Nazarenko
d51107927d unix: add unlink function to os module 2014-12-10 21:49:24 +00:00
Damien George
4140e19c8a tests: Fix print_exception.py to work on Travis CI. 2014-12-10 21:45:51 +00:00
Paul Sokolovsky
e8487ea1be tests: Add test for print_exception() function. 2014-12-10 20:48:53 +00:00
Paul Sokolovsky
6c3fc74656 docs: Add sys.print_exception(). 2014-12-10 20:31:38 +02:00
Damien George
b4fe6e28eb py: Fix function type: () -> (void). 2014-12-10 18:05:42 +00:00
Damien George
78d702c300 py: Allow builtins to be overridden.
This patch adds a configuration option (MICROPY_CAN_OVERRIDE_BUILTINS)
which, when enabled, allows to override all names within the builtins
module.  A builtins override dict is created the first time the user
assigns to a name in the builtins model, and then that dict is searched
first on subsequent lookups.  Note that this implementation doesn't
allow deleting of names.

This patch also does some refactoring of builtins code, creating the
modbuiltins.c file.

Addresses issue #959.
2014-12-09 16:19:48 +00:00
adminpete
e6e8ad8ab2 drivers, nrf24: Nonblocking send now uses send_start and send_done. 2014-12-09 02:30:22 +00:00
adminpete
706955976c drivers, nrf24: Nonblocking send now done by generator. 2014-12-09 02:29:56 +00:00
Peter Hinch
5deceb842d drivers, nrf24: Add nonblocking send option etc. 2014-12-09 02:29:35 +00:00
Damien George
b66a31c42c stmhal: Allow SPI.init to specify prescaler directly; improve SPI docs. 2014-12-08 21:34:07 +00:00
Damien George
008251180d stmhal: Enhance pyb.freq to configure bus (AHB, APB1, APB2) freqs.
This is useful if you need precise control over the speed of
peripherals (eg SPI clock).
2014-12-08 21:32:55 +00:00
Paul Sokolovsky
46c3ab2004 modsys: Add sys.print_exception(exc, file=sys.stdout) function.
The function is modeled after traceback.print_exception(), but unbloated,
and put into existing module to save overhead on adding another module.
Compliant traceback.print_exception() is intended to be implemented in
micropython-lib in terms of sys.print_exception().

This change required refactoring mp_obj_print_exception() to take pfenv_t
interface arguments.

Addresses #751.
2014-12-08 20:25:49 +00:00
Damien George
d0caaadaee stmhal: Allow network, uselect, usocket mods to be used by other ports.
Remove include of stm32f4xx_hal.h, replace by include of MICROPY_HAL_H
where needed, and make it compile without float support.  This makes
these 3 modules much more generic and usable by other ports.
2014-12-07 17:03:47 +00:00
Damien George
1f8a2f6623 windows: define __USE_MINGW_ANSI_STDIO for all Windows compilers. 2014-12-06 19:51:30 +00:00
Damien George
9de6773237 stmhal: Make SPI bus use DMA for transfers.
Uses DMA if interrupts are enabled, polling if they are disabled.
2014-12-06 17:41:17 +00:00
Paul Sokolovsky
d4f80f58b8 esp8266/README: Fix typos. 2014-12-06 13:34:18 +02:00
Damien George
be6d8be91e py: Rename mp_obj_int_get to mp_obj_int_get_truncated; fix struct.pack.
mp_obj_int_get_truncated is used as a "fast path" int accessor that
doesn't check for overflow and returns the int truncated to the machine
word size, ie mp_int_t.

Use mp_obj_int_get_truncated to fix struct.pack when packing maximum word
sized values.

Addresses issues #779 and #998.
2014-12-05 23:13:52 +00:00
Damien George
451a087075 py: Fix printing of size_t entity; fix qemu-arm for changes to lexer. 2014-12-05 22:50:16 +00:00
Damien George
759cc9bcc8 unix-cpy: Fix build due to change in lexer API. 2014-12-05 21:42:28 +00:00
Damien George
a4c52c5a3d py: Optimise lexer by exposing lexer type.
mp_lexer_t type is exposed, mp_token_t type is removed, and simple lexer
functions (like checking current token kind) are now inlined.

This saves 784 bytes ROM on 32-bit unix, 348 bytes on stmhal, and 460
bytes on bare-arm.  It also saves a tiny bit of RAM since mp_lexer_t
is a bit smaller.  Also will run a bit more efficiently.
2014-12-05 19:35:18 +00:00
Paul Sokolovsky
41c07d5b80 docs: uzlib: Typo fix. 2014-12-05 02:08:30 +02:00
Paul Sokolovsky
adf4c4cea8 docs: Add quick docs for uzlib. 2014-12-05 00:40:35 +02:00
Damien George
c0b3d4540b docs: Update network docs to reflect changes to code. 2014-12-04 19:43:56 +00:00
Damien George
29a1ec1bd6 stmhal: Overhaul network drivers; has generic network protocol in C.
This patch overhauls the network driver interface.  A generic NIC must
provide a set of C-level functions to implement low-level socket control
(eg socket, bind, connect, send, recv).  Doing this, the network and
usocket modules can then use such a NIC to implement proper socket
control at the Python level.

This patch also updates the CC3K and WIZNET5K drivers to conform to the
new interface, and fixes some bugs in the drivers.  They now work
reasonably well.
2014-12-04 18:57:57 +00:00
Damien George
d8f239263d drivers, wiznet5k: Add socket_reset; fix orderly shutdown in recv. 2014-12-04 18:57:18 +00:00
Damien George
32ef3a3517 py: Allow bytes/bytearray/array to be init'd by buffer protocol objects.
Behaviour of array initialisation is subtly different for bytes,
bytearray and array.array when argument has buffer protocol.  This patch
gets us CPython conformant (except we allow initialisation of
array.array by buffer with length not a multiple of typecode).
2014-12-04 15:46:14 +00:00
Paul Sokolovsky
3a5352b483 docs: Add skeleton docs for ure module. 2014-12-04 00:07:00 +02:00
Damien George
cd97a43f8d py, vm: Make unum a local variable for each opcode that uses it.
This makes no change to the generated code, but it's now easier to
understand since unum is not a "global" variable anymore.
2014-12-02 19:25:10 +00:00
Damien George
57c70d6073 stmhal: Move RTC HAL init functions to rtc.c, where they belong.
So can remove unnecessary stm32f4xx_hal_msp.c file.
2014-12-02 12:40:37 +00:00
Damien George
578ea6d4a5 docs: Add links to LCD and AMP skin schematics. 2014-12-02 12:32:39 +00:00
Paul Sokolovsky
d8fd3103fa docs: Add quick docs for ubinascii. 2014-12-02 01:51:56 +02:00
Paul Sokolovsky
d96a916405 docs: Add quick docs for uhashlib. 2014-12-02 00:53:19 +02:00
Paul Sokolovsky
7f0699eedf docs: Sort "micro-library" module list alphabetically. 2014-12-01 20:42:38 +02:00
Paul Sokolovsky
6e8ff9cd68 modmicropython: Move mem_info() and qstr_info() functions from unix port.
TODO: Merge useful functionality from modpyb too.
2014-12-01 20:42:24 +02:00
Damien George
17c5ce3727 tools: Make pyboard.py have infinite timeout when running script.
This makes pyboard.py much more useful for long running scripts.  When
running a script via pyboard.py, it now waits until the script finishes,
with no timeout.  CTRL-C can be used to break out of the waiting if
needed.
2014-11-30 21:30:53 +00:00
Damien George
1960475ed7 stmhal: Make pyb.[u]delay use systick with IRQs, busy loop otherwise.
pyb.delay and pyb.udelay now use systick if IRQs are enabled, otherwise
they use a busy loop.  Thus they work correctly when IRQs are disabled.
The busy loop is computed from the current CPU frequency, so works no
matter the CPU frequency.
2014-11-30 21:23:25 +00:00
Damien George
c7ca01ad96 py: Generalise and reduce code size of array +, += and .extend().
By using the buffer protocol for these array operations, we now allow
addition of memoryview objects, and objects with "incompatible"
typecodes (in this case it just adds bytes naively).  This is an
extension to CPython which seems sensible.  It also reduces the code
size.
2014-11-30 14:01:33 +00:00
Henrik Sölver
d8c2b2a1c4 Update documentation for the CAN class 2014-11-30 01:04:56 +00:00
Damien George
b2e731177e py: Implement +, += and .extend for bytearray and array objs.
Addresses issue #994.
2014-11-30 00:00:55 +00:00
Damien George
19fb1b4dd7 stmhal: Add USB_VCP.setinterrupt method, to disable CTRL-C. 2014-11-29 15:23:21 +00:00
Damien George
b395220ef0 esp8266: Add README.md. 2014-11-29 15:06:20 +00:00
Damien George
7288403b9b tests: Split out float test from builtin_round.py. 2014-11-29 14:47:54 +00:00
Damien George
3b603f29ec Use MP_DEFINE_CONST_DICT macro to define module dicts.
This is just a clean-up of the code.  Generated code is exactly the
same.
2014-11-29 14:39:27 +00:00
Damien George
e636279fe0 esp8266: Move more rodata to irom section.
rodata can only go in iram/irom if it's accessed only using word loads
(ie no byte or half-word access).
2014-11-29 14:36:18 +00:00
Paul Sokolovsky
bfdc205934 modubinascii: Add, with hexlify() implementation. 2014-11-29 13:52:47 +00:00
Damien George
d96e6b14c9 esp8266: Make default ESP_SDK variable work correctly.
When esp-open-sdk is built with STANDALONE=y (the default) then ESP_SDK
is set to the correct value, so that "make" just works.
2014-11-28 18:05:25 +00:00
352 changed files with 7737 additions and 14483 deletions

View File

@@ -9,6 +9,7 @@ include ../py/py.mk
CROSS_COMPILE = arm-none-eabi-
INC = -I.
INC += -I..
INC += -I$(PY_SRC)
INC += -I$(BUILD)

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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
---------------------

View File

@@ -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
============================================

View File

@@ -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
---------------------------------

View File

@@ -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.

View File

@@ -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

View File

@@ -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.

View File

@@ -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)

View File

@@ -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``.

View File

@@ -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.

View File

@@ -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

View 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
View 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
View 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
View 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.

View 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
View 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
View File

@@ -0,0 +1,2 @@
{% extends "!layout.html" %}
{% set css_files = css_files + ["_static/customstyle.css"] %}

View File

@@ -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
------------

View File

@@ -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
-------------

View File

@@ -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::

View File

@@ -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():

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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
View 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
*/

View File

@@ -31,4 +31,3 @@ typedef unsigned long DWORD;
#endif
#endif

View File

@@ -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;

View File

@@ -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--) {

View File

@@ -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--) {

View File

@@ -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
View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}
}

View File

@@ -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
View 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;
}

View File

@@ -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; }

View File

@@ -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
View 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
View 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
View 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) */

View File

@@ -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]

View File

@@ -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
View File

@@ -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)))

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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__

View File

@@ -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__

View File

@@ -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,

View File

@@ -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__

View File

@@ -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;

View File

@@ -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,

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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__

View File

@@ -24,6 +24,8 @@
* THE SOFTWARE.
*/
#include <stdint.h>
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"

View File

@@ -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>

View File

@@ -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++) {

View File

@@ -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 },

View File

@@ -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,
};

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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