Skip to content

Commit 9832fdf

Browse files
committed
Expose some of the new module internals
1 parent aea489a commit 9832fdf

File tree

4 files changed

+145
-11
lines changed

4 files changed

+145
-11
lines changed

include/deemon/module.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -874,12 +874,14 @@ DeeModule_GetFileName(DeeModuleObject *__restrict self);
874874
/* Return the relative import name of `self' when accessed from a file or module
875875
* `context_absname'. For more information, see `DeeModule_GetRelNameEx()'.
876876
*
877+
* @param: flags: Set of `DeeModule_RELNAME_F_*'
877878
* @return: * : The module's name, written relative to `context_absname'
878879
* @return: ITER_DONE: The given module is anonymous or has its `Dee_MODULE_FABSFILE' flag set
879880
* @return: NULL: An error was thrown. */
880881
DFUNDEF WUNUSED NONNULL((1)) DREF /*String*/ DeeObject *DCALL
881882
DeeModule_GetRelName(DeeModuleObject *__restrict self,
882-
/*Module|String|Type|None*/ DeeObject *context_absname);
883+
/*Module|String|Type|None*/ DeeObject *context_absname,
884+
unsigned int flags);
883885

884886
/* Same as `DeeModule_GetRelName()', but allows you to specify the context
885887
* path in the same manner as can be specified by `DeeModule_OpenEx()':

src/deemon/execute/modpath.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3853,6 +3853,7 @@ do_import_getattr_string_len(char const *__restrict attr, size_t attrlen) {
38533853
/* Special case: "import_str" is the string "deemon" */
38543854
if (attrlen == 6 && fs_bcmp(attr, "deemon", 6 * sizeof(char)) == 0)
38553855
return_reference(DeeModule_GetDeemon());
3856+
/* TODO: wrap "FileNotFound" errors as "AttributeError" */
38563857
return do_DeeModule_ImportGlobal(attr, attrlen, NULL);
38573858
}
38583859

@@ -3861,6 +3862,7 @@ do_import_getattr_string(char const *__restrict attr) {
38613862
/* Special case: "import_str" is the string "deemon" */
38623863
if (fs_strcmp(attr, "deemon") == 0)
38633864
return_reference(DeeModule_GetDeemon());
3865+
/* TODO: wrap "FileNotFound" errors as "AttributeError" */
38643866
return do_DeeModule_ImportGlobal(attr, strlen(attr), NULL);
38653867
}
38663868

@@ -3871,6 +3873,7 @@ do_import_getattr(DeeObject *__restrict attr) {
38713873
goto err;
38723874
if (WSTR_LENGTH(utf8) == 6 && fs_bcmp(utf8, "deemon", 6 * sizeof(char)) == 0)
38733875
return_reference(DeeModule_GetDeemon());
3876+
/* TODO: wrap "FileNotFound" errors as "AttributeError" */
38743877
return do_DeeModule_ImportGlobal(utf8, WSTR_LENGTH(utf8), (DeeStringObject *)attr);
38753878
err:
38763879
return NULL;
@@ -4224,6 +4227,12 @@ do_DeeModule_PrintRelNameEx_impl(DeeModuleObject *__restrict self,
42244227
return do_DeeModule_PrintRelNameEx_impl2(self, printer, arg, context_absname,
42254228
context_absname_size, flags);
42264229
}
4230+
if unlikely(!context_absname_size) {
4231+
result = DeeError_Throwf(&DeeError_ValueError,
4232+
"Cannot form relative name of %k to empty context string",
4233+
self);
4234+
return result;
4235+
}
42274236
if (context_absname_ob) {
42284237
context_absname_ob = (DREF DeeStringObject *)DeeSystem_MakeNormalAndAbsolute((DeeObject *)context_absname_ob);
42294238
} else {
@@ -4256,8 +4265,10 @@ PRIVATE ATTR_PURE WUNUSED NONNULL((1)) bool DCALL
42564265
DeeModule_CanHaveRelName(DeeModuleObject const *__restrict self) {
42574266
if (self->mo_absname == NULL)
42584267
return false;
4259-
if (self->mo_flags & Dee_MODULE_FABSFILE)
4260-
return false;
4268+
if (self->mo_flags & Dee_MODULE_FABSFILE) {
4269+
if (Dee_TYPE(self) != &DeeModuleDir_Type)
4270+
return false;
4271+
}
42614272
return true;
42624273
}
42634274

@@ -4320,16 +4331,19 @@ do_DeeModule_GetRelNameEx(DeeModuleObject *__restrict self,
43204331
/* Return the relative import name of `self' when accessed from a file or module
43214332
* `context_absname'. For more information, see `DeeModule_GetRelNameEx()'.
43224333
*
4334+
* @param: flags: Set of `DeeModule_RELNAME_F_*'
43234335
* @return: * : The module's name, written relative to `context_absname'
43244336
* @return: ITER_DONE: The given module is anonymous or has its `Dee_MODULE_FABSFILE' flag set
43254337
* @return: NULL: An error was thrown. */
43264338
PUBLIC WUNUSED NONNULL((1)) DREF /*String*/ DeeObject *DCALL
43274339
DeeModule_GetRelName(DeeModuleObject *__restrict self,
4328-
/*Module|String|Type|None*/ DeeObject *context_absname) {
4340+
/*Module|String|Type|None*/ DeeObject *context_absname,
4341+
unsigned int flags) {
43294342
char const *context_absname_utf8;
43304343
size_t context_absname_size;
43314344
DeeStringObject *context_absname_ob = NULL;
43324345
if (context_absname == NULL || DeeNone_Check(context_absname)) {
4346+
no_context:
43334347
context_absname_utf8 = NULL;
43344348
context_absname_size = 0;
43354349
} else if (DeeModule_Check(context_absname)) {
@@ -4338,19 +4352,28 @@ DeeModule_GetRelName(DeeModuleObject *__restrict self,
43384352
return_reference(&str_dot);
43394353
context_absname_utf8 = context_mod->mo_absname;
43404354
context_absname_size = context_absname_utf8 ? strlen(context_absname_utf8) : 0;
4355+
flags &= ~DeeModule_RELNAME_F_CTXDIR;
43414356
} else if (DeeString_Check(context_absname)) {
43424357
context_absname_ob = (DeeStringObject *)context_absname;
43434358
context_absname_utf8 = DeeString_AsUtf8(context_absname);
43444359
if unlikely(!context_absname_utf8)
43454360
goto err;
43464361
context_absname_size = WSTR_LENGTH(context_absname_utf8);
4362+
} else if (DeeType_Check(context_absname)) {
4363+
DREF /*String*/ DeeObject *result;
4364+
context_absname = Dee_AsObject(DeeType_GetModule((DeeTypeObject *)context_absname));
4365+
if (!context_absname)
4366+
goto no_context;
4367+
result = DeeModule_GetRelName(self, context_absname, flags);
4368+
Dee_Decref_unlikely(context_absname);
4369+
return result;
43474370
} else {
4348-
DeeObject_TypeAssertFailed2(context_absname, &DeeModule_Type, &DeeString_Type);
4371+
DeeObject_TypeAssertFailed3(context_absname, &DeeModule_Type, &DeeString_Type, &DeeType_Type);
43494372
goto err;
43504373
}
43514374
return do_DeeModule_GetRelNameEx(self,
43524375
context_absname_utf8, context_absname_size,
4353-
context_absname_ob, DeeModule_RELNAME_F_NORMAL);
4376+
context_absname_ob, flags);
43544377
err:
43554378
return NULL;
43564379
}
@@ -4360,7 +4383,8 @@ DeeModule_GetRelNameEx(DeeModuleObject *__restrict self,
43604383
/*utf-8*/ char const *context_absname,
43614384
size_t context_absname_size, unsigned int flags) {
43624385
return do_DeeModule_GetRelNameEx(self, context_absname,
4363-
context_absname_size, NULL, flags);
4386+
context_absname_size,
4387+
NULL, flags);
43644388
}
43654389

43664390
PUBLIC WUNUSED NONNULL((1, 2)) Dee_ssize_t DCALL

src/deemon/execute/module.c

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include <deemon/dex.h>
5252
#endif /* !CONFIG_NO_DEX */
5353

54+
#include "../runtime/kwlist.h"
5455
#include "../runtime/runtime_error.h"
5556
#include "../runtime/strings.h"
5657

@@ -2433,6 +2434,72 @@ INTERN struct type_attr module_attr = {
24332434

24342435
#ifdef CONFIG_EXPERIMENTAL_MODULE_DIRECTORIES
24352436
#define module_get_code DeeModule_GetRootCode
2437+
2438+
PRIVATE WUNUSED NONNULL((1)) DREF DeeObject *DCALL
2439+
module_get_directory(DeeModuleObject *__restrict self) {
2440+
DREF DeeObject *result = DeeModule_GetDirectory(self);
2441+
Dee_XIncref(result);
2442+
return result;
2443+
}
2444+
2445+
PRIVATE WUNUSED NONNULL((1)) DREF DeeObject *DCALL
2446+
module_get_filename(DeeModuleObject *__restrict self) {
2447+
DREF DeeObject *result = DeeModule_GetFileName(self);
2448+
if (result == ITER_DONE)
2449+
result = DeeRT_ErrUnboundAttrCStr(self, "__filename__");
2450+
return result;
2451+
}
2452+
2453+
PRIVATE WUNUSED NONNULL((1)) int DCALL
2454+
module_bound_filename(DeeModuleObject *__restrict self) {
2455+
return Dee_BOUND_FROMBOOL(self->mo_absname != NULL);
2456+
}
2457+
2458+
PRIVATE WUNUSED NONNULL((1)) DREF DeeObject *DCALL
2459+
module_get_path(DeeModuleObject *__restrict self) {
2460+
DREF DeeObject *result = DeeModule_GetFileName(self);
2461+
if (result == ITER_DONE)
2462+
result = DeeNone_NewRef();
2463+
return result;
2464+
}
2465+
2466+
PRIVATE WUNUSED NONNULL((1)) DREF DeeObject *DCALL
2467+
module_relname(DeeModuleObject *__restrict self, size_t argc,
2468+
DeeObject *const *argv, DeeObject *kw) {
2469+
DREF DeeObject *result;
2470+
unsigned int flags;
2471+
/*[[[deemon (print_DeeArg_UnpackKw from rt.gen.unpack)("__relname__", params: """
2472+
DeeObject *to:?X4?DModule?Dstring?DType?N=!N;
2473+
bool libname = false;
2474+
bool todir = false;
2475+
""", docStringPrefix: "module");]]]*/
2476+
#define module___relname___params "to:?X4?DModule?Dstring?DType?N=!N,libname=!f,todir=!f"
2477+
struct {
2478+
DeeObject *to;
2479+
bool libname;
2480+
bool todir;
2481+
} args;
2482+
args.to = Dee_None;
2483+
args.libname = false;
2484+
args.todir = false;
2485+
if (DeeArg_UnpackStructKw(argc, argv, kw, kwlist__to_libname_todir, "|obb:__relname__", &args))
2486+
goto err;
2487+
/*[[[end]]]*/
2488+
flags = DeeModule_RELNAME_F_NORMAL;
2489+
if (args.libname)
2490+
flags |= DeeModule_RELNAME_F_LIBNAM;
2491+
if (args.todir)
2492+
flags |= DeeModule_RELNAME_F_CTXDIR;
2493+
result = DeeModule_GetRelName(self, args.to, flags);
2494+
if unlikely(result == ITER_DONE)
2495+
goto err_noname;
2496+
return result;
2497+
err_noname:
2498+
DeeError_Throwf(&DeeError_ValueError, "Cannot form relative name for module %k", self);
2499+
err:
2500+
return NULL;
2501+
}
2502+
24362503
#else /* CONFIG_EXPERIMENTAL_MODULE_DIRECTORIES */
24372504
PRIVATE NONNULL((1)) int DCALL
24382505
err_module_not_fully_loaded(DeeModuleObject *__restrict self) {
@@ -2483,6 +2550,8 @@ PRIVATE struct type_member tpconst module_members[] = {
24832550
TYPE_MEMBER_FIELD_DOC("__absname__", STRUCT_STRING, offsetof(DeeModuleObject, mo_absname),
24842551
"The absolute name of this module (as can be passed to "
24852552
/**/ "$import to access this module from any context)"),
2553+
TYPE_MEMBER_FIELD_DOC("__haspath__", STRUCT_CONST | STRUCT_BOOLPTR, offsetof(DeeModuleObject, mo_absname),
2554+
"Deprecated alias for ${this.__filename__ is bound}"),
24862555
#else /* CONFIG_EXPERIMENTAL_MODULE_DIRECTORIES */
24872556
TYPE_MEMBER_FIELD_DOC(STR___name__, STRUCT_OBJECT, offsetof(DeeModuleObject, mo_name),
24882557
"->?Dstring\n"
@@ -2496,6 +2565,23 @@ DeeModule_ViewExports(DeeObject *__restrict self);
24962565
INTDEF WUNUSED NONNULL((1)) DREF DeeObject *DCALL
24972566
DeeModule_ViewGlobals(DeeObject *__restrict self);
24982567

2568+
#ifdef CONFIG_EXPERIMENTAL_MODULE_DIRECTORIES
2569+
PRIVATE struct type_method tpconst module_methods[] = {
2570+
TYPE_KWMETHOD_F("__relname__", &module_relname, METHOD_FNOREFESCAPE,
2571+
"(to:?X4?DModule?Dstring?DType?N=!N,libname=!f,todir=!f)->?Dstring\n"
2572+
"#tValueError{?#__filename__ is unbound, or @to is an empty string and @libname is false, or @this has no libnames}"
2573+
"Form the import name of @this module relative to @to. When @to is a string, it "
2574+
/**/ "should be the filename (like ?#__filename__) of a deemon script relative to "
2575+
/**/ "which the string should be generated. However, when @todir is $true and @to "
2576+
/**/ "is a string, then @to is the directory of the reference file instead of the "
2577+
/**/ "reference file itself\n"
2578+
"When @libname is true, try to return ${__libnames__.first} instead (s.a. ?#__libnames__)"),
2579+
TYPE_METHOD_END
2580+
};
2581+
#else /* CONFIG_EXPERIMENTAL_MODULE_DIRECTORIES */
2582+
#define module_methods NULL
2583+
#endif /* !CONFIG_EXPERIMENTAL_MODULE_DIRECTORIES */
2584+
24992585
PRIVATE struct type_getset tpconst module_getsets[] = {
25002586
TYPE_GETTER_AB("__exports__", &DeeModule_ViewExports,
25012587
"->?M?X2?Dstring?Dint?O\n"
@@ -2517,9 +2603,25 @@ PRIVATE struct type_getset tpconst module_getsets[] = {
25172603
TYPE_GETTER_AB("__globals__", &DeeModule_ViewGlobals,
25182604
"->?S?O\n"
25192605
"Similar to ?#__exports__, however global variables are addressed using their "
2520-
/**/ "internal index. Using this, anonymous global variables (such as property callbacks) "
2521-
/**/ "can be accessed and modified"),
2522-
#ifndef CONFIG_EXPERIMENTAL_MODULE_DIRECTORIES
2606+
/**/ "internal index. Using this, anonymous global variables (such as property "
2607+
/**/ "callbacks) can be accessed and modified"),
2608+
#ifdef CONFIG_EXPERIMENTAL_MODULE_DIRECTORIES
2609+
TYPE_GETTER_AB_F("__directory__", &module_get_directory, METHOD_FNOREFESCAPE,
2610+
"->?S?Dstring\n"
2611+
"Returns the names of all child-modules located "
2612+
/**/ "within the directory specified by ?#__absname__\n"
2613+
"These strings can be used as attribute names with "
2614+
/**/ "?#{op:getattr} to retrieve the relevant module"),
2615+
TYPE_GETTER_BOUND_F("__filename__", &module_get_filename, &module_bound_filename, METHOD_FNOREFESCAPE,
2616+
"->?Dstring\n"
2617+
"#tUnboundAttribute{Module does not originate from the filesystem}\n"
2618+
"Returns the actual filename (as opposed to the unique / "
2619+
/**/ "directory-name returned by ?#__absname__) of this module"),
2620+
TYPE_GETTER_AB_F("__path__", &module_get_path, METHOD_FNOREFESCAPE,
2621+
"->?X2?Dstring?N\n"
2622+
"Deprecated alias for ${this.__filename__ is bound ? this.__filename__ : none}"),
2623+
/* TODO: __libnames__->?S?Dstring (to expose DeeModule_GetLibName() and DeeModule_GetLibNameCount()) */
2624+
#else /* CONFIG_EXPERIMENTAL_MODULE_DIRECTORIES */
25232625
TYPE_GETTER_F("__code__", &module_get_code, METHOD_FNOREFESCAPE,
25242626
"->?Ert:Code\n"
25252627
"#tValueError{The Module hasn't been fully loaded}"
@@ -2593,6 +2695,7 @@ module_class_gethome(DeeObject *__restrict UNUSED(self)) {
25932695
}
25942696

25952697
PRIVATE struct type_getset tpconst module_class_getsets[] = {
2698+
25962699
TYPE_GETTER_AB("home", &module_class_gethome,
25972700
"->?Dstring\n"
25982701
"The deemon home path (usually the path where the deemon executable resides)"),
@@ -2602,6 +2705,9 @@ PRIVATE struct type_getset tpconst module_class_getsets[] = {
26022705
"A tuple of strings describing the search path for system libraries"),
26032706
/* TODO: User-code access to "DeeModule_AddLibPath" */
26042707
/* TODO: User-code access to "DeeModule_RemoveLibPath" */
2708+
/* TODO: User-code access to "DeeModule_NextAbsTree" */
2709+
/* TODO: User-code access to "DeeModule_NextAdrTree" */
2710+
/* TODO: User-code access to "DeeModule_NextLibTree" */
26052711
#else /* CONFIG_EXPERIMENTAL_MODULE_DIRECTORIES */
26062712
TYPE_GETSET_AB("path", &module_class_getpath, NULL, &module_class_setpath,
26072713
"->?DList\n"
@@ -3338,7 +3444,7 @@ PUBLIC DeeTypeObject DeeModule_Type = {
33383444
/* .tp_attr = */ &module_attr,
33393445
/* .tp_with = */ NULL,
33403446
/* .tp_buffer = */ NULL,
3341-
/* .tp_methods = */ NULL,
3447+
/* .tp_methods = */ module_methods,
33423448
/* .tp_getsets = */ module_getsets,
33433449
/* .tp_members = */ module_members,
33443450
/* .tp_class_methods = */ module_class_methods,

src/deemon/runtime/kwlist.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ local kw_lists = {
137137
{"total", "more", "weak"},
138138
{"reason", "fp", "traceback"},
139139
{"reason", "error", "fp", "traceback"},
140+
{"to", "libname", "todir"},
140141
141142
// For runtime errors...
142143
{"value", "minval", "maxval", "positive"},
@@ -265,6 +266,7 @@ DECLARE_KWLIST(kwlist__template, { KEX("template", 0xa21c009f, 0xb466762d86160f0
265266
DECLARE_KWLIST(kwlist__text_module_constants_except_nlocal_nstack_nref_nstatic_argc_keywords_defaults_flags_ddi, { KEX("text", 0xc624ae24, 0x2a28a0084dd3a743), KEX("module", 0xae3684a4, 0xbb78a82535e5801e), KEX("constants", 0x8d73036e, 0xba127eb7623ae369), KEX("except", 0x8aae072b, 0xac70487e4861a6f3), KEX("nlocal", 0xae97b3ed, 0x23bb6e6e6190e9d7), KEX("nstack", 0xb92ec26e, 0x80220c290516f55), KEX("nref", 0x7951b608, 0xb8d28d6292d2f6cb), KEX("nstatic", 0xf17d253b, 0x6229886d9780e339), KEX("argc", 0xe5c6c120, 0xd96a642eb89eed13), KEX("keywords", 0xe751d20, 0x68e3cfd5fbfbc77a), KEX("defaults", 0xd48dea84, 0x2f0dce9444829201), KEX("flags", 0xd9e40622, 0x6afda85728fae70d), KEX("ddi", 0xe141111d, 0x958d321a1dacb4ed), KEND });
266267
DECLARE_KWLIST(kwlist__thisarg, { KEX("thisarg", 0xfeb6b4f, 0xd3f418e6f91d6ac1), KEND });
267268
DECLARE_KWLIST(kwlist__thisarg_value, { KEX("thisarg", 0xfeb6b4f, 0xd3f418e6f91d6ac1), KEX("value", 0xd9093f6e, 0x69e7413ae0c88471), KEND });
269+
DECLARE_KWLIST(kwlist__to_libname_todir, { KEX("to", 0x912a85b, 0x17de168783fb672d), KEX("libname", 0x32598baa, 0xb2f989a293116ac3), KEX("todir", 0x85239856, 0xf4df4864111e59f9), KEND });
268270
DECLARE_KWLIST(kwlist__total_more, { KEX("total", 0x48601e35, 0xd63cdba353c9c786), KEX("more", 0x8a39c376, 0xff9278cf274776cc), KEND });
269271
DECLARE_KWLIST(kwlist__total_more_weak, { KEX("total", 0x48601e35, 0xd63cdba353c9c786), KEX("more", 0x8a39c376, 0xff9278cf274776cc), KEX("weak", 0x41118332, 0xc8855a0749fb5152), KEND });
270272
DECLARE_KWLIST(kwlist__tuple_kwds, { KEX("tuple", 0x8abf5ca6, 0x32af754eabcdc75a), KEX("kwds", 0x6dfae69b, 0x66fee9115d75f3ef), KEND });

0 commit comments

Comments
 (0)