this repo has no description
at trunk 120 lines 4.5 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "function-utils.h" 3 4#include "capi-trampolines.h" 5#include "handles.h" 6#include "runtime.h" 7 8namespace py { 9 10RawObject getExtensionFunction(RawObject object) { 11 if (!object.isBoundMethod()) return Error::notFound(); 12 RawObject function_obj = BoundMethod::cast(object).function(); 13 if (!function_obj.isFunction()) return Error::notFound(); 14 RawFunction function = Function::cast(function_obj); 15 if (!function.isExtension()) return Error::notFound(); 16 return function; 17} 18 19RawObject newCFunction(Thread* thread, PyMethodDef* method, const Object& name, 20 const Object& self, const Object& module_name) { 21 HandleScope scope(thread); 22 Runtime* runtime = thread->runtime(); 23 Function function( 24 &scope, newExtensionFunction(thread, name, 25 reinterpret_cast<void*>(method->ml_meth), 26 method->ml_flags)); 27 if (method->ml_doc != nullptr) { 28 function.setDoc(runtime->newStrFromCStr(method->ml_doc)); 29 } 30 if (runtime->isInstanceOfStr(*module_name)) { 31 function.setModuleName(*module_name); 32 } 33 return runtime->newBoundMethod(function, self); 34} 35 36RawObject newClassMethod(Thread* thread, PyMethodDef* method, 37 const Object& name, const Object& type) { 38 HandleScope scope(thread); 39 Runtime* runtime = thread->runtime(); 40 Function function(&scope, newExtensionFunction( 41 thread, name, bit_cast<void*>(method->ml_meth), 42 method->ml_flags)); 43 if (method->ml_doc != nullptr) { 44 function.setDoc(runtime->newStrFromCStr(method->ml_doc)); 45 } 46 Object result( 47 &scope, thread->invokeFunction2(ID(builtins), ID(_descrclassmethod), type, 48 function)); 49 DCHECK(!result.isError(), "failed to create classmethod descriptor"); 50 return *result; 51} 52 53RawObject newExtensionFunction(Thread* thread, const Object& name, 54 void* function, int flags) { 55 HandleScope scope(thread); 56 Runtime* runtime = thread->runtime(); 57 Function::Entry entry; 58 Function::Entry entry_kw; 59 Function::Entry entry_ex; 60 flags &= ~METH_CLASS & ~METH_STATIC & ~METH_COEXIST; 61 switch (flags) { 62 case METH_NOARGS: 63 entry = methodTrampolineNoArgs; 64 entry_kw = methodTrampolineNoArgsKw; 65 entry_ex = methodTrampolineNoArgsEx; 66 break; 67 case METH_O: 68 entry = methodTrampolineOneArg; 69 entry_kw = methodTrampolineOneArgKw; 70 entry_ex = methodTrampolineOneArgEx; 71 break; 72 case METH_VARARGS: 73 entry = methodTrampolineVarArgs; 74 entry_kw = methodTrampolineVarArgsKw; 75 entry_ex = methodTrampolineVarArgsEx; 76 break; 77 case METH_VARARGS | METH_KEYWORDS: 78 entry = methodTrampolineKeywords; 79 entry_kw = methodTrampolineKeywordsKw; 80 entry_ex = methodTrampolineKeywordsEx; 81 break; 82 case METH_FASTCALL: 83 entry = methodTrampolineFast; 84 entry_kw = methodTrampolineFastKw; 85 entry_ex = methodTrampolineFastEx; 86 break; 87 case METH_FASTCALL | METH_KEYWORDS: 88 entry = methodTrampolineFastWithKeywords; 89 entry_kw = methodTrampolineFastWithKeywordsKw; 90 entry_ex = methodTrampolineFastWithKeywordsEx; 91 break; 92 default: 93 UNIMPLEMENTED("Unsupported MethodDef type"); 94 } 95 Object code(&scope, runtime->newIntFromCPtr(function)); 96 Object none(&scope, NoneType::object()); 97 return thread->runtime()->newFunction( 98 thread, name, code, /*flags=*/Function::Flags::kExtension, 99 /*argcount=*/-1, /*total_args=*/-1, 100 /*total_vars=*/-1, 101 /*stacksize_or_builtin=*/none, entry, entry_kw, entry_ex); 102} 103 104RawObject newMethod(Thread* thread, PyMethodDef* method, const Object& name, 105 const Object& /*type*/) { 106 HandleScope scope(thread); 107 Runtime* runtime = thread->runtime(); 108 Function function(&scope, newExtensionFunction( 109 thread, name, bit_cast<void*>(method->ml_meth), 110 method->ml_flags)); 111 if (method->ml_doc != nullptr) { 112 function.setDoc(runtime->newStrFromCStr(method->ml_doc)); 113 } 114 // TODO(T62932301): We currently return the plain function here which means 115 // we do not check the `self` parameter to be a proper subtype of `type`. 116 // Should we wrap this with a new descriptor type? 117 return *function; 118} 119 120} // namespace py