File: interp_module.py

package info (click to toggle)
pypy3 7.3.19%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 212,236 kB
  • sloc: python: 2,098,316; ansic: 540,565; sh: 21,462; asm: 14,419; cpp: 4,451; makefile: 4,209; objc: 761; xml: 530; exp: 499; javascript: 314; pascal: 244; lisp: 45; csh: 12; awk: 4
file content (168 lines) | stat: -rw-r--r-- 7,426 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rlib.objectmodel import specialize
from rpython.rlib.rarithmetic import widen
from pypy.interpreter.error import oefmt
from pypy.interpreter.executioncontext import ExecutionContext
from pypy.interpreter.module import Module, init_extra_module_attrs
from pypy.module._hpy_universal.apiset import API, DEBUG
from pypy.module._hpy_universal import interp_extfunc, llapi
from pypy.module._hpy_universal.state import State
from pypy.module._hpy_universal.interp_cpy_compat import attach_legacy_methods

NON_DEFAULT_MESSAGE = ("This is not allowed because custom " 
    "HPy_mod_create slot cannot return a builtin module "
    "object and cannot make any use of any other data "
    "defined in the HPyModuleDef. Either do not define "
    "HPy_mod_create slot and let the runtime create a builtin "
    "module object from the provided HPyModuleDef, or do not define "
    "anything else but the HPy_mod_create slot.")

@specialize.arg(0)
def hpymod_create(handles, modname, hpydef):
    space = handles.space
    w_mod = Module(space, space.newtext(modname))
    kinds = llapi.cts.gettype("HPyDef_Kind")
    slots = llapi.cts.gettype("HPySlot_Slot")
    #
    if hpydef.c_size < 0:
        raise oefmt(space.w_SystemError,
            "HPy does not permit HPyModuleDef.size < 0")
    elif hpydef.c_size > 0:
        raise oefmt(space.w_SystemError,
            "Module state is not supported yet in HPy, set "
            "HPyModuleDef.size = 0 if module state is not needed")
    # add the functions defined in hpydef.c_legacy_methods
    if hpydef.c_legacy_methods:
        if space.config.objspace.hpy_cpyext_API:
            pymethods = rffi.cast(rffi.VOIDP, hpydef.c_legacy_methods)
            attach_legacy_methods(space, pymethods, w_mod, modname, None)
        else:
            raise oefmt(space.w_RuntimeError,
                "Module %s contains legacy methods, but _hpy_universal "
                "was compiled without cpyext support", modname)
    #
    # add the native HPy module-level defines
    if hpydef.c_defines:
        create_func = llapi.cts.cast("HPySlot *", 0)
        found_non_create = False
        p = hpydef.c_defines
        i = 0
        while p[i]:
            # hpy native methods
            kind = widen(p[i].c_kind)
            if kind == kinds.HPyDef_Kind_Slot:
                hpyslot = llapi.cts.cast("HPySlot *", p[i].c_meth)
                slot_num = rffi.cast(lltype.Signed, hpyslot.c_slot)
                if slot_num == slots.HPy_mod_create:
                    if create_func:
                        raise oefmt(space.w_SystemError,
                            "Multiple definitions of the HPy_mod_create "
                            "slot in HPyModuleDef.defines.")
                    create_func = hpyslot
                elif slot_num != slots.HPy_mod_exec:
                    raise oefmt(space.w_SystemError,
                        "Unsupported slot in HPyModuleDef.defines (value: %d).",
                         slot_num)
                else:
                    found_non_create = True
            else:
                hpymeth = p[i].c_meth
                name = rffi.constcharp2str(hpymeth.c_name)
                sig = rffi.cast(lltype.Signed, hpymeth.c_signature)
                doc = get_doc(hpymeth.c_doc)
                w_extfunc = handles.w_ExtensionFunction(
                    space, handles, name, sig, doc, hpymeth.c_impl, w_mod)
                space.setattr(w_mod, space.newtext(w_extfunc.name), w_extfunc)
                found_non_create = True
            i += 1
        if create_func:
            if found_non_create:
                raise oefmt(space.w_SystemError,
                    "HPyModuleDef defines a HPy_mod_create slot and some "
                    "other slots or methods. %s", NON_DEFAULT_MESSAGE)
            if (hpydef.c_legacy_methods or hpydef.c_size > 0 or
                hpydef.c_doc or hpydef.c_globals):
                raise oefmt(space.w_SystemError,
                    "HPyModuleDef defines a HPy_mod_create slot and some "
                    "of the other fields are not set to their default "
                    "value. %s", NON_DEFAULT_MESSAGE)
            # fast-call directly to W_ExtensionFunctionMixin.call_o
            func = llapi.cts.cast("HPyFunc_o", create_func.c_impl)
            with handles.using(w_mod) as h_arg:
                h = func(handles.get_ctx(), h_arg, h_arg)
            if h == 0:
                space.fromcache(State).raise_current_exception()
            w_result = handles.deref(h)
            if w_result and isinstance(w_result, type(w_mod)):
                raise oefmt(space.w_SystemError,
                    "HPy_mod_create slot returned a builtin module object. "
                    "This is currently not supported.")
            # Throw away the w_mod and return the result of mod_create()
            return w_result
    if hpydef.c_doc:
        w_doc = space.newtext(rffi.constcharp2str(hpydef.c_doc))
    else:
        w_doc = space.w_None
    space.setattr(w_mod, space.newtext('__doc__'), w_doc)
    space.setattr(w_mod, space.newtext('__file__'), space.w_None)
    init_extra_module_attrs(space, w_mod)
    return w_mod

@specialize.arg(0)
def hpymod_exec_def(handles, w_mod, hpydef):
    """ Traverse the hpydef, and execute any HPy_mod_exec slot
    """
    kinds = llapi.cts.gettype("HPyDef_Kind")
    slots = llapi.cts.gettype("HPySlot_Slot")
    space = handles.space
    if hpydef.c_defines:
        p = hpydef.c_defines
        i = 0
        while p[i]:
            # hpy native methods
            kind = widen(p[i].c_kind)
            if kind == kinds.HPyDef_Kind_Slot:
                hpyslot = llapi.cts.cast("HPySlot *", p[i].c_meth)
                slot_num = rffi.cast(lltype.Signed, hpyslot.c_slot)
                if slot_num == slots.HPy_mod_exec:
                    # fast-call directly to W_ExtensionFunctionMixin.call_o
                    func = llapi.cts.cast("HPyFunc_o", hpyslot.c_impl)
                    with handles.using(w_mod) as h_arg:
                        result = func(handles.get_ctx(), h_arg, h_arg)
                    if result != 0:
                        space.fromcache(State).raise_current_exception()
            i += 1

def get_doc(c_doc):
    if not c_doc:
        return None
    return rffi.constcharp2str(c_doc)

@API.func("HPy HPyGlobal_Load(HPyContext *ctx, HPyGlobal global)")
def HPyGlobal_Load(space, handles, ctx, h_global):
    state = State.get(space)
    d_globals = state.global_handles
    if h_global not in d_globals:
        if h_global:
            w_global = handles.deref(h_global)
            w_s = space.repr(w_global)
            s = space.text_w(w_s)
        else:
            s = "<None>"
        raise oefmt(space.w_ValueError, "unknown HPyGlobal* in HPyGlobal_Load (%s)", s)
    return handles.new(d_globals[h_global])

@API.func("void HPyGlobal_Store(HPyContext *ctx, HPyGlobal *global, HPy h)")
def HPyGlobal_Store(space, handles, ctx, p_global, h_obj):
    if h_obj:
        w_obj = handles.deref(h_obj)
    else:
        w_obj = space.w_None
    state = State.get(space)
    d_globals = state.global_handles
    # Release a potential already existing p_global[0]
    if p_global[0] in d_globals:
        d_globals.pop(p_global[0])
    h_new = handles.new(w_obj)
    d_globals[h_new] = w_obj
    p_global[0] = h_new