this repo has no description
at trunk 124 lines 4.0 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "cpython-data.h" 3#include "cpython-func.h" 4#include "cpython-types.h" 5 6#include "api-handle.h" 7#include "builtins-module.h" 8#include "compile-utils.h" 9#include "globals.h" 10#include "runtime.h" 11#include "str-builtins.h" 12#include "thread.h" 13#include "utils.h" 14 15// Declarations from `Python-ast.h` and `ast.h` which are not part of 16// `Python.h` so we shouldn't add them to `cpython-*.h`. 17extern "C" { 18_mod* PyAST_FromNode(const _node*, PyCompilerFlags*, const char*, PyArena*); 19PyObject* PyAST_mod2obj(_mod* t); 20enum _mod_kind { 21 Module_kind = 1, 22 Interactive_kind = 2, 23 Expression_kind = 3, 24 Suite_kind = 4 25}; 26struct _mod { 27 enum _mod_kind kind; 28 void* dummy; 29}; 30} 31 32namespace py { 33 34static_assert(Code::kCompileFlagsMask == PyCF_MASK, "flags mismatch"); 35 36PY_EXPORT PyObject* _Py_Mangle(PyObject* privateobj, PyObject* ident) { 37 if (privateobj == nullptr) { 38 Py_INCREF(ident); 39 return ident; 40 } 41 Thread* thread = Thread::current(); 42 HandleScope scope(thread); 43 Object privateobj_obj(&scope, 44 ApiHandle::asObject(ApiHandle::fromPyObject(privateobj))); 45 Runtime* runtime = thread->runtime(); 46 Object ident_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(ident))); 47 Str ident_str(&scope, strUnderlying(*ident_obj)); 48 Object mangled(&scope, mangle(thread, privateobj_obj, ident_str)); 49 if (mangled == ident_str) { 50 Py_INCREF(ident); 51 return ident; 52 } 53 return ApiHandle::newReference(runtime, *mangled); 54} 55 56PY_EXPORT PyCodeObject* PyNode_Compile(_node* node, const char* filename) { 57 PyArena* arena = PyArena_New(); 58 if (!arena) return nullptr; 59 _mod* mod = PyAST_FromNode(node, nullptr, filename, arena); 60 if (mod == nullptr) { 61 PyArena_Free(arena); 62 return nullptr; 63 } 64 PyCodeObject* code = PyAST_Compile(mod, filename, nullptr, arena); 65 PyArena_Free(arena); 66 return code; 67} 68 69PY_EXPORT PyCodeObject* PyAST_Compile(_mod* mod, const char* filename, 70 PyCompilerFlags* flags, PyArena* arena) { 71 return PyAST_CompileEx(mod, filename, flags, -1, arena); 72} 73 74PY_EXPORT PyCodeObject* PyAST_CompileEx(_mod* mod, const char* filename_str, 75 PyCompilerFlags* flags, int optimize, 76 PyArena* arena) { 77 PyObject* filename = PyUnicode_DecodeFSDefault(filename_str); 78 if (filename == nullptr) return nullptr; 79 PyCodeObject* co = PyAST_CompileObject(mod, filename, flags, optimize, arena); 80 Py_DECREF(filename); 81 return co; 82} 83 84PY_EXPORT PyCodeObject* PyAST_CompileObject(_mod* mod, PyObject* pyfilename, 85 PyCompilerFlags* flags_ptr, 86 int optimize, PyArena*) { 87 Thread* thread = Thread::current(); 88 HandleScope scope(thread); 89 PyObject* pyast = PyAST_mod2obj(mod); 90 if (pyast == nullptr) return nullptr; 91 Object ast(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyast))); 92 Object filename(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyfilename))); 93 SymbolId mode_id; 94 switch (mod->kind) { 95 case Module_kind: 96 mode_id = ID(exec); 97 break; 98 case Interactive_kind: 99 mode_id = ID(single); 100 break; 101 case Expression_kind: 102 mode_id = ID(eval); 103 break; 104 default: 105 UNREACHABLE("Unknown module kind"); 106 } 107 word flags = flags_ptr ? flags_ptr->cf_flags : 0; 108 // PyCF_SOURCE_IS_UTF8 is not a valid flag to pass through managed code. 109 flags &= ~PyCF_SOURCE_IS_UTF8; 110 if (optimize == -1) { 111 optimize = Py_OptimizeFlag; 112 } 113 Object result(&scope, 114 compile(thread, ast, filename, mode_id, flags, optimize)); 115 if (result.isErrorException()) return nullptr; 116 return reinterpret_cast<PyCodeObject*>( 117 ApiHandle::newReference(thread->runtime(), *result)); 118} 119 120PY_EXPORT int PyCompile_OpcodeStackEffect(int /*opcode*/, int /*oparg*/) { 121 UNIMPLEMENTED("PyCompile_OpcodeStackEffect"); 122} 123 124} // namespace py