10000 [mypyc] Add a mypyc_attr to support interpreted children by msullivan · Pull Request #8004 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

[mypyc] Add a mypyc_attr to support interpreted children #8004

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 28, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
doc tweaks
  • Loading branch information
msullivan committed Nov 27, 2019
commit 8ed1ea473099bbd9269d3eb40212de2bcb8dfa84
7 changes: 7 additions & 0 deletions mypyc/emitclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ def emit_line() -> None:
fields['tp_basicsize'] = base_size

if generate_full:
# Declare setup method that allocates and initializes an object. type is the
# type of the class being initialized, which could be another class if there
# is an interpreted subclass.
emitter.emit_line('static PyObject *{}(PyTypeObject *type);'.format(setup_name))
assert cl.ctor is not None
emitter.emit_line(native_function_header(cl.ctor, emitter) + ';')
Expand Down Expand Up @@ -364,8 +367,12 @@ def generate_vtables(base: ClassIR,
emit empty array definitions to store the vtables and a function to
populate them.

If shadow is True, generate "shadow vtables" that point to the
shadow glue methods (which should dispatch via the Python C-API).

Returns the expression to use to refer to the vtable, which might be
different than the name, if there are trait vtables.

"""

def trait_vtable_name(trait: ClassIR) -> str:
Expand Down
23 changes: 21 additions & 2 deletions mypyc/genops.py
10000
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,8 @@ def compute_vtable(cls: ClassIR) -> None:
# TODO: don't generate a new entry when we overload without changing the type
if fn == cls.get_method(fn.name):
cls.vtable[fn.name] = len(entries)
# If the class contains a glue method referring to itself, that is a
# shadow glue method to support interpreted subclasses.
shadow = cls.glue_methods.get((cls, fn.name))
entries.append(VTableMethod(t, fn.name, fn, shadow))

Expand Down Expand Up @@ -1772,6 +1774,14 @@ def gen_glue(self, sig: FuncSignature, target: FuncIR,
*,
do_py_ops: bool = False
) -> FuncIR:
"""Generate glue methods that mediate between different method types in subclasses.

Works on both properties and methods. See gen_glue_methods below for more details.

If do_py_ops is True, then the glue methods should use generic
C API operations instead of direct calls, to enable generating
"shadow" glue methods that work with interpreted subclasses.
"""
if fdef.is_property:
return self.gen_glue_property(sig, target, cls, base, fdef.line, do_py_ops)
else:
Expand Down Expand Up @@ -1802,6 +1812,9 @@ def f(self, x: object) -> int: ...
we need to generate glue methods that mediate between the
different versions by coercing the arguments and return
values.

If do_pycall is True, then make the call using the C API
instead of a native call.
"""
self.enter(FuncInfo())
self.ret_types[-1] = sig.ret_type
Expand Down Expand Up @@ -1836,9 +1849,15 @@ def f(self, x: object) -> int: ...
def gen_glue_property(self, sig: FuncSignature, target: FuncIR, cls: ClassIR, base: ClassIR,
line: int,
do_pygetattr: bool) -> FuncIR:
"""Similarly to methods, properties of derived types can be covariantly subtyped. Thus,
"""Generate glue methods for properties that mediate between different subclass types.

Similarly to methods, properties of derived types can be covariantly subtyped. Thus,
properties also require glue. However, this only requires the return type to change.
Further, instead of a method call, an attribute get is performed."""
Further, instead of a method call, an attribute get is performed.

If do_pygetattr is True, then get the attribute using the C
API instead of a native call.
"""
self.enter(FuncInfo())

rt_arg = RuntimeArg(SELF_NAME, RInstance(cls))
Expand Down
7 changes: 6 additions & 1 deletion mypyc/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -1762,6 +1762,7 @@ def __init__(self, name: str, module_name: str, is_trait: bool = False,
self.is_augmented = False
self.inherits_python = False
self.has_dict = False
# Do we allow interpreted subclasses? Derived from a mypyc_attr.
self.allow_interpreted_children = False
# If this a subclass of some built-in python class, the name
# of the object for that class. We currently only support this
Expand Down Expand Up @@ -1890,7 +1891,11 @@ def get_method(self, name: str) -> Optional[FuncIR]:
return res[0] if res else None

def subclasses(self) -> Optional[Set['ClassIR']]:
"""Return all subclassses of this class, both direct and indirect."""
"""Return all subclassses of this class, both direct and indirect.

Return None if it is impossible to identify all subclasses, for example
because we are performing separate compilation.
"""
if self.children is None or self.allow_interpreted_children:
return None
result = set(self.children)
Expand Down
0