Nuitka
The Python compiler
Loading...
Searching...
No Matches
helpers.h
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3#ifndef __NUITKA_HELPERS_H__
4#define __NUITKA_HELPERS_H__
5
6// From CPython, to allow us quick access to the dictionary of an module, the
7// structure is normally private, but we need it for quick access to the module
8// dictionary.
9#if PYTHON_VERSION < 0x3c0
10typedef struct {
11 /* Python object folklore: */
12 PyObject_HEAD
13
14 PyObject *md_dict;
16#endif
17
18// Generated code helpers, used in static helper codes:
19extern PyObject *CALL_FUNCTION_WITH_ARGS2(PyThreadState *tstate, PyObject *called, PyObject *const *args);
20extern PyObject *CALL_FUNCTION_WITH_ARGS3(PyThreadState *tstate, PyObject *called, PyObject *const *args);
21extern PyObject *CALL_FUNCTION_WITH_ARGS4(PyThreadState *tstate, PyObject *called, PyObject *const *args);
22extern PyObject *CALL_FUNCTION_WITH_ARGS5(PyThreadState *tstate, PyObject *called, PyObject *const *args);
23
24// For use with "--trace-execution", code can make outputs. Otherwise they
25// are just like comments.
26#include "nuitka/tracing.h"
27
28// For checking values if they changed or not.
29#ifndef __NUITKA_NO_ASSERT__
30extern Py_hash_t DEEP_HASH(PyThreadState *tstate, PyObject *value);
31#endif
32
33// For profiling of Nuitka compiled binaries
34#if _NUITKA_PROFILE
35extern void startProfiling(void);
36extern void stopProfiling(void);
37#endif
38
39#include "nuitka/helper/boolean.h"
40#include "nuitka/helper/dictionaries.h"
41#include "nuitka/helper/indexes.h"
42#include "nuitka/helper/mappings.h"
43#include "nuitka/helper/operations_builtin_types.h"
44#include "nuitka/helper/sets.h"
45#include "nuitka/helper/strings.h"
46
47#include "nuitka/helper/raising.h"
48
49#include "nuitka/helper/ints.h"
50#include "nuitka/helper/richcomparisons.h"
51#include "nuitka/helper/sequences.h"
52
53static inline bool Nuitka_Function_Check(PyObject *object);
54static inline PyObject *Nuitka_Function_GetName(PyObject *object);
55
56static inline bool Nuitka_Generator_Check(PyObject *object);
57static inline PyObject *Nuitka_Generator_GetName(PyObject *object);
58
59#include "nuitka/calling.h"
60#include "nuitka/helper/bytes.h"
61#include "nuitka/helper/complex.h"
62#include "nuitka/helper/floats.h"
63
64NUITKA_MAY_BE_UNUSED static PyObject *LOOKUP_VARS(PyThreadState *tstate, PyObject *source) {
65 CHECK_OBJECT(source);
66
67 PyObject *result = PyObject_GetAttr(source, const_str_plain___dict__);
68
69 if (unlikely(result == NULL)) {
70 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError, "vars() argument must have __dict__ attribute");
71
72 return NULL;
73 }
74
75 return result;
76}
77
78#include "nuitka/helper/attributes.h"
79#include "nuitka/helper/bytearrays.h"
80#include "nuitka/helper/iterators.h"
81#include "nuitka/helper/lists.h"
82#include "nuitka/helper/rangeobjects.h"
83#include "nuitka/helper/slices.h"
84#include "nuitka/helper/subscripts.h"
85#include "nuitka/helper/tuples.h"
86
87#include "nuitka/builtins.h"
88
89#include "helper/operations.h"
90
91// Compile source code given, pretending the file name was given.
92#if PYTHON_VERSION < 0x300
93extern PyObject *COMPILE_CODE(PyThreadState *tstate, PyObject *source_code, PyObject *file_name, PyObject *mode,
94 PyObject *flags, PyObject *dont_inherit);
95#else
96extern PyObject *COMPILE_CODE(PyThreadState *tstate, PyObject *source_code, PyObject *file_name, PyObject *mode,
97 PyObject *flags, PyObject *dont_inherit, PyObject *optimize);
98#endif
99
100#if PYTHON_VERSION < 0x300
101extern bool EXEC_FILE_ARG_HANDLING(PyThreadState *tstate, PyObject **prog, PyObject **name);
102#endif
103
104// For quicker built-in str() functionality, Python2 str
105extern PyObject *BUILTIN_STR(PyObject *value);
106
107// For quicker built-in unicode() functionality, Python3 str or Python2 unicode
108extern PyObject *BUILTIN_UNICODE1(PyObject *value);
109extern PyObject *BUILTIN_UNICODE3(PyObject *value, PyObject *encoding, PyObject *errors);
110
111// For quicker built-in open() functionality.
112#if PYTHON_VERSION < 0x300
113extern PyObject *BUILTIN_OPEN(PyThreadState *tstate, PyObject *file_name, PyObject *mode, PyObject *buffering);
114#else
115extern PyObject *BUILTIN_OPEN(PyThreadState *tstate, PyObject *file_name, PyObject *mode, PyObject *buffering,
116 PyObject *encoding, PyObject *errors, PyObject *newline, PyObject *closefd,
117 PyObject *opener);
118#endif
119
120// Small helper to open files with few arguments in C.
121extern PyObject *BUILTIN_OPEN_BINARY_READ_SIMPLE(PyThreadState *tstate, PyObject *filename);
122extern PyObject *BUILTIN_OPEN_SIMPLE(PyThreadState *tstate, PyObject *filename, char const *mode, bool buffering,
123 PyObject *encoding);
124
125// Small helper to read file contents with few arguments in C.
126extern PyObject *GET_FILE_BYTES(PyThreadState *tstate, PyObject *filename);
127
128// Small helpers to check file attributes
129extern PyObject *OS_PATH_FILE_EXISTS(PyThreadState *tstate, PyObject *filename);
130extern PyObject *OS_PATH_FILE_ISFILE(PyThreadState *tstate, PyObject *filename);
131extern PyObject *OS_PATH_FILE_ISDIR(PyThreadState *tstate, PyObject *filename);
132
133// Small helper to list a directory (like "os.listdir")
134extern PyObject *OS_LISTDIR(PyThreadState *tstate, PyObject *path);
135
136// Small helper to get stat structure of a path (like "os.stat" and "os.lstat)
137extern PyObject *OS_STAT(PyThreadState *tstate, PyObject *path, PyObject *dir_fd, PyObject *follow_symlinks);
138extern PyObject *OS_LSTAT(PyThreadState *tstate, PyObject *path, PyObject *dir_fd);
139
140// Platform standard slash for filenames
141#if defined(_WIN32)
142#define const_platform_sep const_str_backslash
143#else
144#define const_platform_sep const_str_slash
145#endif
146
147// Small helpers to work with filenames from "os.path" module
148extern PyObject *OS_PATH_BASENAME(PyThreadState *tstate, PyObject *filename);
149extern PyObject *OS_PATH_DIRNAME(PyThreadState *tstate, PyObject *filename);
150extern PyObject *OS_PATH_ABSPATH(PyThreadState *tstate, PyObject *filename);
151extern PyObject *OS_PATH_ISABS(PyThreadState *tstate, PyObject *filename);
152extern PyObject *OS_PATH_NORMPATH(PyThreadState *tstate, PyObject *filename);
153
154// Compare two paths if they are the same.
155nuitka_bool compareFilePaths(PyThreadState *tstate, PyObject *filename_a, PyObject *filename_b);
156
157// For quicker built-in chr() functionality.
158extern PyObject *BUILTIN_CHR(PyThreadState *tstate, PyObject *value);
159
160// For quicker built-in ord() functionality.
161extern PyObject *BUILTIN_ORD(PyObject *value);
162
163// For quicker built-in bin() functionality.
164extern PyObject *BUILTIN_BIN(PyObject *value);
165
166// For quicker built-in oct() functionality.
167extern PyObject *BUILTIN_OCT(PyThreadState *tstate, PyObject *value);
168
169// For quicker built-in hex() functionality.
170extern PyObject *BUILTIN_HEX(PyThreadState *tstate, PyObject *value);
171
172// For quicker callable() functionality.
173extern PyObject *BUILTIN_CALLABLE(PyObject *value);
174
175// For quicker iter() functionality if 2 arguments arg given.
176extern PyObject *BUILTIN_ITER2(PyObject *callable, PyObject *sentinel);
177
178// For quicker type() functionality if 1 argument is given.
179extern PyObject *BUILTIN_TYPE1(PyObject *arg);
180
181// For quicker type() functionality if 3 arguments are given (to build a new
182// type).
183extern PyObject *BUILTIN_TYPE3(PyThreadState *tstate, PyObject *module_name, PyObject *name, PyObject *bases,
184 PyObject *dict);
185
186// For built-in built-in len() functionality.
187extern PyObject *BUILTIN_LEN(PyThreadState *tstate, PyObject *boundary);
188
189// For built-in built-in any() functionality.
190extern PyObject *BUILTIN_ANY(PyThreadState *tstate, PyObject *value);
191
192// For built-in built-in super() no args and 2 user args functionality.
193extern PyObject *BUILTIN_SUPER2(PyThreadState *tstate, PyDictObject *module_dict, PyObject *type, PyObject *object);
194extern PyObject *BUILTIN_SUPER0(PyThreadState *tstate, PyDictObject *module_dict, PyObject *type, PyObject *object);
195
196// For built-in built-in all() functionality.
197extern PyObject *BUILTIN_ALL(PyThreadState *tstate, PyObject *value);
198
199// For built-in getattr() functionality.
200extern PyObject *BUILTIN_GETATTR(PyThreadState *tstate, PyObject *object, PyObject *attribute, PyObject *default_value);
201
202// For built-in setattr() functionality.
203extern PyObject *BUILTIN_SETATTR(PyObject *object, PyObject *attribute, PyObject *value);
204
205// For built-in bytearray() functionality.
206extern PyObject *BUILTIN_BYTEARRAY1(PyObject *value);
207extern PyObject *BUILTIN_BYTEARRAY3(PyThreadState *tstate, PyObject *string, PyObject *encoding, PyObject *errors);
208
209// For built-in hash() functionality.
210extern PyObject *BUILTIN_HASH(PyThreadState *tstate, PyObject *value);
211extern Py_hash_t HASH_VALUE_WITHOUT_ERROR(PyThreadState *tstate, PyObject *value);
212extern Py_hash_t HASH_VALUE_WITH_ERROR(PyThreadState *tstate, PyObject *value);
213
214// For built-in sum() functionality.
215extern PyObject *BUILTIN_SUM1(PyThreadState *tstate, PyObject *sequence);
216extern PyObject *BUILTIN_SUM2(PyThreadState *tstate, PyObject *sequence, PyObject *start);
217
218// For built-in built-in abs() functionality.
219extern PyObject *BUILTIN_ABS(PyObject *o);
220
221// For built-in bytes() functionality.
222#if PYTHON_VERSION >= 0x300
223extern PyObject *BUILTIN_BYTES1(PyThreadState *tstate, PyObject *value);
224extern PyObject *BUILTIN_BYTES3(PyThreadState *tstate, PyObject *value, PyObject *encoding, PyObject *errors);
225#endif
226
227// For built-in eval() functionality, works on byte compiled code already.
228extern PyObject *EVAL_CODE(PyThreadState *tstate, PyObject *code, PyObject *globals, PyObject *locals,
229 PyObject *closure);
230
231// For built-in format() functionality.
232extern PyObject *BUILTIN_FORMAT(PyThreadState *tstate, PyObject *value, PyObject *format_spec);
233
234// For built-in staticmethod() functionality.
235extern PyObject *BUILTIN_STATICMETHOD(PyThreadState *tstate, PyObject *function);
236
237// For built-in classmethod() functionality.
238extern PyObject *BUILTIN_CLASSMETHOD(PyThreadState *tstate, PyObject *function);
239
240// For built-in input() functionality, prompt can be NULL.
241extern PyObject *BUILTIN_INPUT(PyThreadState *tstate, PyObject *prompt);
242
243// For built-in "int()" functionality with 2 arguments.
244extern PyObject *BUILTIN_INT2(PyThreadState *tstate, PyObject *value, PyObject *base);
245
246#if PYTHON_VERSION < 0x300
247// For built-in "long()" functionality with 2 arguments.
248extern PyObject *BUILTIN_LONG2(PyThreadState *tstate, PyObject *value, PyObject *base);
249#endif
250
251#include "nuitka/importing.h"
252
253// Hard imports have their own helpers.
254#include "nuitka/helper/import_hard.h"
255
256// For the constant loading:
257
258// Call this to initialize all common constants pre-main.
259#if _NUITKA_MODULE_MODE
260extern void createGlobalConstants(PyThreadState *tstate, PyObject *real_module_name);
261#else
262extern void createGlobalConstants(PyThreadState *tstate);
263#endif
264
265// Call this to check of common constants are still intact.
266#ifndef __NUITKA_NO_ASSERT__
267extern void checkGlobalConstants(void);
268#if !_NUITKA_MODULE_MODE
269extern void checkModuleConstants___main__(PyThreadState *tstate);
270#endif
271#endif
272
273// Call this to initialize "__main__" constants in non-standard processes.
274#if !_NUITKA_MODULE_MODE
275extern void createMainModuleConstants(PyThreadState *tstate);
276#endif
277
278// Deserialize constants from a blob.
279#include "nuitka/constants_blob.h"
280
281// Performance enhancements to Python types.
282extern void enhancePythonTypes(void);
283
284// Setup meta path based loader if any.
285extern void setupMetaPathBasedLoader(PyThreadState *tstate);
286
287/* Replace inspect functions with ones that handle compiles types too. */
288#if PYTHON_VERSION >= 0x300
289extern void patchInspectModule(PyThreadState *tstate);
290#endif
291
292// Replace type comparison with one that accepts compiled types too, will work
293// for "==" and "!=", but not for "is" checks.
294extern void patchTypeComparison(void);
295
296// Patch the CPython type for tracebacks and make it use a free list mechanism
297// to be slightly faster for exception control flows.
298extern void patchTracebackDealloc(void);
299
300// Initialize value for "tp_compare" and "tp_init" defaults.
301extern void _initSlotCompare(void);
302
303// Default __init__ slot wrapper, spell-checker: ignore initproc
304extern python_init_proc default_tp_init_wrapper;
305
306#if PYTHON_VERSION >= 0x300
307// Select the metaclass from specified one and given bases.
308extern PyObject *SELECT_METACLASS(PyThreadState *tstate, PyObject *metaclass, PyObject *bases);
309#endif
310
311#if PYTHON_VERSION >= 0x3a0
312extern PyObject *MATCH_CLASS_ARGS(PyThreadState *tstate, PyObject *matched, PyObject *matched_type,
313 Py_ssize_t positional_count, PyObject **keywords, Py_ssize_t keywords_count);
314#endif
315
316NUITKA_MAY_BE_UNUSED static PyObject *MODULE_NAME1(PyThreadState *tstate, PyObject *module) {
317 assert(PyModule_Check(module));
318 PyObject *module_dict = ((PyModuleObject *)module)->md_dict;
319
320 return DICT_GET_ITEM1(tstate, module_dict, const_str_plain___name__);
321}
322
323NUITKA_MAY_BE_UNUSED static PyObject *MODULE_NAME0(PyThreadState *tstate, PyObject *module) {
324 assert(PyModule_Check(module));
325 PyObject *module_dict = ((PyModuleObject *)module)->md_dict;
326
327 return DICT_GET_ITEM0(tstate, module_dict, const_str_plain___name__);
328}
329
330// Get the binary directory as wide characters.
331extern wchar_t const *getBinaryDirectoryWideChars(bool resolve_symlinks);
332
333// Get the binary directory, translated to ANSI/native path
334extern char const *getBinaryDirectoryHostEncoded(bool resolve_symlinks);
335
336// Get the program directory as an object with symlinks resolved or not.
337extern PyObject *getPythonProgramDirectoryObject(bool resolve_symlinks);
338
339// Get the containing directory as an object with symlinks resolved or not.
340extern PyObject *getContainingDirectoryObject(bool resolve_symlinks);
341
342// Get the original argv[0] as recorded by the bootstrap stage. Returns
343// None, if not available, in module mode.
344#if _NUITKA_EXE_MODE
345extern PyObject *getOriginalArgv0Object(void);
346#endif
347
348#if _NUITKA_STANDALONE_MODE
349extern void setEarlyFrozenModulesFileAttribute(PyThreadState *tstate);
350#endif
351
352/* For making paths relative to where we got loaded from. Do not provide any
353 * absolute paths as relative value, this is not as capable as "os.path.join",
354 * instead just works on strings.
355 */
356extern PyObject *MAKE_RELATIVE_PATH(PyObject *relative);
357
358/* For concatenating two elements path, typically a dirname and a filename.
359
360 We do this in a lot of helper code, and this is shared functionality.
361*/
362extern PyObject *JOIN_PATH2(PyObject *dirname, PyObject *filename);
363
364#include <nuitka/threading.h>
365
366// Make a deep copy of an object of general or specific type.
367extern PyObject *DEEP_COPY(PyThreadState *tstate, PyObject *value);
368extern PyObject *DEEP_COPY_DICT(PyThreadState *tstate, PyObject *dict_value);
369extern PyObject *DEEP_COPY_LIST(PyThreadState *tstate, PyObject *value);
370extern PyObject *DEEP_COPY_TUPLE(PyThreadState *tstate, PyObject *value);
371extern PyObject *DEEP_COPY_SET(PyThreadState *tstate, PyObject *value);
372
373// Constants deep copies are guided by value type descriptions.
374extern PyObject *DEEP_COPY_LIST_GUIDED(PyThreadState *tstate, PyObject *value, char const *guide);
375extern PyObject *DEEP_COPY_TUPLE_GUIDED(PyThreadState *tstate, PyObject *value, char const *guide);
376
377// UnionType, normally not accessible
378extern PyTypeObject *Nuitka_PyUnion_Type;
379
380// Force a garbage collection, for debugging purposes.
381NUITKA_MAY_BE_UNUSED static void forceGC(void) {
382 PyObject_CallObject(PyObject_GetAttrString(PyImport_ImportModule("gc"), "collect"), NULL);
383}
384
385// We provide the sys.version info shortcut as a global value here for ease of use.
386extern PyObject *Py_SysVersionInfo;
387
388#include "nuitka/python_pgo.h"
389
390extern PyObject *MAKE_UNION_TYPE(PyObject *args);
391
392// Our wrapper for "PyType_Ready" that takes care of trying to avoid DLL entry
393// points for generic attributes. spell-checker: ignore aiter
394extern void Nuitka_PyType_Ready(PyTypeObject *type, PyTypeObject *base, bool generic_get_attr, bool generic_set_attr,
395 bool self_iter, bool await_self_iter, bool self_aiter);
396
397#if PYTHON_VERSION >= 0x3b0
398#include "nuitka/exception_groups.h"
399#endif
400
401#if PYTHON_VERSION >= 0x3c0
402#include "nuitka/type_aliases.h"
403#endif
404
405#endif
406
407// Part of "Nuitka", an optimizing Python compiler that is compatible and
408// integrates with CPython, but also works on its own.
409//
410// Licensed under the Apache License, Version 2.0 (the "License");
411// you may not use this file except in compliance with the License.
412// You may obtain a copy of the License at
413//
414// http://www.apache.org/licenses/LICENSE-2.0
415//
416// Unless required by applicable law or agreed to in writing, software
417// distributed under the License is distributed on an "AS IS" BASIS,
418// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
419// See the License for the specific language governing permissions and
420// limitations under the License.
Definition helpers.h:10