From 7dc830582b0ef955d0760de9f9aaed0841afb3dc Mon Sep 17 00:00:00 2001 From: Du Toit Spies Date: Thu, 6 Jun 2024 12:42:29 +0200 Subject: [PATCH 1/4] Added HPySlice_New --- docs/api-reference/function-index.rst | 1 + docs/porting-guide.rst | 1 + hpy/debug/src/autogen_debug_ctx_init.h | 2 ++ hpy/debug/src/autogen_debug_wrappers.c | 14 ++++++++++++++ hpy/devel/include/hpy/cpython/autogen_api_impl.h | 5 +++++ hpy/devel/include/hpy/universal/autogen_ctx.h | 1 + .../include/hpy/universal/autogen_trampolines.h | 4 ++++ hpy/tools/autogen/public_api.h | 14 ++++++++++++++ hpy/trace/src/autogen_trace_ctx_init.h | 6 ++++-- hpy/trace/src/autogen_trace_func_table.c | 5 +++-- hpy/trace/src/autogen_trace_wrappers.c | 13 +++++++++++++ hpy/universal/src/autogen_ctx_def.h | 1 + hpy/universal/src/autogen_ctx_impl.h | 5 +++++ 13 files changed, 68 insertions(+), 4 deletions(-) diff --git a/docs/api-reference/function-index.rst b/docs/api-reference/function-index.rst index d267f1e3..5e2cbcb5 100644 --- a/docs/api-reference/function-index.rst +++ b/docs/api-reference/function-index.rst @@ -75,6 +75,7 @@ HPy Core API Function Index * :c:func:`HPyLong_FromUInt32_t` * :c:func:`HPyLong_FromUInt64_t` * :c:func:`HPyNumber_Check` +* :c:func:`HPySlice_New` * :c:func:`HPySlice_Unpack` * :c:func:`HPyTracker_Add` * :c:func:`HPyTracker_Close` diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index 6f076bba..c2196136 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -276,6 +276,7 @@ with the code for the :term:`CPython ABI` mode, so it is guaranteed to be correc `PySequence_GetSlice `_ :c:func:`HPy_GetSlice` `PySequence_SetSlice `_ :c:func:`HPy_SetSlice` `PySlice_AdjustIndices `_ :c:func:`HPySlice_AdjustIndices` + `PySlice_New `_ :c:func:`HPySlice_New` `PySlice_Unpack `_ :c:func:`HPySlice_Unpack` `PyTuple_Check `_ :c:func:`HPyTuple_Check` `PyType_IsSubtype `_ :c:func:`HPyType_IsSubtype` diff --git a/hpy/debug/src/autogen_debug_ctx_init.h b/hpy/debug/src/autogen_debug_ctx_init.h index 609a5d19..c394c362 100644 --- a/hpy/debug/src/autogen_debug_ctx_init.h +++ b/hpy/debug/src/autogen_debug_ctx_init.h @@ -164,6 +164,7 @@ DHPy debug_ctx_Dict_Keys(HPyContext *dctx, DHPy h); DHPy debug_ctx_Dict_Copy(HPyContext *dctx, DHPy h); int debug_ctx_Tuple_Check(HPyContext *dctx, DHPy h); DHPy debug_ctx_Tuple_FromArray(HPyContext *dctx, const DHPy items[], HPy_ssize_t n); +DHPy debug_ctx_Slice_New(HPyContext *dctx, DHPy start, DHPy stop, DHPy step); int debug_ctx_Slice_Unpack(HPyContext *dctx, DHPy slice, HPy_ssize_t *start, HPy_ssize_t *stop, HPy_ssize_t *step); DHPy debug_ctx_Import_ImportModule(HPyContext *dctx, const char *utf8_name); DHPy debug_ctx_Capsule_New(HPyContext *dctx, void *pointer, const char *utf8_name, HPyCapsule_Destructor *destructor); @@ -439,6 +440,7 @@ static inline void debug_ctx_init_fields(HPyContext *dctx, HPyContext *uctx) dctx->ctx_Dict_Copy = &debug_ctx_Dict_Copy; dctx->ctx_Tuple_Check = &debug_ctx_Tuple_Check; dctx->ctx_Tuple_FromArray = &debug_ctx_Tuple_FromArray; + dctx->ctx_Slice_New = &debug_ctx_Slice_New; dctx->ctx_Slice_Unpack = &debug_ctx_Slice_Unpack; dctx->ctx_Import_ImportModule = &debug_ctx_Import_ImportModule; dctx->ctx_Capsule_New = &debug_ctx_Capsule_New; diff --git a/hpy/debug/src/autogen_debug_wrappers.c b/hpy/debug/src/autogen_debug_wrappers.c index c0fda457..e9eb6a15 100644 --- a/hpy/debug/src/autogen_debug_wrappers.c +++ b/hpy/debug/src/autogen_debug_wrappers.c @@ -1621,6 +1621,20 @@ int debug_ctx_Tuple_Check(HPyContext *dctx, DHPy h) return universal_result; } +DHPy debug_ctx_Slice_New(HPyContext *dctx, DHPy start, DHPy stop, DHPy step) +{ + if (!get_ctx_info(dctx)->is_valid) { + report_invalid_debug_context(); + } + HPy dh_start = DHPy_unwrap(dctx, start); + HPy dh_stop = DHPy_unwrap(dctx, stop); + HPy dh_step = DHPy_unwrap(dctx, step); + get_ctx_info(dctx)->is_valid = false; + HPy universal_result = HPySlice_New(get_info(dctx)->uctx, dh_start, dh_stop, dh_step); + get_ctx_info(dctx)->is_valid = true; + return DHPy_open(dctx, universal_result); +} + int debug_ctx_Slice_Unpack(HPyContext *dctx, DHPy slice, HPy_ssize_t *start, HPy_ssize_t *stop, HPy_ssize_t *step) { if (!get_ctx_info(dctx)->is_valid) { diff --git a/hpy/devel/include/hpy/cpython/autogen_api_impl.h b/hpy/devel/include/hpy/cpython/autogen_api_impl.h index 53cc8e43..4a55fc6d 100644 --- a/hpy/devel/include/hpy/cpython/autogen_api_impl.h +++ b/hpy/devel/include/hpy/cpython/autogen_api_impl.h @@ -569,6 +569,11 @@ HPyAPI_FUNC int HPyTuple_Check(HPyContext *ctx, HPy h) return PyTuple_Check(_h2py(h)); } +HPyAPI_FUNC HPy HPySlice_New(HPyContext *ctx, HPy start, HPy stop, HPy step) +{ + return _py2h(PySlice_New(_h2py(start), _h2py(stop), _h2py(step))); +} + HPyAPI_FUNC int HPySlice_Unpack(HPyContext *ctx, HPy slice, HPy_ssize_t *start, HPy_ssize_t *stop, HPy_ssize_t *step) { return PySlice_Unpack(_h2py(slice), start, stop, step); diff --git a/hpy/devel/include/hpy/universal/autogen_ctx.h b/hpy/devel/include/hpy/universal/autogen_ctx.h index ecf357d8..1abb8e5d 100644 --- a/hpy/devel/include/hpy/universal/autogen_ctx.h +++ b/hpy/devel/include/hpy/universal/autogen_ctx.h @@ -286,4 +286,5 @@ struct _HPyContext_s { HPy (*ctx_GetIter)(HPyContext *ctx, HPy obj); HPy (*ctx_Iter_Next)(HPyContext *ctx, HPy obj); int (*ctx_Iter_Check)(HPyContext *ctx, HPy obj); + HPy (*ctx_Slice_New)(HPyContext *ctx, HPy start, HPy stop, HPy step); }; diff --git a/hpy/devel/include/hpy/universal/autogen_trampolines.h b/hpy/devel/include/hpy/universal/autogen_trampolines.h index c4dc36ca..4579b559 100644 --- a/hpy/devel/include/hpy/universal/autogen_trampolines.h +++ b/hpy/devel/include/hpy/universal/autogen_trampolines.h @@ -618,6 +618,10 @@ HPyAPI_FUNC HPy HPyTuple_FromArray(HPyContext *ctx, const HPy items[], HPy_ssize return ctx->ctx_Tuple_FromArray ( ctx, items, n ); } +HPyAPI_FUNC HPy HPySlice_New(HPyContext *ctx, HPy start, HPy stop, HPy step) { + return ctx->ctx_Slice_New ( ctx, start, stop, step ); +} + HPyAPI_FUNC int HPySlice_Unpack(HPyContext *ctx, HPy slice, HPy_ssize_t *start, HPy_ssize_t *stop, HPy_ssize_t *step) { return ctx->ctx_Slice_Unpack ( ctx, slice, start, stop, step ); } diff --git a/hpy/tools/autogen/public_api.h b/hpy/tools/autogen/public_api.h index ae2c18a6..9948d739 100644 --- a/hpy/tools/autogen/public_api.h +++ b/hpy/tools/autogen/public_api.h @@ -958,6 +958,19 @@ HPy HPyTuple_FromArray(HPyContext *ctx, const HPy items[], HPy_ssize_t n); /* sliceobject.h */ +/** + * Creates a new empty Python slice object. + * + * :param ctx: + * The execution context. + * + * :returns: + * A handle to the new and empty Python slice object or ``HPy_NULL`` in case + * of an error. + */ +HPy_ID(272) +HPy HPySlice_New(HPyContext *ctx, HPy start, HPy stop, HPy step); + /** * Extract the start, stop and step data members from a slice object as C * integers. @@ -987,6 +1000,7 @@ HPy HPyTuple_FromArray(HPyContext *ctx, const HPy items[], HPy_ssize_t n); * :returns: * ``-1`` on error, ``0`` on success */ + HPy_ID(259) int HPySlice_Unpack(HPyContext *ctx, HPy slice, HPy_ssize_t *start, HPy_ssize_t *stop, HPy_ssize_t *step); diff --git a/hpy/trace/src/autogen_trace_ctx_init.h b/hpy/trace/src/autogen_trace_ctx_init.h index 9d5eae4b..fef50284 100644 --- a/hpy/trace/src/autogen_trace_ctx_init.h +++ b/hpy/trace/src/autogen_trace_ctx_init.h @@ -163,6 +163,7 @@ HPy trace_ctx_Dict_Keys(HPyContext *tctx, HPy h); HPy trace_ctx_Dict_Copy(HPyContext *tctx, HPy h); int trace_ctx_Tuple_Check(HPyContext *tctx, HPy h); HPy trace_ctx_Tuple_FromArray(HPyContext *tctx, const HPy items[], HPy_ssize_t n); +HPy trace_ctx_Slice_New(HPyContext *tctx, HPy start, HPy stop, HPy step); int trace_ctx_Slice_Unpack(HPyContext *tctx, HPy slice, HPy_ssize_t *start, HPy_ssize_t *stop, HPy_ssize_t *step); HPy trace_ctx_Import_ImportModule(HPyContext *tctx, const char *utf8_name); HPy trace_ctx_Capsule_New(HPyContext *tctx, void *pointer, const char *utf8_name, HPyCapsule_Destructor *destructor); @@ -201,8 +202,8 @@ static inline void trace_ctx_init_info(HPyTraceInfo *info, HPyContext *uctx) { info->magic_number = HPY_TRACE_MAGIC; info->uctx = uctx; - info->call_counts = (uint64_t *)calloc(272, sizeof(uint64_t)); - info->durations = (_HPyTime_t *)calloc(272, sizeof(_HPyTime_t)); + info->call_counts = (uint64_t *)calloc(273, sizeof(uint64_t)); + info->durations = (_HPyTime_t *)calloc(273, sizeof(_HPyTime_t)); info->on_enter_func = HPy_NULL; info->on_exit_func = HPy_NULL; } @@ -456,6 +457,7 @@ static inline void trace_ctx_init_fields(HPyContext *tctx, HPyContext *uctx) tctx->ctx_Dict_Copy = &trace_ctx_Dict_Copy; tctx->ctx_Tuple_Check = &trace_ctx_Tuple_Check; tctx->ctx_Tuple_FromArray = &trace_ctx_Tuple_FromArray; + tctx->ctx_Slice_New = &trace_ctx_Slice_New; tctx->ctx_Slice_Unpack = &trace_ctx_Slice_Unpack; tctx->ctx_Import_ImportModule = &trace_ctx_Import_ImportModule; tctx->ctx_Capsule_New = &trace_ctx_Capsule_New; diff --git a/hpy/trace/src/autogen_trace_func_table.c b/hpy/trace/src/autogen_trace_func_table.c index 1f45abcd..97d8308d 100644 --- a/hpy/trace/src/autogen_trace_func_table.c +++ b/hpy/trace/src/autogen_trace_func_table.c @@ -12,7 +12,7 @@ #include "trace_internal.h" -#define TRACE_NFUNC 188 +#define TRACE_NFUNC 189 #define NO_FUNC "" static const char *trace_func_table[] = { @@ -288,6 +288,7 @@ static const char *trace_func_table[] = { "ctx_GetIter", "ctx_Iter_Next", "ctx_Iter_Check", + "ctx_Slice_New", NULL /* sentinel */ }; @@ -298,7 +299,7 @@ int hpy_trace_get_nfunc(void) const char * hpy_trace_get_func_name(int idx) { - if (idx >= 0 && idx < 272) + if (idx >= 0 && idx < 273) return trace_func_table[idx]; return NULL; } diff --git a/hpy/trace/src/autogen_trace_wrappers.c b/hpy/trace/src/autogen_trace_wrappers.c index da2bfe95..4940a12a 100644 --- a/hpy/trace/src/autogen_trace_wrappers.c +++ b/hpy/trace/src/autogen_trace_wrappers.c @@ -1994,6 +1994,19 @@ HPy trace_ctx_Tuple_FromArray(HPyContext *tctx, const HPy items[], HPy_ssize_t n return res; } +HPy trace_ctx_Slice_New(HPyContext *tctx, HPy start, HPy stop, HPy step) +{ + HPyTraceInfo *info = hpy_trace_on_enter(tctx, 272); + HPyContext *uctx = info->uctx; + _HPyTime_t _ts_start, _ts_end; + _HPyClockStatus_t r0, r1; + r0 = get_monotonic_clock(&_ts_start); + HPy res = HPySlice_New(uctx, start, stop, step); + r1 = get_monotonic_clock(&_ts_end); + hpy_trace_on_exit(info, 272, r0, r1, &_ts_start, &_ts_end); + return res; +} + int trace_ctx_Slice_Unpack(HPyContext *tctx, HPy slice, HPy_ssize_t *start, HPy_ssize_t *stop, HPy_ssize_t *step) { HPyTraceInfo *info = hpy_trace_on_enter(tctx, 259); diff --git a/hpy/universal/src/autogen_ctx_def.h b/hpy/universal/src/autogen_ctx_def.h index ec33d46f..4bdeec33 100644 --- a/hpy/universal/src/autogen_ctx_def.h +++ b/hpy/universal/src/autogen_ctx_def.h @@ -169,6 +169,7 @@ struct _HPyContext_s g_universal_ctx = { .ctx_Dict_Copy = &ctx_Dict_Copy, .ctx_Tuple_Check = &ctx_Tuple_Check, .ctx_Tuple_FromArray = &ctx_Tuple_FromArray, + .ctx_Slice_New = &ctx_Slice_New, .ctx_Slice_Unpack = &ctx_Slice_Unpack, .ctx_Import_ImportModule = &ctx_Import_ImportModule, .ctx_Capsule_New = &ctx_Capsule_New, diff --git a/hpy/universal/src/autogen_ctx_impl.h b/hpy/universal/src/autogen_ctx_impl.h index 540888e4..15c6e35b 100644 --- a/hpy/universal/src/autogen_ctx_impl.h +++ b/hpy/universal/src/autogen_ctx_impl.h @@ -565,6 +565,11 @@ HPyAPI_IMPL int ctx_Tuple_Check(HPyContext *ctx, HPy h) return PyTuple_Check(_h2py(h)); } +HPyAPI_IMPL HPy ctx_Slice_New(HPyContext *ctx, HPy start, HPy stop, HPy step) +{ + return _py2h(PySlice_New(_h2py(start), _h2py(stop), _h2py(step))); +} + HPyAPI_IMPL int ctx_Slice_Unpack(HPyContext *ctx, HPy slice, HPy_ssize_t *start, HPy_ssize_t *stop, HPy_ssize_t *step) { return PySlice_Unpack(_h2py(slice), start, stop, step); From 11e634d3a76e5cb4534f5617c4b3c7431fd0ee80 Mon Sep 17 00:00:00 2001 From: Du Toit Spies Date: Thu, 6 Jun 2024 15:53:54 +0200 Subject: [PATCH 2/4] Add proper comment to HPySlice_New in public_api.h --- hpy/tools/autogen/public_api.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hpy/tools/autogen/public_api.h b/hpy/tools/autogen/public_api.h index 9948d739..a0360122 100644 --- a/hpy/tools/autogen/public_api.h +++ b/hpy/tools/autogen/public_api.h @@ -963,6 +963,15 @@ HPy HPyTuple_FromArray(HPyContext *ctx, const HPy items[], HPy_ssize_t n); * * :param ctx: * The execution context. + * + * :param start: + * A pointer to a variable where to write the unpacked slice start. Must not + * be ``NULL``. + * :param end: + * A pointer to a variable where to write the unpacked slice end. Must not + * :param step: + * A pointer to a variable where to write the unpacked slice step. Must not + * be ``NULL``. * * :returns: * A handle to the new and empty Python slice object or ``HPy_NULL`` in case From 9d59d56c0a840ecc55825c84d9ee2be4e914b0a5 Mon Sep 17 00:00:00 2001 From: Du Toit Spies Date: Fri, 7 Jun 2024 15:09:59 +0200 Subject: [PATCH 3/4] Added test for HPySlice_New --- test/test_hpyslice.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/test_hpyslice.py b/test/test_hpyslice.py index 8f812682..48d474ff 100644 --- a/test/test_hpyslice.py +++ b/test/test_hpyslice.py @@ -108,3 +108,32 @@ def test_adjust_indices(self): assert mod.f(10, 9, 0, -3) == (3, 9, 0, -3) assert mod.f(10, -1, -10, -3) == (3, 9, 0, -3) assert mod.f(10, 5, 5, -3) == (0, 5, 5, -3) + + def test_new(self): + mod = self.make_module(""" + HPyDef_METH(f, "f", HPyFunc_VARARGS) + static HPy f_impl(HPyContext *ctx, HPy self, const HPy *args, size_t nargs) + { + HPy start, stop, step; + + if (nargs != 3) { + HPyErr_SetString(ctx, ctx->h_TypeError, + "expected exactly 3 arguments"); + return HPy_NULL; + } + + if (HPyArg_Parse(ctx, NULL, args, nargs, "OOO", + &start, &stop, &step) < 0) { + return HPy_NULL; + } + HPy length = HPySlice_New(ctx, start, stop, step); + return length; + } + @EXPORT(f) + @INIT + """) + + assert mod.f(0, 10, 1) == slice(0, 10, 1) + assert mod.f(None, 10, 1) == slice(None, 10, 1) + assert mod.f(1, None, 1) == slice(1, None, 1) + assert mod.f(0, 10, None) == slice(0, 10, None) \ No newline at end of file From 7fdbca11cbfd5f8acd2ade432bd48d9cb890d9bb Mon Sep 17 00:00:00 2001 From: Du Toit Spies Date: Fri, 7 Jun 2024 16:11:46 +0200 Subject: [PATCH 4/4] Fixed issues with HPySlice_New comment and test --- hpy/tools/autogen/public_api.h | 8 +++----- test/test_hpyslice.py | 3 +-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/hpy/tools/autogen/public_api.h b/hpy/tools/autogen/public_api.h index a0360122..b081d943 100644 --- a/hpy/tools/autogen/public_api.h +++ b/hpy/tools/autogen/public_api.h @@ -965,13 +965,11 @@ HPy HPyTuple_FromArray(HPyContext *ctx, const HPy items[], HPy_ssize_t n); * The execution context. * * :param start: - * A pointer to a variable where to write the unpacked slice start. Must not - * be ``NULL``. + * A handle to an object to be used as the slice start value. * :param end: - * A pointer to a variable where to write the unpacked slice end. Must not + * A handle to an object to be used as the slice end value. * :param step: - * A pointer to a variable where to write the unpacked slice step. Must not - * be ``NULL``. + * A handle to an object to be used as the slice step value. * * :returns: * A handle to the new and empty Python slice object or ``HPy_NULL`` in case diff --git a/test/test_hpyslice.py b/test/test_hpyslice.py index 48d474ff..97f45b77 100644 --- a/test/test_hpyslice.py +++ b/test/test_hpyslice.py @@ -126,8 +126,7 @@ def test_new(self): &start, &stop, &step) < 0) { return HPy_NULL; } - HPy length = HPySlice_New(ctx, start, stop, step); - return length; + return HPySlice_New(ctx, start, stop, step); } @EXPORT(f) @INIT