this repo has no description
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