Compare commits

..

164 Commits
v1.1 ... v1.2

Author SHA1 Message Date
Paul Sokolovsky
dce8876dbe unix: file: No fsync() on Windows. 2014-07-13 23:34:35 +03:00
Paul Sokolovsky
ac736f15c9 stream: Factor out mp_stream_write() method to write a memstring to stream. 2014-07-13 23:14:32 +03:00
Paul Sokolovsky
122c9db3db unix: file: Implement .flush() method.
This method apparently should be part of stream interface.
2014-07-13 23:14:24 +03:00
Paul Sokolovsky
a1760a56ff test: Add run-tests-exp.sh, script to run testsuite with only sh dependency.
This script uses expected test results as generated by run-tests --write-exp,
and requires only standard unix shell funtionality (no bash). It is useful
to run testsuite on embedded systems, where there's no CPython and Bash.
2014-07-13 18:49:56 +03:00
Paul Sokolovsky
b82f34edde unix: Allow to disable MICROPY_EMIT_X64 from commandline.
emitnative in particular requires nlr_* to be real functions, so doesn't
compile with MICROPY_NLR_SETJMP=1.
2014-07-13 13:49:51 +03:00
Paul Sokolovsky
2cf381081a run-tests: Add option to write CPython's test results to .exp files.
Mostly to run testsuite on targets which doesn't have CPython.
2014-07-12 16:34:51 +03:00
Paul Sokolovsky
564e46452d py: Add generic helper to align a pointer. 2014-07-12 15:57:28 +03:00
Paul Sokolovsky
58c9586c34 emitbc: Fix structure field alignment issue.
dummy_data field is accessed as uint value (e.g.
in emit_write_bytecode_byte_ptr), but is not aligned as such, which causes
bus errors or incorrect behavior on any arch requiring strictly aligned
data (ARM pre-v7, MIPS, etc, etc).
2014-07-12 15:57:28 +03:00
Paul Sokolovsky
2097c8b1e1 moductypes: Add symbolic constants to specify bitfield position/length. 2014-07-11 00:06:36 +03:00
Paul Sokolovsky
8215847b4d moductypes: Foreign data interface module, roughly based on ctype ideas.
But much smaller and memory-efficient. Uses Python builtin data structures
(dict, tuple, int) to describe structure layout.
2014-07-09 19:28:24 +03:00
Damien George
42b6419056 Merge branch 'dhylands-fix-sdcard-read' 2014-07-07 07:29:52 +01:00
Damien George
594699bc88 stmhal: Protect SD_WriteBlocks by IRQ disable/enable pair. 2014-07-07 07:29:06 +01:00
Dave Hylands
90ba80dc36 Disable IRQs around sdcard reads.
Once the code switches to using DMA, this can be removed.
2014-07-06 09:51:22 -07:00
Paul Sokolovsky
5fa5ca40e6 binary: Factor out mp_binary_set_int(). 2014-07-05 23:54:03 +03:00
Damien George
539681fffd tests: Rename test scripts, changing - to _ for consistency.
From now on, all new tests must use underscore.

Addresses issue #727.
2014-07-05 06:14:29 +01:00
Damien George
0182385ab0 py: Automatically ake __new__ a staticmethod.
Addresses issue #622.
2014-07-05 05:55:00 +01:00
Paul Sokolovsky
4e0eeebdc2 py: Implement sys.maxsize, standard way to check platform "bitness".
Implementing it as a static constant is a bit peculiar and require cooperation
from long int implementation.
2014-07-03 18:09:36 +03:00
Damien George
381618269a parser: Convert (u)int to mp_(u)int_t. 2014-07-03 14:13:33 +01:00
Damien George
54eb4e723e lexer: Convert type (u)int to mp_(u)int_t. 2014-07-03 13:47:47 +01:00
Damien George
40f3c02682 Rename machine_(u)int_t to mp_(u)int_t.
See discussion in issue #50.
2014-07-03 13:25:24 +01:00
Damien George
065aba5875 Merge pull request #739 from errordeveloper/patch-1
qemu: fix typo in readme
2014-07-03 10:16:07 +01:00
Ilya Dmitrichenko
e4e55047b3 qemu: fix typo in readme 2014-07-02 18:30:46 +01:00
Damien George
5e6419cb11 Merge branch 'dhylands-add-timer-deinit' 2014-07-02 14:10:18 +01:00
Damien George
e70b5dbe58 stmhal: Some reordering of code/functions. 2014-07-02 14:09:44 +01:00
Damien George
92a47b4dae Merge branch 'add-timer-deinit' of github.com:dhylands/micropython into dhylands-add-timer-deinit 2014-07-02 14:06:28 +01:00
Damien George
9cd96cf25d Merge pull request #709 from windelbouwman/master
Added hexfile target
2014-07-02 13:53:28 +01:00
Damien George
f83debc716 Merge branch 'dhylands-teensy-new' 2014-07-02 13:45:00 +01:00
Damien George
7a37f647a5 Merge branch 'teensy-new' of github.com:dhylands/micropython into dhylands-teensy-new
Conflicts:
	stmhal/pin_named_pins.c
	stmhal/readline.c

Renamed HAL_H to MICROPY_HAL_H.  Made stmhal/mphal.h which intends to
define the generic Micro Python HAL, which in stmhal sits above the ST
HAL.
2014-07-02 13:42:37 +01:00
Damien George
5fc580475f Merge branch 'dhylands-preserve-except' 2014-07-01 14:28:40 +01:00
Damien George
f0b29729aa py, objexcept: Only check for locked gc if gc is enabled. 2014-07-01 14:28:09 +01:00
Damien George
f065344d3b Merge branch 'preserve-except' of github.com:dhylands/micropython into dhylands-preserve-except 2014-07-01 14:26:37 +01:00
Damien George
aa47f3968b Merge pull request #734 from iabdalkader/copysign
Add copysignf
2014-07-01 14:03:55 +01:00
Dave Hylands
2fe841d2fa Try not to cause a MemoryError when raising an exception during nterrupt handling.
Step 1 fixes #732
2014-06-30 22:49:21 -07:00
Paul Sokolovsky
caa7334141 stackctrl: Add "mp_" prefix. 2014-07-01 02:14:08 +03:00
Paul Sokolovsky
e95b6b5e07 modffi: Add special 'C' code for passing a callback function pointer. 2014-07-01 02:05:34 +03:00
Dave Hylands
0d81c133b3 Add timer_deinit and call it just before doing a soft-restart
This fixes #733.
2014-06-30 08:07:38 -07:00
mux
5d44e6a92c Add copysignf
* Fix #692
2014-06-30 16:31:06 +02:00
Damien George
4039a26679 Merge pull request #710 from iabdalkader/assert
Fix assert_func warning/error
2014-06-30 09:09:24 +01:00
Damien George
b601d9574a py: Improvements to native emitter.
Native emitter can now compile try/except blocks using nlr_push/nlr_pop.
It probably only works for 1 level of exception handling.  It doesn't
work on Thumb (only x64).

Native emitter can also handle some additional op codes.

With this patch, 198 tests now pass using "-X emit=native" option to
micropython.
2014-06-30 05:17:25 +01:00
Paul Sokolovsky
5813efd634 stmhal: pyb.adc: Clarify that buffer with elements of any size can be used.
Based on forum post: http://forum.micropython.org/viewtopic.php?f=6&t=193
2014-06-29 21:34:58 +03:00
Paul Sokolovsky
bb35f425f9 Merge pull request #730 from stinos/windows-mpconfig
windows: Sync mpconfigport.h with the unix' version
2014-06-29 20:50:16 +03:00
Paul Sokolovsky
c10a4405cd gendoc.py: Support modules w/o functions and/or classes.
I.e. don't assume that both are always present.
2014-06-29 15:48:30 +03:00
Paul Sokolovsky
a23475979b modffi: Support short types. 2014-06-29 15:48:21 +03:00
stijn
ec6fa8732b windows: Sync mpconfigport.h with the unix' version
- rearrange/add definitions that were not there so it's easier to compare both
- use MICROPY_PY_SYS_PLATFORM in main.c since it's available anyway
- define EWOULDBLOCK, it is missing from ingw32
2014-06-29 09:40:20 +02:00
Paul Sokolovsky
8139494e54 stmhal: Include mpconfig.h before all other includes.
It defines types used by all other headers.

Fixes #691.
2014-06-28 23:32:03 +03:00
Paul Sokolovsky
9e215fa4c2 py: Make unichar_charlen() accept/return machine_uint_t. 2014-06-28 23:15:29 +03:00
Paul Sokolovsky
a62da515af Merge pull request #729 from stinos/fix-include-order
unix: Fix mpconfig.h not being included before misc.h
2014-06-28 23:12:39 +03:00
stijn
5478ed18ea unix: Fix mpconfig.h not being included before misc.h
This fixes count_lead_ones in misc.h not compiling due to unknown types
2014-06-28 20:49:39 +02:00
Damien George
b1b840554d Merge branch 'unicode' 2014-06-28 10:30:53 +01:00
Damien George
635b60e299 unix, stmhal: Add option for STR_UNICODE to mpconfigport.h.
Unicode is disabled by default for now, since FileIO.read(n) is
currently not implemented for text-mode files, and this is an
often function.
2014-06-28 10:29:52 +01:00
Damien George
8546ce1e28 py: Add missing #endif. 2014-06-28 10:29:22 +01:00
Damien George
41736f8201 tests: Write output in byte mode, not text mode.
This enables testing unicode and non-unicode implementations.
2014-06-28 10:29:12 +01:00
Damien George
e04a44e2f6 py: Small comments, name changes, use of machine_int_t. 2014-06-28 10:27:23 +01:00
Damien George
b3a50f0f3e Merge branch 'master' into unicode
Conflicts:
	py/mpconfig.h
2014-06-28 10:27:15 +01:00
Paul Sokolovsky
8993fb6cf0 py: Add protection against printing too nested or recursive data structures.
With a test which cannot be automatically validated so far.
2014-06-28 02:25:04 +03:00
Paul Sokolovsky
7e4ec3bf4f bare-arm: Hint of setting MICROPY_ERROR_REPORTING to REPORTING_TERSE.
Commented out so far, as enabled leads to dozen more bytes used actually
(due to string pooling effects).
2014-06-27 21:02:04 +03:00
Paul Sokolovsky
81df1e6c98 bare-arm: Disable array module and even bytearray type.
To squeeze few more hundreds of bytes.
2014-06-27 21:02:04 +03:00
Paul Sokolovsky
cb78f862cb py: Allow to disable array module and bytearray type.
array.array and bytearray share big deal of code, so to get real savings,
both need to be disabled.
2014-06-27 21:02:04 +03:00
Paul Sokolovsky
0a1ea40273 bare-arm: Enable link map file.
This port supposed to be demo of uPy minimality, so let people behold it in
details.
2014-06-27 21:02:04 +03:00
Paul Sokolovsky
8a96ebea75 py: Move stack_ctrl_init() to mp_init().
As stack checking is enabled by default, ports which don't call
stack_ctrl_init() are broken now (report RuntimeError on startup). Save
them trouble and just init stack control framework in interpreter init.
2014-06-27 21:02:04 +03:00
Paul Sokolovsky
64c58403ef Merge pull request #720 from iabdalkader/mcu_name
Change MCU name config micro
2014-06-27 18:24:32 +03:00
mux
a75e382a9b Change MCU name config micro 2014-06-27 00:35:53 +02:00
Paul Sokolovsky
3c8ce38d20 Merge pull request #717 from stinos/dead-code
unix: Remove unused CTRL-D definition
2014-06-27 01:23:18 +03:00
Paul Sokolovsky
3659af97c5 Merge pull request #703 from iabdalkader/micro_names
Add MICROPY_HW_MICRO_NAME to boards config
2014-06-27 01:19:17 +03:00
Paul Sokolovsky
ed07d035d5 tests: Add basic test for unicode file i/o. 2014-06-27 00:04:20 +03:00
Paul Sokolovsky
f5f6c3b792 streams: Reading by char count from unicode text streams is not implemented. 2014-06-27 00:04:20 +03:00
Paul Sokolovsky
ce81312d8a misc: Add count_lead_ones() function, useful for UTF-8 handling. 2014-06-27 00:04:20 +03:00
Paul Sokolovsky
63143c94ce tests: Test for explicit start/end args to str methods for unicode. 2014-06-27 00:04:20 +03:00
Paul Sokolovsky
ea2c936c7e objstrunicode: Refactor str_index_to_ptr() following objstr. 2014-06-27 00:04:20 +03:00
Paul Sokolovsky
26fda6dc8e objstr: 64-bit issues. 2014-06-27 00:04:19 +03:00
Paul Sokolovsky
00c904b47a objstrunicode: Signedness issues. 2014-06-27 00:04:19 +03:00
Paul Sokolovsky
1044c3dfe6 unicode: Make get_char()/next_char()/charlen() be 8-bit compatible.
Based on config define.
2014-06-27 00:04:19 +03:00
Paul Sokolovsky
b1949e4c09 tests: Add tests for unicode find()/rfind()/index(). 2014-06-27 00:04:19 +03:00
Paul Sokolovsky
5048df0b7c objstr: find(), rfind(), index(): Make return value be unicode-aware. 2014-06-27 00:04:19 +03:00
Paul Sokolovsky
46d31e9ca9 unicode: Add utf8_ptr_to_index().
Useful when we have pointer to char inside string, but need to return char
index. (E.g. str.find()).
2014-06-27 00:04:19 +03:00
Paul Sokolovsky
ded0fc77f7 py: Add dedicated unicode header. 2014-06-27 00:04:19 +03:00
Paul Sokolovsky
17994d1bd3 tests: Add test for unicode string iteration. 2014-06-27 00:04:19 +03:00
Paul Sokolovsky
79b7fe2ee5 objstrunicode: Implement iterator. 2014-06-27 00:04:19 +03:00
Paul Sokolovsky
cdc020da4b objstrunicode: Re-add buffer protocol back for now, required for io.StringIO. 2014-06-27 00:04:18 +03:00
Paul Sokolovsky
e7f2b4c875 objstrunicode: Revamp len() handling for unicode, and optimize bool(). 2014-06-27 00:04:18 +03:00
Paul Sokolovsky
86d3898e70 objstrunicode: Get rid of bytes checking, it's separate type. 2014-06-27 00:04:18 +03:00
Paul Sokolovsky
d215ee1dc1 py: Make MICROPY_PY_BUILTINS_STR_UNICODE=1 buildable. 2014-06-27 00:04:18 +03:00
Paul Sokolovsky
9731912ccb py: Prune unneeded code from objstrunicode, reuse code in objstr. 2014-06-27 00:04:18 +03:00
Paul Sokolovsky
165eb69b86 vstr: Restore bytestr compatibility. 2014-06-27 00:04:18 +03:00
Paul Sokolovsky
42a52516fe builtin: Restore bytestr compatibility. 2014-06-27 00:04:18 +03:00
Chris Angelico
2ba2299d28 lexer, vstr: Add unicode support. 2014-06-27 00:04:18 +03:00
Chris Angelico
1e3781bc35 tests: Add unicode test. 2014-06-27 00:04:17 +03:00
Chris Angelico
9a1a4beb56 builtin: ord, chr: Unicode support. 2014-06-27 00:04:17 +03:00
Chris Angelico
64b468d873 objstrunicode: Basic implementation of unicode handling.
Squashed commit of the following:

commit 99dc21b67a
Author: Chris Angelico <rosuav@gmail.com>
Date:   Thu Jun 12 02:18:54 2014 +1000

    Optimize as per TODO (thanks Damien!)

commit 5bf0153eca
Author: Chris Angelico <rosuav@gmail.com>
Date:   Tue Jun 10 08:42:06 2014 +1000

    Test a default (= UTF-8) encode and decode

commit c962057ac3
Merge: e2c9782 195de32
Author: Chris Angelico <rosuav@gmail.com>
Date:   Tue Jun 10 05:23:03 2014 +1000

    Merge branch 'master' into unicode, resolving conflict on py/obj.h

commit e2c9782a65
Author: Chris Angelico <rosuav@gmail.com>
Date:   Tue Jun 10 05:05:57 2014 +1000

    More whitespace fixups

commit 086a2a0f57
Author: Chris Angelico <rosuav@gmail.com>
Date:   Tue Jun 10 05:04:20 2014 +1000

    Properly implement string slicing

commit 0d339a143e
Author: Chris Angelico <rosuav@gmail.com>
Date:   Tue Jun 10 02:24:11 2014 +1000

    Support slicing in str_index_to_ptr, and fix a bounds error

commit 24371c7267
Author: Chris Angelico <rosuav@gmail.com>
Date:   Tue Jun 10 02:10:22 2014 +1000

    Break out index-to-pointer calculation into a function

commit 616c24ac01
Author: Chris Angelico <rosuav@gmail.com>
Date:   Tue Jun 10 02:03:11 2014 +1000

    Add tests of string slicing, which currently fail

commit a24d19f676
Author: Chris Angelico <rosuav@gmail.com>
Date:   Tue Jun 10 01:56:53 2014 +1000

    Change string indexing to not precalculate the charlen, and add test for neg indexing

commit 0bcc7ab89e
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sun Jun 8 22:09:17 2014 +1000

    Clean up constant qstr declarations now that charlen isn't needed

commit 5473e1a1db
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sun Jun 8 07:18:42 2014 +1000

    Remove the charlen field from strings, calculating it when required

commit 5c1658ec71
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sun Jun 8 07:11:27 2014 +1000

    Get rid of mp_obj_str_get_data_len() which was used in only one place

commit a019ba968b
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sun Jun 8 06:58:26 2014 +1000

    Add a unichar_charlen() function to calculate length-in-characters from length-in-bytes

commit 44b0d5cff8
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sun Jun 8 06:32:44 2014 +1000

    Use utf8_get/next_char in building up a string's repr

commit 30d1bad33f
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sun Jun 8 06:10:45 2014 +1000

    Make utf8_get_char() and utf8_next_char() actually do what their names say

commit bc990dad9a
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sun Jun 8 02:10:59 2014 +1000

    Revert "Add PEP 393-flags to strings and stub usage."

    This reverts commit c239f50952.

commit f9bebb28ad
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sat Jun 7 15:41:48 2014 +1000

    Whitespace fixes

commit 279de0c8eb
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sat Jun 7 15:28:35 2014 +1000

    Formatting/layout improvements - introduce macros for UTF-8 byte detection, add braces. No functional changes.

commit f1911f53d5
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sat Jun 7 11:56:02 2014 +1000

    Make chr() Unicode-aware

commit f51ad737b4
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sat Jun 7 11:44:07 2014 +1000

    Make a string's repr Unicode-aware

commit 01bd686846
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sat Jun 7 11:33:43 2014 +1000

    Expand the Unicode tests

commit 7bc91904f8
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sat Jun 7 11:27:30 2014 +1000

    Record byte lengths for byte strings

commit bb13212071
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sat Jun 7 11:25:06 2014 +1000

    Make ord() Unicode-aware

commit 03f0cbe905
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sat Jun 7 10:24:35 2014 +1000

    Retain characters as UTF-8 encoded Unicode

commit e924659b85
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sat Jun 7 08:37:27 2014 +1000

    Add support for \u and \U escapes, but not \N (with explanatory comment)

commit 231031ac5f
Author: Chris Angelico <rosuav@gmail.com>
Date:   Sat Jun 7 05:09:35 2014 +1000

    Add character length to qstr

commit 6df1b946fb
Author: Chris Angelico <rosuav@gmail.com>
Date:   Fri Jun 6 13:48:36 2014 +1000

    Add test of UTF-8 encoded source file resulting in properly formed string

commit 16429b81a8
Author: Chris Angelico <rosuav@gmail.com>
Date:   Fri Jun 6 13:44:15 2014 +1000

    Make len(s) return character length (even though creation's still buggy)

commit cd2cf6663c
Author: Chris Angelico <rosuav@gmail.com>
Date:   Fri Jun 6 13:15:36 2014 +1000

    HACK - When indexing a qstr, count its charlen. Stupidly inefficient but POC.

    All tests pass now, though string creation is still buggy.

commit 47c234584d
Author: Chris Angelico <rosuav@gmail.com>
Date:   Fri Jun 6 13:15:32 2014 +1000

    objstr: Record character length separately from byte length

    CAUTION: Buggy, may crash stuff - qstr needs equivalent functionality too

commit b0f41c72af
Author: Chris Angelico <rosuav@gmail.com>
Date:   Fri Jun 6 05:37:36 2014 +1000

    Beginnings of UTF-8 support - construct strings from that many UTF-8-encoded chars, and subscript bytes the same way

commit 89452be641
Author: Chris Angelico <rosuav@gmail.com>
Date:   Fri Jun 6 05:28:47 2014 +1000

    Update comments - now aiming for UTF-8 rather than PEP 393 strings

commit c239f50952
Author: Chris Angelico <rosuav@gmail.com>
Date:   Wed Jun 4 05:28:12 2014 +1000

    Add PEP 393-flags to strings and stub usage.

    The test suite all passes, but nothing has actually been changed.
2014-06-27 00:04:17 +03:00
Paul Sokolovsky
83865347db objstrunicode: Complete copy of objstr, to be patched for unicode support. 2014-06-27 00:04:17 +03:00
Chris Angelico
c88987c1af py: Implement basic unicode functions. 2014-06-27 00:04:17 +03:00
Paul Sokolovsky
12bc13eeb8 mpconfig.h: Add MICROPY_PY_BUILTINS_STR_UNICODE. 2014-06-27 00:04:17 +03:00
Paul Sokolovsky
16ac4962ae tests: Add test for catching infinite function recursion.
Put into misc/ to not complicate life for builds with check disabled.
2014-06-27 00:03:56 +03:00
Paul Sokolovsky
7a8ab5a730 stmhal: Use stackctrl framework. 2014-06-27 00:03:55 +03:00
Paul Sokolovsky
23668698cb py: Add portable framework to query/check C stack usage.
Such mechanism is important to get stable Python functioning, because Python
function calling is handled with C stack. The idea is to sprinkle
STACK_CHECK() calls in places where there can be C recursion.

TODO: Add more STACK_CHECK()'s.
2014-06-27 00:03:55 +03:00
Paul Sokolovsky
91b576d147 Merge pull request #719 from dhylands/pin_fix
Use mp_const_none to initialize mapper and map_dict (fix #701)
2014-06-26 22:49:44 +03:00
Dave Hylands
f170735b73 Use mp_const_none to initialize mapper and map_dict 2014-06-25 16:01:19 -07:00
Paul Sokolovsky
f3de62e6c2 binary: machine_uint_t vs uint dichotomy starts doing real damage. 2014-06-26 00:41:08 +03:00
Paul Sokolovsky
8e01291c18 travis: Use unified diffs for failed tests. 2014-06-26 00:05:53 +03:00
Paul Sokolovsky
7a2f166949 modstruct: Fix alignment handling issues.
Also, factor out mp_binary_get_int() function.
2014-06-25 23:34:44 +03:00
stijn
39b6e27944 unix: Remove unused CTRL-D definition 2014-06-25 13:33:10 +02:00
Paul Sokolovsky
5aa740c3e2 modgc: Add mem_free()/mem_alloc() methods.
Return free/allocated memory on GC heap.
2014-06-25 14:28:11 +03:00
Damien George
e973acde81 Merge branch 'master' of github.com:micropython/micropython 2014-06-25 04:10:34 +01:00
Paul Sokolovsky
939c2e7f44 Merge pull request #690 from stinos/msvc-gc
msvc: Enable GC
2014-06-24 21:34:51 +03:00
Paul Sokolovsky
3c9b24bebe modsocket: Fix uClibc detection. 2014-06-24 21:20:38 +03:00
Paul Sokolovsky
141df2d350 unix: Dump default heap size in usage message. 2014-06-24 16:58:00 +03:00
Damien George
780e54cdc3 py: Implement delete_attr in native emitter. 2014-06-22 18:35:04 +01:00
Paul Sokolovsky
cd590cbfaa unix: Don't error out on #warning directive. 2014-06-22 19:20:55 +03:00
Paul Sokolovsky
ff5932a8d8 modsocket: Workaround uClibc issue with numeric port for getaddrinfo().
It sucks to workaround this on uPy side, but upgrading not upgradable
embedded systems sucks even more.
2014-06-22 19:20:55 +03:00
Paul Sokolovsky
949a49c9da modsocket: Add call to freeaddrinfo(). 2014-06-22 19:11:34 +03:00
Paul Sokolovsky
69d0a1c540 unix: uClibc doesn't like NULL as a buffer arg to realpath().
So, allocate one explicitly.
2014-06-22 19:08:32 +03:00
stijn
de5ce6d461 gc: Use simple cast instead of union to silence compiler 2014-06-22 11:32:32 +02:00
stijn
8abcf666cb windows: Enable GC and implement bss start and end symbols
The pointers to the bss section are acquired in init.c()
by inspecting the PE header. Works for msvc and mingw.
2014-06-22 11:31:16 +02:00
Paul Sokolovsky
a96cc824bd py: Support arm and thumb ARM ISAs, in addition to thumb2.
These changes were tested with QEMU, and by few people of real hardware.
2014-06-22 01:40:45 +03:00
Paul Sokolovsky
59c675a64c py: Include mpconfig.h before all other includes.
It defines types used by all other headers.

Fixes #691.
2014-06-21 22:43:22 +03:00
mux
89b38d96c9 Add NORETURN to __fatal_error 2014-06-21 18:43:44 +02:00
mux
5c8db48541 Fix asser_func warning/error
* Add while(1) to assert_func to avoid func returns warning
* Define a weak attr in mpconfig.h
2014-06-21 17:24:55 +02:00
Paul Sokolovsky
4c4b9d15ab mkrules.mk: Pass $(COPT) to link stage.
In generalize case, optimization options should be passed to all stages of
the build process.
2014-06-20 23:49:30 +03:00
Paul Sokolovsky
0fc7efb663 makefile: Pass STRIPFLAGS_EXTRA to strip.
Expected to be set on command line, with the idea being that for different
targets, there're different smartass ABIs which strive to put unneeded
sections into executables, etc., so let people have flexible way to
strip that.

The option name is similar to previously introduced CLFAGS_EXTRA &
LDFLAGS_EXTRA.
2014-06-20 20:25:35 +03:00
Paul Sokolovsky
17a49431d4 unix: Allow to override MICROPY_GCREGS_SETJMP from cmdline. 2014-06-20 20:22:31 +03:00
Paul Sokolovsky
7cd46a12ae unix: Add CFLAGS_EXTRA & LDFLAGS_EXTRA for command line usage.
The idea is that it should be possible to pass any additional params for
experimentation without need to patch sources (and without need to deviate
from or repeat baseline options).
2014-06-20 20:21:21 +03:00
Paul Sokolovsky
7e56e55252 unix: Refactor order file munging fo MacOSX. 2014-06-20 20:21:11 +03:00
Paul Sokolovsky
eecf3e90c6 unix: Group CFLAGS related stuff together. 2014-06-20 20:21:11 +03:00
Paul Sokolovsky
2099b6897f unix: Allow to override compiler warning options without touching the rest.
Some people want to enable even more warnings. Let them do it without putting
burden on everyone. Some people vice versa think that current settings should
be relaxed. In this regard, -Werror is the most problematic, it disallows to
use #warning directive, and disallows to pass configuration settings on make
command lines. Again, until decided how to deal with these globally, allow to
work around these problems locally.
2014-06-20 20:18:08 +03:00
Paul Sokolovsky
f605172d2b tests/float/: Skip tests if "math" module is not available. 2014-06-20 18:00:23 +03:00
Paul Sokolovsky
3b6f7b95eb py: Separate MICROPY_PY_BUILTINS_COMPLEX from MICROPY_PY_BUILTINS_FLOAT.
One thing is wanting to do 1 / 2 and get something else but 0, and quite
another - doing rocket science ;-).
2014-06-20 18:00:23 +03:00
Paul Sokolovsky
7efbd325bb Merge pull request #697 from stinos/gc-debug
gc: More verbose debugging
2014-06-20 17:33:02 +03:00
Paul Sokolovsky
09e3f8f0d1 Merge pull request #707 from eblot/master-v1.1.1-build-fixes
Fix missing declaration of assert()
Replace ARRAY_SIZE with MP_ARRAY_SIZE
2014-06-20 17:29:58 +03:00
Windel Bouwman
b6af4c8104 Added hexfile target 2014-06-20 16:14:55 +02:00
Paul Sokolovsky
74c710187c bench: Three ways to process a byte buffer. 2014-06-19 22:27:13 +03:00
Paul Sokolovsky
59ced651b5 bench: Add test for map() vs inplace operations in array-likes.
map() is 5 times slower. That's mostly because of inefficiency of creating
containers from iterables of unknown length (like map()).
2014-06-19 22:19:24 +03:00
Paul Sokolovsky
17db096505 bench: Add tests for constructing various containers from iterator.
Both "bound" (like, length known) and "unbound" (length unknown) are tested.
All of list, tuple, bytes, bytesarray offer approximately the same
performance, with "unbound" case being 30 times slower.
2014-06-19 21:44:33 +03:00
Paul Sokolovsky
e53d2197e4 bench: Add test for function call overhead.
For a trivial operation, calling a function is 5 times slower than doing
operation inline.
2014-06-19 20:49:03 +03:00
Emmanuel Blot
f6932d6506 Prefix ARRAY_SIZE with micropython prefix MP_ 2014-06-19 18:54:34 +02:00
Emmanuel Blot
bf3366a48b Add missing “assert.h” file header inclusion from “nlr.h” 2014-06-19 18:47:38 +02:00
mux
fe81eea967 Add MICROPY_HW_MICRO_NAME to boards config 2014-06-19 14:40:57 +02:00
Damien George
b0851e5949 Merge pull request #700 from swegener/for-upstream
bare-arm, stmhal: Disable stack protector
2014-06-18 14:59:39 +01:00
Sven Wegener
c3cabf4e33 bare-arm, stmhal, teensy: Duplicate -nostdlib to CFLAGS
As we are building with -nostdlib gcc features like the stack protector
will fail linking, because the failure handlers are in gcc's internal
libs. Such features are implicitly disabled during compilation when
-nostdlib is used in CFLAGS too.

Signed-off-by: Sven Wegener <sven.wegener@stealer.net>
2014-06-18 13:34:07 +02:00
Sven Wegener
afc67c6dc5 bare-arm, stmhal: Fix --nostdlib to -nostdlib
-nostdlib is the correct option, gcc recognizes the double dash version
when in link-only mode, but not when compiling.

Signed-off-by: Sven Wegener <sven.wegener@stealer.net>
2014-06-18 13:33:47 +02:00
stijn
9acb5e4cf0 gc: Turn off debugging info again 2014-06-18 12:29:03 +02:00
stijn
def10cecd1 gc: Keep debug statements at beginning of scope where possible 2014-06-18 10:20:41 +02:00
Damien George
720f55cc4b Merge pull request #698 from dhylands/adc-fix
Fix problem with ADC reads and multiple channels
2014-06-17 20:52:47 +01:00
Damien George
bcb3ab451b stmhal: Toggle LED using ODR ^= pin_mask. 2014-06-17 19:57:17 +01:00
Dave Hylands
535b88133c Fix problem with ADC reads and multiple channels 2014-06-16 09:41:58 -07:00
stijn
bbcea3f62b gc: More verbose debugging
Add more DEBUG_printf statements to trace gc behaviour
2014-06-16 12:43:35 +02:00
Dave Hylands
4f1b7fec9f Updated teensy to build.
Refactored some stmhal files which are shared with teensy.
2014-06-15 22:48:05 -07:00
Damien George
2547928148 stmhal: Add Python function to set UART for REPL.
This adds a hook to get/set pyb_uart_global_debug from Python, using
pyb.repl_uart().  You can set it to an arbitrary UART object, and then
the REPL (in and out) is repeated on this UART object (as well as on USB
CDC).

Ultimately, this will be replaced with a proper Pythonic interface to
set sys.stdin and sys.stdout.
2014-06-15 09:47:27 +01:00
Damien George
c0711cbefa stmhal: Fix type signatures on functions that take variable args. 2014-06-15 09:32:42 +01:00
Damien George
e79c6696c5 stmhal: Fix file print methods to use print instead of printf.
Also make stdout_print_strn static (ultimately this function needs to be
merged with stdout_tx_strn).
2014-06-15 09:10:07 +01:00
Damien George
34ab8dd6dd stmhal: Update and improve LCD driver.
Still some method names to iron out, and funtionality to add, but this
will do for the first, basic version.
2014-06-15 00:41:47 +01:00
Paul Sokolovsky
0294661da5 parsenum: Signedness issues.
char can be signedness, and using signedness types is dangerous - it can
lead to negative offsets when doing table lookups. We apparently should just
ban char usage.
2014-06-14 18:02:21 +03:00
Damien George
812025bd83 Merge pull request #693 from iabdalkader/assert
Add __assert_func
2014-06-14 15:51:40 +01:00
mux
5f6f47a688 Make __assert_func weak 2014-06-14 17:02:50 +02:00
mux
00db5c81e1 Add __assert_func only if DEBUG=1 2014-06-14 15:53:11 +02:00
mux
34e7b67d3c Add __assert_func
* issue #692
2014-06-14 14:41:11 +02:00
Paul Sokolovsky
e3cfc0d33d objstr: Refactor to work with char pointers instead of indexes.
In preparation for unicode support.
2014-06-14 06:30:30 +03:00
Paul Sokolovsky
7ddbd1bee7 unicode: Add trivial implementation of unichar_charlen(). 2014-06-14 06:30:30 +03:00
Paul Sokolovsky
b0bb458810 unicode: String API is const byte*.
We still have that char vs byte dichotomy, but majority of string operations
now use byte.
2014-06-14 06:22:11 +03:00
Paul Sokolovsky
2ec38a17d4 objstr: Be 8-bit clean even for repr().
This will allow roughly the same behavior as Python3 for non-ASCII strings,
for example, print("<phrase in non-Latin script>".split()) will print list
of words, not weird hex dump (like Python2 behaves). (Of course, that it
will print list of words, if there're "words" in that phrase at all, separated
by ASCII-compatible whitespace; that surely won't apply to every human
language in existence).
2014-06-14 01:21:13 +03:00
Damien George
e9036c295c Merge branch 'stinos-gc-pointers' 2014-06-13 22:34:11 +01:00
Damien George
c037694957 py, gc: Revert ret_ptr to void*, casting to byte* for memset. 2014-06-13 22:33:31 +01:00
Damien George
63b2237323 Merge branch 'gc-pointers' of github.com:stinos/micropython into stinos-gc-pointers 2014-06-13 22:30:46 +01:00
Paul Sokolovsky
e22cddbe2a stream: Use mp_obj_is_true() for EOF testing.
Getting a length of string may be expensive, depending on the underlying
implementation.
2014-06-13 23:53:10 +03:00
stijn
f33385f56d gc: Use byte* pointers instead of void* for pointer arithmetic
void* is of unknown size
2014-06-13 20:42:06 +02:00
346 changed files with 6576 additions and 2027 deletions

View File

@@ -20,4 +20,4 @@ script:
- (cd tests && MICROPY_CPYTHON3=python3.3 ./run-tests)
after_failure:
- (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff $testbase.exp $testbase.out; done)
- (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done)

View File

@@ -13,7 +13,7 @@ INC += -I$(PY_SRC)
INC += -I$(BUILD)
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) $(COPT)
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
#Debugging/Optimization
ifeq ($(DEBUG), 1)
@@ -22,7 +22,7 @@ else
CFLAGS += -Os -DNDEBUG
endif
LDFLAGS = --nostdlib -T stm32f405.ld
LDFLAGS = -nostdlib -T stm32f405.ld -Map=$@.map --cref
LIBS =
SRC_C = \

View File

@@ -12,10 +12,12 @@
#define MICROPY_HELPER_REPL (0)
#define MICROPY_HELPER_LEXER_UNIX (0)
#define MICROPY_ENABLE_SOURCE_LINE (0)
#define MICROPY_PY_BUILTINS_BYTEARRAY (0)
#define MICROPY_PY_BUILTINS_FROZENSET (0)
#define MICROPY_PY_BUILTINS_SET (0)
#define MICROPY_PY_BUILTINS_SLICE (0)
#define MICROPY_PY_BUILTINS_PROPERTY (0)
#define MICROPY_PY_ARRAY (0)
#define MICROPY_PY_COLLECTIONS (0)
#define MICROPY_PY_MATH (0)
#define MICROPY_PY_CMATH (0)
@@ -26,6 +28,8 @@
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
//#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
// type definitions for the specific machine
#define BYTES_PER_WORD (4)
@@ -33,8 +37,8 @@
#define UINT_FMT "%lu"
#define INT_FMT "%ld"
typedef int32_t machine_int_t; // must be pointer size
typedef uint32_t machine_uint_t; // must be pointer size
typedef int32_t mp_int_t; // must be pointer size
typedef uint32_t mp_uint_t; // must be pointer size
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size

633
extmod/moductypes.c Normal file
View File

@@ -0,0 +1,633 @@
#include <stdio.h>
/*
* 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 <assert.h>
#include <string.h>
#include <stdint.h>
#include "mpconfig.h"
#include "misc.h"
#include "nlr.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
#include "objtuple.h"
#include "binary.h"
#if MICROPY_PY_UCTYPES
/// \module uctypes - Access data structures in memory
///
/// The module allows to define layout of raw data structure (using terms
/// of C language), and then access memory buffers using this definition.
/// The module also provides convenience functions to access memory buffers
/// contained in Python objects or wrap memory buffers in Python objects.
/// \constant UINT8_1 - uint8_t value type
/// \class struct - C-like structure
///
/// Encapsulalation of in-memory data structure. This class doesn't define
/// any methods, only attribute access (for structure fields) and
/// indexing (for pointer and array fields).
///
/// Usage:
///
/// # Define layout of a structure with 2 fields
/// # 0 and 4 are byte offsets of fields from the beginning of struct
/// # they are logically ORed with field type
/// FOO_STRUCT = {"a": 0 | uctypes.UINT32, "b": 4 | uctypes.UINT8}
///
/// # Example memory buffer to access (contained in bytes object)
/// buf = b"\x64\0\0\0\0x14"
///
/// # Create structure object referring to address of
/// # the data in the buffer above
/// s = uctypes.struct(FOO_STRUCT, uctypes.addressof(buf))
///
/// # Access fields
/// print(s.a, s.b)
/// # Result:
/// # 100, 20
#define LAYOUT_LITTLE_ENDIAN (0)
#define LAYOUT_BIG_ENDIAN (1)
#define LAYOUT_NATIVE (2)
#define VAL_TYPE_BITS 4
#define BITF_LEN_BITS 5
#define BITF_OFF_BITS 5
#define OFFSET_BITS 17
#if VAL_TYPE_BITS + BITF_LEN_BITS + BITF_OFF_BITS + OFFSET_BITS != 31
#error Invalid encoding field length
#endif
enum {
UINT8, INT8, UINT16, INT16,
UINT32, INT32, UINT64, INT64,
BFUINT8, BFINT8, BFUINT16, BFINT16,
BFUINT32, BFINT32,
FLOAT32, FLOAT64,
};
#define AGG_TYPE_BITS 2
enum {
STRUCT, PTR, ARRAY, BITFIELD,
};
// Here we need to set sign bit right
#define TYPE2SMALLINT(x, nbits) ((((int)x) << (32 - nbits)) >> 1)
#define GET_TYPE(x, nbits) (((x) >> (31 - nbits)) & ((1 << nbits) - 1));
// Bit 0 is "is_signed"
#define GET_SCALAR_SIZE(val_type) (1 << ((val_type) >> 1))
#define VALUE_MASK(type_nbits) ~((int)0x80000000 >> type_nbits)
STATIC const mp_obj_type_t uctypes_struct_type;
typedef struct _mp_obj_uctypes_struct_t {
mp_obj_base_t base;
mp_obj_t desc;
byte *addr;
uint32_t flags;
} mp_obj_uctypes_struct_t;
STATIC NORETURN void syntax_error() {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "syntax error in uctypes descriptor"));
}
STATIC mp_obj_t uctypes_struct_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
if (n_args < 2 || n_args > 3) {
syntax_error();
}
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
o->base.type = type_in;
o->desc = args[0];
o->addr = (void*)mp_obj_get_int(args[1]);
o->flags = LAYOUT_NATIVE;
if (n_args == 3) {
o->flags = mp_obj_get_int(args[2]);
}
return o;
}
STATIC void uctypes_struct_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_uctypes_struct_t *self = self_in;
const char *typen = "unk";
if (MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)) {
typen = "STRUCT";
} else if (MP_OBJ_IS_TYPE(self->desc, &mp_type_tuple)) {
mp_obj_tuple_t *t = (mp_obj_tuple_t*)self->desc;
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
switch (agg_type) {
case PTR: typen = "PTR"; break;
case ARRAY: typen = "ARRAY"; break;
}
} else {
typen = "ERROR";
}
print(env, "<struct %s %p>", typen, self->addr);
}
static inline mp_uint_t uctypes_struct_scalar_size(int val_type) {
if (val_type == FLOAT32) {
return 4;
} else {
return GET_SCALAR_SIZE(val_type & 7);
}
}
STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size) {
mp_obj_dict_t *d = desc_in;
mp_uint_t total_size = 0;
if (!MP_OBJ_IS_TYPE(desc_in, &mp_type_dict)) {
syntax_error();
}
for (mp_uint_t i = 0; i < d->map.alloc; i++) {
if (MP_MAP_SLOT_IS_FILLED(&d->map, i)) {
mp_obj_t v = d->map.table[i].value;
if (MP_OBJ_IS_SMALL_INT(v)) {
mp_uint_t offset = MP_OBJ_SMALL_INT_VALUE(v);
mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS);
offset &= VALUE_MASK(VAL_TYPE_BITS);
mp_uint_t s = uctypes_struct_scalar_size(val_type);
if (s > *max_field_size) {
*max_field_size = s;
}
if (offset + s > total_size) {
total_size = offset + s;
}
} else {
if (!MP_OBJ_IS_TYPE(v, &mp_type_tuple)) {
syntax_error();
}
mp_obj_tuple_t *t = (mp_obj_tuple_t*)v;
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
mp_uint_t agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
offset &= VALUE_MASK(AGG_TYPE_BITS);
switch (agg_type) {
case STRUCT: {
mp_uint_t s = uctypes_struct_size(t->items[1], max_field_size);
if (offset + s > total_size) {
total_size = offset + s;
}
break;
}
case PTR: {
if (offset + sizeof(void*) > total_size) {
total_size = offset + sizeof(void*);
}
if (sizeof(void*) > *max_field_size) {
*max_field_size = sizeof(void*);
}
break;
}
case ARRAY: {
mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]);
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
mp_uint_t item_s;
if (t->len == 2) {
item_s = GET_SCALAR_SIZE(val_type);
if (item_s > *max_field_size) {
*max_field_size = item_s;
}
} else {
item_s = uctypes_struct_size(t->items[2], max_field_size);
}
mp_uint_t byte_sz = item_s * arr_sz;
if (offset + byte_sz > total_size) {
total_size = offset + byte_sz;
}
break;
}
default:
assert(0);
}
}
}
}
// Round size up to alignment of biggest field
total_size = (total_size + *max_field_size - 1) & ~(*max_field_size - 1);
return total_size;
}
STATIC mp_obj_t uctypes_struct_sizeof(mp_obj_t obj_in) {
mp_uint_t max_field_size = 0;
if (MP_OBJ_IS_TYPE(obj_in, &uctypes_struct_type)) {
mp_obj_uctypes_struct_t *obj = obj_in;
obj_in = obj->desc;
}
mp_uint_t size = uctypes_struct_size(obj_in, &max_field_size);
return MP_OBJ_NEW_SMALL_INT(size);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_sizeof_obj, uctypes_struct_sizeof);
STATIC inline mp_obj_t get_unaligned(uint val_type, void *p, int big_endian) {
mp_int_t val = mp_binary_get_int(GET_SCALAR_SIZE(val_type), val_type & 1, big_endian, p);
if (val_type == UINT32) {
return mp_obj_new_int_from_uint(val);
} else {
return mp_obj_new_int(val);
}
}
STATIC inline void set_unaligned(uint val_type, void *p, int big_endian, mp_obj_t val) {
char struct_type = big_endian ? '>' : '<';
static const char type2char[8] = "BbHhIiQq";
mp_binary_set_val(struct_type, type2char[val_type], val, (byte**)&p);
}
static inline mp_uint_t get_aligned_basic(uint val_type, void *p) {
switch (val_type) {
case UINT8:
return *(uint8_t*)p;
case UINT16:
return *(uint16_t*)p;
case UINT32:
return *(uint32_t*)p;
}
assert(0);
return 0;
}
static inline void set_aligned_basic(uint val_type, void *p, mp_uint_t v) {
switch (val_type) {
case UINT8:
*(uint8_t*)p = (uint8_t)v; return;
case UINT16:
*(uint16_t*)p = (uint16_t)v; return;
case UINT32:
*(uint32_t*)p = (uint32_t)v; return;
}
assert(0);
}
STATIC mp_obj_t get_aligned(uint val_type, void *p, mp_int_t index) {
switch (val_type) {
case UINT8:
return MP_OBJ_NEW_SMALL_INT((mp_int_t)((uint8_t*)p)[index]);
case INT8:
return MP_OBJ_NEW_SMALL_INT((mp_int_t)((int8_t*)p)[index]);
case UINT16:
return MP_OBJ_NEW_SMALL_INT((mp_int_t)((uint16_t*)p)[index]);
case INT16:
return MP_OBJ_NEW_SMALL_INT((mp_int_t)((int16_t*)p)[index]);
case UINT32:
return mp_obj_new_int_from_uint(((uint32_t*)p)[index]);
case INT32:
return mp_obj_new_int(((int32_t*)p)[index]);
case UINT64:
case INT64:
return mp_obj_new_int_from_ll(((int64_t*)p)[index]);
case FLOAT32:
return mp_obj_new_float(((float*)p)[index]);
case FLOAT64:
return mp_obj_new_float(((double*)p)[index]);
default:
assert(0);
}
}
STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) {
mp_int_t v = mp_obj_get_int(val);
switch (val_type) {
case UINT8:
((uint8_t*)p)[index] = (uint8_t)v; return;
case INT8:
((int8_t*)p)[index] = (int8_t)v; return;
case UINT16:
((uint16_t*)p)[index] = (uint16_t)v; return;
case INT16:
((int16_t*)p)[index] = (int16_t)v; return;
case UINT32:
((uint32_t*)p)[index] = (uint32_t)v; return;
case INT32:
((int32_t*)p)[index] = (int32_t)v; return;
default:
assert(0);
}
}
STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set_val) {
mp_obj_uctypes_struct_t *self = self_in;
// TODO: Support at least OrderedDict in addition
if (!MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "struct: no fields"));
}
mp_obj_t deref = mp_obj_dict_get(self->desc, MP_OBJ_NEW_QSTR(attr));
if (MP_OBJ_IS_SMALL_INT(deref)) {
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(deref);
mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS);
offset &= VALUE_MASK(VAL_TYPE_BITS);
//printf("scalar type=%d offset=%x\n", val_type, offset);
if (val_type <= INT64) {
// printf("size=%d\n", GET_SCALAR_SIZE(val_type));
if (self->flags == LAYOUT_NATIVE) {
if (set_val == MP_OBJ_NULL) {
return get_aligned(val_type, self->addr + offset, 0);
} else {
set_aligned(val_type, self->addr + offset, 0, set_val);
return set_val; // just !MP_OBJ_NULL
}
} else {
if (set_val == MP_OBJ_NULL) {
return get_unaligned(val_type, self->addr + offset, self->flags);
} else {
set_unaligned(val_type, self->addr + offset, self->flags, set_val);
return set_val; // just !MP_OBJ_NULL
}
}
} else if (val_type >= BFUINT8 && val_type <= BFINT32) {
uint bit_offset = (offset >> 17) & 31;
uint bit_len = (offset >> 22) & 31;
offset &= (1 << 17) - 1;
mp_uint_t val;
if (self->flags == LAYOUT_NATIVE) {
val = get_aligned_basic(val_type & 6, self->addr + offset);
} else {
val = mp_binary_get_int(GET_SCALAR_SIZE(val_type & 7), val_type & 1, self->flags, self->addr + offset);
}
if (set_val == MP_OBJ_NULL) {
val >>= bit_offset;
val &= (1 << bit_len) - 1;
// TODO: signed
assert((val_type & 1) == 0);
return mp_obj_new_int(val);
} else {
mp_uint_t set_val_int = (mp_uint_t)mp_obj_get_int(set_val);
mp_uint_t mask = (1 << bit_len) - 1;
set_val_int &= mask;
set_val_int <<= bit_offset;
mask <<= bit_offset;
val = (val & ~mask) | set_val_int;
if (self->flags == LAYOUT_NATIVE) {
set_aligned_basic(val_type & 6, self->addr + offset, val);
} else {
mp_binary_set_int(GET_SCALAR_SIZE(val_type & 7), self->flags == LAYOUT_BIG_ENDIAN,
self->addr + offset, (byte*)&val);
}
return set_val; // just !MP_OBJ_NULL
}
}
assert(0);
return MP_OBJ_NULL;
}
if (!MP_OBJ_IS_TYPE(deref, &mp_type_tuple)) {
syntax_error();
}
if (set_val != MP_OBJ_NULL) {
// Cannot assign to aggregate
syntax_error();
}
mp_obj_tuple_t *sub = (mp_obj_tuple_t*)deref;
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(sub->items[0]);
mp_uint_t agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
offset &= VALUE_MASK(AGG_TYPE_BITS);
//printf("agg type=%d offset=%x\n", agg_type, offset);
switch (agg_type) {
case STRUCT: {
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
o->base.type = &uctypes_struct_type;
o->desc = sub->items[1];
o->addr = self->addr + offset;
o->flags = self->flags;
return o;
}
case PTR: case ARRAY: {
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
o->base.type = &uctypes_struct_type;
o->desc = sub;
o->addr = self->addr + offset;
o->flags = self->flags;
//printf("PTR/ARR base addr=%p\n", o->addr);
return o;
}
}
// Should be unreachable once all cases are handled
return MP_OBJ_NULL;
}
STATIC void uctypes_struct_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_t val = uctypes_struct_attr_op(self_in, attr, MP_OBJ_NULL);
*dest = val;
}
STATIC bool uctypes_struct_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t val) {
return uctypes_struct_attr_op(self_in, attr, val) != MP_OBJ_NULL;
}
STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
mp_obj_uctypes_struct_t *self = self_in;
if (value == MP_OBJ_NULL) {
// delete
return MP_OBJ_NULL; // op not supported
} else if (value == MP_OBJ_SENTINEL) {
// load
if (!MP_OBJ_IS_TYPE(self->desc, &mp_type_tuple)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "struct: cannot index"));
}
mp_obj_tuple_t *t = (mp_obj_tuple_t*)self->desc;
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
mp_int_t index = MP_OBJ_SMALL_INT_VALUE(index_in);
if (agg_type == ARRAY) {
mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]);
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
if (index >= arr_sz) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "struct: index out of range"));
}
if (t->len == 2) {
byte *p = self->addr + GET_SCALAR_SIZE(val_type) * index;
return get_unaligned(val_type, p, self->flags);
} else {
mp_uint_t dummy = 0;
mp_uint_t size = uctypes_struct_size(t->items[2], &dummy);
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
o->base.type = &uctypes_struct_type;
o->desc = t->items[2];
o->addr = self->addr + size * index;
o->flags = self->flags;
return o;
}
} else if (agg_type == PTR) {
byte *p = *(void**)self->addr;
if (MP_OBJ_IS_SMALL_INT(t->items[1])) {
uint val_type = GET_TYPE(MP_OBJ_SMALL_INT_VALUE(t->items[1]), VAL_TYPE_BITS);
return get_aligned(val_type, p, index);
} else {
mp_uint_t dummy = 0;
mp_uint_t size = uctypes_struct_size(t->items[1], &dummy);
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
o->base.type = &uctypes_struct_type;
o->desc = t->items[1];
o->addr = p + size * index;
o->flags = self->flags;
return o;
}
}
assert(0);
} else {
// store
return MP_OBJ_NULL; // op not supported
}
}
/// \function addressof()
/// Return address of object's data (applies to object providing buffer
/// interface).
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);
}
MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_addressof_obj, uctypes_struct_addressof);
/// \function bytearray_at()
/// 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));
}
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytearray_at_obj, uctypes_struct_bytearray_at);
/// \function bytes_at()
/// 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));
}
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at);
STATIC const mp_obj_type_t uctypes_struct_type = {
{ &mp_type_type },
.name = MP_QSTR_struct,
.print = uctypes_struct_print,
.make_new = uctypes_struct_make_new,
.load_attr = uctypes_struct_load_attr,
.store_attr = uctypes_struct_store_attr,
.subscr = uctypes_struct_subscr,
};
STATIC const mp_map_elem_t mp_module_uctypes_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uctypes) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&uctypes_struct_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sizeof), (mp_obj_t)&uctypes_struct_sizeof_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_addressof), (mp_obj_t)&uctypes_struct_addressof_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytes_at), (mp_obj_t)&uctypes_struct_bytes_at_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytearray_at), (mp_obj_t)&uctypes_struct_bytearray_at_obj },
/// \moduleref uctypes
/// \constant NATIVE - Native structure layout - native endianness,
/// platform-specific field alignment
{ MP_OBJ_NEW_QSTR(MP_QSTR_NATIVE), MP_OBJ_NEW_SMALL_INT(LAYOUT_NATIVE) },
/// \constant LITTLE_ENDIAN - Little-endian structure layout, tightly packed
/// (no alignment constraints)
{ MP_OBJ_NEW_QSTR(MP_QSTR_LITTLE_ENDIAN), MP_OBJ_NEW_SMALL_INT(LAYOUT_LITTLE_ENDIAN) },
/// \constant BIG_ENDIAN - Big-endian structure layout, tightly packed
/// (no alignment constraints)
{ MP_OBJ_NEW_QSTR(MP_QSTR_BIG_ENDIAN), MP_OBJ_NEW_SMALL_INT(LAYOUT_BIG_ENDIAN) },
/// \constant VOID - void value type, may be used only as pointer target type.
{ MP_OBJ_NEW_QSTR(MP_QSTR_VOID), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(UINT8, VAL_TYPE_BITS)) },
/// \constant UINT8 - uint8_t value type
{ MP_OBJ_NEW_QSTR(MP_QSTR_UINT8), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(UINT8, 4)) },
/// \constant INT8 - int8_t value type
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT8), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(INT8, 4)) },
/// \constant UINT16 - uint16_t value type
{ MP_OBJ_NEW_QSTR(MP_QSTR_UINT16), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(UINT16, 4)) },
/// \constant INT16 - int16_t value type
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT16), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(INT16, 4)) },
/// \constant UINT32 - uint32_t value type
{ MP_OBJ_NEW_QSTR(MP_QSTR_UINT32), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(UINT32, 4)) },
/// \constant INT32 - int32_t value type
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT32), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(INT32, 4)) },
/// \constant UINT64 - uint64_t value type
{ MP_OBJ_NEW_QSTR(MP_QSTR_UINT64), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(UINT64, 4)) },
/// \constant INT64 - int64_t value type
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT64), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(INT64, 4)) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFUINT8), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFUINT8, 4)) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFINT8), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFINT8, 4)) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFUINT16), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFUINT16, 4)) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFINT16), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFINT16, 4)) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFUINT32), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFUINT32, 4)) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFINT32), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFINT32, 4)) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BF_POS), MP_OBJ_NEW_SMALL_INT(17) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BF_LEN), MP_OBJ_NEW_SMALL_INT(22) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PTR), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(PTR, AGG_TYPE_BITS)) },
{ 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,
},
};
const mp_obj_module_t mp_module_uctypes = {
.base = { &mp_type_module },
.name = MP_QSTR_uctypes,
.globals = (mp_obj_dict_t*)&mp_module_uctypes_globals,
};
#endif

View File

@@ -28,8 +28,8 @@
#include <assert.h>
#include <string.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "asmthumb.h"
// wrapper around everything in this file
@@ -133,7 +133,7 @@ uint asm_thumb_get_code_size(asm_thumb_t *as) {
void *asm_thumb_get_code(asm_thumb_t *as) {
// need to set low bit to indicate that it's thumb code
return (void *)(((machine_uint_t)as->code_base) | 1);
return (void *)(((mp_uint_t)as->code_base) | 1);
}
/*
@@ -378,7 +378,7 @@ void asm_thumb_bcc_n(asm_thumb_t *as, int cond, uint label) {
}
}
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, machine_uint_t i32) {
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32) {
// movw, movt does it in 8 bytes
// ldr [pc, #], dw does it in 6 bytes, but we might not reach to end of code for dw
@@ -499,7 +499,7 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp
if (0) {
// load ptr to function into register using immediate, then branch
// not relocatable
asm_thumb_mov_reg_i32(as, reg_temp, (machine_uint_t)fun_ptr);
asm_thumb_mov_reg_i32(as, reg_temp, (mp_uint_t)fun_ptr);
asm_thumb_op16(as, OP_BLX(reg_temp));
} else if (1) {
asm_thumb_op16(as, OP_FORMAT_9_10(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, reg_temp, REG_R7, fun_id));

View File

@@ -185,7 +185,7 @@ void asm_thumb_ite_ge(asm_thumb_t *as);
void asm_thumb_b_n(asm_thumb_t *as, uint label);
void asm_thumb_bcc_n(asm_thumb_t *as, int cond, uint label);
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, machine_uint_t i32_src); // convenience
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32_src); // convenience
void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32_src); // convenience
void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32); // convenience
void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num_dest, uint rlo_src); // convenience

View File

@@ -29,8 +29,8 @@
#include <assert.h>
#include <string.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
// wrapper around everything in this file
#if MICROPY_EMIT_X64

View File

@@ -55,6 +55,6 @@ void mp_bytecode_print(const void *descr, const byte *code, int len);
void mp_bytecode_print2(const byte *code, int len);
// Helper macros to access pointer with least significant bit holding a flag
#define MP_TAGPTR_PTR(x) ((void*)((machine_uint_t)(x) & ~((machine_uint_t)1)))
#define MP_TAGPTR_TAG(x) ((machine_uint_t)(x) & 1)
#define MP_TAGPTR_MAKE(ptr, tag) ((void*)((machine_uint_t)(ptr) | tag))
#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))

View File

@@ -29,8 +29,8 @@
#include <string.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "binary.h"
@@ -88,7 +88,7 @@ int mp_binary_get_size(char struct_type, char val_type, uint *palign) {
}
mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index) {
machine_int_t val = 0;
mp_int_t val = 0;
switch (typecode) {
case 'b':
val = ((int8_t*)p)[index];
@@ -125,32 +125,17 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index) {
return MP_OBJ_NEW_SMALL_INT(val);
}
#define is_signed(typecode) (typecode > 'Z')
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
byte *p = *ptr;
uint align;
int size = mp_binary_get_size(struct_type, val_type, &align);
if (struct_type == '@') {
// Make pointer aligned
p = (byte*)(((machine_uint_t)p + align - 1) & ~(align - 1));
#if MP_ENDIANNESS_LITTLE
struct_type = '<';
#else
struct_type = '>';
#endif
}
mp_int_t mp_binary_get_int(uint size, bool is_signed, bool big_endian, byte *p) {
int delta;
if (struct_type == '<') {
if (!big_endian) {
delta = -1;
p += size - 1;
} else {
delta = 1;
}
machine_int_t val = 0;
if (is_signed(val_type) && *p & 0x80) {
mp_int_t val = 0;
if (is_signed && *p & 0x80) {
val = -1;
}
for (uint i = 0; i < size; i++) {
@@ -159,7 +144,28 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
p += delta;
}
*ptr += size;
return val;
}
#define is_signed(typecode) (typecode > 'Z')
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
byte *p = *ptr;
uint align;
int size = mp_binary_get_size(struct_type, val_type, &align);
if (struct_type == '@') {
// Make pointer aligned
p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
#if MP_ENDIANNESS_LITTLE
struct_type = '<';
#else
struct_type = '>';
#endif
}
*ptr = p + size;
mp_int_t val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);
if (val_type == 'O') {
return (mp_obj_t)val;
} else if (val_type == 'S') {
@@ -171,6 +177,23 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
}
}
void mp_binary_set_int(uint val_sz, bool big_endian, byte *p, byte *val_ptr) {
int in_delta, out_delta;
if (big_endian) {
in_delta = -1;
out_delta = 1;
val_ptr += val_sz - 1;
} else {
in_delta = out_delta = 1;
}
for (uint i = val_sz; i > 0; i--) {
*p = *val_ptr;
p += out_delta;
val_ptr += in_delta;
}
}
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr) {
byte *p = *ptr;
uint align;
@@ -178,18 +201,19 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
int size = mp_binary_get_size(struct_type, val_type, &align);
if (struct_type == '@') {
// Make pointer aligned
p = (byte*)(((machine_uint_t)p + align - 1) & ~(align - 1));
p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
#if MP_ENDIANNESS_LITTLE
struct_type = '<';
#else
struct_type = '>';
#endif
}
*ptr = p + size;
#if MP_ENDIANNESS_BIG
#error Not implemented
#endif
machine_int_t val;
mp_int_t val;
byte *in = (byte*)&val;
switch (val_type) {
case 'O':
@@ -199,23 +223,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
val = mp_obj_get_int(val_in);
}
int in_delta, out_delta;
uint val_sz = MIN(size, sizeof(val));
if (struct_type == '>') {
in_delta = -1;
out_delta = 1;
in += val_sz - 1;
} else {
in_delta = out_delta = 1;
}
for (uint i = val_sz; i > 0; i--) {
*p = *in;
p += out_delta;
in += in_delta;
}
*ptr += size;
mp_binary_set_int(MIN(size, sizeof(val)), struct_type == '>', p, in);
}
void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in) {
@@ -233,7 +241,7 @@ void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in)
}
}
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, machine_int_t val) {
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, mp_int_t val) {
switch (typecode) {
case 'b':
((int8_t*)p)[index] = val;

View File

@@ -31,6 +31,8 @@
int mp_binary_get_size(char struct_type, char val_type, uint *palign);
mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index);
void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in);
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, machine_int_t val);
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, mp_int_t val);
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr);
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr);
mp_int_t mp_binary_get_int(uint size, bool is_signed, bool big_endian, byte *p);
void mp_binary_set_int(uint val_sz, bool big_endian, byte *p, byte *val_ptr);

View File

@@ -99,7 +99,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj, mp_builtin___repl_print
mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in);
mp_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in);
if (val < 0) {
val = -val;
}
@@ -113,10 +113,12 @@ mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
} else {
return o_in;
}
#if MICROPY_PY_BUILTINS_COMPLEX
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_complex)) {
mp_float_t real, imag;
mp_obj_complex_get(o_in, &real, &imag);
return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag));
#endif
#endif
} else {
assert(0);
@@ -154,7 +156,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any);
STATIC mp_obj_t mp_builtin_bin(mp_obj_t o_in) {
mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in };
return mp_obj_str_format(ARRAY_SIZE(args), args);
return mp_obj_str_format(MP_ARRAY_SIZE(args), args);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin);
@@ -170,13 +172,40 @@ STATIC mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable);
STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
int ord = mp_obj_get_int(o_in);
#if MICROPY_PY_BUILTINS_STR_UNICODE
mp_int_t c = mp_obj_get_int(o_in);
char str[4];
int len = 0;
if (c < 0x80) {
*str = c; len = 1;
} else if (c < 0x800) {
str[0] = (c >> 6) | 0xC0;
str[1] = (c & 0x3F) | 0x80;
len = 2;
} else if (c < 0x10000) {
str[0] = (c >> 12) | 0xE0;
str[1] = ((c >> 6) & 0x3F) | 0x80;
str[2] = (c & 0x3F) | 0x80;
len = 3;
} else if (c < 0x110000) {
str[0] = (c >> 18) | 0xF0;
str[1] = ((c >> 12) & 0x3F) | 0x80;
str[2] = ((c >> 6) & 0x3F) | 0x80;
str[3] = (c & 0x3F) | 0x80;
len = 4;
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)"));
}
return mp_obj_new_str(str, len, true);
#else
mp_int_t ord = mp_obj_get_int(o_in);
if (0 <= ord && ord <= 0x10ffff) {
char str[1] = {ord};
return mp_obj_new_str(str, 1, true);
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)"));
}
#endif
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr);
@@ -221,8 +250,8 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj, 0, 1, mp_builtin_dir);
STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) {
mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
mp_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
mp_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
mp_obj_t args[2];
args[0] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
@@ -342,13 +371,32 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct);
STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
uint len;
const char *str = mp_obj_str_get_data(o_in, &len);
#if MICROPY_PY_BUILTINS_STR_UNICODE
mp_uint_t charlen = unichar_charlen(str, len);
if (charlen == 1) {
if (MP_OBJ_IS_STR(o_in) && UTF8_IS_NONASCII(*str)) {
mp_int_t ord = *str++ & 0x7F;
for (mp_int_t mask = 0x40; ord & mask; mask >>= 1) {
ord &= ~mask;
}
while (UTF8_IS_CONT(*str)) {
ord = (ord << 6) | (*str++ & 0x3F);
}
return mp_obj_new_int(ord);
} else {
return mp_obj_new_int(((const byte*)str)[0]);
}
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", charlen));
}
#else
if (len == 1) {
// don't sign extend when converting to ord
// TODO unicode
return mp_obj_new_int(((const byte*)str)[0]);
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", len));
}
#endif
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord);
@@ -430,7 +478,7 @@ STATIC mp_obj_t mp_builtin_sorted(uint n_args, const mp_obj_t *args, mp_map_t *k
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted);
STATIC mp_obj_t mp_builtin_id(mp_obj_t o_in) {
return mp_obj_new_int((machine_int_t)o_in);
return mp_obj_new_int((mp_int_t)o_in);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_builtin_id);

View File

@@ -80,3 +80,6 @@ extern const mp_obj_module_t mp_module_micropython;
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;
// extmod modules
extern const mp_obj_module_t mp_module_uctypes;

View File

@@ -26,8 +26,8 @@
#include <stdlib.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -43,8 +43,10 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
// 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 },
#if MICROPY_PY_BUILTINS_FLOAT
#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 },
@@ -150,8 +152,8 @@ const mp_obj_dict_t mp_builtin_object_dict_obj = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_builtin_object_table),
.alloc = ARRAY_SIZE(mp_builtin_object_table),
.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,
},
};
@@ -160,7 +162,9 @@ 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_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
@@ -186,6 +190,12 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
{ 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
// extra builtin modules as defined by a port
MICROPY_PORT_BUILTIN_MODULES
};
@@ -195,8 +205,8 @@ const mp_obj_dict_t mp_builtin_module_dict_obj = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_builtin_module_table),
.alloc = ARRAY_SIZE(mp_builtin_module_table),
.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,
},
};

View File

@@ -31,8 +31,8 @@
#include <assert.h>
#include <math.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -95,7 +95,7 @@ typedef struct _compiler_t {
STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) {
// TODO store the error message to a variable in compiler_t instead of printing it
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
printf(" File \"%s\", line " UINT_FMT "\n", qstr_str(comp->source_file), (machine_uint_t)((mp_parse_node_struct_t*)pn)->source_line);
printf(" File \"%s\", line " UINT_FMT "\n", qstr_str(comp->source_file), (mp_uint_t)((mp_parse_node_struct_t*)pn)->source_line);
} else {
printf(" File \"%s\"\n", qstr_str(comp->source_file));
}
@@ -104,6 +104,9 @@ STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const cha
}
STATIC const mp_map_elem_t mp_constants_table[] = {
#if MICROPY_PY_UCTYPES
{ MP_OBJ_NEW_QSTR(MP_QSTR_uctypes), (mp_obj_t)&mp_module_uctypes },
#endif
// Extra constants as defined by a port
MICROPY_PORT_CONSTANTS
};
@@ -111,8 +114,8 @@ STATIC const mp_map_elem_t mp_constants_table[] = {
STATIC const mp_map_t mp_constants_map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_constants_table),
.alloc = ARRAY_SIZE(mp_constants_table),
.used = MP_ARRAY_SIZE(mp_constants_table),
.alloc = MP_ARRAY_SIZE(mp_constants_table),
.table = (mp_map_elem_t*)mp_constants_table,
};
@@ -158,7 +161,7 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
compile_syntax_error(comp, (mp_parse_node_t)pns, "constant must be an integer");
break;
}
machine_int_t value = MP_PARSE_NODE_LEAF_SMALL_INT(pn_value);
mp_int_t value = MP_PARSE_NODE_LEAF_SMALL_INT(pn_value);
// store the value in the table of dynamic constants
mp_map_elem_t *elem = mp_map_lookup(consts, MP_OBJ_NEW_QSTR(id_qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
@@ -200,8 +203,8 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
case PN_expr:
if (n == 2 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
// int | int
machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 | arg1);
}
break;
@@ -209,16 +212,16 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
case PN_and_expr:
if (n == 2 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
// int & int
machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 & arg1);
}
break;
case PN_shift_expr:
if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
// int << int
if (!(arg1 >= BITS_PER_WORD || arg0 > (MP_SMALL_INT_MAX >> arg1) || arg0 < (MP_SMALL_INT_MIN >> arg1))) {
@@ -235,10 +238,10 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
break;
case PN_arith_expr:
// overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t
// overflow checking here relies on SMALL_INT being strictly smaller than mp_int_t
if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
// int + int
arg0 += arg1;
@@ -258,8 +261,8 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
case PN_term:
if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
// int * int
if (!mp_small_int_mul_overflow(arg0, arg1)) {
@@ -288,7 +291,7 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
case PN_factor_2:
if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
// +int
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg);
@@ -336,7 +339,7 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
mp_obj_t dest[2];
mp_load_method_maybe(elem->value, q_attr, dest);
if (MP_OBJ_IS_SMALL_INT(dest[0]) && dest[1] == NULL) {
machine_int_t val = MP_OBJ_SMALL_INT_VALUE(dest[0]);
mp_int_t val = MP_OBJ_SMALL_INT_VALUE(dest[0]);
if (MP_SMALL_INT_FITS(val)) {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, val);
}
@@ -482,7 +485,7 @@ STATIC void cpython_c_print_quoted_str(vstr_t *vstr, const char *str, uint len,
STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_string)) {
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
cpython_c_print_quoted_str(vstr, (const char*)pns->nodes[0], (machine_uint_t)pns->nodes[1], false);
cpython_c_print_quoted_str(vstr, (const char*)pns->nodes[0], (mp_uint_t)pns->nodes[1], false);
return;
}
@@ -1894,7 +1897,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except,
EMIT_ARG(jump, success_label); // jump over exception handler
EMIT_ARG(label_assign, l1); // start of exception handler
EMIT_ARG(adjust_stack_size, 6); // stack adjust for the 3 exception items, +3 for possible UNWIND_JUMP state
EMIT(start_except_handler);
uint l2 = comp_next_label(comp);
@@ -1966,7 +1969,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except,
compile_decrease_except_level(comp);
EMIT(end_finally);
EMIT_ARG(adjust_stack_size, -5); // stack adjust
EMIT(end_except_handler);
EMIT_ARG(label_assign, success_label);
compile_node(comp, pn_else); // else block, can be null
@@ -2528,7 +2531,7 @@ void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
mp_parse_node_struct_t *pns_string = (mp_parse_node_struct_t*)pns->nodes[i];
assert(MP_PARSE_NODE_STRUCT_KIND(pns_string) == PN_string);
pn_kind = MP_PARSE_NODE_STRING;
n_bytes += (machine_uint_t)pns_string->nodes[1];
n_bytes += (mp_uint_t)pns_string->nodes[1];
}
if (i == 0) {
string_kind = pn_kind;
@@ -2549,8 +2552,8 @@ void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
s_dest += s_len;
} else {
mp_parse_node_struct_t *pns_string = (mp_parse_node_struct_t*)pns->nodes[i];
memcpy(s_dest, (const char*)pns_string->nodes[0], (machine_uint_t)pns_string->nodes[1]);
s_dest += (machine_uint_t)pns_string->nodes[1];
memcpy(s_dest, (const char*)pns_string->nodes[0], (mp_uint_t)pns_string->nodes[1]);
s_dest += (mp_uint_t)pns_string->nodes[1];
}
}
qstr q = qstr_build_end(q_ptr);
@@ -2858,10 +2861,10 @@ void compile_node(compiler_t *comp, mp_parse_node_t pn) {
if (MP_PARSE_NODE_IS_NULL(pn)) {
// pass
} else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
EMIT_ARG(load_const_small_int, arg);
} else if (MP_PARSE_NODE_IS_LEAF(pn)) {
machine_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
mp_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
case MP_PARSE_NODE_ID: EMIT_ARG(load_id, arg); break;
case MP_PARSE_NODE_INTEGER: EMIT_ARG(load_const_int, arg); break;
@@ -2883,7 +2886,7 @@ void compile_node(compiler_t *comp, mp_parse_node_t pn) {
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
EMIT_ARG(set_line_number, pns->source_line);
if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_string) {
EMIT_ARG(load_const_str, qstr_from_strn((const char*)pns->nodes[0], (machine_uint_t)pns->nodes[1]), false);
EMIT_ARG(load_const_str, qstr_from_strn((const char*)pns->nodes[0], (mp_uint_t)pns->nodes[1]), false);
} else {
compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
if (f == NULL) {
@@ -3337,7 +3340,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
return;
}
if (pass > MP_PASS_SCOPE) {
machine_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]);
mp_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]);
for (uint i = 1; i < n_args; i++) {
if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[i])) {
compile_syntax_error(comp, nodes[i], "inline assembler 'data' requires integer arguments");

View File

@@ -65,7 +65,7 @@ typedef struct _emit_method_table_t {
void (*import_from)(emit_t *emit, qstr qstr);
void (*import_star)(emit_t *emit);
void (*load_const_tok)(emit_t *emit, mp_token_kind_t tok);
void (*load_const_small_int)(emit_t *emit, machine_int_t arg);
void (*load_const_small_int)(emit_t *emit, mp_int_t arg);
void (*load_const_int)(emit_t *emit, qstr qstr);
void (*load_const_dec)(emit_t *emit, qstr qstr);
void (*load_const_str)(emit_t *emit, qstr qstr, bool bytes);
@@ -134,6 +134,11 @@ typedef struct _emit_method_table_t {
void (*yield_value)(emit_t *emit);
void (*yield_from)(emit_t *emit);
// these methods are used to control entry to/exit from an exception handler
// they may or may not emit code
void (*start_except_handler)(emit_t *emit);
void (*end_except_handler)(emit_t *emit);
#if MICROPY_EMIT_CPYTHON
// these methods are only needed for emitcpy
void (*load_const_verbatim_str)(emit_t *emit, const char *str);

View File

@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -50,7 +50,6 @@
struct _emit_t {
pass_kind_t pass : 8;
uint last_emit_was_return_value : 8;
byte dummy_data[DUMMY_DATA_SIZE];
int stack_size;
@@ -67,6 +66,8 @@ struct _emit_t {
uint bytecode_offset;
uint bytecode_size;
byte *code_base; // stores both byte code and code info
// Accessed as uint, so must be aligned as such
byte dummy_data[DUMMY_DATA_SIZE];
};
STATIC void emit_bc_rot_two(emit_t *emit);
@@ -99,7 +100,7 @@ STATIC byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_writ
}
STATIC void emit_align_code_info_to_machine_word(emit_t* emit) {
emit->code_info_offset = (emit->code_info_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1));
emit->code_info_offset = (emit->code_info_offset + sizeof(mp_uint_t) - 1) & (~(sizeof(mp_uint_t) - 1));
}
STATIC void emit_write_code_info_qstr(emit_t* emit, qstr qstr) {
@@ -139,7 +140,7 @@ STATIC byte* emit_get_cur_to_write_bytecode(emit_t* emit, int num_bytes_to_write
}
STATIC void emit_align_bytecode_to_machine_word(emit_t* emit) {
emit->bytecode_offset = (emit->bytecode_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1));
emit->bytecode_offset = (emit->bytecode_offset + sizeof(mp_uint_t) - 1) & (~(sizeof(mp_uint_t) - 1));
}
STATIC void emit_write_bytecode_byte(emit_t* emit, byte b1) {
@@ -171,7 +172,7 @@ STATIC void emit_write_bytecode_uint(emit_t* emit, uint num) {
}
// Similar to emit_write_bytecode_uint(), just some extra handling to encode sign
STATIC void emit_write_bytecode_byte_int(emit_t* emit, byte b1, machine_int_t num) {
STATIC void emit_write_bytecode_byte_int(emit_t* emit, byte b1, mp_int_t num) {
emit_write_bytecode_byte(emit, b1);
// We store each 7 bits in a separate byte, and that's how many bytes needed
@@ -206,8 +207,10 @@ STATIC void emit_write_bytecode_byte_uint(emit_t* emit, byte b, uint num) {
STATIC void emit_write_bytecode_byte_ptr(emit_t* emit, byte b, void *ptr) {
emit_write_bytecode_byte(emit, b);
emit_align_bytecode_to_machine_word(emit);
machine_uint_t *c = (machine_uint_t*)emit_get_cur_to_write_bytecode(emit, sizeof(machine_uint_t));
*c = (machine_uint_t)ptr;
mp_uint_t *c = (mp_uint_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_uint_t));
// Verify thar c is already uint-aligned
assert(c == MP_ALIGN(c, sizeof(mp_uint_t)));
*c = (mp_uint_t)ptr;
}
/* currently unused
@@ -269,7 +272,7 @@ STATIC void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
// write code info size; use maximum space (4 bytes) to write it; TODO possible optimise this
{
byte* c = emit_get_cur_to_write_code_info(emit, 4);
machine_uint_t s = emit->code_info_size;
mp_uint_t s = emit->code_info_size;
c[0] = s & 0xff;
c[1] = (s >> 8) & 0xff;
c[2] = (s >> 16) & 0xff;
@@ -428,7 +431,7 @@ STATIC void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
}
}
STATIC void emit_bc_load_const_small_int(emit_t *emit, machine_int_t arg) {
STATIC void emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) {
emit_bc_pre(emit, 1);
emit_write_bytecode_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
}
@@ -849,6 +852,14 @@ STATIC void emit_bc_yield_from(emit_t *emit) {
emit_write_bytecode_byte(emit, MP_BC_YIELD_FROM);
}
STATIC void emit_bc_start_except_handler(emit_t *emit) {
emit_bc_adjust_stack_size(emit, 6); // stack adjust for the 3 exception items, +3 for possible UNWIND_JUMP state
}
STATIC void emit_bc_end_except_handler(emit_t *emit) {
emit_bc_adjust_stack_size(emit, -5); // stack adjust
}
const emit_method_table_t emit_bc_method_table = {
emit_bc_set_native_types,
emit_bc_start_pass,
@@ -934,6 +945,9 @@ const emit_method_table_t emit_bc_method_table = {
emit_bc_raise_varargs,
emit_bc_yield_value,
emit_bc_yield_from,
emit_bc_start_except_handler,
emit_bc_end_except_handler,
};
#endif // !MICROPY_EMIT_CPYTHON

View File

@@ -28,8 +28,8 @@
#include <stdint.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"

View File

@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -173,7 +173,7 @@ STATIC void emit_cpy_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
}
}
STATIC void emit_cpy_load_const_small_int(emit_t *emit, machine_int_t arg) {
STATIC void emit_cpy_load_const_small_int(emit_t *emit, mp_int_t arg) {
emit_pre(emit, 1, 3);
if (emit->pass == MP_PASS_EMIT) {
printf("LOAD_CONST " INT_FMT "\n", arg);
@@ -792,6 +792,14 @@ STATIC void emit_cpy_yield_from(emit_t *emit) {
}
}
STATIC void emit_cpy_start_except_handler(emit_t *emit) {
emit_cpy_adjust_stack_size(emit, 3); // stack adjust for the 3 exception items
}
STATIC void emit_cpy_end_except_handler(emit_t *emit) {
emit_cpy_adjust_stack_size(emit, -5); // stack adjust
}
STATIC void emit_cpy_load_const_verbatim_str(emit_t *emit, const char *str) {
emit_pre(emit, 1, 3);
if (emit->pass == MP_PASS_EMIT) {
@@ -899,6 +907,9 @@ const emit_method_table_t emit_cpython_method_table = {
emit_cpy_yield_value,
emit_cpy_yield_from,
emit_cpy_start_except_handler,
emit_cpy_end_except_handler,
// emitcpy specific functions
emit_cpy_load_const_verbatim_str,
emit_cpy_load_closure,

View File

@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
@@ -95,7 +95,7 @@ void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void
#ifdef DEBUG_PRINT
DEBUG_printf("assign native: kind=%d fun=%p len=%u n_args=%d\n", kind, fun, len, n_args);
byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
byte *fun_data = (byte*)(((mp_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
for (int i = 0; i < 128 && i < len; i++) {
if (i > 0 && i % 16 == 0) {
DEBUG_printf("\n");

View File

@@ -30,8 +30,8 @@
#include <stdarg.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -167,7 +167,7 @@ STATIC uint get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t
if (MP_PARSE_NODE_IS_ID(pn)) {
qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn);
const char *reg_str = qstr_str(reg_qstr);
for (uint i = 0; i < ARRAY_SIZE(reg_name_table); i++) {
for (uint i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) {
const reg_name_t *r = &reg_name_table[i];
if (reg_str[0] == r->name[0] && reg_str[1] == r->name[1] && reg_str[2] == r->name[2] && (reg_str[2] == '\0' || reg_str[3] == '\0')) {
if (r->reg > max_reg) {
@@ -286,7 +286,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m
asm_thumb_b_n(emit->as, label_num);
} else if (op_str[0] == 'b' && op_len == 3) {
uint cc = -1;
for (uint i = 0; i < ARRAY_SIZE(cc_name_table); i++) {
for (uint i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) {
if (op_str[1] == cc_name_table[i].name[0] && op_str[2] == cc_name_table[i].name[1]) {
cc = cc_name_table[i].cc;
}

View File

@@ -48,8 +48,9 @@
#include <string.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -139,7 +140,7 @@ typedef struct _stack_info_t {
stack_info_kind_t kind;
union {
int u_reg;
machine_int_t u_imm;
mp_int_t u_imm;
};
} stack_info_t;
@@ -284,7 +285,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
}
}
asm_thumb_mov_reg_i32(emit->as, REG_R7, (machine_uint_t)mp_fun_table);
asm_thumb_mov_reg_i32(emit->as, REG_R7, (mp_uint_t)mp_fun_table);
#endif
}
@@ -471,7 +472,7 @@ STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) {
adjust_stack(emit, 1);
}
STATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, machine_int_t imm) {
STATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, mp_int_t imm) {
stack_info_t *si = &emit->stack_info[emit->stack_size];
si->vtype = vtype;
si->kind = STACK_IMM;
@@ -515,9 +516,9 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, int reg_dest, in
case VTYPE_BOOL:
si->vtype = VTYPE_PYOBJ;
if (si->u_imm == 0) {
ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)mp_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
ASM_MOV_IMM_TO_LOCAL_USING((mp_uint_t)mp_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
} else {
ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)mp_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
ASM_MOV_IMM_TO_LOCAL_USING((mp_uint_t)mp_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
}
break;
case VTYPE_INT:
@@ -556,7 +557,7 @@ STATIC void emit_call(emit_t *emit, mp_fun_kind_t fun_kind, void *fun) {
#endif
}
STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val, int arg_reg) {
STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, mp_int_t arg_val, int arg_reg) {
need_reg_all(emit);
ASM_MOV_IMM_TO_REG(arg_val, arg_reg);
#if N_X64
@@ -566,8 +567,8 @@ STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, void *f
#endif
}
// the first arg is stored in the code aligned on a machine_uint_t boundary
STATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val, int arg_reg) {
// the first arg is stored in the code aligned on a mp_uint_t boundary
STATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, mp_int_t arg_val, int arg_reg) {
need_reg_all(emit);
ASM_MOV_ALIGNED_IMM_TO_REG(arg_val, arg_reg);
#if N_X64
@@ -577,7 +578,7 @@ STATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind,
#endif
}
STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val1, int arg_reg1, machine_int_t arg_val2, int arg_reg2) {
STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2) {
need_reg_all(emit);
ASM_MOV_IMM_TO_REG(arg_val1, arg_reg1);
ASM_MOV_IMM_TO_REG(arg_val2, arg_reg2);
@@ -588,8 +589,8 @@ STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, void
#endif
}
// the first arg is stored in the code aligned on a machine_uint_t boundary
STATIC void emit_call_with_3_imm_args_and_first_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val1, int arg_reg1, machine_int_t arg_val2, int arg_reg2, machine_int_t arg_val3, int arg_reg3) {
// the first arg is stored in the code aligned on a mp_uint_t boundary
STATIC void emit_call_with_3_imm_args_and_first_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2, mp_int_t arg_val3, int arg_reg3) {
need_reg_all(emit);
ASM_MOV_ALIGNED_IMM_TO_REG(arg_val1, arg_reg1);
ASM_MOV_IMM_TO_REG(arg_val2, arg_reg2);
@@ -670,7 +671,7 @@ STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
DEBUG_printf("load_const_tok %d\n", tok);
emit_native_pre(emit);
int vtype;
machine_uint_t val;
mp_uint_t val;
if (emit->do_viper_types) {
switch (tok) {
case MP_TOKEN_KW_NONE: vtype = VTYPE_PTR_NONE; val = 0; break;
@@ -681,16 +682,16 @@ STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
} else {
vtype = VTYPE_PYOBJ;
switch (tok) {
case MP_TOKEN_KW_NONE: val = (machine_uint_t)mp_const_none; break;
case MP_TOKEN_KW_FALSE: val = (machine_uint_t)mp_const_false; break;
case MP_TOKEN_KW_TRUE: val = (machine_uint_t)mp_const_true; break;
case MP_TOKEN_KW_NONE: val = (mp_uint_t)mp_const_none; break;
case MP_TOKEN_KW_FALSE: val = (mp_uint_t)mp_const_false; break;
case MP_TOKEN_KW_TRUE: val = (mp_uint_t)mp_const_true; break;
default: assert(0); vtype = 0; val = 0; // shouldn't happen
}
}
emit_post_push_imm(emit, vtype, val);
}
STATIC void emit_native_load_const_small_int(emit_t *emit, machine_int_t arg) {
STATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) {
DEBUG_printf("load_const_small_int %d\n", arg);
emit_native_pre(emit);
if (emit->do_viper_types) {
@@ -721,9 +722,13 @@ STATIC void emit_native_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
// not implemented properly
// load a pointer to the asciiz string?
assert(0);
emit_post_push_imm(emit, VTYPE_PTR, (machine_uint_t)qstr_str(qstr));
emit_post_push_imm(emit, VTYPE_PTR, (mp_uint_t)qstr_str(qstr));
} else {
emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_STR, mp_load_const_str, qstr, REG_ARG_1);
if (bytes) {
emit_call_with_imm_arg(emit, 0, mp_load_const_bytes, qstr, REG_ARG_1); // TODO need to add function to runtime table
} else {
emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_STR, mp_load_const_str, qstr, REG_ARG_1);
}
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
}
@@ -810,7 +815,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) {
vtype_kind_t vtype_lhs, vtype_rhs;
emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_2, &vtype_lhs, REG_ARG_1);
if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {
emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (machine_uint_t)MP_OBJ_SENTINEL, REG_ARG_3);
emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (mp_uint_t)MP_OBJ_SENTINEL, REG_ARG_3);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
} else {
printf("ViperTypeError: can't do subscr of types %d and %d\n", vtype_lhs, vtype_rhs);
@@ -917,8 +922,11 @@ STATIC void emit_native_delete_global(emit_t *emit, qstr qstr) {
}
STATIC void emit_native_delete_attr(emit_t *emit, qstr qstr) {
// not supported
assert(0);
vtype_kind_t vtype_base;
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
assert(vtype_base == VTYPE_PYOBJ);
emit_call_with_2_imm_args(emit, MP_F_STORE_ATTR, mp_store_attr, qstr, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3); // arg2 = attribute name, arg3 = value (null for delete)
emit_post(emit);
}
STATIC void emit_native_delete_subscr(emit_t *emit) {
@@ -926,7 +934,7 @@ STATIC void emit_native_delete_subscr(emit_t *emit) {
emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1); // index, base
assert(vtype_index == VTYPE_PYOBJ);
assert(vtype_base == VTYPE_PYOBJ);
emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3);
emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3);
}
STATIC void emit_native_dup_top(emit_t *emit) {
@@ -1054,17 +1062,33 @@ STATIC void emit_native_setup_with(emit_t *emit, uint label) {
// not supported, or could be with runtime call
assert(0);
}
STATIC void emit_native_with_cleanup(emit_t *emit) {
assert(0);
}
STATIC void emit_native_setup_except(emit_t *emit, uint label) {
assert(0);
emit_native_pre(emit);
// need to commit stack because we may jump elsewhere
need_stack_settled(emit);
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_1, sizeof(nlr_buf_t) / sizeof(mp_uint_t)); // arg1 = pointer to nlr buf
emit_call(emit, 0, nlr_push); // TODO need to add function to runtime table
#if N_X64
asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
asm_x64_jcc_label(emit->as, JCC_JNZ, label);
#elif N_THUMB
asm_thumb_cmp_rlo_i8(emit->as, REG_RET, 0);
asm_thumb_bcc_label(emit->as, THUMB_CC_NE, label);
#endif
emit_post(emit);
}
STATIC void emit_native_setup_finally(emit_t *emit, uint label) {
assert(0);
}
STATIC void emit_native_end_finally(emit_t *emit) {
assert(0);
//assert(0);
}
STATIC void emit_native_get_iter(emit_t *emit) {
@@ -1084,7 +1108,7 @@ STATIC void emit_native_for_iter(emit_t *emit, uint label) {
emit_access_stack(emit, 1, &vtype, REG_ARG_1);
assert(vtype == VTYPE_PYOBJ);
emit_call(emit, MP_F_ITERNEXT, mp_iternext);
ASM_MOV_IMM_TO_REG((machine_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
ASM_MOV_IMM_TO_REG((mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
#if N_X64
asm_x64_cmp_r64_with_r64(emit->as, REG_RET, REG_TEMP1);
asm_x64_jcc_label(emit->as, JCC_JE, label);
@@ -1104,19 +1128,31 @@ STATIC void emit_native_for_iter_end(emit_t *emit) {
STATIC void emit_native_pop_block(emit_t *emit) {
emit_native_pre(emit);
emit_call(emit, 0, nlr_pop); // TODO need to add function to runtime table
adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)));
emit_post(emit);
}
STATIC void emit_native_pop_except(emit_t *emit) {
assert(0);
/*
emit_native_pre(emit);
emit_call(emit, 0, nlr_pop); // TODO need to add function to runtime table
adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)));
emit_post(emit);
*/
}
STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
vtype_kind_t vtype;
emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
assert(vtype == VTYPE_PYOBJ);
emit_call_with_imm_arg(emit, MP_F_UNARY_OP, mp_unary_op, op, REG_ARG_1);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
if (op == MP_UNARY_OP_NOT) {
// we need to synthesise this operation
assert(0);
} else {
vtype_kind_t vtype;
emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
assert(vtype == VTYPE_PYOBJ);
emit_call_with_imm_arg(emit, MP_F_UNARY_OP, mp_unary_op, op, REG_ARG_1);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
}
STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
@@ -1230,17 +1266,26 @@ STATIC void emit_native_set_add(emit_t *emit, int set_index) {
STATIC void emit_native_build_slice(emit_t *emit, int n_args) {
DEBUG_printf("build_slice %d\n", n_args);
assert(n_args == 2);
vtype_kind_t vtype_start, vtype_stop;
emit_pre_pop_reg_reg(emit, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop
assert(vtype_start == VTYPE_PYOBJ);
assert(vtype_stop == VTYPE_PYOBJ);
emit_call_with_imm_arg(emit, MP_F_NEW_SLICE, mp_obj_new_slice, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3); // arg3 = step
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
if (n_args == 2) {
vtype_kind_t vtype_start, vtype_stop;
emit_pre_pop_reg_reg(emit, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop
assert(vtype_start == VTYPE_PYOBJ);
assert(vtype_stop == VTYPE_PYOBJ);
emit_call_with_imm_arg(emit, MP_F_NEW_SLICE, mp_obj_new_slice, (mp_uint_t)mp_const_none, REG_ARG_3); // arg3 = step
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
} else {
assert(n_args == 3);
vtype_kind_t vtype_start, vtype_stop, vtype_step;
emit_pre_pop_reg_reg_reg(emit, &vtype_step, REG_ARG_3, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop, arg3 = step
assert(vtype_start == VTYPE_PYOBJ);
assert(vtype_stop == VTYPE_PYOBJ);
assert(vtype_step == VTYPE_PYOBJ);
emit_call(emit, MP_F_NEW_SLICE, mp_obj_new_slice);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
}
STATIC void emit_native_unpack_sequence(emit_t *emit, int n_args) {
// TODO this is untested
DEBUG_printf("unpack_sequence %d\n", n_args);
vtype_kind_t vtype_base;
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
@@ -1250,26 +1295,25 @@ STATIC void emit_native_unpack_sequence(emit_t *emit, int n_args) {
}
STATIC void emit_native_unpack_ex(emit_t *emit, int n_left, int n_right) {
// TODO this is untested
DEBUG_printf("unpack_ex %d %d\n", n_left, n_right);
vtype_kind_t vtype_base;
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
assert(vtype_base == VTYPE_PYOBJ);
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_left + n_right); // arg3 = dest ptr
emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, mp_unpack_ex, n_left + n_right, REG_ARG_2); // arg2 = n_left + n_right
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_left + n_right + 1); // arg3 = dest ptr
emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, mp_unpack_ex, n_left | (n_right << 8), REG_ARG_2); // arg2 = n_left + n_right
}
STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) {
// call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them
emit_native_pre(emit);
if (n_pos_defaults == 0 && n_kw_defaults == 0) {
emit_call_with_3_imm_args_and_first_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3);
emit_call_with_3_imm_args_and_first_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (mp_uint_t)scope->raw_code, REG_ARG_1, (mp_uint_t)MP_OBJ_NULL, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3);
} else {
vtype_kind_t vtype_def_tuple, vtype_def_dict;
emit_pre_pop_reg_reg(emit, &vtype_def_dict, REG_ARG_3, &vtype_def_tuple, REG_ARG_2);
assert(vtype_def_tuple == VTYPE_PYOBJ);
assert(vtype_def_dict == VTYPE_PYOBJ);
emit_call_with_imm_arg_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1);
emit_call_with_imm_arg_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (mp_uint_t)scope->raw_code, REG_ARG_1);
}
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
@@ -1365,9 +1409,16 @@ STATIC void emit_native_return_value(emit_t *emit) {
}
STATIC void emit_native_raise_varargs(emit_t *emit, int n_args) {
// call runtime
assert(0);
assert(n_args == 1);
vtype_kind_t vtype_err;
emit_pre_pop_reg(emit, &vtype_err, REG_ARG_1); // arg1 = object to raise
assert(vtype_err == VTYPE_PYOBJ);
emit_call(emit, 0, mp_make_raise_obj); // TODO need to add function to runtime table
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
emit_pre_pop_reg(emit, &vtype_err, REG_ARG_1);
emit_call(emit, 0, nlr_jump); // TODO need to add function to runtime table
}
STATIC void emit_native_yield_value(emit_t *emit) {
// not supported (for now)
assert(0);
@@ -1377,6 +1428,21 @@ STATIC void emit_native_yield_from(emit_t *emit) {
assert(0);
}
STATIC void emit_native_start_except_handler(emit_t *emit) {
// This instruction follows an nlr_pop, so the stack counter is back to zero, when really
// it should be up by a whole nlr_buf_t. We then want to pop the nlr_buf_t here, but save
// the first 2 elements, so we can get the thrown value.
adjust_stack(emit, 2);
vtype_kind_t vtype_nlr;
emit_pre_pop_reg(emit, &vtype_nlr, REG_ARG_1); // get the thrown value
emit_pre_pop_discard(emit, &vtype_nlr); // discard the linked-list pointer in the nlr_buf
emit_post_push_reg_reg_reg(emit, VTYPE_PYOBJ, REG_ARG_1, VTYPE_PYOBJ, REG_ARG_1, VTYPE_PYOBJ, REG_ARG_1); // push the 3 exception items
}
STATIC void emit_native_end_except_handler(emit_t *emit) {
adjust_stack(emit, -3); // stack adjust (not sure why it's this much...)
}
const emit_method_table_t EXPORT_FUN(method_table) = {
emit_native_set_viper_types,
emit_native_start_pass,
@@ -1462,6 +1528,9 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
emit_native_raise_varargs,
emit_native_yield_value,
emit_native_yield_from,
emit_native_start_except_handler,
emit_native_end_except_handler,
};
#endif // (MICROPY_EMIT_X64 && N_X64) || (MICROPY_EMIT_THUMB && N_THUMB)

View File

@@ -28,8 +28,8 @@
#include <stdint.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -214,6 +214,10 @@ const emit_method_table_t emit_pass1_method_table = {
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
#if MICROPY_EMIT_CPYTHON
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,

156
py/gc.c
View File

@@ -33,7 +33,6 @@
#include "misc.h"
#include "gc.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -52,17 +51,17 @@
#define STACK_SIZE (64) // tunable; minimum is 1
STATIC byte *gc_alloc_table_start;
STATIC machine_uint_t gc_alloc_table_byte_len;
STATIC mp_uint_t gc_alloc_table_byte_len;
#if MICROPY_ENABLE_FINALISER
STATIC byte *gc_finaliser_table_start;
#endif
STATIC machine_uint_t *gc_pool_start;
STATIC machine_uint_t *gc_pool_end;
STATIC mp_uint_t *gc_pool_start;
STATIC mp_uint_t *gc_pool_end;
STATIC int gc_stack_overflow;
STATIC machine_uint_t gc_stack[STACK_SIZE];
STATIC machine_uint_t *gc_sp;
STATIC machine_uint_t gc_lock_depth;
STATIC mp_uint_t gc_stack[STACK_SIZE];
STATIC mp_uint_t *gc_sp;
STATIC mp_uint_t gc_lock_depth;
// ATB = allocation table byte
// 0b00 = FREE -- free block
@@ -94,8 +93,8 @@ STATIC machine_uint_t gc_lock_depth;
#define ATB_HEAD_TO_MARK(block) do { gc_alloc_table_start[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0)
#define ATB_MARK_TO_HEAD(block) do { gc_alloc_table_start[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0)
#define BLOCK_FROM_PTR(ptr) (((ptr) - (machine_uint_t)gc_pool_start) / BYTES_PER_BLOCK)
#define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (machine_uint_t)gc_pool_start))
#define BLOCK_FROM_PTR(ptr) (((ptr) - (mp_uint_t)gc_pool_start) / BYTES_PER_BLOCK)
#define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (mp_uint_t)gc_pool_start))
#define ATB_FROM_BLOCK(bl) ((bl) / BLOCKS_PER_ATB)
#if MICROPY_ENABLE_FINALISER
@@ -112,15 +111,15 @@ STATIC machine_uint_t gc_lock_depth;
// TODO waste less memory; currently requires that all entries in alloc_table have a corresponding block in pool
void gc_init(void *start, void *end) {
// align end pointer on block boundary
end = (void*)((machine_uint_t)end & (~(BYTES_PER_BLOCK - 1)));
DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, end - start);
end = (void*)((mp_uint_t)end & (~(BYTES_PER_BLOCK - 1)));
DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte*)end - (byte*)start);
// calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes):
// T = A + F + P
// F = A * BLOCKS_PER_ATB / BLOCKS_PER_FTB
// P = A * BLOCKS_PER_ATB * BYTES_PER_BLOCK
// => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK)
machine_uint_t total_byte_len = end - start;
mp_uint_t total_byte_len = (byte*)end - (byte*)start;
#if MICROPY_ENABLE_FINALISER
gc_alloc_table_byte_len = total_byte_len * BITS_PER_BYTE / (BITS_PER_BYTE + BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK);
#else
@@ -131,13 +130,13 @@ void gc_init(void *start, void *end) {
gc_alloc_table_start = (byte*)start;
#if MICROPY_ENABLE_FINALISER
machine_uint_t gc_finaliser_table_byte_len = (gc_alloc_table_byte_len * BLOCKS_PER_ATB) / BLOCKS_PER_FTB;
mp_uint_t gc_finaliser_table_byte_len = (gc_alloc_table_byte_len * BLOCKS_PER_ATB) / BLOCKS_PER_FTB;
gc_finaliser_table_start = gc_alloc_table_start + gc_alloc_table_byte_len;
#endif
machine_uint_t gc_pool_block_len = gc_alloc_table_byte_len * BLOCKS_PER_ATB;
gc_pool_start = end - gc_pool_block_len * BYTES_PER_BLOCK;
gc_pool_end = end;
mp_uint_t gc_pool_block_len = gc_alloc_table_byte_len * BLOCKS_PER_ATB;
gc_pool_start = (mp_uint_t*)((byte*)end - gc_pool_block_len * BYTES_PER_BLOCK);
gc_pool_end = (mp_uint_t*)end;
// clear ATBs
memset(gc_alloc_table_start, 0, gc_alloc_table_byte_len);
@@ -173,16 +172,20 @@ void gc_unlock(void) {
gc_lock_depth--;
}
bool gc_is_locked(void) {
return gc_lock_depth != 0;
}
#define VERIFY_PTR(ptr) ( \
(ptr & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \
&& ptr >= (machine_uint_t)gc_pool_start /* must be above start of pool */ \
&& ptr < (machine_uint_t)gc_pool_end /* must be below end of pool */ \
&& ptr >= (mp_uint_t)gc_pool_start /* must be above start of pool */ \
&& ptr < (mp_uint_t)gc_pool_end /* must be below end of pool */ \
)
#define VERIFY_MARK_AND_PUSH(ptr) \
do { \
if (VERIFY_PTR(ptr)) { \
machine_uint_t _block = BLOCK_FROM_PTR(ptr); \
mp_uint_t _block = BLOCK_FROM_PTR(ptr); \
if (ATB_GET_KIND(_block) == AT_HEAD) { \
/* an unmarked head, mark it, and push it on gc stack */ \
ATB_HEAD_TO_MARK(_block); \
@@ -198,18 +201,18 @@ void gc_unlock(void) {
STATIC void gc_drain_stack(void) {
while (gc_sp > gc_stack) {
// pop the next block off the stack
machine_uint_t block = *--gc_sp;
mp_uint_t block = *--gc_sp;
// work out number of consecutive blocks in the chain starting with this one
machine_uint_t n_blocks = 0;
mp_uint_t n_blocks = 0;
do {
n_blocks += 1;
} while (ATB_GET_KIND(block + n_blocks) == AT_TAIL);
// check this block's children
machine_uint_t *scan = (machine_uint_t*)PTR_FROM_BLOCK(block);
for (machine_uint_t i = n_blocks * WORDS_PER_BLOCK; i > 0; i--, scan++) {
machine_uint_t ptr2 = *scan;
mp_uint_t *scan = (mp_uint_t*)PTR_FROM_BLOCK(block);
for (mp_uint_t i = n_blocks * WORDS_PER_BLOCK; i > 0; i--, scan++) {
mp_uint_t ptr2 = *scan;
VERIFY_MARK_AND_PUSH(ptr2);
}
}
@@ -221,7 +224,7 @@ STATIC void gc_deal_with_stack_overflow(void) {
gc_sp = gc_stack;
// scan entire memory looking for blocks which have been marked but not their children
for (machine_uint_t block = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
for (mp_uint_t block = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
// trace (again) if mark bit set
if (ATB_GET_KIND(block) == AT_MARK) {
*gc_sp++ = block;
@@ -241,7 +244,7 @@ STATIC void gc_sweep(void) {
#endif
// free unmarked heads and their tails
int free_tail = 0;
for (machine_uint_t block = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
for (mp_uint_t block = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
switch (ATB_GET_KIND(block)) {
case AT_HEAD:
#if MICROPY_ENABLE_FINALISER
@@ -268,6 +271,7 @@ STATIC void gc_sweep(void) {
case AT_TAIL:
if (free_tail) {
DEBUG_printf("gc_sweep(%p)\n",PTR_FROM_BLOCK(block));
ATB_ANY_TO_FREE(block);
}
break;
@@ -286,9 +290,9 @@ void gc_collect_start(void) {
gc_sp = gc_stack;
}
void gc_collect_root(void **ptrs, machine_uint_t len) {
for (machine_uint_t i = 0; i < len; i++) {
machine_uint_t ptr = (machine_uint_t)ptrs[i];
void gc_collect_root(void **ptrs, mp_uint_t len) {
for (mp_uint_t i = 0; i < len; i++) {
mp_uint_t ptr = (mp_uint_t)ptrs[i];
VERIFY_MARK_AND_PUSH(ptr);
gc_drain_stack();
}
@@ -301,14 +305,14 @@ void gc_collect_end(void) {
}
void gc_info(gc_info_t *info) {
info->total = (gc_pool_end - gc_pool_start) * sizeof(machine_uint_t);
info->total = (gc_pool_end - gc_pool_start) * sizeof(mp_uint_t);
info->used = 0;
info->free = 0;
info->num_1block = 0;
info->num_2block = 0;
info->max_block = 0;
for (machine_uint_t block = 0, len = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
machine_uint_t kind = ATB_GET_KIND(block);
for (mp_uint_t block = 0, len = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
mp_uint_t kind = ATB_GET_KIND(block);
if (kind == AT_FREE || kind == AT_HEAD) {
if (len == 1) {
info->num_1block += 1;
@@ -345,8 +349,8 @@ void gc_info(gc_info_t *info) {
info->free *= BYTES_PER_BLOCK;
}
void *gc_alloc(machine_uint_t n_bytes, bool has_finaliser) {
machine_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK;
void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser) {
mp_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK;
DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks);
// check if GC is locked
@@ -359,10 +363,10 @@ void *gc_alloc(machine_uint_t n_bytes, bool has_finaliser) {
return NULL;
}
machine_uint_t i;
machine_uint_t end_block;
machine_uint_t start_block;
machine_uint_t n_free = 0;
mp_uint_t i;
mp_uint_t end_block;
mp_uint_t start_block;
mp_uint_t n_free = 0;
int collected = 0;
for (;;) {
@@ -395,19 +399,20 @@ found:
// mark rest of blocks as used tail
// TODO for a run of many blocks can make this more efficient
for (machine_uint_t bl = start_block + 1; bl <= end_block; bl++) {
for (mp_uint_t bl = start_block + 1; bl <= end_block; bl++) {
ATB_FREE_TO_TAIL(bl);
}
// get pointer to first block
void *ret_ptr = (void*)(gc_pool_start + start_block * WORDS_PER_BLOCK);
DEBUG_printf("gc_alloc(%p)\n", ret_ptr);
// zero out the additional bytes of the newly allocated blocks
// This is needed because the blocks may have previously held pointers
// to the heap and will not be set to something else if the caller
// doesn't actually use the entire block. As such they will continue
// to point to the heap and may prevent other blocks from being reclaimed.
memset(ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes);
memset((byte*)ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes);
#if MICROPY_ENABLE_FINALISER
if (has_finaliser) {
@@ -422,11 +427,11 @@ found:
}
/*
void *gc_alloc(machine_uint_t n_bytes) {
void *gc_alloc(mp_uint_t n_bytes) {
return _gc_alloc(n_bytes, false);
}
void *gc_alloc_with_finaliser(machine_uint_t n_bytes) {
void *gc_alloc_with_finaliser(mp_uint_t n_bytes) {
return _gc_alloc(n_bytes, true);
}
*/
@@ -438,10 +443,11 @@ void gc_free(void *ptr_in) {
return;
}
machine_uint_t ptr = (machine_uint_t)ptr_in;
mp_uint_t ptr = (mp_uint_t)ptr_in;
DEBUG_printf("gc_free(%p)\n", ptr);
if (VERIFY_PTR(ptr)) {
machine_uint_t block = BLOCK_FROM_PTR(ptr);
mp_uint_t block = BLOCK_FROM_PTR(ptr);
if (ATB_GET_KIND(block) == AT_HEAD) {
// free head and all of its tail blocks
do {
@@ -452,14 +458,14 @@ void gc_free(void *ptr_in) {
}
}
machine_uint_t gc_nbytes(void *ptr_in) {
machine_uint_t ptr = (machine_uint_t)ptr_in;
mp_uint_t gc_nbytes(void *ptr_in) {
mp_uint_t ptr = (mp_uint_t)ptr_in;
if (VERIFY_PTR(ptr)) {
machine_uint_t block = BLOCK_FROM_PTR(ptr);
mp_uint_t block = BLOCK_FROM_PTR(ptr);
if (ATB_GET_KIND(block) == AT_HEAD) {
// work out number of consecutive blocks in the chain starting with this on
machine_uint_t n_blocks = 0;
mp_uint_t n_blocks = 0;
do {
n_blocks += 1;
} while (ATB_GET_KIND(block + n_blocks) == AT_TAIL);
@@ -473,8 +479,8 @@ machine_uint_t gc_nbytes(void *ptr_in) {
#if 0
// old, simple realloc that didn't expand memory in place
void *gc_realloc(void *ptr, machine_uint_t n_bytes) {
machine_uint_t n_existing = gc_nbytes(ptr);
void *gc_realloc(void *ptr, mp_uint_t n_bytes) {
mp_uint_t n_existing = gc_nbytes(ptr);
if (n_bytes <= n_existing) {
return ptr;
} else {
@@ -483,7 +489,7 @@ void *gc_realloc(void *ptr, machine_uint_t n_bytes) {
has_finaliser = false;
} else {
#if MICROPY_ENABLE_FINALISER
has_finaliser = FTB_GET(BLOCK_FROM_PTR((machine_uint_t)ptr));
has_finaliser = FTB_GET(BLOCK_FROM_PTR((mp_uint_t)ptr));
#else
has_finaliser = false;
#endif
@@ -500,7 +506,7 @@ void *gc_realloc(void *ptr, machine_uint_t n_bytes) {
#else // Alternative gc_realloc impl
void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
void *gc_realloc(void *ptr_in, mp_uint_t n_bytes) {
if (gc_lock_depth > 0) {
return NULL;
}
@@ -510,7 +516,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
return gc_alloc(n_bytes, false);
}
machine_uint_t ptr = (machine_uint_t)ptr_in;
mp_uint_t ptr = (mp_uint_t)ptr_in;
// sanity check the ptr
if (!VERIFY_PTR(ptr)) {
@@ -518,7 +524,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
}
// get first block
machine_uint_t block = BLOCK_FROM_PTR(ptr);
mp_uint_t block = BLOCK_FROM_PTR(ptr);
// sanity check the ptr is pointing to the head of a block
if (ATB_GET_KIND(block) != AT_HEAD) {
@@ -526,14 +532,14 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
}
// compute number of new blocks that are requested
machine_uint_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK;
mp_uint_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK;
// get the number of consecutive tail blocks and
// the number of free blocks after last tail block
// stop if we reach (or are at) end of heap
machine_uint_t n_free = 0;
machine_uint_t n_blocks = 1; // counting HEAD block
machine_uint_t max_block = gc_alloc_table_byte_len * BLOCKS_PER_ATB;
mp_uint_t n_free = 0;
mp_uint_t n_blocks = 1; // counting HEAD block
mp_uint_t max_block = gc_alloc_table_byte_len * BLOCKS_PER_ATB;
while (block + n_blocks + n_free < max_block) {
if (n_blocks + n_free >= new_blocks) {
// stop as soon as we find enough blocks for n_bytes
@@ -556,7 +562,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
// check if we can shrink the allocated area
if (new_blocks < n_blocks) {
// free unneeded tail blocks
for (machine_uint_t bl = block + new_blocks; ATB_GET_KIND(bl) == AT_TAIL; bl++) {
for (mp_uint_t bl = block + new_blocks; ATB_GET_KIND(bl) == AT_TAIL; bl++) {
ATB_ANY_TO_FREE(bl);
}
return ptr_in;
@@ -565,13 +571,13 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
// check if we can expand in place
if (new_blocks <= n_blocks + n_free) {
// mark few more blocks as used tail
for (machine_uint_t bl = block + n_blocks; bl < block + new_blocks; bl++) {
for (mp_uint_t bl = block + n_blocks; bl < block + new_blocks; bl++) {
assert(ATB_GET_KIND(bl) == AT_FREE);
ATB_FREE_TO_TAIL(bl);
}
// zero out the additional bytes of the newly allocated blocks (see comment above in gc_alloc)
memset(ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes);
memset((byte*)ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes);
return ptr_in;
}
@@ -590,7 +596,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
return NULL;
}
DEBUG_printf("gc_realloc: allocating new block\n");
DEBUG_printf("gc_realloc(%p -> %p)\n", ptr_in, ptr_out);
memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK);
gc_free(ptr_in);
return ptr_out;
@@ -607,7 +613,7 @@ void gc_dump_info() {
void gc_dump_alloc_table(void) {
printf("GC memory layout; from %p:", gc_pool_start);
for (machine_uint_t bl = 0; bl < gc_alloc_table_byte_len * BLOCKS_PER_ATB; bl++) {
for (mp_uint_t bl = 0; bl < gc_alloc_table_byte_len * BLOCKS_PER_ATB; bl++) {
if (bl % 64 == 0) {
printf("\n%04x: ", (uint)bl);
}
@@ -617,12 +623,12 @@ void gc_dump_alloc_table(void) {
case AT_HEAD: c = 'h'; break;
/* this prints the uPy object type of the head block
case AT_HEAD: {
machine_uint_t *ptr = gc_pool_start + bl * WORDS_PER_BLOCK;
if (*ptr == (machine_uint_t)&mp_type_tuple) { c = 'T'; }
else if (*ptr == (machine_uint_t)&mp_type_list) { c = 'L'; }
else if (*ptr == (machine_uint_t)&mp_type_dict) { c = 'D'; }
else if (*ptr == (machine_uint_t)&mp_type_float) { c = 'F'; }
else if (*ptr == (machine_uint_t)&mp_type_fun_bc) { c = 'B'; }
mp_uint_t *ptr = gc_pool_start + bl * WORDS_PER_BLOCK;
if (*ptr == (mp_uint_t)&mp_type_tuple) { c = 'T'; }
else if (*ptr == (mp_uint_t)&mp_type_list) { c = 'L'; }
else if (*ptr == (mp_uint_t)&mp_type_dict) { c = 'D'; }
else if (*ptr == (mp_uint_t)&mp_type_float) { c = 'F'; }
else if (*ptr == (mp_uint_t)&mp_type_fun_bc) { c = 'B'; }
else { c = 'h'; }
break;
}
@@ -637,23 +643,23 @@ void gc_dump_alloc_table(void) {
#if DEBUG_PRINT
void gc_test(void) {
machine_uint_t len = 500;
machine_uint_t *heap = malloc(len);
gc_init(heap, heap + len / sizeof(machine_uint_t));
mp_uint_t len = 500;
mp_uint_t *heap = malloc(len);
gc_init(heap, heap + len / sizeof(mp_uint_t));
void *ptrs[100];
{
machine_uint_t **p = gc_alloc(16, false);
mp_uint_t **p = gc_alloc(16, false);
p[0] = gc_alloc(64, false);
p[1] = gc_alloc(1, false);
p[2] = gc_alloc(1, false);
p[3] = gc_alloc(1, false);
machine_uint_t ***p2 = gc_alloc(16, false);
mp_uint_t ***p2 = gc_alloc(16, false);
p2[0] = p;
p2[1] = p;
ptrs[0] = p2;
}
for (int i = 0; i < 25; i+=2) {
machine_uint_t *p = gc_alloc(i, false);
mp_uint_t *p = gc_alloc(i, false);
printf("p=%p\n", p);
if (i & 3) {
//ptrs[i] = p;

21
py/gc.h
View File

@@ -30,25 +30,26 @@ void gc_init(void *start, void *end);
// They can be used to prevent the GC from allocating/freeing.
void gc_lock(void);
void gc_unlock(void);
bool gc_is_locked(void);
// A given port must implement gc_collect by using the other collect functions.
void gc_collect(void);
void gc_collect_start(void);
void gc_collect_root(void **ptrs, machine_uint_t len);
void gc_collect_root(void **ptrs, mp_uint_t len);
void gc_collect_end(void);
void *gc_alloc(machine_uint_t n_bytes, bool has_finaliser);
void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser);
void gc_free(void *ptr);
machine_uint_t gc_nbytes(void *ptr);
void *gc_realloc(void *ptr, machine_uint_t n_bytes);
mp_uint_t gc_nbytes(void *ptr);
void *gc_realloc(void *ptr, mp_uint_t n_bytes);
typedef struct _gc_info_t {
machine_uint_t total;
machine_uint_t used;
machine_uint_t free;
machine_uint_t num_1block;
machine_uint_t num_2block;
machine_uint_t max_block;
mp_uint_t total;
mp_uint_t used;
mp_uint_t free;
mp_uint_t num_1block;
mp_uint_t num_2block;
mp_uint_t max_block;
} gc_info_t;
void gc_info(gc_info_t *info);

View File

@@ -32,8 +32,8 @@
#include <stdio.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "lexer.h"
@@ -50,25 +50,25 @@ struct _mp_lexer_t {
unichar chr0, chr1, chr2; // current cached characters from source
uint line; // source line
uint column; // source column
mp_uint_t line; // source line
mp_uint_t column; // source column
int emit_dent; // non-zero when there are INDENT/DEDENT tokens to emit
int nested_bracket_level; // >0 when there are nested brackets over multiple lines
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
uint alloc_indent_level;
uint num_indent_level;
mp_uint_t alloc_indent_level;
mp_uint_t num_indent_level;
uint16_t *indent_level;
vstr_t vstr;
mp_token_t tok_cur;
};
uint mp_optimise_value;
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, int len) {
uint i = 0;
bool str_strn_equal(const char *str, const char *strn, mp_uint_t len) {
mp_uint_t i = 0;
while (i < len && *str == *strn) {
++i;
@@ -81,10 +81,10 @@ bool str_strn_equal(const char *str, const char *strn, int len) {
#ifdef MICROPY_DEBUG_PRINTERS
void mp_token_show(const mp_token_t *tok) {
printf("(%d:%d) kind:%d str:%p len:%d", tok->src_line, tok->src_column, tok->kind, tok->str, tok->len);
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 char *i = tok->str;
const char *j = i + tok->len;
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);
@@ -175,7 +175,7 @@ STATIC void next_char(mp_lexer_t *lex) {
return;
}
int advance = 1;
mp_uint_t advance = 1;
if (lex->chr0 == '\n') {
// LF is a new line
@@ -210,7 +210,7 @@ STATIC void next_char(mp_lexer_t *lex) {
}
}
void indent_push(mp_lexer_t *lex, uint indent) {
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,7 +219,7 @@ void indent_push(mp_lexer_t *lex, uint indent) {
lex->indent_level[lex->num_indent_level++] = indent;
}
uint indent_top(mp_lexer_t *lex) {
mp_uint_t indent_top(mp_lexer_t *lex) {
return lex->indent_level[lex->num_indent_level - 1];
}
@@ -308,9 +308,9 @@ STATIC const char *tok_kw[] = {
"__debug__",
};
STATIC int hex_digit(unichar c) {
STATIC mp_uint_t hex_digit(unichar c) {
// c is assumed to be hex digit
int n = c - '0';
mp_uint_t n = c - '0';
if (n > 9) {
n &= ~('a' - 'A');
n -= ('A' - ('9' + 1));
@@ -320,8 +320,9 @@ STATIC int hex_digit(unichar c) {
// This is called with CUR_CHAR() before first hex digit, and should return with
// it pointing to last hex digit
STATIC bool get_hex(mp_lexer_t *lex, int num_digits, uint *result) {
uint num = 0;
// num_digits must be greater than zero
STATIC bool get_hex(mp_lexer_t *lex, mp_uint_t num_digits, mp_uint_t *result) {
mp_uint_t num = 0;
while (num_digits-- != 0) {
next_char(lex);
unichar c = CUR_CHAR(lex);
@@ -394,7 +395,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
} else if (had_physical_newline && lex->nested_bracket_level == 0) {
tok->kind = MP_TOKEN_NEWLINE;
uint num_spaces = lex->column - 1;
mp_uint_t num_spaces = lex->column - 1;
lex->emit_dent = 0;
if (num_spaces == indent_top(lex)) {
} else if (num_spaces > indent_top(lex)) {
@@ -463,7 +464,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
next_char(lex);
// work out if it's a single or triple quoted literal
int num_quotes;
mp_uint_t num_quotes;
if (is_char_and(lex, quote_char, quote_char)) {
// triple quotes
next_char(lex);
@@ -475,7 +476,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
}
// parse the literal
int n_closing = 0;
mp_uint_t n_closing = 0;
while (!is_end(lex) && (num_quotes > 1 || !is_char(lex, '\n')) && n_closing < num_quotes) {
if (is_char(lex, quote_char)) {
n_closing += 1;
@@ -502,24 +503,37 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
case 'v': c = 0x0b; break;
case 'f': c = 0x0c; break;
case 'r': c = 0x0d; break;
case 'u':
case 'U':
if (is_bytes) {
// b'\u1234' == b'\\u1234'
vstr_add_char(&lex->vstr, '\\');
break;
}
// Otherwise fall through.
case 'x':
{
uint num = 0;
if (!get_hex(lex, 2, &num)) {
mp_uint_t num = 0;
if (!get_hex(lex, (c == 'x' ? 2 : c == 'u' ? 4 : 8), &num)) {
// TODO error message
assert(0);
}
c = num;
break;
}
case 'N': break; // TODO \N{name} only in strings
case 'u': break; // TODO \uxxxx only in strings
case 'U': break; // TODO \Uxxxxxxxx only in strings
case 'N':
// Supporting '\N{LATIN SMALL LETTER A}' == 'a' would require keeping the
// entire Unicode name table in the core. As of Unicode 6.3.0, that's nearly
// 3MB of text; even gzip-compressed and with minimal structure, it'll take
// roughly half a meg of storage. This form of Unicode escape may be added
// later on, but it's definitely not a priority right now. -- CJA 20140607
assert(!"Unicode name escapes not supported");
break;
default:
if (c >= '0' && c <= '7') {
// Octal sequence, 1-3 chars
int digits = 3;
int num = c - '0';
mp_uint_t digits = 3;
mp_uint_t num = c - '0';
while (is_following_odigit(lex) && --digits != 0) {
next_char(lex);
num = num * 8 + (CUR_CHAR(lex) - '0');
@@ -533,7 +547,13 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
}
}
if (c != MP_LEXER_CHAR_EOF) {
vstr_add_char(&lex->vstr, c);
if (c < 0x110000 && !is_bytes) {
vstr_add_char(&lex->vstr, c);
} else if (c < 0x100 && is_bytes) {
vstr_add_byte(&lex->vstr, c);
} else {
assert(!"TODO: Throw an error, invalid escape code probably");
}
}
} else {
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
@@ -608,7 +628,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
// search for encoded delimiter or operator
const char *t = tok_enc;
uint tok_enc_index = 0;
mp_uint_t tok_enc_index = 0;
for (; *t != 0 && !is_char(lex, *t); t += 1) {
if (*t == 'e' || *t == 'c') {
t += 1;
@@ -630,7 +650,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
// get the maximum characters for a valid token
t += 1;
uint t_index = tok_enc_index;
mp_uint_t t_index = tok_enc_index;
for (;;) {
for (; *t == 'e'; t += 1) {
t += 1;
@@ -693,11 +713,11 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
// 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 (int i = 0; tok_kw[i] != NULL; i++) {
for (int i = 0; i < ARRAY_SIZE(tok_kw); i++) {
//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 (i == ARRAY_SIZE(tok_kw) - 1) {
// tok_kw[ARRAY_SIZE(tok_kw) - 1] == "__debug__"
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);
} else {
tok->kind = MP_TOKEN_KW_FALSE + i;

View File

@@ -131,12 +131,12 @@ typedef enum _mp_token_kind_t {
} mp_token_kind_t;
typedef struct _mp_token_t {
uint src_line; // source line
uint src_column; // source column
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)
uint len; // (byte) length of string of token
mp_uint_t len; // (byte) length of string of token
} mp_token_t;
// the next-char function must return the next character in the stream
@@ -151,7 +151,7 @@ typedef struct _mp_lexer_t mp_lexer_t;
void mp_token_show(const mp_token_t *tok);
mp_lexer_t *mp_lexer_new(qstr src_name, void *stream_data, mp_lexer_stream_next_char_t stream_next_char, mp_lexer_stream_close_t stream_close);
mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, uint len, uint free_len);
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);
@@ -177,4 +177,4 @@ typedef enum {
mp_import_stat_t mp_import_stat(const char *path);
mp_lexer_t *mp_lexer_new_from_file(const char *filename);
extern uint mp_optimise_value;
extern mp_uint_t mp_optimise_value;

View File

@@ -24,13 +24,13 @@
* THE SOFTWARE.
*/
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "lexer.h"
typedef struct _mp_lexer_str_buf_t {
uint free_len; // if > 0, src_beg will be freed when done by: m_free(src_beg, free_len)
mp_uint_t free_len; // if > 0, src_beg will be freed when done by: m_free(src_beg, free_len)
const char *src_beg; // beginning of source
const char *src_cur; // current location in source
const char *src_end; // end (exclusive) of source
@@ -51,7 +51,7 @@ STATIC void str_buf_free(mp_lexer_str_buf_t *sb) {
m_del_obj(mp_lexer_str_buf_t, sb);
}
mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, uint len, uint free_len) {
mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len) {
mp_lexer_str_buf_t *sb = m_new_obj(mp_lexer_str_buf_t);
sb->free_len = free_len;
sb->src_beg = str;

View File

@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#if MICROPY_HELPER_LEXER_UNIX

View File

@@ -28,8 +28,8 @@
#include <stdlib.h>
#include <string.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#if 0 // print debugging info
#define DEBUG_printf DEBUG_printf

View File

@@ -27,8 +27,8 @@
#include <stdlib.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
@@ -167,7 +167,7 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
}
}
machine_uint_t hash = mp_obj_hash(index);
mp_uint_t hash = mp_obj_hash(index);
uint pos = hash % map->alloc;
uint start_pos = pos;
mp_map_elem_t *avail_slot = NULL;
@@ -270,7 +270,7 @@ mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t looku
return NULL;
}
}
machine_uint_t hash = mp_obj_hash(index);
mp_uint_t hash = mp_obj_hash(index);
uint pos = hash % set->alloc;
uint start_pos = pos;
mp_obj_t *avail_slot = NULL;

View File

@@ -82,14 +82,17 @@ int m_get_peak_bytes_allocated(void);
/** array helpers ***********************************************/
// get the number of elements in a fixed-size array
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
// align ptr to the nearest multiple of "alignment"
#define MP_ALIGN(ptr, alignment) (void*)(((mp_uint_t)(ptr) + ((alignment) - 1)) & ~((alignment) - 1))
/** unichar / UTF-8 *********************************************/
typedef int unichar; // TODO
unichar utf8_get_char(const char *s);
char *utf8_next_char(const char *s);
unichar utf8_get_char(const byte *s);
const byte *utf8_next_char(const byte *s);
bool unichar_isspace(unichar c);
bool unichar_isalpha(unichar c);
@@ -100,6 +103,9 @@ bool unichar_isupper(unichar c);
bool unichar_islower(unichar c);
unichar unichar_tolower(unichar c);
unichar unichar_toupper(unichar c);
mp_uint_t unichar_charlen(const char *str, mp_uint_t len);
#define UTF8_IS_NONASCII(ch) ((ch) & 0x80)
#define UTF8_IS_CONT(ch) (((ch) & 0xC0) == 0x80)
/** variable string *********************************************/
@@ -163,4 +169,18 @@ int DEBUG_printf(const char *fmt, ...);
extern uint mp_verbose_flag;
// This is useful for unicode handling. Some CPU archs has
// special instructions for efficient implentation of this
// function (e.g. CLZ on ARM).
// NOTE: this function is unused at the moment
#ifndef count_lead_ones
static inline uint count_lead_ones(byte val) {
uint c = 0;
for (byte mask = 0x80; val & mask; mask >>= 1) {
c++;
}
return c;
}
#endif
#endif // _INCLUDED_MINILIB_H

View File

@@ -73,9 +73,9 @@ all: $(PROG)
$(PROG): $(OBJ)
$(ECHO) "LINK $@"
$(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS)
$(Q)$(CC) $(COPT) -o $@ $(OBJ) $(LIB) $(LDFLAGS)
ifndef DEBUG
$(Q)$(STRIP) $(PROG)
$(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG)
endif
$(Q)$(SIZE) $(PROG)
@@ -97,4 +97,10 @@ print-cfg:
$(ECHO) "OBJ = $(OBJ)"
.PHONY: print-cfg
print-def:
@$(ECHO) "The following defines are built into the $(CC) compiler"
touch __empty__.c
@$(CC) -E -Wp,-dM __empty__.c
@$(RM) -f __empty__.c
-include $(OBJ:.o=.P)

View File

@@ -24,12 +24,14 @@
* THE SOFTWARE.
*/
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
#if MICROPY_PY_ARRAY
STATIC const mp_map_elem_t mp_module_array_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_array) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_array), (mp_obj_t)&mp_type_array },
@@ -40,8 +42,8 @@ STATIC const mp_obj_dict_t mp_module_array_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_module_array_globals_table),
.alloc = ARRAY_SIZE(mp_module_array_globals_table),
.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,
},
};
@@ -51,3 +53,5 @@ const mp_obj_module_t mp_module_array = {
.name = MP_QSTR_array,
.globals = (mp_obj_dict_t*)&mp_module_array_globals,
};
#endif

View File

@@ -26,8 +26,8 @@
#include <math.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -142,8 +142,8 @@ STATIC const mp_obj_dict_t mp_module_cmath_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_module_cmath_globals_table),
.alloc = ARRAY_SIZE(mp_module_cmath_globals_table),
.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,
},
};

View File

@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -42,8 +42,8 @@ STATIC const mp_obj_dict_t mp_module_collections_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_module_collections_globals_table),
.alloc = ARRAY_SIZE(mp_module_collections_globals_table),
.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,
},
};

View File

@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -42,7 +42,7 @@ extern uint gc_collected;
STATIC mp_obj_t py_gc_collect(void) {
gc_collect();
#if MICROPY_PY_GC_COLLECT_RETVAL
return MP_OBJ_NEW_SMALL_INT((machine_uint_t)gc_collected);
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)gc_collected);
#else
return mp_const_none;
#endif
@@ -61,11 +61,27 @@ STATIC mp_obj_t gc_enable(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(gc_enable_obj, gc_enable);
STATIC mp_obj_t gc_mem_free(void) {
gc_info_t info;
gc_info(&info);
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)info.free);
}
MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_free_obj, gc_mem_free);
STATIC mp_obj_t gc_mem_alloc(void) {
gc_info_t info;
gc_info(&info);
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)info.used);
}
MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_alloc_obj, gc_mem_alloc);
STATIC const mp_map_elem_t mp_module_gc_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_gc) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_collect), (mp_obj_t)&gc_collect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&gc_disable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&gc_enable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_free), (mp_obj_t)&gc_mem_free_obj },
{ 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 = {
@@ -73,8 +89,8 @@ STATIC const mp_obj_dict_t mp_module_gc_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_module_gc_globals_table),
.alloc = ARRAY_SIZE(mp_module_gc_globals_table),
.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,
},
};

View File

@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -57,8 +57,8 @@ STATIC const mp_obj_dict_t mp_module_io_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_module_io_globals_table),
.alloc = ARRAY_SIZE(mp_module_io_globals_table),
.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,
},
};

View File

@@ -26,8 +26,8 @@
#include <math.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -48,7 +48,7 @@
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((machine_int_t)MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
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_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
// These are also used by cmath.c
@@ -172,8 +172,8 @@ STATIC const mp_obj_dict_t mp_module_math_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_module_math_globals_table),
.alloc = ARRAY_SIZE(mp_module_math_globals_table),
.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,
},
};

View File

@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -35,15 +35,15 @@
#if MICROPY_MEM_STATS
STATIC mp_obj_t mp_micropython_mem_total() {
return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_total_bytes_allocated());
return MP_OBJ_NEW_SMALL_INT((mp_int_t)m_get_total_bytes_allocated());
}
STATIC mp_obj_t mp_micropython_mem_current() {
return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_current_bytes_allocated());
return MP_OBJ_NEW_SMALL_INT((mp_int_t)m_get_current_bytes_allocated());
}
STATIC mp_obj_t mp_micropython_mem_peak() {
return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_peak_bytes_allocated());
return MP_OBJ_NEW_SMALL_INT((mp_int_t)m_get_peak_bytes_allocated());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_total_obj, mp_micropython_mem_total);
@@ -65,8 +65,8 @@ STATIC const mp_obj_dict_t mp_module_micropython_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_module_micropython_globals_table),
.alloc = ARRAY_SIZE(mp_module_micropython_globals_table),
.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,
},
};

View File

@@ -27,8 +27,8 @@
#include <assert.h>
#include <string.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -74,13 +74,13 @@ STATIC char get_fmt_type(const char **fmt) {
return t;
}
STATIC machine_uint_t get_fmt_num(const char **p) {
STATIC mp_uint_t get_fmt_num(const char **p) {
const char *num = *p;
uint len = 1;
while (unichar_isdigit(*++num)) {
len++;
}
machine_uint_t val = (machine_uint_t)MP_OBJ_SMALL_INT_VALUE(mp_parse_num_integer(*p, len, 10));
mp_uint_t val = (mp_uint_t)MP_OBJ_SMALL_INT_VALUE(mp_parse_num_integer(*p, len, 10));
*p = num;
return val;
}
@@ -99,10 +99,10 @@ STATIC uint calcsize_items(const char *fmt) {
STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
const char *fmt = mp_obj_str_get_str(fmt_in);
char fmt_type = get_fmt_type(&fmt);
machine_uint_t size;
mp_uint_t size;
for (size = 0; *fmt; fmt++) {
uint align = 1;
machine_uint_t cnt = 1;
mp_uint_t cnt = 1;
if (unichar_isdigit(*fmt)) {
cnt = get_fmt_num(&fmt);
}
@@ -111,14 +111,14 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
assert(*fmt == 's');
}
machine_uint_t sz;
mp_uint_t sz;
if (*fmt == 's') {
sz = cnt;
} else {
sz = (machine_uint_t)mp_binary_get_size(fmt_type, *fmt, &align);
sz = (mp_uint_t)mp_binary_get_size(fmt_type, *fmt, &align);
}
// TODO
assert(sz != (machine_uint_t)-1);
assert(sz != (mp_uint_t)-1);
// Apply alignment
size = (size + align - 1) & ~(align - 1);
size += sz;
@@ -138,7 +138,7 @@ STATIC mp_obj_t struct_unpack(mp_obj_t fmt_in, mp_obj_t data_in) {
byte *p = bufinfo.buf;
for (uint i = 0; i < size; i++) {
machine_uint_t sz = 1;
mp_uint_t sz = 1;
if (unichar_isdigit(*fmt)) {
sz = get_fmt_num(&fmt);
}
@@ -170,7 +170,7 @@ STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) {
memset(p, 0, size);
for (uint i = 1; i < n_args; i++) {
machine_uint_t sz = 1;
mp_uint_t sz = 1;
if (unichar_isdigit(*fmt)) {
sz = get_fmt_num(&fmt);
}
@@ -182,7 +182,7 @@ STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) {
if (*fmt == 's') {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[i], &bufinfo, MP_BUFFER_READ);
machine_uint_t to_copy = sz;
mp_uint_t to_copy = sz;
if (bufinfo.len < to_copy) {
to_copy = bufinfo.len;
}
@@ -210,8 +210,8 @@ STATIC const mp_obj_dict_t mp_module_struct_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_module_struct_globals_table),
.alloc = ARRAY_SIZE(mp_module_struct_globals_table),
.used = MP_ARRAY_SIZE(mp_module_struct_globals_table),
.alloc = MP_ARRAY_SIZE(mp_module_struct_globals_table),
.table = (mp_map_elem_t*)mp_module_struct_globals_table,
},
};

View File

@@ -24,8 +24,10 @@
* THE SOFTWARE.
*/
#include "misc.h"
#include <stdint.h>
#include <limits.h>
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -33,6 +35,8 @@
#include "objlist.h"
#include "objtuple.h"
#include "objstr.h"
#include "mpz.h"
#include "objint.h"
#if MICROPY_PY_SYS
@@ -44,6 +48,8 @@ extern struct _dummy_t mp_sys_stdin_obj;
extern struct _dummy_t mp_sys_stdout_obj;
extern struct _dummy_t mp_sys_stderr_obj;
extern mp_obj_int_t mp_maxsize_obj;
mp_obj_list_t mp_sys_path_obj;
mp_obj_list_t mp_sys_argv_obj;
#define I(n) MP_OBJ_NEW_SMALL_INT(n)
@@ -70,6 +76,19 @@ STATIC const mp_map_elem_t mp_module_sys_globals_table[] = {
#else
{ MP_OBJ_NEW_QSTR(MP_QSTR_byteorder), MP_OBJ_NEW_QSTR(MP_QSTR_big) },
#endif
#if MICROPY_PY_SYS_MAXSIZE
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
// INT_MAX is not representable as small int, as we know that small int
// takes one bit for tag. So, we have little choice but to provide this
// value. Apps also should be careful to not try to compare sys.maxsize
// with some number (which may not fit in available int size), but instead
// count number of significant bits in sys.maxsize.
{ MP_OBJ_NEW_QSTR(MP_QSTR_maxsize), MP_OBJ_NEW_SMALL_INT(INT_MAX >> 1) },
#else
{ MP_OBJ_NEW_QSTR(MP_QSTR_maxsize), (mp_obj_t)&mp_maxsize_obj },
#endif
#endif
#if MICROPY_PY_SYS_EXIT
{ MP_OBJ_NEW_QSTR(MP_QSTR_exit), (mp_obj_t)&mp_sys_exit_obj },
@@ -87,8 +106,8 @@ STATIC const mp_obj_dict_t mp_module_sys_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = ARRAY_SIZE(mp_module_sys_globals_table),
.alloc = ARRAY_SIZE(mp_module_sys_globals_table),
.used = MP_ARRAY_SIZE(mp_module_sys_globals_table),
.alloc = MP_ARRAY_SIZE(mp_module_sys_globals_table),
.table = (mp_map_elem_t*)mp_module_sys_globals_table,
},
};

View File

@@ -157,6 +157,12 @@
#define MICROPY_ENABLE_GC_FINALISER (0)
#endif
// Whether to check C stack usage. C stack used for calling Python functions,
// etc. Not checking means segfault on overflow.
#ifndef MICROPY_STACK_CHECK
#define MICROPY_STACK_CHECK (1)
#endif
// Whether to include REPL helper function
#ifndef MICROPY_HELPER_REPL
#define MICROPY_HELPER_REPL (0)
@@ -223,6 +229,10 @@ typedef double mp_float_t;
#define MICROPY_PY_BUILTINS_FLOAT (0)
#endif
#ifndef MICROPY_PY_BUILTINS_COMPLEX
#define MICROPY_PY_BUILTINS_COMPLEX (MICROPY_PY_BUILTINS_FLOAT)
#endif
// Enable features which improve CPython compatibility
// but may lead to more code size/memory usage.
// TODO: Originally intended as generic category to not
@@ -239,6 +249,16 @@ typedef double mp_float_t;
/*****************************************************************************/
/* Fine control over Python builtins, classes, modules, etc */
// Whether str object is proper unicode
#ifndef MICROPY_PY_BUILTINS_STR_UNICODE
#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
#endif
// Whether to support bytearray object
#ifndef MICROPY_PY_BUILTINS_BYTEARRAY
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
#endif
// Whether to support set object
#ifndef MICROPY_PY_BUILTINS_SET
#define MICROPY_PY_BUILTINS_SET (1)
@@ -259,6 +279,13 @@ typedef double mp_float_t;
#define MICROPY_PY_BUILTINS_PROPERTY (1)
#endif
// Whether to provide "array" module. Note that large chunk of the
// underlying code is shared with "bytearray" builtin type, so to
// get real savings, it should be disabled too.
#ifndef MICROPY_PY_ARRAY
#define MICROPY_PY_ARRAY (1)
#endif
// Whether to provide "collections" module
#ifndef MICROPY_PY_COLLECTIONS
#define MICROPY_PY_COLLECTIONS (1)
@@ -309,6 +336,11 @@ typedef double mp_float_t;
#define MICROPY_PY_SYS (1)
#endif
// Whether to provide "sys.maxsize" constant
#ifndef MICROPY_PY_SYS_MAXSIZE
#define MICROPY_PY_SYS_MAXSIZE (0)
#endif
// Whether to provide "sys.exit" function
#ifndef MICROPY_PY_SYS_EXIT
#define MICROPY_PY_SYS_EXIT (0)
@@ -319,6 +351,12 @@ typedef double mp_float_t;
#define MICROPY_PY_SYS_STDFILES (0)
#endif
// Extended modules
#ifndef MICROPY_PY_UCTYPES
#define MICROPY_PY_UCTYPES (0)
#endif
/*****************************************************************************/
/* Hooks for a port to add builtins */
@@ -348,8 +386,8 @@ typedef double mp_float_t;
#define BITS_PER_BYTE (8)
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
// machine_int_t value with most significant bit set
#define WORD_MSBIT_HIGH (((machine_uint_t)1) << (BYTES_PER_WORD * 8 - 1))
// mp_int_t value with most significant bit set
#define WORD_MSBIT_HIGH (((mp_uint_t)1) << (BYTES_PER_WORD * 8 - 1))
#if !defined(MP_ENDIANNESS_LITTLE) && !defined(MP_ENDIANNESS_BIG)
// Just because most archs are such?
@@ -360,14 +398,14 @@ typedef double mp_float_t;
#define MP_ENDIANNESS_LITTLE (0)
#endif
// printf format spec to use for machine_int_t and friends
// printf format spec to use for mp_int_t and friends
#ifndef INT_FMT
#ifdef __LP64__
// Archs where machine_int_t == long, long != int
// Archs where mp_int_t == long, long != int
#define UINT_FMT "%lu"
#define INT_FMT "%ld"
#else
// Archs where machine_int_t == int
// Archs where mp_int_t == int
#define UINT_FMT "%u"
#define INT_FMT "%d"
#endif
@@ -377,3 +415,8 @@ typedef double mp_float_t;
#ifndef NORETURN
#define NORETURN __attribute__((noreturn))
#endif
// Modifier for weak functions
#ifndef MP_WEAK
#define MP_WEAK __attribute__((weak))
#endif

View File

@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "mpz.h"
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
@@ -351,7 +351,7 @@ STATIC uint mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, uint jlen, mpz_dig_t *kdig
modifies den_dig memory, but restors it to original state at end
*/
STATIC void mpn_div(mpz_dig_t *num_dig, machine_uint_t *num_len, mpz_dig_t *den_dig, machine_uint_t den_len, mpz_dig_t *quo_dig, machine_uint_t *quo_len) {
STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig, mp_uint_t den_len, mpz_dig_t *quo_dig, mp_uint_t *quo_len) {
mpz_dig_t *orig_num_dig = num_dig;
mpz_dig_t *orig_quo_dig = quo_dig;
mpz_dig_t norm_shift = 0;
@@ -502,12 +502,12 @@ void mpz_init_zero(mpz_t *z) {
z->dig = NULL;
}
void mpz_init_from_int(mpz_t *z, machine_int_t val) {
void mpz_init_from_int(mpz_t *z, mp_int_t val) {
mpz_init_zero(z);
mpz_set_from_int(z, val);
}
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, uint alloc, machine_int_t val) {
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, uint alloc, mp_int_t val) {
z->neg = 0;
z->fixed_dig = 1;
z->alloc = alloc;
@@ -528,7 +528,7 @@ mpz_t *mpz_zero(void) {
return z;
}
mpz_t *mpz_from_int(machine_int_t val) {
mpz_t *mpz_from_int(mp_int_t val) {
mpz_t *z = mpz_zero();
mpz_set_from_int(z, val);
return z;
@@ -594,10 +594,10 @@ void mpz_set(mpz_t *dest, const mpz_t *src) {
memcpy(dest->dig, src->dig, src->len * sizeof(mpz_dig_t));
}
void mpz_set_from_int(mpz_t *z, machine_int_t val) {
void mpz_set_from_int(mpz_t *z, mp_int_t val) {
mpz_need_dig(z, MPZ_NUM_DIG_FOR_INT);
machine_uint_t uval;
mp_uint_t uval;
if (val < 0) {
z->neg = 1;
uval = -val;
@@ -704,7 +704,7 @@ int mpz_cmp(const mpz_t *z1, const mpz_t *z2) {
#if 0
// obsolete
// compares mpz with an integer that fits within DIG_SIZE bits
int mpz_cmp_sml_int(const mpz_t *z, machine_int_t sml_int) {
int mpz_cmp_sml_int(const mpz_t *z, mp_int_t sml_int) {
int cmp;
if (z->neg == 0) {
if (sml_int < 0) return 1;
@@ -830,7 +830,7 @@ void mpz_not_inpl(mpz_t *dest, const mpz_t *z) {
/* computes dest = lhs << rhs
can have dest, lhs the same
*/
void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, machine_int_t rhs) {
void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, mp_int_t rhs) {
if (lhs->len == 0 || rhs == 0) {
mpz_set(dest, lhs);
} else if (rhs < 0) {
@@ -845,7 +845,7 @@ void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, machine_int_t rhs) {
/* computes dest = lhs >> rhs
can have dest, lhs the same
*/
void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, machine_int_t rhs) {
void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, mp_int_t rhs) {
if (lhs->len == 0 || rhs == 0) {
mpz_set(dest, lhs);
} else if (rhs < 0) {
@@ -1214,12 +1214,12 @@ mpz_t *mpz_mod(const mpz_t *lhs, const mpz_t *rhs) {
#endif
// TODO check that this correctly handles overflow in all cases
machine_int_t mpz_as_int(const mpz_t *i) {
machine_int_t val = 0;
mp_int_t mpz_as_int(const mpz_t *i) {
mp_int_t val = 0;
mpz_dig_t *d = i->dig + i->len;
while (--d >= i->dig) {
machine_int_t oldval = val;
mp_int_t oldval = val;
val = (val << DIG_SIZE) | *d;
if (val < oldval) {
// overflow, return +/- "infinity"
@@ -1241,12 +1241,12 @@ machine_int_t mpz_as_int(const mpz_t *i) {
}
// TODO check that this correctly handles overflow in all cases
bool mpz_as_int_checked(const mpz_t *i, machine_int_t *value) {
machine_int_t val = 0;
bool mpz_as_int_checked(const mpz_t *i, mp_int_t *value) {
mp_int_t val = 0;
mpz_dig_t *d = i->dig + i->len;
while (--d >= i->dig) {
machine_int_t oldval = val;
mp_int_t oldval = val;
val = (val << DIG_SIZE) | *d;
if (val < oldval) {
// overflow

View File

@@ -29,27 +29,27 @@ typedef uint32_t mpz_dbl_dig_t;
typedef int32_t mpz_dbl_dig_signed_t;
typedef struct _mpz_t {
machine_uint_t neg : 1;
machine_uint_t fixed_dig : 1;
machine_uint_t alloc : 30;
machine_uint_t len;
mp_uint_t neg : 1;
mp_uint_t fixed_dig : 1;
mp_uint_t alloc : 30;
mp_uint_t len;
mpz_dig_t *dig;
} mpz_t;
#define MPZ_DIG_SIZE (15) // see mpn_div for why this needs to be at most 15
#define MPZ_NUM_DIG_FOR_INT (sizeof(machine_int_t) * 8 / MPZ_DIG_SIZE + 1)
#define MPZ_NUM_DIG_FOR_INT (sizeof(mp_int_t) * 8 / MPZ_DIG_SIZE + 1)
#define MPZ_NUM_DIG_FOR_LL (sizeof(long long) * 8 / MPZ_DIG_SIZE + 1)
// convenience macro to declare an mpz with a digit array from the stack, initialised by an integer
#define MPZ_CONST_INT(z, val) mpz_t z; mpz_dig_t z ## _digits[MPZ_NUM_DIG_FOR_INT]; mpz_init_fixed_from_int(&z, z_digits, MPZ_NUM_DIG_FOR_INT, val);
void mpz_init_zero(mpz_t *z);
void mpz_init_from_int(mpz_t *z, machine_int_t val);
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, uint dig_alloc, machine_int_t val);
void mpz_init_from_int(mpz_t *z, mp_int_t val);
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, uint dig_alloc, mp_int_t val);
void mpz_deinit(mpz_t *z);
mpz_t *mpz_zero();
mpz_t *mpz_from_int(machine_int_t i);
mpz_t *mpz_from_int(mp_int_t i);
mpz_t *mpz_from_ll(long long i);
mpz_t *mpz_from_str(const char *str, uint len, bool neg, uint base);
void mpz_free(mpz_t *z);
@@ -57,7 +57,7 @@ void mpz_free(mpz_t *z);
mpz_t *mpz_clone(const mpz_t *src);
void mpz_set(mpz_t *dest, const mpz_t *src);
void mpz_set_from_int(mpz_t *z, machine_int_t src);
void mpz_set_from_int(mpz_t *z, mp_int_t src);
void mpz_set_from_ll(mpz_t *z, long long i);
uint mpz_set_from_str(mpz_t *z, const char *str, uint len, bool neg, uint base);
@@ -79,8 +79,8 @@ mpz_t *mpz_pow(const mpz_t *lhs, const mpz_t *rhs);
void mpz_abs_inpl(mpz_t *dest, const mpz_t *z);
void mpz_neg_inpl(mpz_t *dest, const mpz_t *z);
void mpz_not_inpl(mpz_t *dest, const mpz_t *z);
void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, machine_int_t rhs);
void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, machine_int_t rhs);
void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, mp_int_t rhs);
void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, mp_int_t rhs);
void mpz_add_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
void mpz_mul_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
@@ -96,8 +96,8 @@ void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const m
mpz_t *mpz_div(const mpz_t *lhs, const mpz_t *rhs);
mpz_t *mpz_mod(const mpz_t *lhs, const mpz_t *rhs);
machine_int_t mpz_as_int(const mpz_t *z);
bool mpz_as_int_checked(const mpz_t *z, machine_int_t *value);
mp_int_t mpz_as_int(const mpz_t *z);
bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value);
#if MICROPY_PY_BUILTINS_FLOAT
mp_float_t mpz_as_float(const mpz_t *z);
#endif

View File

@@ -29,6 +29,7 @@
#include <limits.h>
#include <setjmp.h>
#include <assert.h>
typedef struct _nlr_buf_t nlr_buf_t;
struct _nlr_buf_t {
@@ -44,7 +45,7 @@ struct _nlr_buf_t {
#else
void *regs[8];
#endif
#elif defined(__thumb2__)
#elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__)
void *regs[10];
#else
#define MICROPY_NLR_SETJMP (1)

View File

@@ -24,19 +24,21 @@
* THE SOFTWARE.
*/
#if defined(__thumb2__) && !MICROPY_NLR_SETJMP
/* thumb callee save: bx, bp, sp, r12, r14, r14, r15 */
#if !MICROPY_NLR_SETJMP && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__))
/* arm callee save: bx, bp, sp, r12, r14, r14, r15 */
.syntax unified
/*.cpu cortex-m4*/
.thumb
/*.thumb*/
.text
.align 2
/* uint nlr_push(r0=nlr_buf_t *nlr) */
.global nlr_push
#if defined(__thumb2__)
.thumb
.thumb_func
#endif
.type nlr_push, %function
nlr_push:
str lr, [r0, #8] @ store lr into nlr_buf
@@ -64,8 +66,10 @@ nlr_push:
@ void nlr_pop()
.global nlr_pop
#if defined(__thumb2__)
.thumb
.thumb_func
#endif
.type nlr_pop, %function
nlr_pop:
ldr r3, .L5 @ load addr of nlr_top
@@ -80,8 +84,10 @@ nlr_pop:
/* void nlr_jump(r0=uint val) */
.global nlr_jump
#if defined(__thumb2__)
.thumb
.thumb_func
#endif
.type nlr_jump, %function
nlr_jump:
ldr r3, .L2 @ load addr of nlr_top

View File

@@ -35,6 +35,7 @@
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
#include "stackctrl.h"
mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
@@ -59,6 +60,8 @@ void printf_wrapper(void *env, const char *fmt, ...) {
}
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
// There can be data structures nested too deep, or just recursive
MP_STACK_CHECK();
#if !NDEBUG
if (o_in == NULL) {
print(env, "(nil)");
@@ -80,7 +83,7 @@ void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {
// helper function to print an exception with traceback
void mp_obj_print_exception(mp_obj_t exc) {
if (mp_obj_is_exception_instance(exc)) {
machine_uint_t n, *values;
mp_uint_t n, *values;
mp_obj_exception_get_traceback(exc, &n, &values);
if (n > 0) {
assert(n % 3 == 0);
@@ -142,7 +145,7 @@ bool mp_obj_is_callable(mp_obj_t o_in) {
return mp_obj_get_type(o_in)->call != NULL;
}
machine_int_t mp_obj_hash(mp_obj_t o_in) {
mp_int_t mp_obj_hash(mp_obj_t o_in) {
if (o_in == mp_const_false) {
return 0; // needs to hash to same as the integer 0, since False==0
} else if (o_in == mp_const_true) {
@@ -152,13 +155,13 @@ machine_int_t mp_obj_hash(mp_obj_t o_in) {
} else if (MP_OBJ_IS_STR(o_in) || MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) {
return mp_obj_str_get_hash(o_in);
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_NoneType)) {
return (machine_int_t)o_in;
return (mp_int_t)o_in;
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_fun_native) || MP_OBJ_IS_TYPE(o_in, &mp_type_fun_bc)) {
return (machine_int_t)o_in;
return (mp_int_t)o_in;
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_tuple)) {
return mp_obj_tuple_hash(o_in);
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_type)) {
return (machine_int_t)o_in;
return (mp_int_t)o_in;
// TODO hash class and instances
// TODO delegate to __hash__ method if it exists
@@ -222,7 +225,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
return false;
}
machine_int_t mp_obj_get_int(mp_const_obj_t arg) {
mp_int_t mp_obj_get_int(mp_const_obj_t arg) {
// This function essentially performs implicit type conversion to int
// Note that Python does NOT provide implicit type conversion from
// float to int in the core expression language, try some_list[1.0].
@@ -241,8 +244,8 @@ machine_int_t mp_obj_get_int(mp_const_obj_t arg) {
// returns false if arg is not of integral type
// returns true and sets *value if it is of integral type
// can throw OverflowError if arg is of integral type, but doesn't fit in a machine_int_t
bool mp_obj_get_int_maybe(mp_const_obj_t arg, machine_int_t *value) {
// can throw OverflowError if arg is of integral type, but doesn't fit in a mp_int_t
bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value) {
if (arg == mp_const_false) {
*value = 0;
} else if (arg == mp_const_true) {
@@ -274,6 +277,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) {
}
}
#if MICROPY_PY_BUILTINS_COMPLEX
void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
if (arg == mp_const_false) {
*real = 0;
@@ -297,6 +301,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
}
}
#endif
#endif
void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items) {
if (MP_OBJ_IS_TYPE(o, &mp_type_tuple)) {
@@ -325,8 +330,8 @@ void mp_obj_get_array_fixed_n(mp_obj_t o, uint len, mp_obj_t **items) {
}
// is_slice determines whether the index is a slice index
uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index, bool is_slice) {
machine_int_t i;
uint mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, bool is_slice) {
mp_int_t i;
if (MP_OBJ_IS_SMALL_INT(index)) {
i = MP_OBJ_SMALL_INT_VALUE(index);
} else if (!mp_obj_get_int_maybe(index, &i)) {
@@ -352,8 +357,13 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index,
// may return MP_OBJ_NULL
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
if (MP_OBJ_IS_STR(o_in) || MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) {
return MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_str_get_len(o_in));
if (
#if !MICROPY_PY_BUILTINS_STR_UNICODE
// It's simple - unicode is slow, non-unicode is fast
MP_OBJ_IS_STR(o_in) ||
#endif
MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) {
return MP_OBJ_NEW_SMALL_INT((mp_int_t)mp_obj_str_get_len(o_in));
} else {
mp_obj_type_t *type = mp_obj_get_type(o_in);
if (type->unary_op != NULL) {

View File

@@ -35,11 +35,6 @@
typedef machine_ptr_t mp_obj_t;
typedef machine_const_ptr_t mp_const_obj_t;
// Integers that fit in a pointer have this type
// (do we need to expose this in the public API?)
typedef machine_int_t mp_small_int_t;
// Anything that wants to be a Micro Python object must have
// mp_obj_base_t as its first member (except small ints and qstrs)
@@ -73,18 +68,18 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
// These macros check for small int, qstr or object, and access small int and qstr values
// these macros have now become inline functions; see below
//#define MP_OBJ_IS_SMALL_INT(o) ((((mp_small_int_t)(o)) & 1) != 0)
//#define MP_OBJ_IS_QSTR(o) ((((mp_small_int_t)(o)) & 3) == 2)
//#define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 3) == 0)
//#define MP_OBJ_IS_SMALL_INT(o) ((((mp_int_t)(o)) & 1) != 0)
//#define MP_OBJ_IS_QSTR(o) ((((mp_int_t)(o)) & 3) == 2)
//#define MP_OBJ_IS_OBJ(o) ((((mp_int_t)(o)) & 3) == 0)
#define MP_OBJ_IS_TYPE(o, t) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)(o))->type == (t))) // this does not work for checking a string, use below macro for that
#define MP_OBJ_IS_INT(o) (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int))
#define MP_OBJ_IS_STR(o) (MP_OBJ_IS_QSTR(o) || MP_OBJ_IS_TYPE(o, &mp_type_str))
#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_small_int_t)(o)) >> 1)
#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 1)
#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)(((small_int) << 1) | 1))
#define MP_OBJ_QSTR_VALUE(o) (((mp_small_int_t)(o)) >> 2)
#define MP_OBJ_NEW_QSTR(qstr) ((mp_obj_t)((((machine_uint_t)qstr) << 2) | 2))
#define MP_OBJ_QSTR_VALUE(o) (((mp_int_t)(o)) >> 2)
#define MP_OBJ_NEW_QSTR(qstr) ((mp_obj_t)((((mp_uint_t)qstr) << 2) | 2))
// These macros are used to declare and define constant function objects
// You can put "static" in front of the definitions to make them local
@@ -137,10 +132,10 @@ typedef struct _mp_map_elem_t {
// would also need a trucated dict structure
typedef struct _mp_map_t {
machine_uint_t all_keys_are_qstrs : 1;
machine_uint_t table_is_fixed_array : 1;
machine_uint_t used : (8 * sizeof(machine_uint_t) - 2);
machine_uint_t alloc;
mp_uint_t all_keys_are_qstrs : 1;
mp_uint_t table_is_fixed_array : 1;
mp_uint_t used : (8 * sizeof(mp_uint_t) - 2);
mp_uint_t alloc;
mp_map_elem_t *table;
} mp_map_t;
@@ -151,7 +146,7 @@ typedef enum _mp_map_lookup_kind_t {
MP_MAP_LOOKUP_REMOVE_IF_FOUND, // 2
} mp_map_lookup_kind_t;
static inline bool MP_MAP_SLOT_IS_FILLED(const mp_map_t *map, machine_uint_t pos) { return ((map)->table[pos].key != MP_OBJ_NULL && (map)->table[pos].key != MP_OBJ_SENTINEL); }
static inline bool MP_MAP_SLOT_IS_FILLED(const mp_map_t *map, mp_uint_t pos) { return ((map)->table[pos].key != MP_OBJ_NULL && (map)->table[pos].key != MP_OBJ_SENTINEL); }
void mp_map_init(mp_map_t *map, int n);
void mp_map_init_fixed_table(mp_map_t *map, int n, const mp_obj_t *table);
@@ -165,12 +160,12 @@ void mp_map_dump(mp_map_t *map);
// Underlying set implementation (not set object)
typedef struct _mp_set_t {
machine_uint_t alloc;
machine_uint_t used;
mp_uint_t alloc;
mp_uint_t used;
mp_obj_t *table;
} mp_set_t;
static inline bool MP_SET_SLOT_IS_FILLED(const mp_set_t *set, machine_uint_t pos) { return ((set)->table[pos] != MP_OBJ_NULL && (set)->table[pos] != MP_OBJ_SENTINEL); }
static inline bool MP_SET_SLOT_IS_FILLED(const mp_set_t *set, mp_uint_t pos) { return ((set)->table[pos] != MP_OBJ_NULL && (set)->table[pos] != MP_OBJ_SENTINEL); }
void mp_set_init(mp_set_t *set, int n);
mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind);
@@ -216,7 +211,7 @@ typedef struct _mp_buffer_info_t {
//int ver; // ?
void *buf;
machine_int_t len; // in bytes
mp_int_t len; // in bytes
int typecode; // as per binary.h
// Rationale: to load arbitrary-sized sprites directly to LCD
@@ -227,7 +222,7 @@ typedef struct _mp_buffer_info_t {
#define MP_BUFFER_WRITE (2)
#define MP_BUFFER_RW (MP_BUFFER_READ | MP_BUFFER_WRITE)
typedef struct _mp_buffer_p_t {
machine_int_t (*get_buffer)(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags);
mp_int_t (*get_buffer)(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags);
} mp_buffer_p_t;
bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags);
void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags);
@@ -236,8 +231,8 @@ void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags);
typedef struct _mp_stream_p_t {
// On error, functions should return -1 and fill in *errcode (values are
// implementation-dependent, but will be exposed to user, e.g. via exception).
machine_int_t (*read)(mp_obj_t obj, void *buf, machine_uint_t size, int *errcode);
machine_int_t (*write)(mp_obj_t obj, const void *buf, machine_uint_t size, int *errcode);
mp_int_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
mp_int_t (*write)(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode);
// add seek() ?
int is_bytes : 1;
} mp_stream_p_t;
@@ -365,8 +360,8 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict);
mp_obj_t mp_obj_new_none(void);
mp_obj_t mp_obj_new_bool(bool value);
mp_obj_t mp_obj_new_cell(mp_obj_t obj);
mp_obj_t mp_obj_new_int(machine_int_t value);
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value);
mp_obj_t mp_obj_new_int(mp_int_t value);
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value);
mp_obj_t mp_obj_new_int_from_str_len(const char **str, uint len, bool neg, uint base);
mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception)
mp_obj_t mp_obj_new_str(const char* data, uint len, bool make_qstr_if_not_already);
@@ -406,20 +401,20 @@ void mp_obj_print_exception(mp_obj_t exc);
int mp_obj_is_true(mp_obj_t arg);
// TODO make these all lower case when they have proven themselves
static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o) { return ((((mp_small_int_t)(o)) & 3) == 0); }
static inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o) { return ((((mp_small_int_t)(o)) & 1) != 0); }
static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 3) == 0); }
static inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 1) != 0); }
//static inline bool MP_OBJ_IS_TYPE(mp_const_obj_t o, const mp_obj_type_t *t) { return (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)(o))->type == (t))); } // this does not work for checking a string, use below macro for that
//static inline bool MP_OBJ_IS_INT(mp_const_obj_t o) { return (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int)); } // returns true if o is a small int or long int
static inline bool mp_obj_is_integer(mp_const_obj_t o) { return MP_OBJ_IS_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_bool); } // returns true if o is bool, small int or long int
static inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o) { return ((((mp_small_int_t)(o)) & 3) == 2); }
static inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 3) == 2); }
//static inline bool MP_OBJ_IS_STR(mp_const_obj_t o) { return (MP_OBJ_IS_QSTR(o) || MP_OBJ_IS_TYPE(o, &mp_type_str)); }
bool mp_obj_is_callable(mp_obj_t o_in);
machine_int_t mp_obj_hash(mp_obj_t o_in);
mp_int_t mp_obj_hash(mp_obj_t o_in);
bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2);
machine_int_t mp_obj_get_int(mp_const_obj_t arg);
bool mp_obj_get_int_maybe(mp_const_obj_t arg, machine_int_t *value);
mp_int_t mp_obj_get_int(mp_const_obj_t arg);
bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value);
#if MICROPY_PY_BUILTINS_FLOAT
mp_float_t mp_obj_get_float(mp_obj_t self_in);
void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
@@ -427,26 +422,26 @@ void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
//qstr mp_obj_get_qstr(mp_obj_t arg);
void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items);
void mp_obj_get_array_fixed_n(mp_obj_t o, uint len, mp_obj_t **items);
uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index, bool is_slice);
uint mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, bool is_slice);
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); /* may return MP_OBJ_NULL */
mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val);
// bool
// TODO make lower case when it has proven itself
static inline mp_obj_t MP_BOOL(machine_int_t x) { return x ? mp_const_true : mp_const_false; }
static inline mp_obj_t MP_BOOL(mp_int_t x) { return x ? mp_const_true : mp_const_false; }
// cell
mp_obj_t mp_obj_cell_get(mp_obj_t self_in);
void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj);
// int
// For long int, returns value truncated to machine_int_t
machine_int_t mp_obj_int_get(mp_const_obj_t self_in);
// For long int, returns value truncated to mp_int_t
mp_int_t mp_obj_int_get(mp_const_obj_t self_in);
#if MICROPY_PY_BUILTINS_FLOAT
mp_float_t mp_obj_int_as_float(mp_obj_t self_in);
#endif
// Will raise exception if value doesn't fit into machine_int_t
machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in);
// Will raise exception if value doesn't fit into mp_int_t
mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in);
// exception
#define mp_obj_is_native_exception_instance(o) (mp_obj_get_type(o)->make_new == mp_obj_exception_make_new)
@@ -454,8 +449,8 @@ bool mp_obj_is_exception_type(mp_obj_t self_in);
bool mp_obj_is_exception_instance(mp_obj_t self_in);
bool mp_obj_exception_match(mp_obj_t exc, const mp_obj_type_t *exc_type);
void mp_obj_exception_clear_traceback(mp_obj_t self_in);
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block);
void mp_obj_exception_get_traceback(mp_obj_t self_in, machine_uint_t *n, machine_uint_t **values);
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, mp_uint_t line, qstr block);
void mp_obj_exception_get_traceback(mp_obj_t self_in, mp_uint_t *n, mp_uint_t **values);
mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in);
mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args);
@@ -469,7 +464,7 @@ qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway conve
const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated
const char *mp_obj_str_get_data(mp_obj_t self_in, uint *len);
mp_obj_t mp_obj_str_intern(mp_obj_t str);
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len);
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len, bool is_bytes);
#if MICROPY_PY_BUILTINS_FLOAT
// float
@@ -488,7 +483,7 @@ mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_im
// tuple
void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
void mp_obj_tuple_del(mp_obj_t self_in);
machine_int_t mp_obj_tuple_hash(mp_obj_t self_in);
mp_int_t mp_obj_tuple_hash(mp_obj_t self_in);
// list
struct _mp_obj_list_t;
@@ -562,14 +557,14 @@ const mp_obj_t *mp_obj_property_get(mp_obj_t self_in);
// slice indexes resolved to particular sequence
typedef struct {
machine_uint_t start;
machine_uint_t stop;
machine_int_t step;
mp_uint_t start;
mp_uint_t stop;
mp_int_t step;
} mp_bound_slice_t;
void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest);
#if MICROPY_PY_BUILTINS_SLICE
bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes);
bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes);
#endif
#define mp_seq_copy(dest, src, len, item_t) memcpy(dest, src, len * sizeof(item_t))
#define mp_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, (len1) * sizeof(item_t)); memcpy(dest + (len1), src2, (len2) * sizeof(item_t)); }

View File

@@ -37,13 +37,15 @@
#include "runtime.h"
#include "binary.h"
#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY
typedef struct _mp_obj_array_t {
mp_obj_base_t base;
machine_uint_t typecode : 8;
mp_uint_t typecode : 8;
// free is number of unused elements after len used elements
// alloc size = len + free
machine_uint_t free : (8 * sizeof(machine_uint_t) - 8);
machine_uint_t len; // in elements
mp_uint_t free : (8 * sizeof(mp_uint_t) - 8);
mp_uint_t len; // in elements
void *items;
} mp_obj_array_t;
@@ -58,7 +60,7 @@ STATIC void array_print(void (*print)(void *env, const char *fmt, ...), void *en
mp_obj_array_t *o = o_in;
if (o->typecode == BYTEARRAY_TYPECODE) {
print(env, "bytearray(b", o->typecode);
mp_str_print_quoted(print, env, o->items, o->len);
mp_str_print_quoted(print, env, o->items, o->len, true);
} else {
print(env, "array('%c'", o->typecode);
if (o->len > 0) {
@@ -204,7 +206,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
}
}
STATIC machine_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, int flags) {
STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, int flags) {
mp_obj_array_t *o = o_in;
bufinfo->buf = o->items;
bufinfo->len = o->len * mp_binary_get_size('@', o->typecode, NULL);
@@ -283,7 +285,7 @@ mp_obj_t mp_obj_new_bytearray_by_ref(uint n, void *items) {
typedef struct _mp_obj_array_it_t {
mp_obj_base_t base;
mp_obj_array_t *array;
machine_uint_t cur;
mp_uint_t cur;
} mp_obj_array_it_t;
STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
@@ -310,3 +312,5 @@ STATIC mp_obj_t array_iterator_new(mp_obj_t array_in) {
o->cur = 0;
return o;
}
#endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY

View File

@@ -61,7 +61,7 @@ STATIC mp_obj_t bool_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp
}
STATIC mp_obj_t bool_unary_op(int op, mp_obj_t o_in) {
machine_int_t value = ((mp_obj_bool_t*)o_in)->value;
mp_int_t value = ((mp_obj_bool_t*)o_in)->value;
switch (op) {
case MP_UNARY_OP_BOOL: return o_in;
case MP_UNARY_OP_POSITIVE: return MP_OBJ_NEW_SMALL_INT(value);
@@ -74,7 +74,7 @@ STATIC mp_obj_t bool_unary_op(int op, mp_obj_t o_in) {
STATIC mp_obj_t bool_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
if (MP_BINARY_OP_OR <= op && op <= MP_BINARY_OP_NOT_EQUAL) {
return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_is_true(lhs_in)), rhs_in);
return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT((mp_int_t)mp_obj_is_true(lhs_in)), rhs_in);
}
return MP_OBJ_NULL; // op not supported
}

View File

@@ -37,7 +37,7 @@
typedef struct _mp_obj_closure_t {
mp_obj_base_t base;
mp_obj_t fun;
machine_uint_t n_closed;
mp_uint_t n_closed;
mp_obj_t closed[];
} mp_obj_closure_t;

View File

@@ -36,7 +36,7 @@
#include "runtime0.h"
#include "runtime.h"
#if MICROPY_PY_BUILTINS_FLOAT
#if MICROPY_PY_BUILTINS_COMPLEX
#include <math.h>

View File

@@ -75,7 +75,7 @@ STATIC mp_obj_t dict_unary_op(int op, mp_obj_t self_in) {
mp_obj_dict_t *self = self_in;
switch (op) {
case MP_UNARY_OP_BOOL: return MP_BOOL(self->map.used != 0);
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->map.used);
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((mp_int_t)self->map.used);
default: return MP_OBJ_NULL; // op not supported
}
}
@@ -94,10 +94,10 @@ STATIC mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
return mp_const_false;
}
machine_uint_t size = o->map.alloc;
mp_uint_t size = o->map.alloc;
mp_map_t *map = &o->map;
for (machine_uint_t i = 0; i < size; i++) {
for (mp_uint_t i = 0; i < size; i++) {
if (MP_MAP_SLOT_IS_FILLED(map, i)) {
mp_map_elem_t *elem = mp_map_lookup(&rhs->map, map->table[i].key, MP_MAP_LOOKUP);
if (elem == NULL || !mp_obj_equal(map->table[i].value, elem->value)) {
@@ -155,12 +155,12 @@ STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
typedef struct _mp_obj_dict_it_t {
mp_obj_base_t base;
mp_obj_dict_t *dict;
machine_uint_t cur;
mp_uint_t cur;
} mp_obj_dict_it_t;
STATIC mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in) {
mp_obj_dict_it_t *self = self_in;
machine_uint_t max = self->dict->map.alloc;
mp_uint_t max = self->dict->map.alloc;
mp_map_t *map = &self->dict->map;
for (int i = self->cur; i < max; i++) {
@@ -374,7 +374,7 @@ STATIC mp_obj_t dict_update(uint n_args, const mp_obj_t *args, mp_map_t *kwargs)
}
// update the dict with any keyword args
for (machine_uint_t i = 0; i < kwargs->alloc; i++) {
for (mp_uint_t i = 0; i < kwargs->alloc; i++) {
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
mp_map_lookup(&self->map, kwargs->table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = kwargs->table[i].value;
}
@@ -403,7 +403,7 @@ typedef struct _mp_obj_dict_view_it_t {
mp_obj_base_t base;
mp_dict_view_kind_t kind;
mp_obj_dict_it_t *iter;
machine_uint_t cur;
mp_uint_t cur;
} mp_obj_dict_view_it_t;
typedef struct _mp_obj_dict_view_t {

View File

@@ -27,8 +27,8 @@
#include <stdlib.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -36,7 +36,7 @@
typedef struct _mp_obj_enumerate_t {
mp_obj_base_t base;
mp_obj_t iter;
machine_int_t cur;
mp_int_t cur;
} mp_obj_enumerate_t;
STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in);
@@ -45,7 +45,7 @@ STATIC const mp_arg_t enumerate_make_new_args[] = {
{ MP_QSTR_iterable, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_start, MP_ARG_INT, {.u_int = 0} },
};
#define ENUMERATE_MAKE_NEW_NUM_ARGS ARRAY_SIZE(enumerate_make_new_args)
#define ENUMERATE_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(enumerate_make_new_args)
STATIC mp_obj_t enumerate_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
#if MICROPY_CPYTHON_COMPAT

View File

@@ -37,6 +37,7 @@
#include "objtype.h"
#include "runtime.h"
#include "runtime0.h"
#include "gc.h"
typedef struct _mp_obj_exception_t {
mp_obj_base_t base;
@@ -334,19 +335,26 @@ void mp_obj_exception_clear_traceback(mp_obj_t self_in) {
self->traceback = MP_OBJ_NULL;
}
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block) {
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, mp_uint_t line, qstr block) {
#if MICROPY_ENABLE_GC
if (gc_is_locked()) {
// We can't allocate memory, so don't bother to try
return;
}
#endif
GET_NATIVE_EXCEPTION(self, self_in);
// for traceback, we are just using the list object for convenience, it's not really a list of Python objects
if (self->traceback == MP_OBJ_NULL) {
self->traceback = mp_obj_new_list(0, NULL);
}
mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)file);
mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)line);
mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)block);
mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)file);
mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)line);
mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)block);
}
void mp_obj_exception_get_traceback(mp_obj_t self_in, machine_uint_t *n, machine_uint_t **values) {
void mp_obj_exception_get_traceback(mp_obj_t self_in, mp_uint_t *n, mp_uint_t **values) {
GET_NATIVE_EXCEPTION(self, self_in);
if (self->traceback == MP_OBJ_NULL) {

View File

@@ -102,9 +102,12 @@ STATIC mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
STATIC mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_float_t *lhs = lhs_in;
#if MICROPY_PY_BUILTINS_COMPLEX
if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
return mp_obj_complex_binary_op(op, lhs->value, 0, rhs_in);
} else {
} else
#endif
{
return mp_obj_float_binary_op(op, lhs->value, rhs_in);
}
}

View File

@@ -39,6 +39,7 @@
#include "runtime0.h"
#include "runtime.h"
#include "bc.h"
#include "stackctrl.h"
#if 0 // print debugging info
#define DEBUG_PRINT (1)
@@ -196,7 +197,7 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, uint expected, ui
// With this macro you can tune the maximum number of function state bytes
// that will be allocated on the stack. Any function that needs more
// than this will use the heap.
#define VM_MAX_STATE_ON_STACK (10 * sizeof(machine_uint_t))
#define VM_MAX_STATE_ON_STACK (10 * sizeof(mp_uint_t))
// Set this to enable a simple stack overflow check.
#define VM_DETECT_STACK_OVERFLOW (0)
@@ -204,8 +205,10 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, uint expected, ui
// code_state should have ->ip filled in (pointing past code info block),
// as well as ->n_state.
void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// This function is pretty complicated. It's main aim is to be efficient in speed and RAM
// usage for the common case of positional only args.
mp_obj_fun_bc_t *self = self_in;
machine_uint_t n_state = code_state->n_state;
mp_uint_t n_state = code_state->n_state;
const byte *ip = code_state->ip;
code_state->code_info = self->bytecode;
@@ -353,8 +356,7 @@ continue2:;
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// This function is pretty complicated. It's main aim is to be efficient in speed and RAM
// usage for the common case of positional only args.
MP_STACK_CHECK();
DEBUG_printf("Input n_args: %d, n_kw: %d\n", n_args, n_kw);
DEBUG_printf("Input pos args: ");
@@ -367,12 +369,12 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o
const byte *ip = self->bytecode;
// get code info size, and skip line number table
machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
mp_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
ip += code_info_size;
// bytecode prelude: state size and exception stack size; 16 bit uints
machine_uint_t n_state = ip[0] | (ip[1] << 8);
machine_uint_t n_exc_stack = ip[2] | (ip[3] << 8);
mp_uint_t n_state = ip[0] | (ip[1] << 8);
mp_uint_t n_exc_stack = ip[2] | (ip[3] << 8);
ip += 4;
#if VM_DETECT_STACK_OVERFLOW
@@ -507,13 +509,13 @@ typedef struct _mp_obj_fun_asm_t {
void *fun;
} mp_obj_fun_asm_t;
typedef machine_uint_t (*inline_asm_fun_0_t)();
typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t);
typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t);
typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t);
typedef mp_uint_t (*inline_asm_fun_0_t)();
typedef mp_uint_t (*inline_asm_fun_1_t)(mp_uint_t);
typedef mp_uint_t (*inline_asm_fun_2_t)(mp_uint_t, mp_uint_t);
typedef mp_uint_t (*inline_asm_fun_3_t)(mp_uint_t, mp_uint_t, mp_uint_t);
// convert a Micro Python object to a sensible value for inline asm
STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
// TODO for byte_array, pass pointer to the array
if (MP_OBJ_IS_SMALL_INT(obj)) {
return MP_OBJ_SMALL_INT_VALUE(obj);
@@ -526,42 +528,42 @@ STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
} else if (MP_OBJ_IS_STR(obj)) {
// pointer to the string (it's probably constant though!)
uint l;
return (machine_uint_t)mp_obj_str_get_data(obj, &l);
return (mp_uint_t)mp_obj_str_get_data(obj, &l);
} else {
mp_obj_type_t *type = mp_obj_get_type(obj);
if (0) {
#if MICROPY_PY_BUILTINS_FLOAT
} else if (type == &mp_type_float) {
// convert float to int (could also pass in float registers)
return (machine_int_t)mp_obj_float_get(obj);
return (mp_int_t)mp_obj_float_get(obj);
#endif
} else if (type == &mp_type_tuple) {
// pointer to start of tuple (could pass length, but then could use len(x) for that)
uint len;
mp_obj_t *items;
mp_obj_tuple_get(obj, &len, &items);
return (machine_uint_t)items;
return (mp_uint_t)items;
} else if (type == &mp_type_list) {
// pointer to start of list (could pass length, but then could use len(x) for that)
uint len;
mp_obj_t *items;
mp_obj_list_get(obj, &len, &items);
return (machine_uint_t)items;
return (mp_uint_t)items;
} else {
mp_buffer_info_t bufinfo;
if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_WRITE)) {
// supports the buffer protocol, return a pointer to the data
return (machine_uint_t)bufinfo.buf;
return (mp_uint_t)bufinfo.buf;
} else {
// just pass along a pointer to the object
return (machine_uint_t)obj;
return (mp_uint_t)obj;
}
}
}
}
// convert a return value from inline asm to a sensible Micro Python object
STATIC mp_obj_t convert_val_from_inline_asm(machine_uint_t val) {
STATIC mp_obj_t convert_val_from_inline_asm(mp_uint_t val) {
return MP_OBJ_NEW_SMALL_INT(val);
}
@@ -570,7 +572,7 @@ STATIC mp_obj_t fun_asm_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_
mp_arg_check_num(n_args, n_kw, self->n_args, self->n_args, false);
machine_uint_t ret;
mp_uint_t ret;
if (n_args == 0) {
ret = ((inline_asm_fun_0_t)self->fun)();
} else if (n_args == 1) {

View File

@@ -26,15 +26,15 @@
typedef struct _mp_obj_fun_bc_t {
mp_obj_base_t base;
mp_obj_dict_t *globals; // the context within which this function was defined
machine_uint_t n_pos_args : 16; // number of arguments this function takes
machine_uint_t n_kwonly_args : 16; // number of arguments this function takes
machine_uint_t n_def_args : 16; // number of default arguments
machine_uint_t has_def_kw_args : 1; // set if this function has default keyword args
machine_uint_t takes_var_args : 1; // set if this function takes variable args
machine_uint_t takes_kw_args : 1; // set if this function takes keyword args
const byte *bytecode; // bytecode for the function
qstr *args; // argument names (needed to resolve positional args passed as keywords)
mp_obj_dict_t *globals; // the context within which this function was defined
mp_uint_t n_pos_args : 16; // number of arguments this function takes
mp_uint_t n_kwonly_args : 16; // number of arguments this function takes
mp_uint_t n_def_args : 16; // number of default arguments
mp_uint_t has_def_kw_args : 1; // set if this function has default keyword args
mp_uint_t takes_var_args : 1; // set if this function takes variable args
mp_uint_t takes_kw_args : 1; // set if this function takes keyword args
const byte *bytecode; // bytecode for the function
qstr *args; // argument names (needed to resolve positional args passed as keywords)
// the following extra_args array is allocated space to take (in order):
// - values of positional default args (if any)
// - a single slot for default kw args dict (if it has them)

View File

@@ -59,12 +59,12 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp
const byte *bytecode = self_fun->bytecode;
// get code info size, and skip the line number table
machine_uint_t code_info_size = bytecode[0] | (bytecode[1] << 8) | (bytecode[2] << 16) | (bytecode[3] << 24);
mp_uint_t code_info_size = bytecode[0] | (bytecode[1] << 8) | (bytecode[2] << 16) | (bytecode[3] << 24);
bytecode += code_info_size;
// bytecode prelude: get state size and exception stack size
machine_uint_t n_state = bytecode[0] | (bytecode[1] << 8);
machine_uint_t n_exc_stack = bytecode[2] | (bytecode[3] << 8);
mp_uint_t n_state = bytecode[0] | (bytecode[1] << 8);
mp_uint_t n_exc_stack = bytecode[2] | (bytecode[3] << 8);
bytecode += 4;
// allocate the generator object, with room for local stack and exception stack

View File

@@ -64,7 +64,7 @@ STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, co
return mp_parse_num_integer(s, l, 0);
#if MICROPY_PY_BUILTINS_FLOAT
} else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) {
return MP_OBJ_NEW_SMALL_INT((machine_int_t)(MICROPY_FLOAT_C_FUN(trunc)(mp_obj_float_get(args[0]))));
return MP_OBJ_NEW_SMALL_INT((mp_int_t)(MICROPY_FLOAT_C_FUN(trunc)(mp_obj_float_get(args[0]))));
#endif
} else {
// try to convert to small int (eg from bool)
@@ -85,7 +85,7 @@ STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, co
void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
// The size of this buffer is rather arbitrary. If it's not large
// enough, a dynamic one will be allocated.
char stack_buf[sizeof(machine_int_t) * 4];
char stack_buf[sizeof(mp_int_t) * 4];
char *buf = stack_buf;
int buf_size = sizeof(stack_buf);
int fmt_size;
@@ -101,7 +101,7 @@ void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env,
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
typedef mp_longint_impl_t fmt_int_t;
#else
typedef mp_small_int_t fmt_int_t;
typedef mp_int_t fmt_int_t;
#endif
STATIC const uint log_base2_floor[] = {
@@ -145,7 +145,7 @@ char *mp_obj_int_formatted(char **buf, int *buf_size, int *fmt_size, mp_const_ob
// Not a small int.
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
const mp_obj_int_t *self = self_in;
// Get the value to format; mp_obj_get_int truncates to machine_int_t.
// Get the value to format; mp_obj_get_int truncates to mp_int_t.
num = self->val;
#else
// Delegate to the implementation for the long int.
@@ -241,7 +241,7 @@ mp_obj_t mp_obj_new_int_from_ll(long long val) {
return mp_const_none;
}
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
// SMALL_INT accepts only signed numbers, of one bit less size
// then word size, which totals 2 bits less for unsigned numbers.
if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) {
@@ -251,7 +251,7 @@ mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
return mp_const_none;
}
mp_obj_t mp_obj_new_int(machine_int_t value) {
mp_obj_t mp_obj_new_int(mp_int_t value) {
if (MP_SMALL_INT_FITS(value)) {
return MP_OBJ_NEW_SMALL_INT(value);
}
@@ -259,11 +259,11 @@ mp_obj_t mp_obj_new_int(machine_int_t value) {
return mp_const_none;
}
machine_int_t mp_obj_int_get(mp_const_obj_t self_in) {
mp_int_t mp_obj_int_get(mp_const_obj_t self_in) {
return MP_OBJ_SMALL_INT_VALUE(self_in);
}
machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
return MP_OBJ_SMALL_INT_VALUE(self_in);
}
@@ -304,7 +304,7 @@ STATIC mp_obj_t int_from_bytes(uint n_args, const mp_obj_t *args) {
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
// convert the bytes to an integer
machine_uint_t value = 0;
mp_uint_t value = 0;
for (const byte* buf = (const byte*)bufinfo.buf + bufinfo.len - 1; buf >= (byte*)bufinfo.buf; buf--) {
value = (value << 8) | *buf;
}
@@ -316,7 +316,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 2, 3, int_fro
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, (const mp_obj_t)&int_from_bytes_fun_obj);
STATIC mp_obj_t int_to_bytes(uint n_args, const mp_obj_t *args) {
machine_int_t val = mp_obj_int_get_checked(args[0]);
mp_int_t val = mp_obj_int_get_checked(args[0]);
uint len = MP_OBJ_SMALL_INT_VALUE(args[1]);
byte *data;
@@ -326,7 +326,7 @@ STATIC mp_obj_t int_to_bytes(uint n_args, const mp_obj_t *args) {
// TODO: Support signed param
mp_obj_t o = mp_obj_str_builder_start(&mp_type_bytes, len, &data);
memset(data, 0, len);
memcpy(data, &val, len < sizeof(machine_int_t) ? len : sizeof(machine_int_t));
memcpy(data, &val, len < sizeof(mp_int_t) ? len : sizeof(mp_int_t));
return mp_obj_str_builder_end(o);
}

View File

@@ -50,6 +50,11 @@
#define SUFFIX ""
#endif
#if MICROPY_PY_SYS_MAXSIZE
// Export value for sys.maxsize
const mp_obj_int_t mp_maxsize_obj = {{&mp_type_int}, INT_MAX};
#endif
bool mp_obj_int_is_positive(mp_obj_t self_in) {
if (MP_OBJ_IS_SMALL_INT(self_in)) {
return MP_OBJ_SMALL_INT_VALUE(self_in) >= 0;
@@ -140,14 +145,14 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
}
}
mp_obj_t mp_obj_new_int(machine_int_t value) {
mp_obj_t mp_obj_new_int(mp_int_t value) {
if (MP_SMALL_INT_FITS(value)) {
return MP_OBJ_NEW_SMALL_INT(value);
}
return mp_obj_new_int_from_ll(value);
}
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
// SMALL_INT accepts only signed numbers, of one bit less size
// than word size, which totals 2 bits less for unsigned numbers.
if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) {
@@ -174,7 +179,7 @@ mp_obj_t mp_obj_new_int_from_str_len(const char **str, uint len, bool neg, uint
return o;
}
machine_int_t mp_obj_int_get(mp_const_obj_t self_in) {
mp_int_t mp_obj_int_get(mp_const_obj_t self_in) {
if (MP_OBJ_IS_SMALL_INT(self_in)) {
return MP_OBJ_SMALL_INT_VALUE(self_in);
} else {
@@ -183,7 +188,7 @@ machine_int_t mp_obj_int_get(mp_const_obj_t self_in) {
}
}
machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
// TODO: Check overflow
return mp_obj_int_get(self_in);
}

View File

@@ -43,6 +43,26 @@
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
#if MICROPY_PY_SYS_MAXSIZE
// Export value for sys.maxsize
#define DIG_MASK ((1 << MPZ_DIG_SIZE) - 1)
STATIC const mpz_dig_t maxsize_dig[MPZ_NUM_DIG_FOR_INT] = {
(INT_MAX >> MPZ_DIG_SIZE * 0) & DIG_MASK,
(INT_MAX >> MPZ_DIG_SIZE * 1) & DIG_MASK,
(INT_MAX >> MPZ_DIG_SIZE * 2) & DIG_MASK,
#if (INT_MAX >> MPZ_DIG_SIZE * 2) > DIG_MASK
(INT_MAX >> MPZ_DIG_SIZE * 3) & DIG_MASK,
(INT_MAX >> MPZ_DIG_SIZE * 4) & DIG_MASK,
// (INT_MAX >> MPZ_DIG_SIZE * 5) & DIG_MASK,
#endif
};
const mp_obj_int_t mp_maxsize_obj = {
{&mp_type_int},
{.fixed_dig = 1, .len = MPZ_NUM_DIG_FOR_INT, .alloc = MPZ_NUM_DIG_FOR_INT, .dig = (mpz_dig_t*)maxsize_dig}
};
#undef DIG_MASK
#endif
STATIC mp_obj_int_t *mp_obj_int_new_mpz(void) {
mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
o->base.type = &mp_type_int;
@@ -121,8 +141,10 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
#if MICROPY_PY_BUILTINS_FLOAT
} else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_float)) {
return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);
#if MICROPY_PY_BUILTINS_COMPLEX
} else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
return mp_obj_complex_binary_op(op, mpz_as_float(zlhs), 0, rhs_in);
#endif
#endif
} else {
// delegate to generic function to check for extra cases
@@ -196,7 +218,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
case MP_BINARY_OP_RSHIFT:
case MP_BINARY_OP_INPLACE_RSHIFT: {
// TODO check conversion overflow
machine_int_t irhs = mpz_as_int(zrhs);
mp_int_t irhs = mpz_as_int(zrhs);
if (irhs < 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
}
@@ -239,7 +261,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
}
}
mp_obj_t mp_obj_new_int(machine_int_t value) {
mp_obj_t mp_obj_new_int(mp_int_t value) {
if (MP_SMALL_INT_FITS(value)) {
return MP_OBJ_NEW_SMALL_INT(value);
}
@@ -252,7 +274,7 @@ mp_obj_t mp_obj_new_int_from_ll(long long val) {
return o;
}
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
// SMALL_INT accepts only signed numbers, of one bit less size
// than word size, which totals 2 bits less for unsigned numbers.
if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) {
@@ -268,7 +290,7 @@ mp_obj_t mp_obj_new_int_from_str_len(const char **str, uint len, bool neg, uint
return o;
}
machine_int_t mp_obj_int_get(mp_const_obj_t self_in) {
mp_int_t mp_obj_int_get(mp_const_obj_t self_in) {
if (MP_OBJ_IS_SMALL_INT(self_in)) {
return MP_OBJ_SMALL_INT_VALUE(self_in);
} else {
@@ -277,12 +299,12 @@ machine_int_t mp_obj_int_get(mp_const_obj_t self_in) {
}
}
machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
if (MP_OBJ_IS_SMALL_INT(self_in)) {
return MP_OBJ_SMALL_INT_VALUE(self_in);
} else {
const mp_obj_int_t *self = self_in;
machine_int_t value;
mp_int_t value;
if (mpz_as_int_checked(&self->mpz, &value)) {
return value;
} else {

View File

@@ -127,7 +127,7 @@ STATIC mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
return o;
}
case MP_BINARY_OP_MULTIPLY: {
machine_int_t n;
mp_int_t n;
if (!mp_obj_get_int_maybe(rhs, &n)) {
return MP_OBJ_NULL; // op not supported
}
@@ -488,7 +488,7 @@ void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
typedef struct _mp_obj_list_it_t {
mp_obj_base_t base;
mp_obj_list_t *list;
machine_uint_t cur;
mp_uint_t cur;
} mp_obj_list_it_t;
mp_obj_t list_it_iternext(mp_obj_t self_in) {

View File

@@ -26,7 +26,7 @@
typedef struct _mp_obj_list_t {
mp_obj_base_t base;
machine_uint_t alloc;
machine_uint_t len;
mp_uint_t alloc;
mp_uint_t len;
mp_obj_t *items;
} mp_obj_list_t;

View File

@@ -36,7 +36,7 @@
typedef struct _mp_obj_map_t {
mp_obj_base_t base;
machine_uint_t n_iters;
mp_uint_t n_iters;
mp_obj_t fun;
mp_obj_t iters[];
} mp_obj_map_t;

View File

@@ -39,9 +39,9 @@
typedef struct _mp_obj_range_it_t {
mp_obj_base_t base;
// TODO make these values generic objects or something
machine_int_t cur;
machine_int_t stop;
machine_int_t step;
mp_int_t cur;
mp_int_t stop;
mp_int_t step;
} mp_obj_range_it_t;
STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) {
@@ -77,9 +77,9 @@ mp_obj_t mp_obj_new_range_iterator(int cur, int stop, int step) {
typedef struct _mp_obj_range_t {
mp_obj_base_t base;
// TODO make these values generic objects or something
machine_int_t start;
machine_int_t stop;
machine_int_t step;
mp_int_t start;
mp_int_t stop;
mp_int_t step;
} mp_obj_range_t;
STATIC mp_obj_t range_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {

View File

@@ -47,7 +47,7 @@ typedef struct _mp_obj_set_t {
typedef struct _mp_obj_set_it_t {
mp_obj_base_t base;
mp_obj_set_t *set;
machine_uint_t cur;
mp_uint_t cur;
} mp_obj_set_it_t;
STATIC mp_obj_t set_it_iternext(mp_obj_t self_in);
@@ -160,10 +160,10 @@ const mp_obj_type_t mp_type_set_it = {
STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set_it));
mp_obj_set_it_t *self = self_in;
machine_uint_t max = self->set->set.alloc;
mp_uint_t max = self->set->set.alloc;
mp_set_t *set = &self->set->set;
for (machine_uint_t i = self->cur; i < max; i++) {
for (mp_uint_t i = self->cur; i < max; i++) {
if (MP_SET_SLOT_IS_FILLED(set, i)) {
self->cur = i + 1;
return set->table[i];
@@ -476,7 +476,7 @@ STATIC mp_obj_t set_unary_op(int op, mp_obj_t self_in) {
mp_obj_set_t *self = self_in;
switch (op) {
case MP_UNARY_OP_BOOL: return MP_BOOL(self->set.used != 0);
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->set.used);
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((mp_int_t)self->set.used);
default: return MP_OBJ_NULL; // op not supported
}
}

View File

@@ -32,6 +32,7 @@
#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
#include "unicode.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
@@ -43,16 +44,7 @@
STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t *args, mp_obj_t dict);
const mp_obj_t mp_const_empty_bytes;
// use this macro to extract the string hash
#define GET_STR_HASH(str_obj_in, str_hash) uint str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)str_obj_in)->hash; }
// use this macro to extract the string length
#define GET_STR_LEN(str_obj_in, str_len) uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t*)str_obj_in)->len; }
// use this macro to extract the string data and length
#define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) const byte *str_data; uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; }
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str);
STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in);
STATIC NORETURN void arg_type_mixup();
@@ -64,7 +56,8 @@ STATIC bool is_str_or_bytes(mp_obj_t o) {
/******************************************************************************/
/* str */
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) {
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env,
const byte *str_data, uint str_len, bool is_bytes) {
// this escapes characters, but it will be very slow to print (calling print many times)
bool has_single_quote = false;
bool has_double_quote = false;
@@ -85,7 +78,10 @@ void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *e
print(env, "\\%c", quote_char);
} else if (*s == '\\') {
print(env, "\\\\");
} else if (32 <= *s && *s <= 126) {
} else if (*s >= 0x20 && *s != 0x7f && (!is_bytes || *s < 0x80)) {
// In strings, anything which is not ascii control character
// is printed as is, this includes characters in range 0x80-0xff
// (which can be non-Latin letters, etc.)
print(env, "%c", *s);
} else if (*s == '\n') {
print(env, "\\n");
@@ -109,7 +105,7 @@ STATIC void str_print(void (*print)(void *env, const char *fmt, ...), void *env,
if (is_bytes) {
print(env, "b");
}
mp_str_print_quoted(print, env, str_data, str_len);
mp_str_print_quoted(print, env, str_data, str_len, is_bytes);
}
}
@@ -230,9 +226,9 @@ wrong_args:
// like strstr but with specified length and allows \0 bytes
// TODO replace with something more efficient/standard
STATIC const byte *find_subbytes(const byte *haystack, machine_uint_t hlen, const byte *needle, machine_uint_t nlen, machine_int_t direction) {
STATIC const byte *find_subbytes(const byte *haystack, mp_uint_t hlen, const byte *needle, mp_uint_t nlen, mp_int_t direction) {
if (hlen >= nlen) {
machine_uint_t str_index, str_index_end;
mp_uint_t str_index, str_index_end;
if (direction > 0) {
str_index = 0;
str_index_end = hlen - nlen;
@@ -255,7 +251,7 @@ STATIC const byte *find_subbytes(const byte *haystack, machine_uint_t hlen, cons
return NULL;
}
STATIC mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_t mp_obj_str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
GET_STR_DATA_LEN(lhs_in, lhs_data, lhs_len);
mp_obj_type_t *lhs_type = mp_obj_get_type(lhs_in);
mp_obj_type_t *rhs_type = mp_obj_get_type(rhs_in);
@@ -348,6 +344,15 @@ uncomparable:
return MP_OBJ_NULL; // op not supported
}
#if !MICROPY_PY_BUILTINS_STR_UNICODE
// objstrunicode defines own version
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, uint self_len,
mp_obj_t index, bool is_slice) {
mp_uint_t index_val = mp_get_index(type, self_len, index, is_slice);
return self_data + index_val;
}
#endif
STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_type_t *type = mp_obj_get_type(self_in);
GET_STR_DATA_LEN(self_in, self_data, self_len);
@@ -363,11 +368,11 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
return mp_obj_new_str_of_type(type, self_data + slice.start, slice.stop - slice.start);
}
#endif
uint index_val = mp_get_index(type, self_len, index, false);
const byte *p = str_index_to_ptr(type, self_data, self_len, index, false);
if (type == &mp_type_bytes) {
return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)self_data[index_val]);
return MP_OBJ_NEW_SMALL_INT((mp_int_t)*p);
} else {
return mp_obj_new_str((char*)self_data + index_val, 1, true);
return mp_obj_new_str((char*)p, 1, true);
}
} else {
return MP_OBJ_NULL; // op not supported
@@ -430,7 +435,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
STATIC mp_obj_t str_split(uint n_args, const mp_obj_t *args) {
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
machine_int_t splits = -1;
mp_int_t splits = -1;
mp_obj_t sep = mp_const_none;
if (n_args > 1) {
sep = args[1];
@@ -510,8 +515,8 @@ STATIC mp_obj_t str_rsplit(uint n_args, const mp_obj_t *args) {
mp_obj_t sep = args[1];
GET_STR_DATA_LEN(args[0], s, len);
machine_int_t splits = mp_obj_get_int(args[2]);
machine_int_t org_splits = splits;
mp_int_t splits = mp_obj_get_int(args[2]);
mp_int_t org_splits = splits;
// Preallocate list to the max expected # of elements, as we
// will fill it from the end.
mp_obj_list_t *res = mp_obj_new_list(splits + 1, NULL);
@@ -561,8 +566,8 @@ STATIC mp_obj_t str_rsplit(uint n_args, const mp_obj_t *args) {
return res;
}
STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t direction, bool is_index) {
STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, mp_int_t direction, bool is_index) {
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
assert(2 <= n_args && n_args <= 4);
assert(MP_OBJ_IS_STR(args[0]));
assert(MP_OBJ_IS_STR(args[1]));
@@ -570,16 +575,16 @@ STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t dire
GET_STR_DATA_LEN(args[0], haystack, haystack_len);
GET_STR_DATA_LEN(args[1], needle, needle_len);
machine_uint_t start = 0;
machine_uint_t end = haystack_len;
const byte *start = haystack;
const byte *end = haystack + haystack_len;
if (n_args >= 3 && args[2] != mp_const_none) {
start = mp_get_index(&mp_type_str, haystack_len, args[2], true);
start = str_index_to_ptr(self_type, haystack, haystack_len, args[2], true);
}
if (n_args >= 4 && args[3] != mp_const_none) {
end = mp_get_index(&mp_type_str, haystack_len, args[3], true);
end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true);
}
const byte *p = find_subbytes(haystack + start, end - start, needle, needle_len, direction);
const byte *p = find_subbytes(start, end - start, needle, needle_len, direction);
if (p == NULL) {
// not found
if (is_index) {
@@ -589,6 +594,11 @@ STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t dire
}
} else {
// found
#if MICROPY_PY_BUILTINS_STR_UNICODE
if (self_type == &mp_type_str) {
return MP_OBJ_NEW_SMALL_INT(utf8_ptr_to_index(haystack, p));
}
#endif
return MP_OBJ_NEW_SMALL_INT(p - haystack);
}
}
@@ -611,16 +621,17 @@ STATIC mp_obj_t str_rindex(uint n_args, const mp_obj_t *args) {
// TODO: (Much) more variety in args
STATIC mp_obj_t str_startswith(uint n_args, const mp_obj_t *args) {
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
GET_STR_DATA_LEN(args[0], str, str_len);
GET_STR_DATA_LEN(args[1], prefix, prefix_len);
uint index_val = 0;
const byte *start = str;
if (n_args > 2) {
index_val = mp_get_index(&mp_type_str, str_len, args[2], true);
start = str_index_to_ptr(self_type, str, str_len, args[2], true);
}
if (prefix_len + index_val > str_len) {
if (prefix_len + (start - str) > str_len) {
return mp_const_false;
}
return MP_BOOL(memcmp(str + index_val, prefix, prefix_len) == 0);
return MP_BOOL(memcmp(start, prefix, prefix_len) == 0);
}
STATIC mp_obj_t str_endswith(uint n_args, const mp_obj_t *args) {
@@ -659,16 +670,16 @@ STATIC mp_obj_t str_uni_strip(int type, uint n_args, const mp_obj_t *args) {
GET_STR_DATA_LEN(args[0], orig_str, orig_str_len);
machine_uint_t first_good_char_pos = 0;
mp_uint_t first_good_char_pos = 0;
bool first_good_char_pos_set = false;
machine_uint_t last_good_char_pos = 0;
machine_uint_t i = 0;
machine_int_t delta = 1;
mp_uint_t last_good_char_pos = 0;
mp_uint_t i = 0;
mp_int_t delta = 1;
if (type == RSTRIP) {
i = orig_str_len - 1;
delta = -1;
}
for (machine_uint_t len = orig_str_len; len > 0; len--) {
for (mp_uint_t len = orig_str_len; len > 0; len--) {
if (find_subbytes(chars_to_del, chars_to_del_len, &orig_str[i], 1, 1) == NULL) {
if (!first_good_char_pos_set) {
first_good_char_pos_set = true;
@@ -694,7 +705,7 @@ STATIC mp_obj_t str_uni_strip(int type, uint n_args, const mp_obj_t *args) {
assert(last_good_char_pos >= first_good_char_pos);
//+1 to accomodate the last character
machine_uint_t stripped_len = last_good_char_pos - first_good_char_pos + 1;
mp_uint_t stripped_len = last_good_char_pos - first_good_char_pos + 1;
if (stripped_len == orig_str_len) {
// If nothing was stripped, don't bother to dup original string
// TODO: watch out for this case when we'll get to bytearray.strip()
@@ -757,7 +768,7 @@ static mp_obj_t arg_as_int(mp_obj_t arg) {
// TODO: Needs a way to construct an mpz integer from a float
mp_small_int_t num = mp_obj_get_float(arg);
mp_int_t num = mp_obj_get_float(arg);
return MP_OBJ_NEW_SMALL_INT(num);
}
#endif
@@ -1318,7 +1329,7 @@ not_enough_args:
STATIC mp_obj_t str_replace(uint n_args, const mp_obj_t *args) {
assert(MP_OBJ_IS_STR(args[0]));
machine_int_t max_rep = -1;
mp_int_t max_rep = -1;
if (n_args == 4) {
max_rep = mp_obj_get_int(args[3]);
if (max_rep == 0) {
@@ -1359,11 +1370,11 @@ STATIC mp_obj_t str_replace(uint n_args, const mp_obj_t *args) {
// first pass computes the required length of the replaced string
// second pass does the replacements
for (;;) {
machine_uint_t replaced_str_index = 0;
machine_uint_t num_replacements_done = 0;
mp_uint_t replaced_str_index = 0;
mp_uint_t num_replacements_done = 0;
const byte *old_occurrence;
const byte *offset_ptr = str;
machine_uint_t str_len_remain = str_len;
mp_uint_t str_len_remain = str_len;
if (old_len == 0) {
// if old_str is empty, copy new_str to start of replaced string
// copy the replacement string
@@ -1418,6 +1429,7 @@ STATIC mp_obj_t str_replace(uint n_args, const mp_obj_t *args) {
}
STATIC mp_obj_t str_count(uint n_args, const mp_obj_t *args) {
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
assert(2 <= n_args && n_args <= 4);
assert(MP_OBJ_IS_STR(args[0]));
assert(MP_OBJ_IS_STR(args[1]));
@@ -1425,33 +1437,35 @@ STATIC mp_obj_t str_count(uint n_args, const mp_obj_t *args) {
GET_STR_DATA_LEN(args[0], haystack, haystack_len);
GET_STR_DATA_LEN(args[1], needle, needle_len);
machine_uint_t start = 0;
machine_uint_t end = haystack_len;
const byte *start = haystack;
const byte *end = haystack + haystack_len;
if (n_args >= 3 && args[2] != mp_const_none) {
start = mp_get_index(&mp_type_str, haystack_len, args[2], true);
start = str_index_to_ptr(self_type, haystack, haystack_len, args[2], true);
}
if (n_args >= 4 && args[3] != mp_const_none) {
end = mp_get_index(&mp_type_str, haystack_len, args[3], true);
end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true);
}
// if needle_len is zero then we count each gap between characters as an occurrence
if (needle_len == 0) {
return MP_OBJ_NEW_SMALL_INT(end - start + 1);
return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char*)start, end - start) + 1);
}
// count the occurrences
machine_int_t num_occurrences = 0;
for (machine_uint_t haystack_index = start; haystack_index + needle_len <= end; haystack_index++) {
if (memcmp(&haystack[haystack_index], needle, needle_len) == 0) {
mp_int_t num_occurrences = 0;
for (const byte *haystack_ptr = start; haystack_ptr + needle_len <= end;) {
if (memcmp(haystack_ptr, needle, needle_len) == 0) {
num_occurrences++;
haystack_index += needle_len - 1;
haystack_ptr += needle_len;
} else {
haystack_ptr = utf8_next_char(haystack_ptr);
}
}
return MP_OBJ_NEW_SMALL_INT(num_occurrences);
}
STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, machine_int_t direction) {
STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, mp_int_t direction) {
if (!is_str_or_bytes(self_in)) {
assert(0);
}
@@ -1477,7 +1491,7 @@ STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, machine_int_t di
const byte *position_ptr = find_subbytes(str, str_len, sep, sep_len, direction);
if (position_ptr != NULL) {
machine_uint_t position = position_ptr - str;
mp_uint_t position = position_ptr - str;
result[0] = mp_obj_new_str_of_type(self_type, str, position);
result[1] = arg;
result[2] = mp_obj_new_str_of_type(self_type, str + position + sep_len, str_len - position - sep_len);
@@ -1595,7 +1609,7 @@ STATIC mp_obj_t str_encode(uint n_args, const mp_obj_t *args) {
}
#endif
STATIC machine_int_t str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, int flags) {
mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, int flags) {
if (flags == MP_BUFFER_READ) {
GET_STR_DATA_LEN(self_in, str_data, str_len);
bufinfo->buf = (void*)str_data;
@@ -1612,38 +1626,45 @@ STATIC machine_int_t str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo,
}
#if MICROPY_CPYTHON_COMPAT
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj, 1, 3, bytes_decode);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj, 1, 3, bytes_decode);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode);
#endif
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj, 1, 2, str_lstrip);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj, 1, 2, str_rstrip);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, mp_obj_str_format);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_lower_obj, str_lower);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_upper_obj, str_upper);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isspace_obj, str_isspace);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isalpha_obj, str_isalpha);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isdigit_obj, str_isdigit);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isupper_obj, str_isupper);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_islower_obj, str_islower);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex);
MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj, 1, 2, str_lstrip);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj, 1, 2, str_rstrip);
MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, mp_obj_str_format);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count);
MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition);
MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition);
MP_DEFINE_CONST_FUN_OBJ_1(str_lower_obj, str_lower);
MP_DEFINE_CONST_FUN_OBJ_1(str_upper_obj, str_upper);
MP_DEFINE_CONST_FUN_OBJ_1(str_isspace_obj, str_isspace);
MP_DEFINE_CONST_FUN_OBJ_1(str_isalpha_obj, str_isalpha);
MP_DEFINE_CONST_FUN_OBJ_1(str_isdigit_obj, str_isdigit);
MP_DEFINE_CONST_FUN_OBJ_1(str_isupper_obj, str_isupper);
MP_DEFINE_CONST_FUN_OBJ_1(str_islower_obj, str_islower);
STATIC const mp_map_elem_t str_locals_dict_table[] = {
#if MICROPY_CPYTHON_COMPAT
{ MP_OBJ_NEW_QSTR(MP_QSTR_decode), (mp_obj_t)&bytes_decode_obj },
#if !MICROPY_PY_BUILTINS_STR_UNICODE
// If we have separate unicode type, then here we have methods only
// for bytes type, and it should not have encode() methods. Otherwise,
// we have non-compliant-but-practical bytestring type, which shares
// method table with bytes, so they both have encode() and decode()
// methods (which should do type checking at runtime).
{ MP_OBJ_NEW_QSTR(MP_QSTR_encode), (mp_obj_t)&str_encode_obj },
#endif
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_find), (mp_obj_t)&str_find_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rfind), (mp_obj_t)&str_rfind_obj },
@@ -1673,17 +1694,19 @@ STATIC const mp_map_elem_t str_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(str_locals_dict, str_locals_dict_table);
#if !MICROPY_PY_BUILTINS_STR_UNICODE
const mp_obj_type_t mp_type_str = {
{ &mp_type_type },
.name = MP_QSTR_str,
.print = str_print,
.make_new = str_make_new,
.binary_op = str_binary_op,
.binary_op = mp_obj_str_binary_op,
.subscr = str_subscr,
.getiter = mp_obj_new_str_iterator,
.buffer_p = { .get_buffer = str_get_buffer },
.buffer_p = { .get_buffer = mp_obj_str_get_buffer },
.locals_dict = (mp_obj_t)&str_locals_dict,
};
#endif
// Reuses most of methods from str
const mp_obj_type_t mp_type_bytes = {
@@ -1691,10 +1714,10 @@ const mp_obj_type_t mp_type_bytes = {
.name = MP_QSTR_bytes,
.print = str_print,
.make_new = bytes_make_new,
.binary_op = str_binary_op,
.binary_op = mp_obj_str_binary_op,
.subscr = str_subscr,
.getiter = mp_obj_new_bytes_iterator,
.buffer_p = { .get_buffer = str_get_buffer },
.buffer_p = { .get_buffer = mp_obj_str_get_buffer },
.locals_dict = (mp_obj_t)&str_locals_dict,
};
@@ -1848,9 +1871,10 @@ const char *mp_obj_str_get_data(mp_obj_t self_in, uint *len) {
typedef struct _mp_obj_str_it_t {
mp_obj_base_t base;
mp_obj_t str;
machine_uint_t cur;
mp_uint_t cur;
} mp_obj_str_it_t;
#if !MICROPY_PY_BUILTINS_STR_UNICODE
STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
mp_obj_str_it_t *self = self_in;
GET_STR_DATA_LEN(self->str, str, len);
@@ -1870,11 +1894,20 @@ STATIC const mp_obj_type_t mp_type_str_it = {
.iternext = str_it_iternext,
};
mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
o->base.type = &mp_type_str_it;
o->str = str;
o->cur = 0;
return o;
}
#endif
STATIC mp_obj_t bytes_it_iternext(mp_obj_t self_in) {
mp_obj_str_it_t *self = self_in;
GET_STR_DATA_LEN(self->str, str, len);
if (self->cur < len) {
mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT((mp_small_int_t)str[self->cur]);
mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT((mp_int_t)str[self->cur]);
self->cur += 1;
return o_out;
} else {
@@ -1889,14 +1922,6 @@ STATIC const mp_obj_type_t mp_type_bytes_it = {
.iternext = bytes_it_iternext,
};
mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
o->base.type = &mp_type_str_it;
o->str = str;
o->cur = 0;
return o;
}
mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str) {
mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
o->base.type = &mp_type_bytes_it;

View File

@@ -27,13 +27,61 @@
typedef struct _mp_obj_str_t {
mp_obj_base_t base;
// XXX here we assume the hash size is 16 bits (it is at the moment; see qstr.c)
machine_uint_t hash : 16;
mp_uint_t hash : 16;
// len == number of bytes used in data, alloc = len + 1 because (at the moment) we also append a null byte
machine_uint_t len : 16;
mp_uint_t len : 16;
const byte *data;
} mp_obj_str_t;
#define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte*)str};
// use this macro to extract the string hash
#define GET_STR_HASH(str_obj_in, str_hash) \
uint str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) \
{ str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)str_obj_in)->hash; }
// use this macro to extract the string length
#define GET_STR_LEN(str_obj_in, str_len) \
uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) \
{ str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t*)str_obj_in)->len; }
// use this macro to extract the string data and length
#define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \
const byte *str_data; uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) \
{ str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } \
else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; }
mp_obj_t mp_obj_str_format(uint n_args, const mp_obj_t *args);
mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, uint len);
mp_obj_t mp_obj_str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in);
mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, int flags);
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, uint self_len,
mp_obj_t index, bool is_slice);
MP_DECLARE_CONST_FUN_OBJ(str_encode_obj);
MP_DECLARE_CONST_FUN_OBJ(str_find_obj);
MP_DECLARE_CONST_FUN_OBJ(str_rfind_obj);
MP_DECLARE_CONST_FUN_OBJ(str_index_obj);
MP_DECLARE_CONST_FUN_OBJ(str_rindex_obj);
MP_DECLARE_CONST_FUN_OBJ(str_join_obj);
MP_DECLARE_CONST_FUN_OBJ(str_split_obj);
MP_DECLARE_CONST_FUN_OBJ(str_rsplit_obj);
MP_DECLARE_CONST_FUN_OBJ(str_startswith_obj);
MP_DECLARE_CONST_FUN_OBJ(str_endswith_obj);
MP_DECLARE_CONST_FUN_OBJ(str_strip_obj);
MP_DECLARE_CONST_FUN_OBJ(str_lstrip_obj);
MP_DECLARE_CONST_FUN_OBJ(str_rstrip_obj);
MP_DECLARE_CONST_FUN_OBJ(str_format_obj);
MP_DECLARE_CONST_FUN_OBJ(str_replace_obj);
MP_DECLARE_CONST_FUN_OBJ(str_count_obj);
MP_DECLARE_CONST_FUN_OBJ(str_partition_obj);
MP_DECLARE_CONST_FUN_OBJ(str_rpartition_obj);
MP_DECLARE_CONST_FUN_OBJ(str_lower_obj);
MP_DECLARE_CONST_FUN_OBJ(str_upper_obj);
MP_DECLARE_CONST_FUN_OBJ(str_isspace_obj);
MP_DECLARE_CONST_FUN_OBJ(str_isalpha_obj);
MP_DECLARE_CONST_FUN_OBJ(str_isdigit_obj);
MP_DECLARE_CONST_FUN_OBJ(str_isupper_obj);
MP_DECLARE_CONST_FUN_OBJ(str_islower_obj);

View File

@@ -43,7 +43,7 @@ typedef struct _mp_obj_stringio_t {
mp_obj_base_t base;
vstr_t *vstr;
// StringIO has single pointer used for both reading and writing
machine_uint_t pos;
mp_uint_t pos;
} mp_obj_stringio_t;
STATIC void stringio_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
@@ -51,9 +51,9 @@ STATIC void stringio_print(void (*print)(void *env, const char *fmt, ...), void
print(env, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self->vstr);
}
STATIC machine_int_t stringio_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) {
STATIC mp_int_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_stringio_t *o = o_in;
machine_uint_t remaining = o->vstr->len - o->pos;
mp_uint_t remaining = o->vstr->len - o->pos;
if (size > remaining) {
size = remaining;
}
@@ -62,9 +62,9 @@ STATIC machine_int_t stringio_read(mp_obj_t o_in, void *buf, machine_uint_t size
return size;
}
STATIC machine_int_t stringio_write(mp_obj_t o_in, const void *buf, machine_uint_t size, int *errcode) {
STATIC mp_int_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
mp_obj_stringio_t *o = o_in;
machine_uint_t remaining = o->vstr->alloc - o->pos;
mp_uint_t remaining = o->vstr->alloc - o->pos;
if (size > remaining) {
// Take all what's already allocated...
o->vstr->len = o->vstr->alloc;

359
py/objstrunicode.c Normal file
View File

@@ -0,0 +1,359 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
* 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 <stdbool.h>
#include <string.h>
#include <assert.h>
#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
#include "pfenv.h"
#include "objstr.h"
#include "objlist.h"
#if MICROPY_PY_BUILTINS_STR_UNICODE
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
/******************************************************************************/
/* str */
STATIC void uni_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) {
// this escapes characters, but it will be very slow to print (calling print many times)
bool has_single_quote = false;
bool has_double_quote = false;
for (const byte *s = str_data, *top = str_data + str_len; !has_double_quote && s < top; s++) {
if (*s == '\'') {
has_single_quote = true;
} else if (*s == '"') {
has_double_quote = true;
}
}
int quote_char = '\'';
if (has_single_quote && !has_double_quote) {
quote_char = '"';
}
print(env, "%c", quote_char);
const byte *s = str_data, *top = str_data + str_len;
while (s < top) {
unichar ch;
ch = utf8_get_char(s);
s = utf8_next_char(s);
if (ch == quote_char) {
print(env, "\\%c", quote_char);
} else if (ch == '\\') {
print(env, "\\\\");
} else if (32 <= ch && ch <= 126) {
print(env, "%c", ch);
} else if (ch == '\n') {
print(env, "\\n");
} else if (ch == '\r') {
print(env, "\\r");
} else if (ch == '\t') {
print(env, "\\t");
} else if (ch < 0x100) {
print(env, "\\x%02x", ch);
} else if (ch < 0x10000) {
print(env, "\\u%04x", ch);
} else {
print(env, "\\U%08x", ch);
}
}
print(env, "%c", quote_char);
}
STATIC void uni_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
GET_STR_DATA_LEN(self_in, str_data, str_len);
if (kind == PRINT_STR) {
print(env, "%.*s", str_len, str_data);
} else {
uni_print_quoted(print, env, str_data, str_len);
}
}
STATIC mp_obj_t uni_unary_op(int op, mp_obj_t self_in) {
GET_STR_DATA_LEN(self_in, str_data, str_len);
switch (op) {
case MP_UNARY_OP_BOOL:
return MP_BOOL(str_len != 0);
case MP_UNARY_OP_LEN:
return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char *)str_data, str_len));
default:
return MP_OBJ_NULL; // op not supported
}
}
STATIC mp_obj_t str_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
#if MICROPY_CPYTHON_COMPAT
if (n_kw != 0) {
mp_arg_error_unimpl_kw();
}
#endif
switch (n_args) {
case 0:
return MP_OBJ_NEW_QSTR(MP_QSTR_);
case 1:
{
vstr_t *vstr = vstr_new();
mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[0], PRINT_STR);
mp_obj_t s = mp_obj_new_str(vstr->buf, vstr->len, false);
vstr_free(vstr);
return s;
}
case 2:
case 3:
{
// TODO: validate 2nd/3rd args
if (!MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
}
GET_STR_DATA_LEN(args[0], str_data, str_len);
GET_STR_HASH(args[0], str_hash);
mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
o->data = str_data;
o->hash = str_hash;
return o;
}
default:
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "str takes at most 3 arguments"));
}
}
// Convert an index into a pointer to its lead byte. Out of bounds indexing will raise IndexError or
// be capped to the first/last character of the string, depending on is_slice.
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, uint self_len,
mp_obj_t index, bool is_slice) {
mp_int_t i;
// Copied from mp_get_index; I don't want bounds checking, just give me
// the integer as-is. (I can't bounds-check without scanning the whole
// string; an out-of-bounds index will be caught in the loops below.)
if (MP_OBJ_IS_SMALL_INT(index)) {
i = MP_OBJ_SMALL_INT_VALUE(index);
} else if (!mp_obj_get_int_maybe(index, &i)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "string indices must be integers, not %s", mp_obj_get_type_str(index)));
}
const byte *s, *top = self_data + self_len;
if (i < 0)
{
// Negative indexing is performed by counting from the end of the string.
for (s = top - 1; i; --s) {
if (s < self_data) {
if (is_slice) {
return self_data;
}
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "string index out of range"));
}
if (!UTF8_IS_CONT(*s)) {
++i;
}
}
++s;
} else if (!i) {
return self_data; // Shortcut - str[0] is its base pointer
} else {
// Positive indexing, correspondingly, counts from the start of the string.
// It's assumed that negative indexing will generally be used with small
// absolute values (eg str[-1], not str[-1000000]), which means it'll be
// more efficient this way.
for (s = self_data; true; ++s) {
if (s >= top) {
if (is_slice) {
return top;
}
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "string index out of range"));
}
while (UTF8_IS_CONT(*s)) {
++s;
}
if (!i--) {
return s;
}
}
}
return s;
}
STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_type_t *type = mp_obj_get_type(self_in);
GET_STR_DATA_LEN(self_in, self_data, self_len);
if (value == MP_OBJ_SENTINEL) {
// load
#if MICROPY_PY_BUILTINS_SLICE
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_obj_t ostart, ostop, ostep;
mp_obj_slice_get(index, &ostart, &ostop, &ostep);
if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
"only slices with step=1 (aka None) are supported"));
}
if (type == &mp_type_bytes) {
mp_int_t start = 0, stop = self_len;
if (ostart != mp_const_none) {
start = MP_OBJ_SMALL_INT_VALUE(ostart);
if (start < 0) {
start = self_len + start;
}
}
if (ostop != mp_const_none) {
stop = MP_OBJ_SMALL_INT_VALUE(ostop);
if (stop < 0) {
stop = self_len + stop;
}
}
return mp_obj_new_str_of_type(type, self_data + start, stop - start);
}
const byte *pstart, *pstop;
if (ostart != mp_const_none) {
pstart = str_index_to_ptr(type, self_data, self_len, ostart, true);
} else {
pstart = self_data;
}
if (ostop != mp_const_none) {
// pstop will point just after the stop character. This depends on
// the \0 at the end of the string.
pstop = str_index_to_ptr(type, self_data, self_len, ostop, true);
} else {
pstop = self_data + self_len;
}
if (pstop < pstart) {
return MP_OBJ_NEW_QSTR(MP_QSTR_);
}
return mp_obj_new_str_of_type(type, (const byte *)pstart, pstop - pstart);
}
#endif
if (type == &mp_type_bytes) {
uint index_val = mp_get_index(type, self_len, index, false);
return MP_OBJ_NEW_SMALL_INT((mp_int_t)self_data[index_val]);
}
const byte *s = str_index_to_ptr(type, self_data, self_len, index, false);
int len = 1;
if (UTF8_IS_NONASCII(*s)) {
// Count the number of 1 bits (after the first)
for (char mask = 0x40; *s & mask; mask >>= 1) {
++len;
}
}
return mp_obj_new_str((const char*)s, len, true); // This will create a one-character string
} else {
return MP_OBJ_NULL; // op not supported
}
}
STATIC const mp_map_elem_t str_locals_dict_table[] = {
#if MICROPY_CPYTHON_COMPAT
{ MP_OBJ_NEW_QSTR(MP_QSTR_encode), (mp_obj_t)&str_encode_obj },
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_find), (mp_obj_t)&str_find_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rfind), (mp_obj_t)&str_rfind_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_index), (mp_obj_t)&str_index_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rindex), (mp_obj_t)&str_rindex_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_join), (mp_obj_t)&str_join_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_split), (mp_obj_t)&str_split_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rsplit), (mp_obj_t)&str_rsplit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_startswith), (mp_obj_t)&str_startswith_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_endswith), (mp_obj_t)&str_endswith_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_strip), (mp_obj_t)&str_strip_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_lstrip), (mp_obj_t)&str_lstrip_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rstrip), (mp_obj_t)&str_rstrip_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_format), (mp_obj_t)&str_format_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_replace), (mp_obj_t)&str_replace_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_count), (mp_obj_t)&str_count_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_partition), (mp_obj_t)&str_partition_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rpartition), (mp_obj_t)&str_rpartition_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_lower), (mp_obj_t)&str_lower_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_upper), (mp_obj_t)&str_upper_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_isspace), (mp_obj_t)&str_isspace_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_isalpha), (mp_obj_t)&str_isalpha_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_isdigit), (mp_obj_t)&str_isdigit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_isupper), (mp_obj_t)&str_isupper_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_islower), (mp_obj_t)&str_islower_obj },
};
STATIC MP_DEFINE_CONST_DICT(str_locals_dict, str_locals_dict_table);
const mp_obj_type_t mp_type_str = {
{ &mp_type_type },
.name = MP_QSTR_str,
.print = uni_print,
.make_new = str_make_new,
.unary_op = uni_unary_op,
.binary_op = mp_obj_str_binary_op,
.subscr = str_subscr,
.getiter = mp_obj_new_str_iterator,
.buffer_p = { .get_buffer = mp_obj_str_get_buffer },
.locals_dict = (mp_obj_t)&str_locals_dict,
};
/******************************************************************************/
/* str iterator */
typedef struct _mp_obj_str_it_t {
mp_obj_base_t base;
mp_obj_t str;
mp_uint_t cur;
} mp_obj_str_it_t;
STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
mp_obj_str_it_t *self = self_in;
GET_STR_DATA_LEN(self->str, str, len);
if (self->cur < len) {
const byte *cur = str + self->cur;
const byte *end = utf8_next_char(str + self->cur);
mp_obj_t o_out = mp_obj_new_str((const char*)cur, end - cur, true);
self->cur += end - cur;
return o_out;
} else {
return MP_OBJ_STOP_ITERATION;
}
}
STATIC const mp_obj_type_t mp_type_str_it = {
{ &mp_type_type },
.name = MP_QSTR_iterator,
.getiter = mp_identity,
.iternext = str_it_iternext,
};
mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
o->base.type = &mp_type_str_it;
o->str = str;
o->cur = 0;
return o;
}
#endif // MICROPY_PY_BUILTINS_STR_UNICODE

View File

@@ -252,11 +252,11 @@ void mp_obj_tuple_del(mp_obj_t self_in) {
m_del_var(mp_obj_tuple_t, mp_obj_t, self->len, self);
}
machine_int_t mp_obj_tuple_hash(mp_obj_t self_in) {
mp_int_t mp_obj_tuple_hash(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
mp_obj_tuple_t *self = self_in;
// start hash with pointer to empty tuple, to make it fairly unique
machine_int_t hash = (machine_int_t)mp_const_empty_tuple;
mp_int_t hash = (mp_int_t)mp_const_empty_tuple;
for (uint i = 0; i < self->len; i++) {
hash += mp_obj_hash(self->items[i]);
}
@@ -269,7 +269,7 @@ machine_int_t mp_obj_tuple_hash(mp_obj_t self_in) {
typedef struct _mp_obj_tuple_it_t {
mp_obj_base_t base;
mp_obj_tuple_t *tuple;
machine_uint_t cur;
mp_uint_t cur;
} mp_obj_tuple_it_t;
STATIC mp_obj_t tuple_it_iternext(mp_obj_t self_in) {

View File

@@ -26,7 +26,7 @@
typedef struct _mp_obj_tuple_t {
mp_obj_base_t base;
machine_uint_t len;
mp_uint_t len;
mp_obj_t items[];
} mp_obj_tuple_t;

View File

@@ -46,6 +46,8 @@
#define DEBUG_printf(...) (void)0
#endif
STATIC mp_obj_t static_class_method_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args);
/******************************************************************************/
// instance object
@@ -101,7 +103,7 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t
struct class_lookup_data {
mp_obj_instance_t *obj;
qstr attr;
machine_uint_t meth_offset;
mp_uint_t meth_offset;
mp_obj_t *dest;
bool is_type;
};
@@ -749,6 +751,8 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
assert(MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)); // Micro Python restriction, for now
assert(MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)); // Micro Python restriction, for now
// TODO might need to make a copy of locals_dict; at least that's how CPython does it
// Basic validation of base classes
uint len;
mp_obj_t *items;
@@ -783,6 +787,16 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "multiple bases have instance lay-out conflict"));
}
mp_map_t *locals_map = mp_obj_dict_get_map(o->locals_dict);
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP);
if (elem != NULL) {
// __new__ slot exists; check if it is a function
if (MP_OBJ_IS_TYPE(elem->value, &mp_type_fun_native) || MP_OBJ_IS_TYPE(elem->value, &mp_type_fun_bc)) {
// __new__ is a function, wrap it in a staticmethod decorator
elem->value = static_class_method_make_new((mp_obj_t)&mp_type_staticmethod, 1, 0, &elem->value);
}
}
return o;
}

View File

@@ -30,8 +30,8 @@
#include <assert.h>
#include <string.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parsenumbase.h"
@@ -109,20 +109,20 @@ STATIC const rule_t *rules[] = {
};
typedef struct _rule_stack_t {
unsigned int src_line : 24;
unsigned int rule_id : 8;
int32_t arg_i; // what should be the size and signedness?
mp_uint_t src_line : 24;
mp_uint_t rule_id : 8;
mp_uint_t arg_i : 32; // what should the bit-size be?
} rule_stack_t;
typedef struct _parser_t {
bool had_memory_error;
uint rule_stack_alloc;
uint rule_stack_top;
mp_uint_t rule_stack_alloc;
mp_uint_t rule_stack_top;
rule_stack_t *rule_stack;
uint result_stack_alloc;
uint result_stack_top;
mp_uint_t result_stack_alloc;
mp_uint_t result_stack_top;
mp_parse_node_t *result_stack;
mp_lexer_t *lexer;
@@ -132,7 +132,7 @@ STATIC inline void memory_error(parser_t *parser) {
parser->had_memory_error = true;
}
STATIC void push_rule(parser_t *parser, int src_line, const rule_t *rule, int arg_i) {
STATIC void push_rule(parser_t *parser, mp_uint_t src_line, const rule_t *rule, mp_uint_t arg_i) {
if (parser->had_memory_error) {
return;
}
@@ -151,14 +151,14 @@ STATIC void push_rule(parser_t *parser, int src_line, const rule_t *rule, int ar
rs->arg_i = arg_i;
}
STATIC void push_rule_from_arg(parser_t *parser, uint arg) {
STATIC void push_rule_from_arg(parser_t *parser, mp_uint_t arg) {
assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE);
uint rule_id = arg & RULE_ARG_ARG_MASK;
mp_uint_t rule_id = arg & RULE_ARG_ARG_MASK;
assert(rule_id < RULE_maximum_number_of);
push_rule(parser, mp_lexer_cur(parser->lexer)->src_line, rules[rule_id], 0);
}
STATIC void pop_rule(parser_t *parser, const rule_t **rule, uint *arg_i, uint *src_line) {
STATIC void pop_rule(parser_t *parser, const rule_t **rule, mp_uint_t *arg_i, mp_uint_t *src_line) {
assert(!parser->had_memory_error);
parser->rule_stack_top -= 1;
*rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];
@@ -166,7 +166,7 @@ STATIC void pop_rule(parser_t *parser, const rule_t **rule, uint *arg_i, uint *s
*src_line = parser->rule_stack[parser->rule_stack_top].src_line;
}
mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) {
mp_parse_node_t mp_parse_node_new_leaf(mp_int_t kind, mp_int_t arg) {
if (kind == MP_PARSE_NODE_SMALL_INT) {
return (mp_parse_node_t)(kind | (arg << 1));
}
@@ -176,8 +176,8 @@ mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) {
void mp_parse_node_free(mp_parse_node_t pn) {
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
uint rule_id = MP_PARSE_NODE_STRUCT_KIND(pns);
mp_uint_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
mp_uint_t rule_id = MP_PARSE_NODE_STRUCT_KIND(pns);
if (rule_id == RULE_string) {
return;
}
@@ -185,7 +185,7 @@ void mp_parse_node_free(mp_parse_node_t pn) {
if (adjust) {
n--;
}
for (uint i = 0; i < n; i++) {
for (mp_uint_t i = 0; i < n; i++) {
mp_parse_node_free(pns->nodes[i]);
}
if (adjust) {
@@ -196,22 +196,22 @@ void mp_parse_node_free(mp_parse_node_t pn) {
}
#if MICROPY_DEBUG_PRINTERS
void mp_parse_node_print(mp_parse_node_t pn, int indent) {
void mp_parse_node_print(mp_parse_node_t pn, mp_uint_t indent) {
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
printf("[% 4d] ", (int)((mp_parse_node_struct_t*)pn)->source_line);
} else {
printf(" ");
}
for (int i = 0; i < indent; i++) {
for (mp_uint_t i = 0; i < indent; i++) {
printf(" ");
}
if (MP_PARSE_NODE_IS_NULL(pn)) {
printf("NULL\n");
} else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
printf("int(" INT_FMT ")\n", arg);
} else if (MP_PARSE_NODE_IS_LEAF(pn)) {
machine_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
mp_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
case MP_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break;
case MP_PARSE_NODE_INTEGER: printf("int(%s)\n", qstr_str(arg)); break;
@@ -227,13 +227,13 @@ void mp_parse_node_print(mp_parse_node_t pn, int indent) {
if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_string) {
printf("literal str(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
} else {
uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
mp_uint_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
#ifdef USE_RULE_NAME
printf("%s(%d) (n=%d)\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns)]->rule_name, MP_PARSE_NODE_STRUCT_KIND(pns), n);
printf("%s(" UINT_FMT ") (n=" UINT_FMT ")\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns)]->rule_name, (mp_uint_t)MP_PARSE_NODE_STRUCT_KIND(pns), n);
#else
printf("rule(%u) (n=%d)\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns), n);
printf("rule(" UINT_FMT ") (n=" UINT_FMT ")\n", (mp_uint_t)MP_PARSE_NODE_STRUCT_KIND(pns), n);
#endif
for (uint i = 0; i < n; i++) {
for (mp_uint_t i = 0; i < n; i++) {
mp_parse_node_print(pns->nodes[i], indent + 2);
}
}
@@ -244,7 +244,7 @@ void mp_parse_node_print(mp_parse_node_t pn, int indent) {
/*
STATIC void result_stack_show(parser_t *parser) {
printf("result stack, most recent first\n");
for (int i = parser->result_stack_top - 1; i >= 0; i--) {
for (mp_int_t i = parser->result_stack_top - 1; i >= 0; i--) {
mp_parse_node_print(parser->result_stack[i], 0);
}
}
@@ -258,7 +258,7 @@ STATIC mp_parse_node_t pop_result(parser_t *parser) {
return parser->result_stack[--parser->result_stack_top];
}
STATIC mp_parse_node_t peek_result(parser_t *parser, int pos) {
STATIC mp_parse_node_t peek_result(parser_t *parser, mp_uint_t pos) {
if (parser->had_memory_error) {
return MP_PARSE_NODE_NULL;
}
@@ -282,7 +282,7 @@ STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
parser->result_stack[parser->result_stack_top++] = pn;
}
STATIC void push_result_string(parser_t *parser, int src_line, const char *str, uint len) {
STATIC void push_result_string(parser_t *parser, mp_uint_t src_line, const char *str, mp_uint_t len) {
mp_parse_node_struct_t *pn = m_new_obj_var_maybe(mp_parse_node_struct_t, mp_parse_node_t, 2);
if (pn == NULL) {
memory_error(parser);
@@ -292,7 +292,7 @@ STATIC void push_result_string(parser_t *parser, int src_line, const char *str,
pn->kind_num_nodes = RULE_string | (2 << 8);
char *p = m_new(char, len);
memcpy(p, str, len);
pn->nodes[0] = (machine_int_t)p;
pn->nodes[0] = (mp_int_t)p;
pn->nodes[1] = len;
push_result_node(parser, (mp_parse_node_t)pn);
}
@@ -305,14 +305,14 @@ STATIC void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
} else if (tok->kind == MP_TOKEN_NUMBER) {
bool dec = false;
bool small_int = true;
machine_int_t int_val = 0;
int len = tok->len;
mp_int_t int_val = 0;
mp_uint_t len = tok->len;
const char *str = tok->str;
int base = 0;
int i = mp_parse_num_base(str, len, &base);
mp_uint_t base = 0;
mp_uint_t i = mp_parse_num_base(str, len, &base);
bool overflow = false;
for (; i < len; i++) {
int dig;
mp_uint_t dig;
if (unichar_isdigit(str[i]) && str[i] - '0' < base) {
dig = str[i] - '0';
} else if (base == 16 && 'a' <= str[i] && str[i] <= 'f') {
@@ -369,7 +369,7 @@ STATIC void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
push_result_node(parser, pn);
}
STATIC void push_result_rule(parser_t *parser, int src_line, const rule_t *rule, int num_args) {
STATIC void push_result_rule(parser_t *parser, mp_uint_t src_line, const rule_t *rule, mp_uint_t num_args) {
mp_parse_node_struct_t *pn = m_new_obj_var_maybe(mp_parse_node_struct_t, mp_parse_node_t, num_args);
if (pn == NULL) {
memory_error(parser);
@@ -377,7 +377,7 @@ STATIC void push_result_rule(parser_t *parser, int src_line, const rule_t *rule,
}
pn->source_line = src_line;
pn->kind_num_nodes = (rule->rule_id & 0xff) | (num_args << 8);
for (int i = num_args; i > 0; i--) {
for (mp_uint_t i = num_args; i > 0; i--) {
pn->nodes[i - 1] = pop_result(parser);
}
push_result_node(parser, (mp_parse_node_t)pn);
@@ -407,7 +407,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
}
// work out the top-level rule to use, and push it on the stack
int top_level_rule;
mp_uint_t top_level_rule;
switch (input_kind) {
case MP_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break;
case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;
@@ -417,8 +417,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
// parse!
uint n, i; // state for the current rule
uint rule_src_line; // source line for the first token matched by the current rule
mp_uint_t n, i; // state for the current rule
mp_uint_t rule_src_line; // source line for the first token matched by the current rule
bool backtrack = false;
const rule_t *rule = NULL;
mp_token_kind_t tok_kind;
@@ -541,7 +541,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
// count number of arguments for the parse_node
i = 0;
emit_rule = false;
for (int x = 0; x < n; ++x) {
for (mp_uint_t x = 0; x < n; ++x) {
if ((rule->arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
tok_kind = rule->arg[x] & RULE_ARG_ARG_MASK;
if (tok_kind >= MP_TOKEN_NAME) {
@@ -589,8 +589,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
i += 1;
}
int num_not_nil = 0;
for (int x = 0; x < i; ++x) {
mp_uint_t num_not_nil = 0;
for (mp_uint_t x = 0; x < i; ++x) {
if (peek_result(&parser, x) != MP_PARSE_NODE_NULL) {
num_not_nil += 1;
}
@@ -605,7 +605,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
} else if (num_not_nil == 1) {
// single result, leave it on stack
mp_parse_node_t pn = MP_PARSE_NODE_NULL;
for (int x = 0; x < i; ++x) {
for (mp_uint_t x = 0; x < i; ++x) {
mp_parse_node_t pn2 = pop_result(&parser);
if (pn2 != MP_PARSE_NODE_NULL) {
pn = pn2;
@@ -653,7 +653,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
}
} else {
for (;;) {
uint arg = rule->arg[i & 1 & n];
mp_uint_t arg = rule->arg[i & 1 & n];
switch (arg & RULE_ARG_KIND_MASK) {
case RULE_ARG_TOK:
if (mp_lexer_is_kind(lex, arg & RULE_ARG_ARG_MASK)) {

View File

@@ -46,7 +46,7 @@ struct _mp_lexer_t;
#define MP_PARSE_NODE_BYTES (0x12)
#define MP_PARSE_NODE_TOKEN (0x16)
typedef machine_uint_t mp_parse_node_t; // must be pointer size
typedef mp_uint_t mp_parse_node_t; // must be pointer size
typedef struct _mp_parse_node_struct_t {
uint32_t source_line; // line number in source file
@@ -69,15 +69,15 @@ typedef struct _mp_parse_node_struct_t {
#define MP_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0x1f)
// TODO should probably have int and uint versions of this macro
#define MP_PARSE_NODE_LEAF_ARG(pn) (((machine_uint_t)(pn)) >> 5)
#define MP_PARSE_NODE_LEAF_SMALL_INT(pn) (((machine_int_t)(pn)) >> 1)
#define MP_PARSE_NODE_LEAF_ARG(pn) (((mp_uint_t)(pn)) >> 5)
#define MP_PARSE_NODE_LEAF_SMALL_INT(pn) (((mp_int_t)(pn)) >> 1)
#define MP_PARSE_NODE_STRUCT_KIND(pns) ((pns)->kind_num_nodes & 0xff)
#define MP_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8)
mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg);
mp_parse_node_t mp_parse_node_new_leaf(mp_int_t kind, mp_int_t arg);
void mp_parse_node_free(mp_parse_node_t pn);
void mp_parse_node_print(mp_parse_node_t pn, int indent);
void mp_parse_node_print(mp_parse_node_t pn, mp_uint_t indent);
typedef enum {
MP_PARSE_SINGLE_INPUT,

View File

@@ -29,8 +29,8 @@
#include <stdint.h>
#include <stdio.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -43,7 +43,7 @@
#define STR_INVALID_SYNTAX "invalid syntax"
void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind) {
printf(" File \"%s\", line %d, column %d\n", qstr_str(mp_lexer_source_name(lex)), mp_lexer_cur(lex)->src_line, mp_lexer_cur(lex)->src_column);
printf(" File \"%s\", line " UINT_FMT ", column " UINT_FMT "\n", qstr_str(mp_lexer_source_name(lex)), mp_lexer_cur(lex)->src_line, mp_lexer_cur(lex)->src_column);
switch (parse_error_kind) {
case MP_PARSE_ERROR_MEMORY:
printf("MemoryError: %s\n", STR_MEMORY);

View File

@@ -27,21 +27,23 @@
#include <stdbool.h>
#include <stdlib.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "nlr.h"
#include "obj.h"
#include "parsenumbase.h"
#include "parsenum.h"
#include "smallint.h"
#include "runtime.h"
#if MICROPY_PY_BUILTINS_FLOAT
#include <math.h>
#endif
mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) {
const char *restrict top = str + len;
mp_obj_t mp_parse_num_integer(const char *restrict str_, mp_uint_t len, mp_uint_t base) {
const byte *restrict str = (const byte *)str_;
const byte *restrict top = str + len;
bool neg = false;
mp_obj_t ret_val;
@@ -65,14 +67,14 @@ mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) {
}
// parse optional base prefix
str += mp_parse_num_base(str, top - str, &base);
str += mp_parse_num_base((const char*)str, top - str, &base);
// string should be an integer number
machine_int_t int_val = 0;
const char *restrict str_val_start = str;
mp_int_t int_val = 0;
const byte *restrict str_val_start = str;
for (; str < top; str++) {
// get next digit as a value
int dig = *str;
mp_uint_t dig = *str;
if (unichar_isdigit(dig) && dig - '0' < base) {
// 0-9 digit
dig = dig - '0';
@@ -129,9 +131,9 @@ have_ret_val:
overflow:
// reparse using long int
{
const char *s2 = str_val_start;
const char *s2 = (const char*)str_val_start;
ret_val = mp_obj_new_int_from_str_len(&s2, top - str_val_start, neg, base);
str = s2;
str = (const byte*)s2;
goto have_ret_val;
}
@@ -139,11 +141,13 @@ value_error:
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid syntax for integer with base %d: '%s'", base, str));
}
#define PARSE_DEC_IN_INTG (1)
#define PARSE_DEC_IN_FRAC (2)
#define PARSE_DEC_IN_EXP (3)
typedef enum {
PARSE_DEC_IN_INTG,
PARSE_DEC_IN_FRAC,
PARSE_DEC_IN_EXP,
} parse_dec_in_t;
mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool force_complex) {
mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, bool force_complex) {
#if MICROPY_PY_BUILTINS_FLOAT
const char *top = str + len;
mp_float_t dec_val = 0;
@@ -185,12 +189,12 @@ mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool f
}
} else {
// string should be a decimal number
int in = PARSE_DEC_IN_INTG;
parse_dec_in_t in = PARSE_DEC_IN_INTG;
bool exp_neg = false;
int exp_val = 0;
int exp_extra = 0;
mp_int_t exp_val = 0;
mp_int_t exp_extra = 0;
for (; str < top; str++) {
int dig = *str;
mp_uint_t dig = *str;
if ('0' <= dig && dig <= '9') {
dig -= '0';
if (in == PARSE_DEC_IN_EXP) {
@@ -251,10 +255,15 @@ mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool f
}
// return the object
#if MICROPY_PY_BUILTINS_COMPLEX
if (imag) {
return mp_obj_new_complex(0, dec_val);
} else if (force_complex) {
return mp_obj_new_complex(dec_val, 0);
#else
if (imag || force_complex) {
mp_not_implemented("complex values not supported");
#endif
} else {
return mp_obj_new_float(dec_val);
}

View File

@@ -24,5 +24,5 @@
* THE SOFTWARE.
*/
mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base);
mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool force_complex);
mp_obj_t mp_parse_num_integer(const char *restrict str, mp_uint_t len, mp_uint_t base);
mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, bool force_complex);

View File

@@ -24,15 +24,15 @@
* THE SOFTWARE.
*/
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "parsenumbase.h"
// find real radix base, and strip preceding '0x', '0o' and '0b'
// puts base in *base, and returns number of bytes to skip the prefix
int mp_parse_num_base(const char *str, uint len, int *base) {
const char *p = str;
int c = *(p++);
mp_uint_t mp_parse_num_base(const char *str, mp_uint_t len, mp_uint_t *base) {
const byte *p = (const byte*)str;
unichar c = *(p++);
if ((*base == 0 || *base == 16) && c == '0') {
c = *(p++);
if ((c | 32) == 'x') {
@@ -63,6 +63,5 @@ int mp_parse_num_base(const char *str, uint len, int *base) {
}
p--;
}
return p - str;
return p - (const byte*)str;
}

View File

@@ -24,4 +24,4 @@
* THE SOFTWARE.
*/
int mp_parse_num_base(const char *str, uint len, int *base);
mp_uint_t mp_parse_num_base(const char *str, mp_uint_t len, mp_uint_t *base);

View File

@@ -27,8 +27,8 @@
#include <stdint.h>
#include <string.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "mpz.h"
@@ -111,14 +111,14 @@ int pfenv_print_strn(const pfenv_t *pfenv, const char *str, unsigned int len, in
// 32-bits is 10 digits, add 3 for commas, 1 for sign, 1 for terminating null
// We can use 16 characters for 32-bit and 32 characters for 64-bit
#define INT_BUF_SIZE (sizeof(machine_int_t) * 4)
#define INT_BUF_SIZE (sizeof(mp_int_t) * 4)
// This function is used by stmhal port to implement printf.
// It needs to be a separate function to pfenv_print_mp_int, since converting to a mp_int looses the MSB.
int pfenv_print_int(const pfenv_t *pfenv, machine_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) {
int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) {
char sign = 0;
if (sgn) {
if ((machine_int_t)x < 0) {
if ((mp_int_t)x < 0) {
sign = '-';
x = -x;
} else if (flags & PF_FLAG_SHOW_SIGN) {
@@ -232,7 +232,7 @@ int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int sgn, int base, int
// The size of this buffer is rather arbitrary. If it's not large
// enough, a dynamic one will be allocated.
char stack_buf[sizeof(machine_int_t) * 4];
char stack_buf[sizeof(mp_int_t) * 4];
char *buf = stack_buf;
int buf_size = sizeof(stack_buf);
int fmt_size = 0;

View File

@@ -44,7 +44,7 @@ typedef struct _pfenv_t {
void pfenv_vstr_add_strn(void *data, const char *str, unsigned int len);
int pfenv_print_strn(const pfenv_t *pfenv, const char *str, unsigned int len, int flags, char fill, int width);
int pfenv_print_int(const pfenv_t *pfenv, machine_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width);
int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width);
int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int sgn, int base, int base_char, int flags, char fill, int width, int prec);
#if MICROPY_PY_BUILTINS_FLOAT
int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec);

View File

@@ -43,6 +43,7 @@ PY_O_BASENAME = \
parsenum.o \
emitglue.o \
runtime.o \
stackctrl.o \
argcheck.o \
map.o \
obj.o \
@@ -74,6 +75,7 @@ PY_O_BASENAME = \
objset.o \
objslice.o \
objstr.o \
objstrunicode.o \
objstringio.o \
objtuple.o \
objtype.o \
@@ -100,6 +102,7 @@ PY_O_BASENAME = \
repl.o \
smallint.o \
pfenv.o \
../extmod/moductypes.o
# prepend the build destination prefix to the py object files
PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME))

View File

@@ -27,8 +27,8 @@
#include <assert.h>
#include <string.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
// NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings)
@@ -55,9 +55,9 @@
#define Q_GET_DATA(q) ((q) + 4)
// this must match the equivalent function in makeqstrdata.py
machine_uint_t qstr_compute_hash(const byte *data, uint len) {
mp_uint_t qstr_compute_hash(const byte *data, uint len) {
// djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html
machine_uint_t hash = 5381;
mp_uint_t hash = 5381;
for (const byte *top = data + len; data < top; data++) {
hash = ((hash << 5) + hash) ^ (*data); // hash * 33 ^ data
}
@@ -132,7 +132,7 @@ STATIC qstr qstr_add(const byte *q_ptr) {
qstr qstr_find_strn(const char *str, uint str_len) {
// work out hash of str
machine_uint_t str_hash = qstr_compute_hash((const byte*)str, str_len);
mp_uint_t str_hash = qstr_compute_hash((const byte*)str, str_len);
// search pools for the data
for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) {
@@ -154,7 +154,7 @@ qstr qstr_from_str(const char *str) {
qstr qstr_from_strn(const char *str, uint len) {
qstr q = qstr_find_strn(str, len);
if (q == 0) {
machine_uint_t hash = qstr_compute_hash((const byte*)str, len);
mp_uint_t hash = qstr_compute_hash((const byte*)str, len);
byte *q_ptr = m_new(byte, 4 + len + 1);
q_ptr[0] = hash;
q_ptr[1] = hash >> 8;
@@ -178,8 +178,8 @@ byte *qstr_build_start(uint len, byte **q_ptr) {
qstr qstr_build_end(byte *q_ptr) {
qstr q = qstr_find_strn((const char*)Q_GET_DATA(q_ptr), Q_GET_LENGTH(q_ptr));
if (q == 0) {
machine_uint_t len = Q_GET_LENGTH(q_ptr);
machine_uint_t hash = qstr_compute_hash(Q_GET_DATA(q_ptr), len);
mp_uint_t len = Q_GET_LENGTH(q_ptr);
mp_uint_t hash = qstr_compute_hash(Q_GET_DATA(q_ptr), len);
q_ptr[0] = hash;
q_ptr[1] = hash >> 8;
q_ptr[4 + len] = '\0';
@@ -190,7 +190,7 @@ qstr qstr_build_end(byte *q_ptr) {
return q;
}
machine_uint_t qstr_hash(qstr q) {
mp_uint_t qstr_hash(qstr q) {
return Q_GET_HASH(find_qstr(q));
}

View File

@@ -39,13 +39,13 @@ enum {
MP_QSTR_number_of,
};
typedef machine_uint_t qstr;
typedef mp_uint_t qstr;
#define QSTR_FROM_STR_STATIC(s) (qstr_from_strn((s), strlen(s)))
void qstr_init(void);
machine_uint_t qstr_compute_hash(const byte *data, uint len);
mp_uint_t qstr_compute_hash(const byte *data, uint len);
qstr qstr_find_strn(const char *str, uint str_len); // returns MP_QSTR_NULL if not found
qstr qstr_from_str(const char *str);
@@ -56,7 +56,7 @@ qstr qstr_from_strn(const char *str, uint len);
byte* qstr_build_start(uint len, byte **q_ptr);
qstr qstr_build_end(byte *q_ptr);
machine_uint_t qstr_hash(qstr q);
mp_uint_t qstr_hash(qstr q);
const char* qstr_str(qstr q);
uint qstr_len(qstr q);
const byte* qstr_data(qstr q, uint *len);

View File

@@ -352,6 +352,9 @@ Q(stdout)
Q(stderr)
Q(version)
Q(version_info)
#if MICROPY_PY_SYS_MAXSIZE
Q(maxsize)
#endif
#endif
#if MICROPY_PY_STRUCT
@@ -360,6 +363,46 @@ Q(pack)
Q(unpack)
#endif
#if MICROPY_PY_UCTYPES
Q(uctypes)
Q(sizeof)
Q(addressof)
Q(bytes_at)
Q(bytearray_at)
Q(NATIVE)
Q(LITTLE_ENDIAN)
Q(BIG_ENDIAN)
Q(VOID)
Q(UINT8)
Q(INT8)
Q(UINT16)
Q(INT16)
Q(UINT32)
Q(INT32)
Q(UINT64)
Q(INT64)
Q(BFUINT8)
Q(BFINT8)
Q(BFUINT16)
Q(BFINT16)
Q(BFUINT32)
Q(BFINT32)
Q(FLOAT32)
Q(FLOAT64)
Q(ARRAY)
Q(PTR)
//Q(BITFIELD)
Q(BF_POS)
Q(BF_LEN)
#endif
#if MICROPY_PY_IO
Q(_io)
Q(readall)
@@ -377,6 +420,8 @@ Q(gc)
Q(collect)
Q(disable)
Q(enable)
Q(mem_free)
Q(mem_alloc)
#endif
#if MICROPY_PY_BUILTINS_PROPERTY

View File

@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "repl.h"
#if MICROPY_HELPER_REPL

View File

@@ -45,6 +45,7 @@
#include "smallint.h"
#include "objgenerator.h"
#include "lexer.h"
#include "stackctrl.h"
#if 0 // print debugging info
#define DEBUG_PRINT (1)
@@ -69,6 +70,8 @@ const mp_obj_module_t mp_module___main__ = {
};
void mp_init(void) {
mp_stack_ctrl_init();
// call port specific initialization if any
#ifdef MICROPY_PORT_INIT_FUNC
MICROPY_PORT_INIT_FUNC;
@@ -184,7 +187,7 @@ mp_obj_t mp_unary_op(int op, mp_obj_t arg) {
DEBUG_OP_printf("unary %d %p\n", op, arg);
if (MP_OBJ_IS_SMALL_INT(arg)) {
mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(arg);
mp_int_t val = MP_OBJ_SMALL_INT_VALUE(arg);
switch (op) {
case MP_UNARY_OP_BOOL:
return MP_BOOL(val != 0);
@@ -269,17 +272,17 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
}
if (MP_OBJ_IS_SMALL_INT(lhs)) {
mp_small_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs);
mp_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs);
if (MP_OBJ_IS_SMALL_INT(rhs)) {
mp_small_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
mp_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
// This is a binary operation: lhs_val op rhs_val
// We need to be careful to handle overflow; see CERT INT32-C
// Operations that can overflow:
// + result always fits in machine_int_t, then handled by SMALL_INT check
// - result always fits in machine_int_t, then handled by SMALL_INT check
// + result always fits in mp_int_t, then handled by SMALL_INT check
// - result always fits in mp_int_t, then handled by SMALL_INT check
// * checked explicitly
// / if lhs=MIN and rhs=-1; result always fits in machine_int_t, then handled by SMALL_INT check
// % if lhs=MIN and rhs=-1; result always fits in machine_int_t, then handled by SMALL_INT check
// / if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check
// % if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check
// << checked explicitly
switch (op) {
case MP_BINARY_OP_OR:
@@ -320,7 +323,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
case MP_BINARY_OP_MULTIPLY:
case MP_BINARY_OP_INPLACE_MULTIPLY: {
// If long long type exists and is larger than machine_int_t, then
// If long long type exists and is larger than mp_int_t, then
// we can use the following code to perform overflow-checked multiplication.
// Otherwise (eg in x64 case) we must use mp_small_int_mul_overflow.
#if 0
@@ -331,7 +334,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
return mp_obj_new_int_from_ll(res);
} else {
// use standard precision
lhs_val = (mp_small_int_t)res;
lhs_val = (mp_int_t)res;
}
#endif
@@ -378,7 +381,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative power with no float support"));
#endif
} else {
machine_int_t ans = 1;
mp_int_t ans = 1;
while (rhs_val > 0) {
if (rhs_val & 1) {
if (mp_small_int_mul_overflow(ans, lhs_val)) {
@@ -426,6 +429,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
} else {
return res;
}
#if MICROPY_PY_BUILTINS_COMPLEX
} else if (MP_OBJ_IS_TYPE(rhs, &mp_type_complex)) {
mp_obj_t res = mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
if (res == MP_OBJ_NULL) {
@@ -433,6 +437,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
} else {
return res;
}
#endif
#endif
}
}

View File

@@ -41,13 +41,13 @@ typedef enum {
typedef union _mp_arg_val_t {
bool u_bool;
machine_int_t u_int;
mp_int_t u_int;
mp_obj_t u_obj;
} mp_arg_val_t;
typedef struct _mp_arg_t {
qstr qstr;
machine_uint_t flags;
mp_uint_t flags;
mp_arg_val_t defval;
} mp_arg_t;

View File

@@ -29,8 +29,8 @@
#include <stdio.h>
#include <assert.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "parse.h"

View File

@@ -53,9 +53,9 @@ void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void
#if MICROPY_PY_BUILTINS_SLICE
bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes) {
bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes) {
mp_obj_t ostart, ostop, ostep;
machine_int_t start, stop;
mp_int_t start, stop;
mp_obj_slice_get(slice, &ostart, &ostop, &ostep);
if (ostart == mp_const_none) {
@@ -103,8 +103,8 @@ bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_
#endif
mp_obj_t mp_seq_extract_slice(uint len, const mp_obj_t *seq, mp_bound_slice_t *indexes) {
machine_int_t start = indexes->start, stop = indexes->stop;
machine_int_t step = indexes->step;
mp_int_t start = indexes->start, stop = indexes->stop;
mp_int_t step = indexes->step;
mp_obj_t res = mp_obj_new_list(0, NULL);
@@ -231,7 +231,7 @@ mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp
}
}
for (machine_uint_t i = start; i < stop; i++) {
for (mp_uint_t i = start; i < stop; i++) {
if (mp_obj_equal(items[i], value)) {
// Common sense says this cannot overflow small int
return MP_OBJ_NEW_SMALL_INT(i);
@@ -242,7 +242,7 @@ mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp
}
mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value) {
machine_uint_t count = 0;
mp_uint_t count = 0;
for (uint i = 0; i < len; i++) {
if (mp_obj_equal(items[i], value)) {
count++;

View File

@@ -49,9 +49,9 @@
} while ((*ip++ & 0x80) != 0); \
}
#define DECODE_PTR do { \
ip = (byte*)(((machine_uint_t)ip + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1))); /* align ip */ \
unum = *(machine_uint_t*)ip; \
ip += sizeof(machine_uint_t); \
ip = (byte*)(((mp_uint_t)ip + sizeof(mp_uint_t) - 1) & (~(sizeof(mp_uint_t) - 1))); /* align ip */ \
unum = *(mp_uint_t*)ip; \
ip += sizeof(mp_uint_t); \
} while (0)
void mp_bytecode_print2(const byte *ip, int len);
@@ -60,7 +60,7 @@ void mp_bytecode_print(const void *descr, const byte *ip, int len) {
const byte *ip_start = ip;
// get code info size
machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
mp_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
const byte *code_info = ip;
ip += code_info_size;
@@ -92,8 +92,8 @@ void mp_bytecode_print(const void *descr, const byte *ip, int len) {
// print out line number info
{
machine_int_t bc = (code_info + code_info_size) - ip;
machine_uint_t source_line = 1;
mp_int_t bc = (code_info + code_info_size) - ip;
mp_uint_t source_line = 1;
printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
for (const byte* ci = code_info + 12; *ci; ci++) {
bc += *ci & 31;
@@ -106,7 +106,7 @@ void mp_bytecode_print(const void *descr, const byte *ip, int len) {
void mp_bytecode_print2(const byte *ip, int len) {
const byte *ip_start = ip;
machine_uint_t unum;
mp_uint_t unum;
qstr qstr;
while (ip - ip_start < len) {
printf("%02u ", (uint)(ip - ip_start));
@@ -129,7 +129,7 @@ void mp_bytecode_print2(const byte *ip, int len) {
break;
case MP_BC_LOAD_CONST_SMALL_INT: {
machine_int_t num = 0;
mp_int_t num = 0;
if ((ip[0] & 0x40) != 0) {
// Number is negative
num--;
@@ -445,14 +445,14 @@ void mp_bytecode_print2(const byte *ip, int len) {
case MP_BC_MAKE_CLOSURE: {
DECODE_PTR;
machine_uint_t n_closed_over = *ip++;
mp_uint_t n_closed_over = *ip++;
printf("MAKE_CLOSURE %p " UINT_FMT, (void*)unum, n_closed_over);
break;
}
case MP_BC_MAKE_CLOSURE_DEFARGS: {
DECODE_PTR;
machine_uint_t n_closed_over = *ip++;
mp_uint_t n_closed_over = *ip++;
printf("MAKE_CLOSURE_DEFARGS %p " UINT_FMT, (void*)unum, n_closed_over);
break;
}

View File

@@ -24,13 +24,13 @@
* THE SOFTWARE.
*/
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "smallint.h"
bool mp_small_int_mul_overflow(machine_int_t x, machine_int_t y) {
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) {
// Check for multiply overflow; see CERT INT32-C
if (x > 0) { // x is positive
if (y > 0) { // x and y are positive
@@ -56,20 +56,19 @@ bool mp_small_int_mul_overflow(machine_int_t x, machine_int_t y) {
return false;
}
machine_int_t mp_small_int_modulo(machine_int_t dividend, machine_int_t divisor) {
machine_int_t lsign = (dividend >= 0) ? 1 :-1;
machine_int_t rsign = (divisor >= 0) ? 1 :-1;
mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor) {
mp_int_t lsign = (dividend >= 0) ? 1 :-1;
mp_int_t rsign = (divisor >= 0) ? 1 :-1;
dividend %= divisor;
if (lsign != rsign) {
dividend += divisor;
}
return dividend;
return dividend;
}
machine_int_t mp_small_int_floor_divide(machine_int_t num, machine_int_t denom) {
machine_int_t lsign = num > 0 ? 1 : -1;
machine_int_t rsign = denom > 0 ? 1 : -1;
mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom) {
mp_int_t lsign = num > 0 ? 1 : -1;
mp_int_t rsign = denom > 0 ? 1 : -1;
if (lsign == -1) {num *= -1;}
if (rsign == -1) {denom *= -1;}
if (lsign != rsign){

View File

@@ -27,10 +27,10 @@
// Functions for small integer arithmetic
// In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range
#define MP_SMALL_INT_MIN ((mp_small_int_t)(((machine_int_t)WORD_MSBIT_HIGH) >> 1))
#define MP_SMALL_INT_MAX ((mp_small_int_t)(~(MP_SMALL_INT_MIN)))
#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)WORD_MSBIT_HIGH) >> 1))
#define MP_SMALL_INT_MAX ((mp_int_t)(~(MP_SMALL_INT_MIN)))
#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0)
bool mp_small_int_mul_overflow(machine_int_t x, machine_int_t y);
machine_int_t mp_small_int_modulo(machine_int_t dividend, machine_int_t divisor);
machine_int_t mp_small_int_floor_divide(machine_int_t num, machine_int_t denom);
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y);
mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor);
mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom);

63
py/stackctrl.c Normal file
View File

@@ -0,0 +1,63 @@
/*
* 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 "mpconfig.h"
#include "misc.h"
#include "nlr.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
#include "stackctrl.h"
// Stack top at the start of program
char *stack_top;
void mp_stack_ctrl_init() {
volatile int stack_dummy;
stack_top = (char*)&stack_dummy;
}
uint mp_stack_usage() {
// Assumes descending stack
volatile int stack_dummy;
return stack_top - (char*)&stack_dummy;
}
#if MICROPY_STACK_CHECK
static uint stack_limit = 10240;
void mp_stack_set_limit(uint limit) {
stack_limit = limit;
}
void mp_stack_check() {
if (mp_stack_usage() >= stack_limit) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "maximum recursion depth exceeded"));
}
}
#endif // MICROPY_STACK_CHECK

41
py/stackctrl.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* 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.
*/
void mp_stack_ctrl_init();
uint mp_stack_usage();
#if MICROPY_STACK_CHECK
void mp_stack_set_limit(uint limit);
void mp_stack_check();
#define MP_STACK_CHECK() mp_stack_check()
#else
#define mp_stack_set_limit(limit)
#define MP_STACK_CHECK()
#endif

View File

@@ -33,9 +33,13 @@
#include "qstr.h"
#include "obj.h"
#include "objstr.h"
#include "runtime.h"
#include "stream.h"
#if MICROPY_STREAMS_NON_BLOCK
#include <errno.h>
#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
#define EWOULDBLOCK 140
#endif
#endif
// This file defines generic Python stream read/write methods which
@@ -63,13 +67,20 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
}
machine_int_t sz;
mp_int_t sz;
if (n_args == 1 || ((sz = mp_obj_get_int(args[1])) == -1)) {
return stream_readall(args[0]);
}
#if MICROPY_PY_BUILTINS_STR_UNICODE
if (!o->type->stream_p->is_bytes) {
mp_not_implemented("Reading from unicode text streams by character count");
}
#endif
byte *buf = m_new(byte, sz);
int error;
machine_int_t out_sz = o->type->stream_p->read(o, buf, sz, &error);
mp_int_t out_sz = o->type->stream_p->read(o, buf, sz, &error);
if (out_sz == -1) {
if (is_nonblocking_error(error)) {
// https://docs.python.org/3.4/library/io.html#io.RawIOBase.read
@@ -87,18 +98,15 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) {
}
}
STATIC mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t len) {
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
if (o->type->stream_p == NULL || o->type->stream_p->write == NULL) {
// CPython: io.UnsupportedOperation, OSError subclass
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
}
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
int error;
machine_int_t out_sz = o->type->stream_p->write(self_in, bufinfo.buf, bufinfo.len, &error);
mp_int_t out_sz = o->type->stream_p->write(self_in, buf, len, &error);
if (out_sz == -1) {
if (is_nonblocking_error(error)) {
// http://docs.python.org/3/library/io.html#io.RawIOBase.write
@@ -114,6 +122,12 @@ STATIC mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) {
}
}
STATIC mp_obj_t stream_write_method(mp_obj_t self_in, mp_obj_t arg) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
return mp_stream_write(self_in, bufinfo.buf, bufinfo.len);
}
STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
@@ -128,7 +142,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
int error;
int current_read = DEFAULT_BUFFER_SIZE;
while (true) {
machine_int_t out_sz = o->type->stream_p->read(self_in, p, current_read, &error);
mp_int_t out_sz = o->type->stream_p->read(self_in, p, current_read, &error);
if (out_sz == -1) {
if (is_nonblocking_error(error)) {
// With non-blocking streams, we read as much as we can.
@@ -171,7 +185,7 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
}
machine_int_t max_size = -1;
mp_int_t max_size = -1;
if (n_args > 1) {
max_size = MP_OBJ_SMALL_INT_VALUE(args[1]);
}
@@ -190,7 +204,7 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "out of memory"));
}
machine_int_t out_sz = o->type->stream_p->read(o, p, 1, &error);
mp_int_t out_sz = o->type->stream_p->read(o, p, 1, &error);
if (out_sz == -1) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error));
}
@@ -217,7 +231,7 @@ STATIC mp_obj_t stream_unbuffered_readlines(mp_obj_t self) {
mp_obj_t lines = mp_obj_new_list(0, NULL);
for (;;) {
mp_obj_t line = stream_unbuffered_readline(1, &self);
if (mp_obj_str_get_len(line) == 0) {
if (!mp_obj_is_true(line)) {
break;
}
mp_obj_list_append(lines, line);
@@ -228,7 +242,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj, stream_unbuffered_
mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
mp_obj_t l_in = stream_unbuffered_readline(1, &self);
if (mp_obj_str_get_len(l_in) != 0) {
if (mp_obj_is_true(l_in)) {
return l_in;
}
return MP_OBJ_STOP_ITERATION;
@@ -237,4 +251,4 @@ mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj, 1, 2, stream_read);
MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_readall_obj, stream_readall);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj, 1, 2, stream_unbuffered_readline);
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write_obj, stream_write);
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write_obj, stream_write_method);

View File

@@ -32,3 +32,5 @@ MP_DECLARE_CONST_FUN_OBJ(mp_stream_write_obj);
// Iterator which uses mp_stream_unbuffered_readline_obj
mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self);
mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t len);

View File

@@ -26,8 +26,8 @@
#include <stdint.h>
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
// attribute flags
#define FL_PRINT (0x01)
@@ -65,14 +65,65 @@ STATIC const uint8_t attr[] = {
AT_LO, AT_LO, AT_LO, AT_PR, AT_PR, AT_PR, AT_PR, 0
};
unichar utf8_get_char(const char *s) {
// TODO: Rename to str_get_char
unichar utf8_get_char(const byte *s) {
#if MICROPY_PY_BUILTINS_STR_UNICODE
unichar ord = *s++;
if (!UTF8_IS_NONASCII(ord)) return ord;
ord &= 0x7F;
for (unichar mask = 0x40; ord & mask; mask >>= 1) {
ord &= ~mask;
}
while (UTF8_IS_CONT(*s)) {
ord = (ord << 6) | (*s++ & 0x3F);
}
return ord;
#else
return *s;
#endif
}
char *utf8_next_char(const char *s) {
return (char*)(s + 1);
// TODO: Rename to str_next_char
const byte *utf8_next_char(const byte *s) {
#if MICROPY_PY_BUILTINS_STR_UNICODE
++s;
while (UTF8_IS_CONT(*s)) {
++s;
}
return s;
#else
return s + 1;
#endif
}
mp_uint_t utf8_ptr_to_index(const char *s, const char *ptr) {
mp_uint_t i = 0;
while (ptr > s) {
if (!UTF8_IS_CONT(*--ptr)) {
i++;
}
}
return i;
}
// TODO: Rename to str_charlen
mp_uint_t unichar_charlen(const char *str, mp_uint_t len)
{
#if MICROPY_PY_BUILTINS_STR_UNICODE
mp_uint_t charlen = 0;
for (const char *top = str + len; str < top; ++str) {
if (!UTF8_IS_CONT(*str)) {
++charlen;
}
}
return charlen;
#else
return len;
#endif
}
// Be aware: These unichar_is* functions are actually ASCII-only!
bool unichar_isspace(unichar c) {
return c < 128 && (attr[c] & FL_SPACE) != 0;
}

Some files were not shown because too many files have changed in this diff Show More