Wrap hardcoded docstrings behind a macro so they can be removed from builds

This commit is contained in:
K. Lange 2021-03-09 17:58:38 +09:00
parent fc9f55efb1
commit e3e1fbb13a
19 changed files with 336 additions and 186 deletions

View File

@ -794,14 +794,18 @@ void _createAndBind_builtins(void) {
krk_defineNative(&vm.baseClasses->objectClass->methods, ".__repr__", _strBase); /* Override if necesary */
krk_defineNative(&vm.baseClasses->objectClass->methods, ".__hash__", obj_hash);
krk_finalizeClass(vm.baseClasses->objectClass);
vm.baseClasses->objectClass->docstring = S("Base class for all types.");
KRK_DOC(vm.baseClasses->objectClass,
"@brief Base class for all types.\n\n"
"The @c object base class provides the fallback implementations of methods like "
"@ref object___dir__ \"__dir__\". All object and primitive types eventually inherit from @c object."
);
vm.baseClasses->moduleClass = krk_newClass(S("module"), vm.baseClasses->objectClass);
krk_push(OBJECT_VAL(vm.baseClasses->moduleClass));
krk_defineNative(&vm.baseClasses->moduleClass->methods, ".__repr__", _module_repr);
krk_defineNative(&vm.baseClasses->moduleClass->methods, ".__str__", _module_repr);
krk_finalizeClass(vm.baseClasses->moduleClass);
vm.baseClasses->moduleClass->docstring = S("Type of imported modules and packages.");
KRK_DOC(vm.baseClasses->moduleClass, "Type of imported modules and packages.");
vm.builtins = krk_newInstance(vm.baseClasses->moduleClass);
krk_attachNamedObject(&vm.modules, "__builtins__", (KrkObj*)vm.builtins);
@ -811,8 +815,18 @@ void _createAndBind_builtins(void) {
krk_attachNamedObject(&vm.builtins->fields, "__name__", (KrkObj*)S("__builtins__"));
krk_attachNamedValue(&vm.builtins->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&vm.builtins->fields, "__doc__",
(KrkObj*)S("Internal module containing built-in functions and classes."));
KRK_DOC(vm.builtins,
"@brief Internal module containing built-in functions and classes.\n\n"
"Classes and functions from the @c \\__builtins__ module are generally available from "
"all global namespaces. Built-in names can still be shadowed by module-level globals "
"and function-level locals, so none the names in this module are not reserved. When "
"a built-in name has been shadowed, the original can be referenced directly as "
" @c \\__builtins__.name instead.\n\n"
"Built-in names may be bound from several sources. Most come from the core interpreter "
"directly, but some may come from loaded C extension modules or the interpreter binary. "
"Kuroko source modules are also free to append new names to the built-in name space by "
"attaching new properties to the @c \\__builtins__ instance."
);
krk_makeClass(vm.builtins, &vm.baseClasses->propertyClass, "Property", vm.baseClasses->objectClass);
krk_defineNative(&vm.baseClasses->propertyClass->methods, ".__repr__", _property_repr);
@ -822,16 +836,21 @@ void _createAndBind_builtins(void) {
krk_finalizeClass(vm.baseClasses->propertyClass);
krk_makeClass(vm.builtins, &Helper, "Helper", vm.baseClasses->objectClass);
Helper->docstring = S("Special object that prints a helpful message when passed to @ref repr");
BIND_METHOD(Helper,__call__)->doc = "@arguments obj=None\nPrints the help documentation attached to @p obj or "
"starts the interactive help system.";
KRK_DOC(Helper,
"@brief Special object that prints a helpeful message.\n\n"
"Object that prints help summary when passed to @ref repr.");
KRK_DOC(BIND_METHOD(Helper,__call__),
"@brief Prints help text.\n"
"@arguments obj=None\n\n"
"Prints the help documentation attached to @p obj or starts the interactive help system by "
"importing the @ref mod_help module.");
BIND_METHOD(Helper,__repr__);
krk_finalizeClass(Helper);
krk_attachNamedObject(&vm.builtins->fields, "help", (KrkObj*)krk_newInstance(Helper));
krk_makeClass(vm.builtins, &LicenseReader, "LicenseReader", vm.baseClasses->objectClass);
LicenseReader->docstring = S("Special object that prints Kuroko's copyright information when passed to @ref repr");
BIND_METHOD(LicenseReader,__call__)->doc = "Print the full license statement.";
KRK_DOC(LicenseReader, "Special object that prints Kuroko's copyright information when passed to @ref repr");
KRK_DOC(BIND_METHOD(LicenseReader,__call__), "Print the full license statement.");
BIND_METHOD(LicenseReader,__repr__);
krk_finalizeClass(LicenseReader);
krk_attachNamedObject(&vm.builtins->fields, "license", (KrkObj*)krk_newInstance(LicenseReader));

View File

@ -72,7 +72,9 @@ typedef enum {
typedef void (*ParseFn)(int);
typedef struct {
#ifdef ENABLE_SCAN_TRACING
const char * name;
#endif
ParseFn prefix;
ParseFn infix;
Precedence precedence;
@ -2485,7 +2487,11 @@ static void dict(int canAssign) {
consume(TOKEN_RIGHT_BRACE,"Expected } at end of dict expression.");
}
#define RULE(token, a, b, c) [token] = {# token, a, b, c}
#ifndef ENABLE_SCAN_TRACING
# define RULE(token, a, b, c) [token] = {a, b, c}
#else
# define RULE(token, a, b, c) [token] = {# token, a, b, c}
#endif
ParseRule krk_parseRules[] = {
RULE(TOKEN_LEFT_PAREN, grouping, call, PREC_CALL),

View File

@ -690,20 +690,63 @@ void _createAndBind_disMod(void) {
krk_attachNamedObject(&vm.modules, "dis", (KrkObj*)module);
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("dis"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__",
(KrkObj*)S("@brief Provides tools for disassembling bytecode."));
BIND_FUNC(module, dis)->doc = "@brief Disassemble an object.\n"
KRK_DOC(module,
"@brief Provides tools for disassembling bytecode.\n\n"
"### Code Disassembly in Kuroko\n\n"
"The @c dis module contains functions for dealing with _code objects_ which "
"represent the compiled bytecode of a Kuroko function. The bytecode compilation "
"process is entirely static and bytecode analysis can be performed without calling "
"into the VM to run dynamic code.\n\n"
"### Debugger Breakpoints\n\n"
"Kuroko interpreters can provide a debugger hook through the C API's "
"@ref krk_debug_registerCallback() function. Breakpoints can be managed both "
"from the C API and from this module's @ref addbreakpoint, @ref delbreakpoint, "
"@ref enablebreakpoint, and @ref disablebreakpoint methods."
);
KRK_DOC(BIND_FUNC(module, dis),
"@brief Disassemble an object.\n"
"@arguments obj\n\n"
"Dumps a disassembly of the bytecode in the code object associated with @p obj. "
"If @p obj can not be disassembled, a @ref TypeError is raised.";
"If @p obj can not be disassembled, a @ref TypeError is raised.");
BIND_FUNC(module, build);
BIND_FUNC(module, examine);
KRK_DOC(BIND_FUNC(module, build),
"@brief Compile a string to a code object.\n"
"@arguments code\n\n"
"Compiles the string @p code and returns a code object. If a syntax "
"error is encountered, it will be raised.");
BIND_FUNC(module, addbreakpoint);
BIND_FUNC(module, delbreakpoint);
BIND_FUNC(module, enablebreakpoint);
BIND_FUNC(module, disablebreakpoint);
KRK_DOC(BIND_FUNC(module, examine),
"@brief Convert a code object to a list of instructions.\n"
"@arguments func\n\n"
"Examines the code object @p func and returns a list representation of its instructions. "
"Each instruction entry is a tuple of the opcode, total instruction size in bytes, and "
"the operand of the argument, either as an integer for jump offsets, the actual value for "
"constant operands, or the name of a local or global variable if available.");
KRK_DOC(BIND_FUNC(module, addbreakpoint),
"@brief Attach a breakpoint to a code object.\n"
"@arguments func, line\n\n"
"@p func may be a filename string, or a function, method, or code object. Returns "
"the new breakpoint index, or raises @ref Exception if a breakpoint code not be added.");
KRK_DOC(BIND_FUNC(module, delbreakpoint),
"@brief Delete a breakpoint.\n"
"@arguments handle\n\n"
"Delete the breakpoint specified by @p handle, disabling it if it was enabled. "
"May raise @ref IndexError if @p handle is not a valid breakpoint handle.");
KRK_DOC(BIND_FUNC(module, enablebreakpoint),
"@brief Enable a breakpoint.\n"
"@arguments handle\n\n"
"Enable the breakpoint specified by @p handle. May raise @ref IndexError if "
"@p handle is not a valid breakpoint handle.");
KRK_DOC(BIND_FUNC(module, disablebreakpoint),
"@brief Disable a breakpoint.\n"
"@arguments handle\n\n"
"Disable the breakpoint specified by @p handle. May raise @ref IndexError if "
"@p handle is not a valid breakpoint handle.");
krk_attachNamedValue(&module->fields, "BREAKPOINT_ONCE", INTEGER_VAL(KRK_BREAKPOINT_ONCE));
krk_attachNamedValue(&module->fields, "BREAKPOINT_REPEAT", INTEGER_VAL(KRK_BREAKPOINT_REPEAT));

View File

@ -494,43 +494,41 @@ void _createAndBind_fileioMod(void) {
krk_attachNamedObject(&vm.modules, "fileio", (KrkObj*)module);
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("fileio"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__", (KrkObj*)S(
KRK_DOC(module,
"@brief Provides access to C <stdio> buffered file I/O functions.\n\n"
"The @c fileio module provides classes and functions for reading "
"and writing files using the system's buffer I/O interfaces, as "
"well as classes for listing the contents of directories."
));
);
/* Define a class to represent files. (Should this be a helper method?) */
krk_makeClass(module, &File, "File", vm.baseClasses->objectClass);
File->docstring = S(
"Interface to a buffered file stream."
);
KRK_DOC(File,"Interface to a buffered file stream.");
File->allocSize = sizeof(struct File);
File->_ongcsweep = _file_sweep;
/* Add methods to it... */
BIND_METHOD(File,read)->doc = "@brief Read from the stream.\n"
KRK_DOC(BIND_METHOD(File,read), "@brief Read from the stream.\n"
"@arguments bytes=-1\n\n"
"Reads up to @p bytes bytes from the stream. If @p bytes is @c -1 then reading "
"will continue until the system returns _end of file_.";
BIND_METHOD(File,readline)->doc = "@brief Read one line from the stream.";
BIND_METHOD(File,readlines)->doc = "@brief Read the entire stream and return a list of lines.";
BIND_METHOD(File,write)->doc = "@brief Write to the stream.\n"
"will continue until the system returns _end of file_.");
KRK_DOC(BIND_METHOD(File,readline), "@brief Read one line from the stream.");
KRK_DOC(BIND_METHOD(File,readlines), "@brief Read the entire stream and return a list of lines.");
KRK_DOC(BIND_METHOD(File,write), "@brief Write to the stream.\n"
"@arguments data\n\n"
"Writes the contents of @p data to the stream.";
BIND_METHOD(File,close)->doc = "@brief Close the stream and flush any remaining buffered writes.";
BIND_METHOD(File,flush)->doc = "@brief Flush unbuffered writes to the stream.";
"Writes the contents of @p data to the stream.");
KRK_DOC(BIND_METHOD(File,close), "@brief Close the stream and flush any remaining buffered writes.");
KRK_DOC(BIND_METHOD(File,flush), "@brief Flush unbuffered writes to the stream.");
BIND_METHOD(File,__str__);
BIND_METHOD(File,__init__)->doc = "@bsnote{%File objects can not be initialized using this constructor. "
"Use the <a class=\"el\" href=\"#open\">open()</a> function instead.}";
KRK_DOC(BIND_METHOD(File,__init__), "@bsnote{%File objects can not be initialized using this constructor. "
"Use the <a class=\"el\" href=\"#open\">open()</a> function instead.}");
BIND_METHOD(File,__enter__);
BIND_METHOD(File,__exit__);
krk_defineNative(&File->methods, ".__repr__", FUNC_NAME(File,__str__));
krk_finalizeClass(File);
krk_makeClass(module, &BinaryFile, "BinaryFile", File);
BinaryFile->docstring = S(
KRK_DOC(BinaryFile,
"Equivalent to @ref File but using @ref bytes instead of string @ref str."
);
BIND_METHOD(BinaryFile,read);
@ -540,18 +538,18 @@ void _createAndBind_fileioMod(void) {
krk_finalizeClass(BinaryFile);
krk_makeClass(module, &Directory, "Directory", vm.baseClasses->objectClass);
Directory->docstring = S(
KRK_DOC(Directory,
"Represents an opened file system directory."
);
Directory->allocSize = sizeof(struct Directory);
Directory->_ongcsweep = _dir_sweep;
BIND_METHOD(Directory,__repr__);
BIND_METHOD(Directory,__iter__)->doc = "@brief Iterates over the contents of the directory.\n\n"
"Each iteration returns @ref dict with two entries: <i>\"name\"</i> and <i>\"inode\"</i>.";
BIND_METHOD(Directory,__call__)->doc = "@brief Yields one iteration through the directory.";
KRK_DOC(BIND_METHOD(Directory,__iter__), "@brief Iterates over the contents of the directory.\n\n"
"Each iteration returns @ref dict with two entries: <i>\"name\"</i> and <i>\"inode\"</i>.");
KRK_DOC(BIND_METHOD(Directory,__call__), "@brief Yields one iteration through the directory.");
BIND_METHOD(Directory,__enter__);
BIND_METHOD(Directory,__exit__)->doc = "@brief Closes the directory upon exit from a @c with block.";
BIND_METHOD(Directory,close)->doc = "@brief Close the directory.\n\nFurther reads can not be made after the directory has been closed.";
KRK_DOC(BIND_METHOD(Directory,__exit__), "@brief Closes the directory upon exit from a @c with block.");
KRK_DOC(BIND_METHOD(Directory,close), "@brief Close the directory.\n\nFurther reads can not be made after the directory has been closed.");
krk_finalizeClass(Directory);
/* Make an instance for stdout, stderr, and stdin */
@ -560,13 +558,13 @@ void _createAndBind_fileioMod(void) {
makeFileInstance(module, "stderr", stderr);
/* Our base will be the open method */
BIND_FUNC(module,open)->doc = "@brief Open a file.\n"
KRK_DOC(BIND_FUNC(module,open), "@brief Open a file.\n"
"@arguments path,mode=\"r\"\n\n"
"Opens @p path using the modestring @p mode. Supported modestring characters depend on the system implementation. "
"If the last character of @p mode is @c 'b' a @ref BinaryFile will be returned. If the file could not be opened, "
"an @ref IOError will be raised.";
BIND_FUNC(module,opendir)->doc = "@brief Open a directory for scanning.\n"
"an @ref IOError will be raised.");
KRK_DOC(BIND_FUNC(module,opendir), "@brief Open a directory for scanning.\n"
"@arguments path\n\n"
"Opens the directory at @p path and returns a @ref Directory object. If @p path could not be opened or is not "
"a directory, @ref IOError will be raised.";
"a directory, @ref IOError will be raised.");
}

View File

@ -838,7 +838,7 @@ _finishArgs:
* Add general builtins that aren't part of the core VM.
* This is where we provide @c input in particular.
*/
BIND_FUNC(vm.builtins,input)->doc = "@brief Read a line of input.\n"
KRK_DOC(BIND_FUNC(vm.builtins,input), "@brief Read a line of input.\n"
"@arguments [prompt], promptwidth=None, syntax=None\n\n"
"Read a line of input from @c stdin. If the @c rline library is available, "
"it will be used to gather input. Input reading stops on end-of file or when "
@ -850,7 +850,7 @@ _finishArgs:
"characters with multi-column East-Asian Character Width be sure to pass a value "
"for @p promptwidth that reflects the display width of your prompt. "
"If provided, @p syntax specifies the name of an @c rline syntax module to "
"provide color highlighting of the input line.";
"provide color highlighting of the input line.");
if (moduleAsMain) {
krk_push(OBJECT_VAL(krk_copyString("__main__",8)));
@ -864,14 +864,14 @@ _finishArgs:
return out;
} else if (optind == argc) {
/* Add builtins for the repl, but hide them from the globals() list. */
BIND_FUNC(vm.builtins,exit)->doc = "@brief Exit the interactive repl.\n\n"
"Only available from the interactive interpreter; exits the repl.";
BIND_FUNC(vm.builtins,paste)->doc = "@brief Toggle paste mode.\n"
KRK_DOC(BIND_FUNC(vm.builtins,exit), "@brief Exit the interactive repl.\n\n"
"Only available from the interactive interpreter; exits the repl.");
KRK_DOC(BIND_FUNC(vm.builtins,paste), "@brief Toggle paste mode.\n"
"@arguments enabled=None\n\n"
"Toggles paste-safe mode, disabling automatic indentation in the repl. "
"If @p enabled is specified, the mode can be directly specified, otherwise "
"it will be set to the opposite of the current mode. The new mode will be "
"printed to stderr.";
"printed to stderr.");
/* The repl runs in the context of a top-level module so each input
* line can share a globals state with the others. */

View File

@ -293,14 +293,16 @@ size_t krk_collectGarbage(void) {
return out;
}
static KrkValue krk_collectGarbage_wrapper(int argc, KrkValue argv[], int hasKw) {
KRK_FUNC(collect,{
FUNCTION_TAKES_NONE();
if (&krk_currentThread != vm.threads) return krk_runtimeError(vm.exceptions->valueError, "only the main thread can do that");
return INTEGER_VAL(krk_collectGarbage());
}
})
static KrkValue krk_generations(int argc, KrkValue argv[], int hasKw) {
#define MAX_GEN 4
krk_integer_type generations[MAX_GEN] = {0,0,0,0};
KRK_FUNC(generations,{
FUNCTION_TAKES_NONE();
krk_integer_type generations[MAX_GEN] = {0};
KrkObj * object = vm.objects;
while (object) {
generations[object->generation]++;
@ -315,17 +317,17 @@ static KrkValue krk_generations(int argc, KrkValue argv[], int hasKw) {
outTuple->values.count = MAX_GEN;
krk_tupleUpdateHash(outTuple);
return OBJECT_VAL(outTuple);
}
})
static KrkValue _gc_pause(int argc, KrkValue argv[], int hasKw) {
KRK_FUNC(pause,{
FUNCTION_TAKES_NONE();
vm.globalFlags |= (KRK_GLOBAL_GC_PAUSED);
return NONE_VAL();
}
})
static KrkValue _gc_resume(int argc, KrkValue argv[], int hasKw) {
KRK_FUNC(resume,{
FUNCTION_TAKES_NONE();
vm.globalFlags &= ~(KRK_GLOBAL_GC_PAUSED);
return NONE_VAL();
}
})
_noexport
void _createAndBind_gcMod(void) {
@ -338,15 +340,14 @@ void _createAndBind_gcMod(void) {
krk_attachNamedObject(&vm.modules, "gc", (KrkObj*)gcModule);
krk_attachNamedObject(&gcModule->fields, "__name__", (KrkObj*)S("gc"));
krk_attachNamedValue(&gcModule->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&gcModule->fields, "__doc__",
(KrkObj*)S("@brief Namespace containing methods for controlling the garbge collector."));
KRK_DOC(gcModule, "@brief Namespace containing methods for controlling the garbge collector.");
krk_defineNative(&gcModule->fields, "collect", krk_collectGarbage_wrapper)->doc =
"@brief Triggers one cycle of garbage collection.";
krk_defineNative(&gcModule->fields, "generations", krk_generations)->doc =
"@brief Returns a 4-tuple of the counts of objects in each stage of garbage collection.";
krk_defineNative(&gcModule->fields, "pause", _gc_pause)->doc =
"@brief Disables automatic garbage collection until @ref resume is called.";
krk_defineNative(&gcModule->fields, "resume", _gc_resume)->doc =
"@brief Re-enable automatic garbage collection after it was stopped by @ref pause ";
KRK_DOC(BIND_FUNC(gcModule,collect),
"@brief Triggers one cycle of garbage collection.");
KRK_DOC(BIND_FUNC(gcModule,generations),
"@brief Returns a 4-tuple of the counts of objects in each stage of garbage collection.");
KRK_DOC(BIND_FUNC(gcModule,pause),
"@brief Disables automatic garbage collection until @ref resume is called.");
KRK_DOC(BIND_FUNC(gcModule,resume),
"@brief Re-enable automatic garbage collection after it was stopped by @ref pause ");
}

View File

@ -70,5 +70,5 @@ void _createAndBind_type(void) {
krk_defineNative(&vm.baseClasses->typeClass->methods, ".__str__", _class_to_str);
krk_defineNative(&vm.baseClasses->typeClass->methods, ".__repr__", _class_to_str);
krk_finalizeClass(vm.baseClasses->typeClass);
vm.baseClasses->typeClass->docstring = S("Obtain the object representation of the class of an object.");
KRK_DOC(vm.baseClasses->typeClass, "Obtain the object representation of the class of an object.");
}

View File

@ -215,10 +215,11 @@ _corrupt:
_noexport
void _createAndBind_bytesClass(void) {
KrkClass * bytes = ADD_BASE_CLASS(vm.baseClasses->bytesClass, "bytes", vm.baseClasses->objectClass);
BIND_METHOD(bytes,__init__)->doc =
"@arguments iter=None\n"
KRK_DOC(BIND_METHOD(bytes,__init__),
"@brief An array of bytes.\n"
"@arguments iter=None\n\n"
"Creates a new @ref bytes object. If @p iter is provided, it should be a @ref tuple or @ref list "
"of integers within the range @c 0 and @c 255.";
"of integers within the range @c 0 and @c 255.");
BIND_METHOD(bytes,__repr__);
BIND_METHOD(bytes,__len__);
BIND_METHOD(bytes,__contains__);

View File

@ -387,7 +387,7 @@ void _createAndBind_dictClass(void) {
BIND_METHOD(dict,update);
krk_defineNative(&dict->methods, ".__str__", FUNC_NAME(dict,__repr__));
krk_finalizeClass(dict);
dict->docstring = S("Mapping of arbitrary keys to values.");
KRK_DOC(dict, "Mapping of arbitrary keys to values.");
BUILTIN_FUNCTION("dictOf", krk_dict_of, "Convert argument sequence to dict object.");

View File

@ -504,7 +504,7 @@ void _createAndBind_listClass(void) {
krk_defineNative(&list->methods, ".__delitem__", FUNC_NAME(list,pop));
krk_defineNative(&list->methods, ".__str__", FUNC_NAME(list,__repr__));
krk_finalizeClass(list);
list->docstring = S("Mutable sequence of arbitrary values.");
KRK_DOC(list, "Mutable sequence of arbitrary values.");
BUILTIN_FUNCTION("listOf", krk_list_of, "Convert argument sequence to list object.");
BUILTIN_FUNCTION("sorted", _sorted, "Return a sorted representation of an iterable.");

View File

@ -107,7 +107,7 @@ void _createAndBind_numericClasses(void) {
BIND_METHOD(int,__float__);
krk_defineNative(&_int->methods, ".__repr__", FUNC_NAME(int,__str__));
krk_finalizeClass(_int);
_int->docstring = S("Convert a number or string type to an integer representation.");
KRK_DOC(_int, "Convert a number or string type to an integer representation.");
KrkClass * _float = ADD_BASE_CLASS(vm.baseClasses->floatClass, "float", vm.baseClasses->objectClass);
BIND_METHOD(float,__init__);
@ -116,14 +116,14 @@ void _createAndBind_numericClasses(void) {
BIND_METHOD(float,__str__);
krk_defineNative(&_float->methods, ".__repr__", FUNC_NAME(float,__str__));
krk_finalizeClass(_float);
_float->docstring = S("Convert a number or string type to a float representation.");
KRK_DOC(_float, "Convert a number or string type to a float representation.");
KrkClass * _bool = ADD_BASE_CLASS(vm.baseClasses->boolClass, "bool", vm.baseClasses->intClass);
BIND_METHOD(bool,__init__);
BIND_METHOD(bool,__str__);
krk_defineNative(&_bool->methods, ".__repr__", FUNC_NAME(bool,__str__));
krk_finalizeClass(_bool);
_bool->docstring = S("Returns False if the argument is 'falsey', otherwise True.");
KRK_DOC(_bool, "Returns False if the argument is 'falsey', otherwise True.");
KrkClass * _NoneType = ADD_BASE_CLASS(vm.baseClasses->noneTypeClass, "NoneType", vm.baseClasses->objectClass);
BIND_METHOD(NoneType, __str__);

View File

@ -107,7 +107,7 @@ void _createAndBind_rangeClass(void) {
krk_defineNative(&vm.baseClasses->rangeClass->methods, ".__iter__", _range_iter);
krk_defineNative(&vm.baseClasses->rangeClass->methods, ".__repr__", _range_repr);
krk_finalizeClass(vm.baseClasses->rangeClass);
vm.baseClasses->rangeClass->docstring = S("range(max), range(min, max[, step]): "
KRK_DOC(vm.baseClasses->rangeClass, "range(max), range(min, max[, step]): "
"An iterable object that produces numeric values. "
"'min' is inclusive, 'max' is exclusive.");

View File

@ -924,7 +924,7 @@ void _createAndBind_strClass(void) {
krk_defineNative(&str->methods,".__delslice__",FUNC_NAME(str,__set__));
krk_defineNative(&str->methods,".__delitem__",FUNC_NAME(str,__set__));
krk_finalizeClass(str);
str->docstring = S("Obtain a string representation of an object.");
KRK_DOC(str, "Obtain a string representation of an object.");
KrkClass * striterator = ADD_BASE_CLASS(vm.baseClasses->striteratorClass, "striterator", vm.baseClasses->objectClass);
BIND_METHOD(striterator,__init__);

168
src/os.c
View File

@ -623,8 +623,7 @@ void _createAndBind_osMod(void) {
krk_attachNamedObject(&vm.modules, "os", (KrkObj*)module);
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("os"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__",
(KrkObj*)S("@brief Provides access to low-level system operations."));
KRK_DOC(module, "@brief Provides access to low-level system operations.");
#ifdef _WIN32
krk_attachNamedObject(&module->fields, "name", (KrkObj*)S("nt"));
@ -684,121 +683,153 @@ void _createAndBind_osMod(void) {
#endif
krk_makeClass(module, &OSError, "OSError", vm.exceptions->baseException);
OSError->docstring = S(
KRK_DOC(OSError,
"Raised when system functions return a failure code. @p Exception.arg will provide a textual description of the error."
);
krk_finalizeClass(OSError);
BIND_FUNC(module,uname)->doc = "@brief Returns a @ref dict of attributes describing the current platform.\n\n"
KRK_DOC(BIND_FUNC(module,uname),
"@brief Returns a @ref dict of attributes describing the current platform.\n\n"
"On POSIX platforms, the result should match the contents and layout of a standard @c uname() call. "
"On Windows, values are synthesized from available information.";
BIND_FUNC(module,system)->doc = "@brief Call the system shell.\n"
"On Windows, values are synthesized from available information.");
KRK_DOC(BIND_FUNC(module,system),
"@brief Call the system shell.\n"
"@arguments cmd\n\n"
"Runs @p cmd using the system shell and returns the platform-dependent return value.";
BIND_FUNC(module,getcwd)->doc = "@brief Get the name of the current working directory.";
BIND_FUNC(module,chdir)->doc = "@brief Change the current working directory.\n"
"Runs @p cmd using the system shell and returns the platform-dependent return value.");
KRK_DOC(BIND_FUNC(module,getcwd),
"@brief Get the name of the current working directory.");
KRK_DOC(BIND_FUNC(module,chdir),
"@brief Change the current working directory.\n"
"@arguments newcwd\n\n"
"Attempts to change the working directory to @p newcwd. Raises @ref OSError on failure.";
BIND_FUNC(module,getpid)->doc = "@brief Obtain the system process identifier.";
BIND_FUNC(module,strerror)->doc = "@brief Convert an integer error code to a string.\n"
"Attempts to change the working directory to @p newcwd. Raises @ref OSError on failure.");
KRK_DOC(BIND_FUNC(module,getpid),
"@brief Obtain the system process identifier.");
KRK_DOC(BIND_FUNC(module,strerror),
"@brief Convert an integer error code to a string.\n"
"@arguments errorno\n\n"
"Provides the string description for the error code specified by @p errorno.";
BIND_FUNC(module,abort)->doc = "@brief Abort the current process.\n\n"
"@bsnote{This will exit the interpreter without calling cleanup routines.}";
BIND_FUNC(module,remove)->doc = "@brief Delete a file.\n"
"Provides the string description for the error code specified by @p errorno.");
KRK_DOC(BIND_FUNC(module,abort),
"@brief Abort the current process.\n\n"
"@bsnote{This will exit the interpreter without calling cleanup routines.}");
KRK_DOC(BIND_FUNC(module,remove),
"@brief Delete a file.\n"
"@arguments path\n\n"
"Attempts to delete the file at @p path.";
BIND_FUNC(module,truncate)->doc = "@brief Resize a file.\n"
"Attempts to delete the file at @p path.");
KRK_DOC(BIND_FUNC(module,truncate),
"@brief Resize a file.\n"
"@arguments path,length\n\n"
"Attempts to resize the file at @p path to @p length bytes.";
BIND_FUNC(module,dup)->doc = "@brief Duplicate a file descriptor.\n"
"Attempts to resize the file at @p path to @p length bytes.");
KRK_DOC(BIND_FUNC(module,dup),
"@brief Duplicate a file descriptor.\n"
"@arguments fd\n\n"
"Returns a new file descriptor pointing to the same file as @p fd.";
BIND_FUNC(module,dup2)->doc = "@brief Duplicate a file descriptor.\n"
"Returns a new file descriptor pointing to the same file as @p fd.");
KRK_DOC(BIND_FUNC(module,dup2),
"@brief Duplicate a file descriptor.\n"
"@arguments oldfd,newfd\n\n"
"Like @ref dup but the new file descriptor is placed at @p newfd.\n";
BIND_FUNC(module,isatty)->doc = "@brief Determine if a file descriptor is a terminal.\n"
"Like @ref dup but the new file descriptor is placed at @p newfd.\n");
KRK_DOC(BIND_FUNC(module,isatty),
"@brief Determine if a file descriptor is a terminal.\n"
"@arguments fd\n\n"
"Returns a @ref bool indicating whether the open file descriptor @p fd refers to a terminal.";
BIND_FUNC(module,lseek)->doc = "@brief Seek an open file descriptor.\n"
"Returns a @ref bool indicating whether the open file descriptor @p fd refers to a terminal.");
KRK_DOC(BIND_FUNC(module,lseek),
"@brief Seek an open file descriptor.\n"
"@arguments fd,pos,how\n\n"
"Seeks the open file descriptor @p fd by @p pos bytes as specified in @p how. "
"Use the values @c SEEK_SET, @c SEEK_CUR, and @c SEEK_END for @p how.";
BIND_FUNC(module,open)->doc = "@brief Open a file.\n"
"Use the values @c SEEK_SET, @c SEEK_CUR, and @c SEEK_END for @p how.");
KRK_DOC(BIND_FUNC(module,open),
"@brief Open a file.\n"
"@arguments path,flags,mode=0o777\n\n"
"Opens the file at @p path with the specified @p flags and @p mode. Returns a file descriptor.\n\n"
"@bsnote{Not to be confused with <a class=\"el\" href=\"mod_fileio.html#open\">fileio.open</a>}";
BIND_FUNC(module,close)->doc = "@brief Close an open file descriptor.\n"
"@arguments fd";
BIND_FUNC(module,read)->doc = "@brief Read from an open file descriptor.\n"
"@bsnote{Not to be confused with <a class=\"el\" href=\"mod_fileio.html#open\">fileio.open</a>}");
KRK_DOC(BIND_FUNC(module,close),
"@brief Close an open file descriptor.\n"
"@arguments fd");
KRK_DOC(BIND_FUNC(module,read),
"@brief Read from an open file descriptor.\n"
"@arguments fd,n\n\n"
"Reads at most @p n bytes from the open file descriptor @p fd.";
BIND_FUNC(module,write)->doc = "@brief Write to an open file descriptor.\n"
"Reads at most @p n bytes from the open file descriptor @p fd.");
KRK_DOC(BIND_FUNC(module,write),
"@brief Write to an open file descriptor.\n"
"@arguments fd,data\n\n"
"Writes the @ref bytes object @p data to the open file descriptor @p fd.";
BIND_FUNC(module,mkdir)->doc = "@brief Create a directory.\n"
"Writes the @ref bytes object @p data to the open file descriptor @p fd.");
KRK_DOC(BIND_FUNC(module,mkdir),
"@brief Create a directory.\n"
"@arguments path,mode=0o777\n\n"
"Creates a directory at @p path.";
"Creates a directory at @p path.");
BIND_FUNC(module,execl)->doc = "@brief Replace the current process.\n"
KRK_DOC(BIND_FUNC(module,execl),
"@brief Replace the current process.\n"
"@arguments path,[args...]\n\n"
"The @c exec* family of functions replaces the calling process's image with a new one. "
"@c execl takes a @p path to a binary and an arbitrary number of @ref str arguments to "
"pass to the new executable.";
BIND_FUNC(module,execle)->doc = "@brief Replace the current process.\n"
"pass to the new executable.");
KRK_DOC(BIND_FUNC(module,execle),
"@brief Replace the current process.\n"
"@arguments path,[args...],env\n\n"
"The @c exec* family of functions replaces the calling process's image with a new one. "
"@c execle takes a @p path to a binary, an arbitrary number of @ref str arguments to "
"pass to the new executable, and @ref list of @c 'KEY=VALUE' pairs to set as the new "
"environment.";
BIND_FUNC(module,execlp)->doc = "@brief Replace the current process.\n"
"environment.");
KRK_DOC(BIND_FUNC(module,execlp),
"@brief Replace the current process.\n"
"@arguments filename,[args...]\n\n"
"The @c exec* family of functions replaces the calling process's image with a new one. "
"@c execlp takes a @p filename of a binary and an arbitrary number of @ref str arguments to "
"pass to the new executable. @p filename will be searched for in @c $PATH.";
BIND_FUNC(module,execv)->doc = "@brief Replace the current process.\n"
"pass to the new executable. @p filename will be searched for in @c $PATH.");
KRK_DOC(BIND_FUNC(module,execv),
"@brief Replace the current process.\n"
"@arguments path,args\n\n"
"The @c exec* family of functions replaces the calling process's image with a new one. "
"@c execv takes a @p path to a binary and a @ref list @p args of @ref str arguments to "
"pass to the new executable.";
BIND_FUNC(module,execvp)->doc = "@brief Replace the current process.\n"
"pass to the new executable.");
KRK_DOC(BIND_FUNC(module,execvp),
"@brief Replace the current process.\n"
"@arguments filename,args\n\n"
"The @c exec* family of functions replaces the calling process's image with a new one. "
"@c execvp takes a @p filename of a binary and a @ref list @p args of @ref str arguments to "
"pass to the new executable. @p filename will be searched for in @c $PATH.";
"pass to the new executable. @p filename will be searched for in @c $PATH.");
DO_INT(F_OK);
DO_INT(R_OK);
DO_INT(W_OK);
DO_INT(X_OK);
BIND_FUNC(module,access)->doc = "@brief Determine if a file can be accessed.\n"
KRK_DOC(BIND_FUNC(module,access),
"@brief Determine if a file can be accessed.\n"
"@arguments path,mask\n\n"
"Use the values @c F_OK, @c R_OK, @c W_OK, and @c X_OK to construct @p mask and check if the current "
"process has sufficient access rights to perform the requested operations on the file "
"at @p path.";
"at @p path.");
#ifndef _WIN32
BIND_FUNC(module,pipe)->doc = "@brief Create a pipe.\n\n"
"Creates a _pipe_, returning a two-tuple of file descriptors for the read and write ends respectively.";
BIND_FUNC(module,kill)->doc = "@brief Send a signal to a process.\n"
KRK_DOC(BIND_FUNC(module,pipe),
"@brief Create a pipe.\n\n"
"Creates a _pipe_, returning a two-tuple of file descriptors for the read and write ends respectively.");
KRK_DOC(BIND_FUNC(module,kill),
"@brief Send a signal to a process.\n"
"@arguments pid,signum\n\n"
"Send the signal @p signum to the process at @p pid.\n";
BIND_FUNC(module,fork)->doc = "@brief Fork the current process.\n\n"
"Returns the PID of the new child process in the original process and @c 0 in the child.";
BIND_FUNC(module,symlink)->doc = "@brief Create a symbolic link.\n"
"Send the signal @p signum to the process at @p pid.\n");
KRK_DOC(BIND_FUNC(module,fork),
"@brief Fork the current process.\n\n"
"Returns the PID of the new child process in the original process and @c 0 in the child.");
KRK_DOC(BIND_FUNC(module,symlink),
"@brief Create a symbolic link.\n"
"@arguments src,dst\n\n"
"Creates a symbolic link at @p src pointing to @p dst.";
BIND_FUNC(module,sync)->doc = "@brief Commit filesystem caches to disk.";
"Creates a symbolic link at @p src pointing to @p dst.");
KRK_DOC(BIND_FUNC(module,sync),
"@brief Commit filesystem caches to disk.");
BIND_FUNC(module,tcgetpgrp)->doc = "@brief Get the terminal foreground process group.\n"
KRK_DOC(BIND_FUNC(module,tcgetpgrp),
"@brief Get the terminal foreground process group.\n"
"@arguments fd\n\n"
"Return the PID representing the foreground process group of the terminal specified by the file descriptor @p fd.";
BIND_FUNC(module,tcsetpgrp)->doc = "@brief %Set the terminal foreground process group.\n"
"Return the PID representing the foreground process group of the terminal specified by the file descriptor @p fd.");
KRK_DOC(BIND_FUNC(module,tcsetpgrp),
"@brief %Set the terminal foreground process group.\n"
"@arguments fd,pgrp\n\n"
"%Set the PID representing the foreground process group of the terminal specified by the file descriptor @p fd to @p pgrp.";
BIND_FUNC(module,ttyname)->doc = "@brief Get the path to a terminal device.\n"
"%Set the PID representing the foreground process group of the terminal specified by the file descriptor @p fd to @p pgrp.");
KRK_DOC(BIND_FUNC(module,ttyname),
"@brief Get the path to a terminal device.\n"
"@arguments fd\n\n"
"Returns a @ref str representing the path to the terminal device provided by the file descriptor @p fd.";
"Returns a @ref str representing the path to the terminal device provided by the file descriptor @p fd.");
#endif
_loadEnviron(module);
@ -808,16 +839,17 @@ void _createAndBind_osMod(void) {
BIND_METHOD(stat_result,__repr__);
krk_finalizeClass(stat_result);
BIND_FUNC(module,stat)->doc = "@brief Get the status of a file\n"
KRK_DOC(BIND_FUNC(module,stat),
"@brief Get the status of a file\n"
"@arguments path\n\n"
"Runs the @c stat system call on @p path. Returns a @ref stat_result.\n";
"Runs the @c stat system call on @p path. Returns a @ref stat_result.\n");
module = krk_newInstance(vm.baseClasses->moduleClass);
krk_attachNamedObject(&vm.modules, "stat", (KrkObj*)module);
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("stat"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__",
(KrkObj*)S("@brief Functions to check results from @ref stat calls."));
KRK_DOC(module,
"@brief Functions to check results from @ref stat calls.");
BIND_FUNC(module,S_ISBLK);
BIND_FUNC(module,S_ISCHR);

View File

@ -206,38 +206,41 @@ void _createAndBind_threadsMod(void) {
krk_attachNamedObject(&vm.modules, "threading", (KrkObj*)threadsModule);
krk_attachNamedObject(&threadsModule->fields, "__name__", (KrkObj*)S("threading"));
krk_attachNamedValue(&threadsModule->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&threadsModule->fields, "__doc__",
(KrkObj*)S("Methods and classes for creating platform threads."));
KRK_DOC(threadsModule,
"@brief Methods and classes for creating platform threads.");
BIND_FUNC(threadsModule, current_thread)->doc = "@arguments \nReturns the @ref Thread object associated with the calling thread, if one exists.";
KRK_DOC(BIND_FUNC(threadsModule, current_thread),
"@brief Obtain a reference to the current thread.\n"
"@arguments \n\n"
"Returns the @ref Thread object associated with the calling thread, if one exists.");
krk_makeClass(threadsModule, &ThreadError, "ThreadError", vm.exceptions->baseException);
ThreadError->docstring = S(
KRK_DOC(ThreadError,
"Raised in various situations when an action on a thread is invalid."
);
krk_finalizeClass(ThreadError);
krk_makeClass(threadsModule, &Thread, "Thread", vm.baseClasses->objectClass);
Thread->docstring = S(
KRK_DOC(Thread,
"Base class for building threaded execution contexts.\n\n"
"The @ref Thread class should be subclassed and the subclass should implement a @c run method."
);
Thread->allocSize = sizeof(struct Thread);
BIND_METHOD(Thread,start)->doc = "Start the thread. A thread may only be started once.";
BIND_METHOD(Thread,join)->doc = "Join the thread. Does not return until the thread finishes.";
BIND_METHOD(Thread,is_alive)->doc = "Query the status of the thread.";
AS_NATIVE(BIND_PROP(Thread,tid)->method)->doc = "The platform-specific thread identifier, if available. Usually an integer.";
KRK_DOC(BIND_METHOD(Thread,start), "Start the thread. A thread may only be started once.");
KRK_DOC(BIND_METHOD(Thread,join), "Join the thread. Does not return until the thread finishes.");
KRK_DOC(BIND_METHOD(Thread,is_alive), "Query the status of the thread.");
KRK_DOC(AS_NATIVE(BIND_PROP(Thread,tid)->method), "The platform-specific thread identifier, if available. Usually an integer.");
krk_finalizeClass(Thread);
krk_makeClass(threadsModule, &Lock, "Lock", vm.baseClasses->objectClass);
Lock->docstring = S(
KRK_DOC(Lock,
"Represents an atomic mutex.\n\n"
"@ref Lock objects allow for exclusive access to a resource and can be used in a @c with block."
);
Lock->allocSize = sizeof(struct Lock);
BIND_METHOD(Lock,__init__)->doc = "Initialize a system mutex.";
BIND_METHOD(Lock,__enter__)->doc = "Acquire the lock.";
BIND_METHOD(Lock,__exit__)->doc = "Release the lock.";
KRK_DOC(BIND_METHOD(Lock,__init__), "Initialize a system mutex.");
KRK_DOC(BIND_METHOD(Lock,__enter__),"Acquire the lock.");
KRK_DOC(BIND_METHOD(Lock,__exit__), "Release the lock.");
BIND_METHOD(Lock,__repr__);
krk_finalizeClass(Lock);
}

View File

@ -38,15 +38,14 @@ void _createAndBind_timeMod(void) {
krk_attachNamedObject(&vm.modules, "time", (KrkObj*)module);
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("time"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__",
(KrkObj*)S("@brief Provides timekeeping functions."));
BIND_FUNC(module,sleep)->doc = "@brief Pause execution of the current thread.\n"
KRK_DOC(module, "@brief Provides timekeeping functions.");
KRK_DOC(BIND_FUNC(module,sleep), "@brief Pause execution of the current thread.\n"
"@arguments secs\n\n"
"Uses the system @c usleep() function to sleep for @p secs seconds, which may be a @ref float or @ref int. "
"The available precision is platform-dependent.";
BIND_FUNC(module,time)->doc = "@brief Return the elapsed seconds since the system epoch.\n\n"
"The available precision is platform-dependent.");
KRK_DOC(BIND_FUNC(module,time), "@brief Return the elapsed seconds since the system epoch.\n\n"
"Returns a @ref float representation of the number of seconds since the platform's epoch date. "
"On POSIX platforms, this is the number of seconds since 1 January 1970. "
"The precision of the return value is platform-dependent.";
"The precision of the return value is platform-dependent.");
}

View File

@ -37,10 +37,6 @@ static inline const char * _method_name(const char * func) {
#define ADD_BASE_CLASS(obj, name, baseClass) krk_makeClass(vm.builtins, &obj, name, baseClass)
#define BUILTIN_FUNCTION(name, func, docStr) do { \
krk_defineNative(&vm.builtins->fields, name, func)->doc = docStr; \
} while (0)
/* _method_name works for this, but let's skip the inlined function call where possible */
#define _function_name(f) (f+5)
@ -259,3 +255,39 @@ static inline KrkValue discardStringBuilder(struct StringBuilder * sb) {
} \
} while (0)
static inline void _setDoc_class(KrkClass * thing, const char * text, size_t size) {
thing->docstring = krk_copyString(text, size);
}
static inline void _setDoc_instance(KrkInstance * thing, const char * text, size_t size) {
krk_attachNamedObject(&thing->fields, "__doc__", (KrkObj*)krk_copyString(text, size));
}
static inline void _setDoc_native(KrkNative * thing, const char * text, size_t size) {
(void)size;
thing->doc = text;
}
/**
* @def KRK_DOC(thing,text)
* @brief Attach documentation to a thing of various types.
*
* Classes store their docstrings directly, rather than in their attribute tables.
* Instances use the attribute table and store strings with the name @c \__doc__.
* Native functions store direct C string pointers for documentation.
*
* This macro provides a generic interface for applying documentation strings to
* any of the above types, and handles not attaching documentation when built
* with KRK_NO_DOCUMENTATION.
*/
#ifdef KRK_NO_DOCUMENTATION
# define KRK_DOC(thing, text) (thing);
#else
# define KRK_DOC(thing, text) \
_Generic(&((thing)[0]), \
KrkClass*: _setDoc_class, \
KrkInstance*: _setDoc_instance, \
KrkNative*: _setDoc_native \
)(thing,text,sizeof(text)-1)
#endif
#define BUILTIN_FUNCTION(name, func, docStr) KRK_DOC(krk_defineNative(&vm.builtins->fields, name, func), docStr)

View File

@ -1201,30 +1201,36 @@ void krk_initVM(int flags) {
krk_attachNamedObject(&vm.modules, "kuroko", (KrkObj*)vm.system);
krk_attachNamedObject(&vm.system->fields, "__name__", (KrkObj*)S("kuroko"));
krk_attachNamedValue(&vm.system->fields, "__file__", NONE_VAL()); /* (built-in) */
krk_attachNamedObject(&vm.system->fields, "__doc__", (KrkObj*)S("System module."));
KRK_DOC(vm.system, "@brief System module.");
krk_attachNamedObject(&vm.system->fields, "version",
(KrkObj*)S(KRK_VERSION_MAJOR "." KRK_VERSION_MINOR "." KRK_VERSION_PATCH KRK_VERSION_EXTRA));
krk_attachNamedObject(&vm.system->fields, "buildenv", (KrkObj*)S(KRK_BUILD_COMPILER));
krk_attachNamedObject(&vm.system->fields, "builddate", (KrkObj*)S(KRK_BUILD_DATE));
krk_defineNative(&vm.system->fields, "getsizeof", krk_getsize)->doc = "Calculate the approximate size of an object in bytes.\n"
KRK_DOC(krk_defineNative(&vm.system->fields, "getsizeof", krk_getsize),
"@brief Calculate the approximate size of an object in bytes.\n"
"@arguments value\n\n"
"@param value Value to examine.";
krk_defineNative(&vm.system->fields, "set_clean_output", krk_setclean)->doc = "Disables terminal escapes in some output from the VM.\n"
"@param value Value to examine.");
KRK_DOC(krk_defineNative(&vm.system->fields, "set_clean_output", krk_setclean),
"@brief Disables terminal escapes in some output from the VM.\n"
"@arguments clean=True\n\n"
"@param clean Whether to remove escapes.";
krk_defineNative(&vm.system->fields, "set_tracing", krk_set_tracing)->doc = "Toggle debugging modes.\n"
"@param clean Whether to remove escapes.");
KRK_DOC(krk_defineNative(&vm.system->fields, "set_tracing", krk_set_tracing),
"@brief Toggle debugging modes.\n"
"@arguments tracing=None,disassembly=None,scantracing=None,stressgc=None\n\n"
"Enables or disables tracing options for the current thread.\n\n"
"@param tracing Enables instruction tracing.\n"
"@param disassembly Prints bytecode disassembly after compilation.\n"
"@param scantracing Prints debug output from the token scanner during compilation.\n"
"@param stressgc Forces a garbage collection cycle on each heap allocation.";
krk_defineNative(&vm.system->fields, "importmodule", krk_import_wrapper)->doc = "Import a module by string name\n"
"@param stressgc Forces a garbage collection cycle on each heap allocation.");
KRK_DOC(krk_defineNative(&vm.system->fields, "importmodule", krk_import_wrapper),
"@brief Import a module by string name\n"
"@arguments module\n\n"
"Imports the dot-separated module @p module as if it were imported by the @c import statement and returns the resulting module object.\n\n"
"@param module A string with a dot-separated package or module name";
krk_defineNative(&vm.system->fields, "modules", krk_module_list)->doc = "Get the list of valid names from the module table";
krk_defineNative(&vm.system->fields, "unload", krk_unload)->doc = "Removes a module from the module table. It is not necessarily garbage collected if other references to it exist.";
"@param module A string with a dot-separated package or module name");
KRK_DOC(krk_defineNative(&vm.system->fields, "modules", krk_module_list),
"Get the list of valid names from the module table");
KRK_DOC(krk_defineNative(&vm.system->fields, "unload", krk_unload),
"Removes a module from the module table. It is not necessarily garbage collected if other references to it exist.");
krk_attachNamedObject(&vm.system->fields, "module", (KrkObj*)vm.baseClasses->moduleClass);
krk_attachNamedObject(&vm.system->fields, "path_sep", (KrkObj*)S(PATH_SEP));
KrkValue module_paths = krk_list_of(0,NULL,0);

View File

@ -370,6 +370,16 @@ extern KrkValue krk_pop(void);
*/
extern KrkValue krk_peek(int distance);
/**
* @brief Swap the top of the stack of the value @p distance slots down.
*
* Exchanges the values at the top of the stack and @p distance slots from the top
* without removing or shuffling anything in between.
*
* @param distance How from down from the top of the stack to swap (0 = the top)
*/
extern void krk_swap(int distance);
/**
* @brief Get the name of the type of a value.
* @memberof KrkValue