def handle_method_call(self, env, node, call_node): """ Resolve an extension method of a static (C++/Cython-like) vtable: typedef { double (*method1)(double); ... } vtab_struct; vtab_struct *vtab = *(vtab_struct **) (((char *) obj) + vtab_offset) void *method = vtab[index] """ # Make the object we call the method on clone-able node.value = nodes.CloneableNode(node.value) ext_type = node.value.type offset = ext_type.vtab_offset vtable_struct = ext_type.vtab_type.to_struct() vtable_struct_type = vtable_struct.ref() vtab_struct_pointer_pointer = nodes.value_at_offset( node.value, offset, vtable_struct_type.pointer()) vtab_struct_pointer = nodes.DereferenceNode( vtab_struct_pointer_pointer) vmethod = nodes.StructAttribute(vtab_struct_pointer, node.attr, ast.Load(), vtable_struct_type) # Insert first argument 'self' in args list args = call_node.args args.insert(0, nodes.CloneNode(node.value)) result = nodes.NativeFunctionCallNode(node.type, vmethod, args) return result
def retrieve_closure_from_numbafunc(self, node): """ Retrieve the closure scope from ((NumbaFunctionObject *) numba_func).func_closure """ # TODO: use llvmwrapper.get_closure_scope() pointer = nodes.ptrfromobj(node.func) type = typedefs.NumbaFunctionObject.ref() closure_obj_struct = nodes.CoercionNode(pointer, type) cur_scope = nodes.StructAttribute(closure_obj_struct, 'func_closure', ctx=ast.Load(), type=type) return cur_scope
def handle_attribute_lookup(self, env, node): """ Resolve an extension attribute for a static object layout. ((attributes_struct *) (((char *) obj) + attributes_offset))->attribute :node: ExtTypeAttribute AST node """ ext_type = node.value.type offset = ext_type.attr_offset type = ext_type.attribute_table.to_struct() if isinstance(node.ctx, ast.Load): value_type = type.ref() # Load result else: value_type = type.pointer() # Use pointer for storage struct_pointer = nodes.value_at_offset(node.value, offset, value_type) result = nodes.StructAttribute(struct_pointer, node.attr, node.ctx, type.ref()) return result