44extern "C" {
55#endif
66
7- #ifndef HPY_UNIVERSAL_ABI
8- /* It would be nice if we could include hpy.h WITHOUT bringing in all the
9- stuff from Python.h, to make sure that people don't use the CPython API by
10- mistake. How to achieve it, though? */
7+ /* ~~~~~~~~~~~~~~~~ HPy ABI version ~~~~~~~~~~~~~~~ */
8+ // NOTE: these must be kept on sync with the equivalent variables in hpy/devel/abitag.py
9+ /**
10+ * The ABI version.
11+ *
12+ * Minor version N+1 is binary compatible to minor version N. Major versions
13+ * are not binary compatible (note: HPy can run several binary incompatible
14+ * versions in one process).
15+ */
16+ #define HPY_ABI_VERSION 0
17+ #define HPY_ABI_VERSION_MINOR 0
18+ #define HPY_ABI_TAG "hpy0"
19+
20+
21+ /* ~~~~~~~~~~~~~~~~ HPy ABI macros ~~~~~~~~~~~~~~~~ */
22+
23+ /* The following macros are used to determine which kind of module we want to
24+ compile. The build system must set one of these (e.g. by using `gcc
25+ -D...`). This is the approach used by the setuptools support provided by
26+ hpy.devel:
27+
28+ - HPY_ABI_CPYTHON
29+ - HPY_ABI_UNIVERSAL
30+ - HPY_ABI_HYBRID
31+
32+ In addition we also define HPY_ABI which is a string literal containing a
33+ string representation of it.
34+ */
35+
36+ #if defined(HPY_ABI_CPYTHON )
37+ # if defined(HPY_ABI_HYBRID )
38+ # error "Conflicting macros are defined: HPY_ABI_CPYTHON and HPY_ABI_HYBRID"
39+ # endif
40+ # if defined(HPY_ABI_UNIVERSAL )
41+ # error "Conflicting macros are defined: HPY_ABI_CPYTHON and HPY_ABI_UNIVERSAL"
42+ # endif
43+ # define HPY_ABI "cpython"
44+
45+ #elif defined(HPY_ABI_HYBRID )
46+ # if defined(HPY_ABI_UNIVERSAL )
47+ # error "Conflicting macros are defined: HPY_ABI_HYBRID and HPY_ABI_UNIVERSAL"
48+ # endif
49+ # define HPY_ABI "hybrid"
50+
51+ #elif defined(HPY_ABI_UNIVERSAL )
52+ # define HPY_ABI "universal"
53+
54+ #else
55+ # error "Cannot determine the desired HPy ABI: you must set one of HPY_ABI_CPYTHON, HPY_ABI_UNIVERSAL or HPY_ABI_HYBRID"
56+ #endif
57+
58+
59+ #if defined(HPY_ABI_CPYTHON ) || defined(HPY_ABI_HYBRID )
1160# define PY_SSIZE_T_CLEAN
1261# include <Python.h>
1362#endif
@@ -25,6 +74,7 @@ extern "C" {
2574# define _HPy_HIDDEN
2675# define _HPy_UNUSED
2776#endif /* __GNUC__ */
77+ #define _HPy_UNUSED_ARG (x ) (__HPy_UNUSED_TAGGED ## x) _HPy_UNUSED
2878
2979#if defined(__clang__ ) || \
3080 (defined(__GNUC__ ) && \
@@ -37,6 +87,28 @@ extern "C" {
3787# define _HPy_NO_RETURN
3888#endif
3989
90+
91+ // clang and gcc supports __has_attribute, MSVC doesn't. This should be enough
92+ // to be able to use it portably
93+ #ifdef __has_attribute
94+ # define _HPY_compiler_has_attribute (x ) __has_attribute(x)
95+ #else
96+ # define _HPY_compiler_has_attribute (x ) 0
97+ #endif
98+
99+ #ifdef HPY_ABI_UNIVERSAL
100+ # if _HPY_compiler_has_attribute (error )
101+ // gcc, clang>=14
102+ # define _HPY_LEGACY __attribute__((error("Cannot use legacy functions when targeting the HPy Universal ABI")))
103+ # else
104+ // we don't have any diagnostic feature, too bad
105+ # define _HPY_LEGACY
106+ # endif
107+ #else
108+ // in non-universal modes, we don't attach any attribute
109+ # define _HPY_LEGACY
110+ #endif
111+
40112#if defined(_MSC_VER ) && defined(__cplusplus ) // MSVC C4576
41113# define _hconv (h ) {h}
42114# define _hfconv (h ) {h}
@@ -67,6 +139,9 @@ extern "C" {
67139 */
68140#define HPyAPI_FUNC _HPy_UNUSED static inline
69141
142+ /** An alias for ``HPyAPI_FUNC`` so we can handle it properly in the docs. */
143+ #define HPyAPI_INLINE_HELPER HPyAPI_FUNC
144+
70145/**
71146 * CPython implementations for ``HPyAPI_FUNC``
72147 * functions. Generally speaking, they are put in ctx_*.c files and they are
@@ -104,7 +179,8 @@ extern "C" {
104179
105180 - PyPy: ._i is an index into a list
106181
107- - GraalPython: ???
182+ - GraalPy: ._i is a tagged value, either an index into a list,
183+ or an immediate integer or double value
108184
109185 - Debug mode: _i is a pointer to a DebugHandle, which contains a
110186 another HPy among other stuff
@@ -123,15 +199,12 @@ typedef struct { intptr_t _i; } HPyThreadState;
123199#define HPy_NULL _hconv(0)
124200#define HPy_IsNull (h ) ((h)._i == 0)
125201
126- #define HPyListBuilder_IsNull (h ) ((h)._lst == 0)
127- #define HPyTupleBuilder_IsNull (h ) ((h)._tup == 0)
128-
129202#define HPyField_NULL _hfconv(0)
130203#define HPyField_IsNull (f ) ((f)._i == 0)
131204
132205/* Convenience functions to cast between HPy and void*. We need to decide
133206 whether these are part of the official API or not, and maybe introduce a
134- better naming convetion . For now, they are needed for ujson. */
207+ better naming convention . For now, they are needed for ujson. */
135208static inline HPy HPy_FromVoidP (void * p ) { return _hconv ((intptr_t )p ); }
136209static inline void * HPy_AsVoidP (HPy h ) { return (void * )h ._i ; }
137210
@@ -140,51 +213,75 @@ static inline void* HPy_AsVoidP(HPy h) { return (void*)h._i; }
140213
141214typedef struct _HPyContext_s HPyContext ;
142215
143- #ifdef HPY_UNIVERSAL_ABI
216+ /** An enumeration of the different kinds of source code strings. */
217+ typedef enum {
218+ /** Parse isolated expressions (e.g. ``a + b``). */
219+ HPy_SourceKind_Expr = 0 ,
220+
221+ /**
222+ * Parse sequences of statements as read from a file or other source. This
223+ * is the symbol to use when compiling arbitrarily long Python source code.
224+ */
225+ HPy_SourceKind_File = 1 ,
226+
227+ /**
228+ * Parse a single statement. This is the mode used for the interactive
229+ * interpreter loop.
230+ */
231+ HPy_SourceKind_Single = 2 ,
232+ } HPy_SourceKind ;
233+
234+ #ifdef HPY_ABI_CPYTHON
235+ typedef Py_ssize_t HPy_ssize_t ;
236+ typedef Py_hash_t HPy_hash_t ;
237+ typedef Py_UCS4 HPy_UCS4 ;
238+
239+ # define HPY_SSIZE_T_MAX PY_SSIZE_T_MAX
240+ # define HPY_SSIZE_T_MIN PY_SSIZE_T_MIN
241+
242+ #else
144243 typedef intptr_t HPy_ssize_t ;
145244 typedef intptr_t HPy_hash_t ;
146245 typedef uint32_t HPy_UCS4 ;
147246
247+ # define HPY_SSIZE_T_MAX INTPTR_MAX
248+ # define HPY_SSIZE_T_MIN (-HPY_SSIZE_T_MAX-1)
249+
148250 /* HPyCapsule field keys */
149251 typedef enum {
150252 HPyCapsule_key_Pointer = 0 ,
151253 HPyCapsule_key_Name = 1 ,
152254 HPyCapsule_key_Context = 2 ,
153255 HPyCapsule_key_Destructor = 3 ,
154256 } _HPyCapsule_key ;
155-
156- #else
157- typedef Py_ssize_t HPy_ssize_t ;
158- typedef Py_hash_t HPy_hash_t ;
159- typedef Py_UCS4 HPy_UCS4 ;
160257#endif
161258
162- typedef void (* HPyCapsule_Destructor )(const char * name , void * pointer , void * context );
163-
164259
165260/* ~~~~~~~~~~~~~~~~ Additional #includes ~~~~~~~~~~~~~~~~ */
166261
167262#include "hpy/cpy_types.h"
263+ #include "hpy/hpyexports.h"
168264#include "hpy/macros.h"
169265#include "hpy/hpyfunc.h"
170266#include "hpy/hpydef.h"
171267#include "hpy/hpytype.h"
172268#include "hpy/hpymodule.h"
173269#include "hpy/runtime/argparse.h"
174270#include "hpy/runtime/buildvalue.h"
271+ #include "hpy/runtime/format.h"
175272#include "hpy/runtime/helpers.h"
176273#include "hpy/runtime/structseq.h"
177274
178- #ifdef HPY_UNIVERSAL_ABI
179- # include "hpy/universal/autogen_ctx.h"
180- # include "hpy/universal/autogen_trampolines.h"
181- # include "hpy/universal/misc_trampolines.h"
182- #else
183- // CPython-ABI
275+ #ifdef HPY_ABI_CPYTHON
276+ # include "hpy/cpython/autogen_ctx.h"
184277# include "hpy/runtime/ctx_funcs.h"
185278# include "hpy/runtime/ctx_type.h"
186279# include "hpy/cpython/misc.h"
187280# include "hpy/cpython/autogen_api_impl.h"
281+ #else
282+ # include "hpy/universal/autogen_ctx.h"
283+ # include "hpy/universal/autogen_trampolines.h"
284+ # include "hpy/universal/misc_trampolines.h"
188285#endif
189286
190287#include "hpy/inline_helpers.h"
0 commit comments