コード例 #1
0
def specialize_parent_vtable(cls: ClassIR, parent: ClassIR) -> VTableEntries:
    """Generate the part of a vtable corresponding to a parent class or trait"""
    updated = []
    for entry in parent.vtable_entries:
        if isinstance(entry, VTableMethod):
            # Find the original method corresponding to this vtable entry.
            # (This may not be the method in the entry, if it was overridden.)
            orig_parent_method = entry.cls.get_method(entry.name)
            assert orig_parent_method
            method_cls = cls.get_method_and_class(entry.name)
            if method_cls:
                child_method, defining_cls = method_cls
                # TODO: emit a wrapper for __init__ that raises or something
                if (is_same_method_signature(orig_parent_method.sig, child_method.sig)
                        or orig_parent_method.name == '__init__'):
                    entry = VTableMethod(entry.cls, entry.name, child_method, entry.shadow_method)
                else:
                    entry = VTableMethod(entry.cls, entry.name,
                                         defining_cls.glue_methods[(entry.cls, entry.name)],
                                         entry.shadow_method)
        else:
            # If it is an attribute from a trait, we need to find out
            # the real class it got mixed in at and point to that.
            if parent.is_trait:
                _, origin_cls = cls.attr_details(entry.name)
                entry = VTableAttr(origin_cls, entry.name, entry.is_setter)
        updated.append(entry)
    return updated
コード例 #2
0
ファイル: emitclass.py プロジェクト: JoeCare/mypy-1
def generate_slots(cl: ClassIR, table: SlotTable, emitter: Emitter) -> Dict[str, str]:
    fields = OrderedDict()  # type: Dict[str, str]
    # Sort for determinism on Python 3.5
    for name, (slot, generator) in sorted(table.items()):
        method_cls = cl.get_method_and_class(name)
        if method_cls and (method_cls[1] == cl or name in ALWAYS_FILL):
            fields[slot] = generator(cl, method_cls[0], emitter)

    return fields
コード例 #3
0
ファイル: emitclass.py プロジェクト: alanhdu/mypy
def generate_slots(cl: ClassIR, table: SlotTable, emitter: Emitter) -> Dict[str, str]:
    fields: Dict[str, str] = OrderedDict()
    generated: Dict[str, str] = {}
    # Sort for determinism on Python 3.5
    for name, (slot, generator) in sorted(table.items(), key=lambda x: slot_key(x[0])):
        method_cls = cl.get_method_and_class(name)
        if method_cls and (method_cls[1] == cl or name in ALWAYS_FILL):
            if slot in generated:
                # Reuse previously generated wrapper.
                fields[slot] = generated[slot]
            else:
                # Generate new wrapper.
                name = generator(cl, method_cls[0], emitter)
                fields[slot] = name
                generated[slot] = name

    return fields
コード例 #4
0
ファイル: vtable.py プロジェクト: sthagen/mypy
def specialize_parent_vtable(cls: ClassIR, parent: ClassIR) -> VTableEntries:
    """Generate the part of a vtable corresponding to a parent class or trait"""
    updated = []
    for entry in parent.vtable_entries:
        # Find the original method corresponding to this vtable entry.
        # (This may not be the method in the entry, if it was overridden.)
        orig_parent_method = entry.cls.get_method(entry.name)
        assert orig_parent_method
        method_cls = cls.get_method_and_class(entry.name)
        if method_cls:
            child_method, defining_cls = method_cls
            # TODO: emit a wrapper for __init__ that raises or something
            if (is_same_method_signature(orig_parent_method.sig,
                                         child_method.sig)
                    or orig_parent_method.name == '__init__'):
                entry = VTableMethod(entry.cls, entry.name, child_method,
                                     entry.shadow_method)
            else:
                entry = VTableMethod(
                    entry.cls, entry.name,
                    defining_cls.glue_methods[(entry.cls, entry.name)],
                    entry.shadow_method)
        updated.append(entry)
    return updated
コード例 #5
0
ファイル: emitwrapper.py プロジェクト: srittau/mypy
def generate_set_del_item_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str:
    """Generates a wrapper for native __setitem__ method (also works for __delitem__).

    This is used with the mapping protocol slot. Arguments are taken as *PyObjects and we
    return a negative C int on error.

    Create a separate wrapper function for __delitem__ as needed and have the
    __setitem__ wrapper call it if the value is NULL. Return the name
    of the outer (__setitem__) wrapper.
    """
    method_cls = cl.get_method_and_class('__delitem__')
    del_name = None
    if method_cls and method_cls[1] == cl:
        # Generate a separate wrapper for __delitem__
        del_name = generate_del_item_wrapper(cl, method_cls[0], emitter)

    args = fn.args
    if fn.name == '__delitem__':
        # Add an extra argument for value that we expect to be NULL.
        args = list(args) + [RuntimeArg('___value', object_rprimitive, ARG_POS)]

    name = '{}{}{}'.format(DUNDER_PREFIX, '__setitem__', cl.name_prefix(emitter.names))
    input_args = ', '.join('PyObject *obj_{}'.format(arg.name) for arg in args)
    emitter.emit_line('static int {name}({input_args}) {{'.format(
        name=name,
        input_args=input_args,
    ))

    # First check if this is __delitem__
    emitter.emit_line('if (obj_{} == NULL) {{'.format(args[2].name))
    if del_name is not None:
        # We have a native implementation, so call it
        emitter.emit_line('return {}(obj_{}, obj_{});'.format(del_name,
                                                              args[0].name,
                                                              args[1].name))
    else:
        # Try to call superclass method instead
        emitter.emit_line(
            'PyObject *super = CPy_Super(CPyModule_builtins, obj_{});'.format(args[0].name))
        emitter.emit_line('if (super == NULL) return -1;')
        emitter.emit_line(
            'PyObject *result = PyObject_CallMethod(super, "__delitem__", "O", obj_{});'.format(
                args[1].name))
        emitter.emit_line('Py_DECREF(super);')
        emitter.emit_line('Py_XDECREF(result);')
        emitter.emit_line('return result == NULL ? -1 : 0;')
    emitter.emit_line('}')

    method_cls = cl.get_method_and_class('__setitem__')
    if method_cls and method_cls[1] == cl:
        generate_set_del_item_wrapper_inner(fn, emitter, args)
    else:
        emitter.emit_line(
            'PyObject *super = CPy_Super(CPyModule_builtins, obj_{});'.format(args[0].name))
        emitter.emit_line('if (super == NULL) return -1;')
        emitter.emit_line('PyObject *result;')

        if method_cls is None and cl.builtin_base is None:
            msg = "'{}' object does not support item assignment".format(cl.name)
            emitter.emit_line(
                'PyErr_SetString(PyExc_TypeError, "{}");'.format(msg))
            emitter.emit_line('result = NULL;')
        else:
            # A base class may have __setitem__
            emitter.emit_line(
                'result = PyObject_CallMethod(super, "__setitem__", "OO", obj_{}, obj_{});'.format(
                    args[1].name, args[2].name))
        emitter.emit_line('Py_DECREF(super);')
        emitter.emit_line('Py_XDECREF(result);')
        emitter.emit_line('return result == NULL ? -1 : 0;')
        emitter.emit_line('}')
    return name