def register_once_per_class(self): """ Register code-generation information to the target context. The registration is executed once per (class, targetcontext) """ registry = imputils.Registry() if (type(self), self.targetctx) not in self.registered_targetctx: self.implement_constructor(registry) self.implement_attribute(registry) self.targetctx.insert_func_defn(registry.functions) self.targetctx.insert_attr_defn(registry.attributes) self.registered_targetctx[type(self), self.targetctx] = registry
class ClassBuilder(object): """ A jitclass builder for a mutable jitclass. This will register typing and implementation hooks to the given typing and target contexts. """ class_impl_registry = imputils.Registry() implemented_methods = set() def __init__(self, class_type, methods, typingctx, targetctx): self.class_type = class_type self.methods = methods self.typingctx = typingctx self.targetctx = targetctx def register(self): """ Register to the frontend and backend. """ # Register generic implementations for all jitclasses self._register_methods(self.class_impl_registry, self.class_type.instance_type) # NOTE other registrations are done at the top-level # (see ctor_impl and attr_impl below) self.targetctx.install_registry(self.class_impl_registry) def _register_methods(self, registry, instance_type): """ Register method implementations for the given instance type. """ for meth in instance_type.jitmethods: # There's no way to retrive the particular method name # inside the implementation function, so we have to register a # specific closure for each different name if meth not in self.implemented_methods: self._implement_method(registry, meth) self.implemented_methods.add(meth) def _implement_method(self, registry, attr): @registry.lower((types.ClassInstanceType, attr), types.ClassInstanceType, types.VarArg(types.Any)) def imp(context, builder, sig, args): instance_type = sig.args[0] method = instance_type.jitmethods[attr] disp_type = types.Dispatcher(method) call = context.get_function(disp_type, sig) out = call(builder, args) _add_linking_libs(context, call) return imputils.impl_ret_new_ref(context, builder, sig.return_type, out)
def implement_backend(self, instance_type): registry = imputils.Registry() self.register_methods(registry, instance_type) self.targetctx.insert_func_defn(registry.functions) self.targetctx.insert_attr_defn(registry.attributes)
class ClassBuilder(object): """ A jitclass builder for a mutable jitclass. This will register typing and implementation hooks to the given typing and target contexts. """ class_impl_registry = imputils.Registry() implemented_methods = set() def __init__(self, class_type, methods, typingctx, targetctx): self.class_type = class_type self.methods = methods self.typingctx = typingctx self.targetctx = targetctx def register(self): """ Register to the frontend and backend. """ # Register generic implementations for all jitclasses self._register_methods(self.class_impl_registry, self.class_type.instance_type) # NOTE other registrations are done at the top-level # (see ctor_impl and attr_impl below) self.targetctx.install_registry(self.class_impl_registry) def _register_methods(self, registry, instance_type): """ Register method implementations for the given instance type. """ for meth in instance_type.jitmethods: # There's no way to retrive the particular method name # inside the implementation function, so we have to register a # specific closure for each different name if meth not in self.implemented_methods: self._implement_method(registry, meth) self.implemented_methods.add(meth) def _implement_method(self, registry, attr): # create a separate instance of imp method to avoid closure clashing def get_imp(): def imp(context, builder, sig, args): instance_type = sig.args[0] method = instance_type.jitmethods[attr] disp_type = types.Dispatcher(method) call = context.get_function(disp_type, sig) out = call(builder, args) _add_linking_libs(context, call) return imputils.impl_ret_new_ref(context, builder, sig.return_type, out) return imp def _getsetitem_gen(getset): _dunder_meth = "__%s__" % getset op = getattr(operator, getset) @templates.infer_global(op) class GetSetItem(templates.AbstractTemplate): def generic(self, args, kws): instance = args[0] if isinstance(instance, types.ClassInstanceType) and \ _dunder_meth in instance.jitmethods: meth = instance.jitmethods[_dunder_meth] disp_type = types.Dispatcher(meth) sig = disp_type.get_call_type(self.context, args, kws) return sig # lower both {g,s}etitem and __{g,s}etitem__ to catch the calls # from python and numba imputils.lower_builtin((types.ClassInstanceType, _dunder_meth), types.ClassInstanceType, types.VarArg(types.Any))(get_imp()) imputils.lower_builtin(op, types.ClassInstanceType, types.VarArg(types.Any))(get_imp()) dunder_stripped = attr.strip('_') if dunder_stripped in ("getitem", "setitem"): _getsetitem_gen(dunder_stripped) else: registry.lower( (types.ClassInstanceType, attr), types.ClassInstanceType, types.VarArg(types.Any))(get_imp())