Commit Graph

156 Commits

Author SHA1 Message Date
microDev 193a8d2e67
add traceback object 2021-08-04 12:10:57 +05:30
Jeff Epler 52540a9830 Rename EXTENDED_FIELDS -> MP_TYPE_EXTENDED_FIELDS 2021-07-12 06:57:59 -05:00
Jeff Epler 7302bc09a7 rename the type flag to EXTENDED for consistency 2021-07-09 14:59:37 -05:00
Jeff Epler 0d756066e8 milestone: coverage make test_full passes 2021-07-06 10:37:32 -05:00
Jeff Epler df56ba207f WIP 2021-07-06 09:25:56 -05:00
Scott Shawcroft 3fda0c0a1b
Fix board builds and use MP_ERROR_TEXT in py and extmod 2021-05-05 17:51:52 -07:00
Jeff Epler 716a82ba67 set the coroutine generator for native generators 2021-05-05 11:36:40 -05:00
Scott Shawcroft f0bb26d70f
Merge MicroPython 1.13 into CircuitPython 2021-05-04 18:06:33 -07:00
Scott Shawcroft b35fa44c8a
Merge MicroPython 1.12 into CircuitPython 2021-05-03 14:01:18 -07:00
Jeff Epler dfa7c3d32d codeformat: Fix handling of `**`
After discussing with danh, I noticed that `a/**/b` would not match `a/b`.

After correcting this and re-running "pre-commit run --all", additional
files were reindented, including the codeformat script itself.
2021-04-30 15:30:13 -05:00
Scott Shawcroft 76033d5115
Merge MicroPython v1.11 into CircuitPython 2021-04-26 15:47:41 -07:00
Scott Shawcroft 09f7b43c64
Merge MicroPython 1.10 into CircuitPython 2021-04-21 15:59:17 -07:00
Scott Shawcroft b057fb8a4b
codeformat 2021-04-19 22:22:44 -07:00
microDev a52eb88031
run code formatting script 2021-03-15 19:27:36 +05:30
Kenny 98aa4b7943 update async tests with less upython workaround and more cpython compatibility 2020-10-10 23:39:32 -07:00
Kenny bf849ff674 async def syntax rigor and __await__ magic method
Some examples of improved compliance with CPython that currently
have divergent behavior in CircuitPython are listed below:

* yield from is not allowed in async methods
```
>>> async def f():
...     yield from 'abc'
...
Traceback (most recent call last):
  File "<stdin>", line 2, in f
SyntaxError: 'yield from' inside async function
```

* await only works on awaitable expressions
```
>>> async def f():
...     await 'not awaitable'
...
>>> f().send(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
AttributeError: 'str' object has no attribute '__await__'
```

* only __await__()able expressions are awaitable
Okay this one actually does not work in circuitpython at all today.
This is how CPython works though and pretending __await__ does not
exist will only bite users who write both.
```
>>> class c:
...     pass
...
>>> def f(self):
...     yield
...     yield
...     return 'f to pay respects'
...
>>> c.__await__ = f  # could just as easily have put it on the class but this shows how it's wired
>>> async def g():
...     awaitable_thing = c()
...     partial = await awaitable_thing
...     return 'press ' + partial
...
>>> q = g()
>>> q.send(None)
>>> q.send(None)
>>> q.send(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration: press f to pay respects
```
2020-10-10 15:45:08 -07:00
Kenny e9b4e0bd35 remove new char*s because m0 is way oversubscribed 2020-07-23 20:41:10 -07:00
Kenny 51a79b1af7 add coroutine behavior for generators
coroutines don't have __next__; they also call themselves coroutines.
This does not change the fact that `async def` methods are generators,
but it does make them behave more like CPython.
2020-07-23 20:40:16 -07:00
Diego Elio Pettenò 34b4993d63 Add license to some obvious files. 2020-07-06 19:16:25 +01:00
Damien George 332d83343f py: Rework mp_convert_member_lookup to properly handle built-ins.
This commit fixes lookups of class members to make it so that built-in
functions that are used as methods/functions of a class work correctly.

The mp_convert_member_lookup() function is pretty much completely changed
by this commit, but for the most part it's just reorganised and the
indenting changed.  The functional changes are:

- staticmethod and classmethod checks moved to later in the if-logic,
  because they are less common and so should be checked after the more
  common cases.

- The explicit mp_obj_is_type(member, &mp_type_type) check is removed
  because it's now subsumed by other, more general tests in this function.

- MP_TYPE_FLAG_BINDS_SELF and MP_TYPE_FLAG_BUILTIN_FUN type flags added to
  make the checks in this function much simpler (now they just test this
  bit in type->flags).

- An extra check is made for mp_obj_is_instance_type(type) to fix lookup of
  built-in functions.

Fixes #1326 and #6198.

Signed-off-by: Damien George <damien@micropython.org>
2020-06-30 23:55:32 +10:00
Jim Mussared def76fe4d9 all: Use MP_ERROR_TEXT for all error messages. 2020-04-05 15:02:06 +10:00
Damien George 69661f3343 all: Reformat C and Python source code with tools/codeformat.py.
This is run with uncrustify 0.70.1, and black 19.10b0.
2020-02-28 10:33:03 +11:00
Damien George 97eca38c4f py: Add mp_raise_type helper macro and use it where appropriate.
This provides a more consistent C-level API to raise exceptions, ie moving
away from nlr_raise towards mp_raise_XXX.  It also reduces code size by a
small amount on some ports.
2020-02-13 11:03:37 +11:00
Damien George edc7a8bf1d py/objgenerator: Use mp_obj_new_exception_arg1 to make StopIteration. 2020-01-23 13:37:25 +11:00
Jim Mussared 5578182ec9 py/objgenerator: Allow pend_throw to an unstarted generator.
Replace the is_running field with a tri-state variable to indicate
running/not-running/pending-exception.

Update tests to cover the various cases.

This allows cancellation in uasyncio even if the coroutine hasn't been
executed yet.  Fixes #5242
2019-11-04 15:51:16 +11:00
Jim Mussared 576ed89224 py/objgenerator: Remove globals from mp_obj_gen_instance_t.
This wasn't necessary as the wrapped function already has a reference to
its globals.  But it had a dual purpose of tracking whether the function
was currently running, so replace it with a bool.
2019-11-04 15:50:59 +11:00
Damien George 306ec5369a py/emitnative: Add support for archs that cannot read executable data.
In which case place the native function prelude in a bytes object, linked
from the const_table of that function.  An architecture should define
N_PRELUDE_AS_BYTES_OBJ to 1 before including py/emitnative.c to emit
correct machine code, then enable MICROPY_EMIT_NATIVE_PRELUDE_AS_BYTES_OBJ
so the runtime can correctly handle the prelude being in a bytes object.
2019-10-05 13:42:39 +10:00
Damien George b5ebfadbd6 py: Compress first part of bytecode prelude.
The start of the bytecode prelude contains 6 numbers telling the amount of
stack needed for the Python values and exceptions, and the signature of the
function.  Prior to this patch these numbers were all encoded one after the
other (2x variable unsigned integers, then 4x bytes), but using so many
bytes is unnecessary.

An entropy analysis of around 150,000 bytecode functions from the CPython
standard library showed that the optimal Shannon coding would need about
7.1 bits on average to encode these 6 numbers, compared to the existing 48
bits.

This patch attempts to get close to this optimal value by packing the 6
numbers into a single, varible-length unsigned integer via bit-wise
interleaving.  The interleaving scheme is chosen to minimise the average
number of bytes needed, and at the same time keep the scheme simple enough
so it can be implemented without too much overhead in code size or speed.
The scheme requires about 10.5 bits on average to store the 6 numbers.

As a result most functions which originally took 6 bytes to encode these 6
numbers now need only 1 byte (in 80% of cases).
2019-10-01 12:26:22 +10:00
Damien George 81d04a0200 py: Add n_state to mp_code_state_t struct.
This value is used often enough that it is better to cache it instead of
decode it each time.
2019-10-01 12:26:22 +10:00
Damien George 4c5e1a0368 py/bc: Change mp_code_state_t.exc_sp to exc_sp_idx.
Change from a pointer to an index, to make space in mp_code_state_t.
2019-10-01 12:26:22 +10:00
Damien George 973c87d8fa py/objgenerator: Move defn of mp_const_GeneratorExit_obj here.
Because the mp_obj_exception_t type is now globally available.
2019-08-22 16:05:05 +10:00
Laurens Valk a73859d5af py/objgenerator: Add missing #if guard for PY_GENERATOR_PEND_THROW.
Without it, gen_instance_pend_throw_obj is defined but not used when
MICROPY_PY_GENERATOR_PEND_THROW is set to 0.
2019-07-09 13:24:23 +10:00
Damien George 4268d0e1ac py/objgenerator: Remove unneeded forward decl and clean up white space. 2019-05-09 13:49:07 +10:00
Damien George dac9d47671 py/objgenerator: Fix handling of None passed as 2nd arg to throw().
Fixes issue #4527.
2019-05-09 13:40:28 +10:00
Damien George eee1e8841a py: Downcase all MP_OBJ_IS_xxx macros to make a more consistent C API.
These macros could in principle be (inline) functions so it makes sense to
have them lower case, to match the other C API functions.

The remaining macros that are upper case are:
- MP_OBJ_TO_PTR, MP_OBJ_FROM_PTR
- MP_OBJ_NEW_SMALL_INT, MP_OBJ_SMALL_INT_VALUE
- MP_OBJ_NEW_QSTR, MP_OBJ_QSTR_VALUE
- MP_OBJ_FUN_MAKE_SIG
- MP_DECLARE_CONST_xxx
- MP_DEFINE_CONST_xxx

These must remain macros because they are used when defining const data (at
least, MP_OBJ_NEW_SMALL_INT is so it makes sense to have
MP_OBJ_SMALL_INT_VALUE also a macro).

For those macros that have been made lower case, compatibility macros are
provided for the old names so that users do not need to change their code
immediately.
2019-02-12 14:54:51 +11:00
Damien George cc2bd63c57 py/emitnative: Implement yield and yield-from in native emitter.
This commit adds first class support for yield and yield-from in the native
emitter, including send and throw support, and yields enclosed in exception
handlers (which requires pulling down the NLR stack before yielding, then
rebuilding it when resuming).

This has been fully tested and is working on unix x86 and x86-64, and
stm32.  Also basic tests have been done with the esp8266 port.  Performance
of existing native code is unchanged.
2018-10-01 13:31:11 +10:00
Damien George d95947b48a py/vm: When VM raises exception put exc obj at beginning of func state.
Instead of at end of state, n_state - 1.  It was originally (way back in
v1.0) put at the end of the state because the VM didn't have a pointer to
the start.  But now that the VM takes a mp_code_state_t pointer it does
have a pointer to the start of the state so can put the exception object
there.

This commit saves about 30 bytes of code on all architectures, and, more
importantly, reduces C-stack usage by a couple of words (8 bytes on Thumb2
and 16 bytes on x86-64) for every (non-generator) call of a bytecode
function because fun_bc_call no longer needs to remember the n_state
variable.
2018-09-29 23:25:08 +10:00
Damien George fc1bb51af5 py/objgenerator: Remove TODO about returning gen being called again.
The code implements correct behaviour, as tested by the new test case added
in this commit.
2018-09-27 15:18:24 +10:00
Damien George 3f6ffe059f py/objgenerator: Implement PEP479, StopIteration convs to RuntimeError.
This commit implements PEP479 which disallows raising StopIteration inside
a generator to signal that it should be finished.  Instead, the generator
should simply return when it is complete.

See https://www.python.org/dev/peps/pep-0479/ for details.
2018-09-20 15:36:59 +10:00
Scott Shawcroft 96ebf5bc3f
Two fixes and translate more strings.
* Fix finding translations with escaped characters.
* Add back \r to translations since its needed by screen.
2018-08-09 13:29:30 -07:00
Dan Halbert 7c219600a2 WIP: after merge; before testing 2018-07-11 16:45:30 -04:00
Damien George e2e22e3d7e py/objgenerator: Implement __name__ with normal fun attr accessor code.
With the recent change b488a4a848, a
generating function now has the same layout in memory as a normal bytecode
function, and so can reuse the latter's attribute accessor code to
implement __name__.
2018-07-10 16:33:57 +10:00
Damien George b488a4a848 py/objgenerator: Eliminate need for mp_obj_gen_wrap wrapper instances.
For generating functions there is no need to wrap the bytecode function in
a generator wrapper instance.  Instead the type of the bytecode function
can be changed to mp_type_gen_wrap.  This reduces code size and saves a
block of GC heap RAM for each generator.
2018-07-02 15:30:57 +10:00
Damien George 400273a799 py/objgenerator: Protect against reentering a generator.
Generators that are already executing cannot be reexecuted.  This patch
puts in a check for such a case.

Thanks to @jepler for finding the bug.
2018-05-22 16:54:03 +10:00
Damien George 771cb359af py/objgenerator: Save state in old_globals instead of local variable.
The code_state.old_globals variable is there to save the globals state so
should be used for this purpose, to avoid the need for additional local
variables on the C stack.
2018-05-22 16:39:19 +10:00
Jeff Epler cbf981f330 py/objgenerator: Check stack before resuming a generator.
This turns a hard crash in a recursive generator into a 'maximum recursion
depth exceeded' exception.
2018-04-10 14:06:26 +10:00
Jeff Epler a909007fef py/objgenerator: Check stack before resuming a generator
This turns a hard crash in a recursive generator into
a 'maximum recursion depth exceeded' exception.
2018-04-01 16:40:15 -05:00
Paul Sokolovsky 6364401666 py/objgenerator: Allow to pend an exception for next execution.
This implements .pend_throw(exc) method, which sets up an exception to be
triggered on the next call to generator's .__next__() or .send() method.
This is unlike .throw(), which immediately starts to execute the generator
to process the exception. This effectively adds Future-like capabilities
to generator protocol (exception will be raised in the future).

The need for such a method arised to implement uasyncio wait_for() function
efficiently (its behavior is clearly "Future" like, and normally would
require to introduce an expensive Future wrapper around all native
couroutines, like upstream asyncio does).

py/objgenerator: pend_throw: Return previous pended value.

This effectively allows to store an additional value (not necessary an
exception) in a coroutine while it's not being executed. uasyncio has
exactly this usecase: to mark a coro waiting in I/O queue (and thus
not executed in the normal scheduling queue), for the purpose of
implementing wait_for() function (cancellation of such waiting coro
by a timeout).
2017-12-15 20:20:36 +02:00
Damien George 64f11470be py/objgenerator: Remove unreachable code for STOP_ITERATION case.
This commit essentially reverts aa9dbb1b03
where this if-condition was added.  It seems that even when that commit
was made the code was never reached by any tests, nor reachable by
analysis (see below).  The same is true with the code as it currently
stands: no test triggers this if-condition, nor any uasyncio examples.
Analysing the flow of the program also shows that it's not reachable:

==START==
-> to trigger this if condition mp_execute_bytecode() must return
   MP_VM_RETURN_YIELD with *sp==MP_OBJ_STOP_ITERATION

   -> mp_execute_bytecode() can only return MP_VM_RETURN_YIELD from the
      MP_BC_YIELD_VALUE bytecode, which can happen in 2 ways:

      -> 1) from a "yield <x>" in bytecode, but <x> must always be a proper
         object, never MP_OBJ_STOP_ITERATION; ==END1==

      -> 2) via yield from, via mp_resume() which must return
         MP_VM_RETURN_YIELD with ret_value==MP_OBJ_STOP_ITERATION, which
         can happen in 3 ways:

         -> 1) it delegates to mp_obj_gen_resume(); go back to ==START==

         -> 2) it returns MP_VM_RETURN_YIELD directly but with a guard that
            ret_val!=MP_OBJ_STOP_ITERATION; ==END2==

         -> 3) it returns MP_VM_RETURN_YIELD with ret_val set from
            mp_call_method_n_kw(), but mp_call_method_n_kw() must return a
            proper object, never MP_OBJ_STOP_ITERATION; ==END3==

The above shows there is no way to trigger the if-condition and it can be
removed.
2017-11-30 12:06:41 +11:00
Scott Shawcroft 73c15dcf8b Merge commit 'f869d6b2e339c04469c6c9ea3fb2fabd7bbb2d8c' into nrf2_merge
This is prep for merging in the NRF5 pull request.
2017-10-24 22:31:16 -07:00