Write a bunch more docs

This commit is contained in:
K. Lange 2021-02-20 20:44:07 +09:00
parent c5b04d55b1
commit a5ff538dc1
10 changed files with 287 additions and 99 deletions

View File

@ -32,6 +32,7 @@ ALIASES += methodstart{4}="\anchor \1 \htmlonly<\3 class=\"memtitle \4\"><span c
ALIASES += methodstart{5}="\anchor \1 \htmlonly<\3 class=\"memtitle \4\"><span class=\"permalink\"><a href=\"#\1\">_</a></span>\2</\3><div class=\"memitem\"><div class=\"memproto\">\5</div><div class=\"memdoc\">\endhtmlonly"
ALIASES += methodend="\htmlonly</div></div>\endhtmlonly"
ALIASES += bsnote{1}="\htmlonly<div class=\"alert alert-warning\">\endhtmlonly\1\htmlonly</div>\endhtmlonly"
ALIASES += bsnote{2}="\htmlonly<div class=\"alert alert-\1\">\endhtmlonly\2\htmlonly</div>\endhtmlonly"
ALIASES += modulelist{1}="\htmlonly<div class=\"directory\"><table class=\"directory\">\endhtmlonly\1\htmlonly</table></div>\endhtmlonly"
ALIASES += krkmodule{2}="\htmlonly<tr class=\"autoalternate\"><td class=\"entry\"><span style\"width:16px;display:inline-block;\">&nbsp;</span><span class=\"icona\"><span class=\"icon\">M</span></span>\endhtmlonly@ref \1\htmlonly</td><td class=\"desc\">\endhtmlonly\2\htmlonly</td</tr>\endhtmlonly"

View File

@ -1,8 +1,11 @@
"""
JSON parser
@brief JSON parser
Provides methods for parsing the JSON data interchange format.
"""
def loads(s):
'''@brief Parse @p s as a JSON string.'''
let i = 0
let value # okay dumb scoping thing, but we'll assign this to _value later...
def peek():

View File

@ -368,6 +368,22 @@ static KrkValue _property_doc(int argc, KrkValue argv[], int hasKw) {
return NONE_VAL();
}
static KrkValue _property_name(int argc, KrkValue argv[], int hasKw) {
if (argc != 1 || !IS_PROPERTY(argv[0])) return krk_runtimeError(vm.exceptions->typeError, "?");
KrkValue method = AS_PROPERTY(argv[0])->method;
if (IS_NATIVE(method) && AS_NATIVE(method)->name) {
return OBJECT_VAL(krk_copyString(AS_NATIVE(method)->name, strlen(AS_NATIVE(method)->name)));
} else if (IS_CLOSURE(method)) {
return OBJECT_VAL(AS_CLOSURE(method)->function->name);
}
return NONE_VAL();
}
static KrkValue _property_method(int argc, KrkValue argv[], int hasKw) {
if (argc != 1 || !IS_PROPERTY(argv[0])) return krk_runtimeError(vm.exceptions->typeError, "?");
return AS_PROPERTY(argv[0])->method;
}
_noexport
void _createAndBind_builtins(void) {
vm.baseClasses->objectClass = krk_newClass(S("object"), NULL);
@ -402,6 +418,8 @@ void _createAndBind_builtins(void) {
krk_makeClass(vm.builtins, &vm.baseClasses->propertyClass, "Property", vm.baseClasses->objectClass);
krk_defineNative(&vm.baseClasses->propertyClass->methods, ".__repr__", _property_repr);
krk_defineNative(&vm.baseClasses->propertyClass->methods, ":__doc__", _property_doc);
krk_defineNative(&vm.baseClasses->propertyClass->methods, ":__name__", _property_name);
krk_defineNative(&vm.baseClasses->propertyClass->methods, ":__method__", _property_method);
krk_finalizeClass(vm.baseClasses->propertyClass);
krk_makeClass(vm.builtins, &Helper, "Helper", vm.baseClasses->objectClass);

View File

@ -206,7 +206,12 @@ KRK_FUNC(dis,{
krk_runtimeError(vm.exceptions->typeError, "Can not disassemble built-in method of '%s'", krk_typeName(AS_BOUND_METHOD(argv[0])->receiver));
}
} else if (IS_CLASS(argv[0])) {
krk_runtimeError(vm.exceptions->typeError, "todo: class disassembly");
KrkValue code;
if (krk_tableGet(&AS_CLASS(argv[0])->fields, OBJECT_VAL(S("__func__")), &code) && IS_CLOSURE(code)) {
KrkFunction * func = AS_CLOSURE(code)->function;
krk_disassembleCodeObject(stdout, func, AS_CLASS(argv[0])->name->chars);
}
/* TODO Methods! */
} else {
krk_runtimeError(vm.exceptions->typeError, "Don't know how to disassemble '%s'", krk_typeName(argv[0]));
}
@ -221,6 +226,9 @@ void _createAndBind_disMod(void) {
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("dis"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__",
(KrkObj*)S("Provides tools for disassembling bytecode."));
BIND_FUNC(module, dis);
(KrkObj*)S("@brief Provides tools for disassembling bytecode."));
BIND_FUNC(module, dis)->doc = "@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.";
}

View File

@ -483,29 +483,45 @@ 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("Provides access to C <stdio> buffered file I/O functions."));
krk_attachNamedObject(&module->fields, "__doc__", (KrkObj*)S(
"@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."
);
File->allocSize = sizeof(struct File);
File->_ongcsweep = _file_sweep;
/* Add methods to it... */
BIND_METHOD(File,read);
BIND_METHOD(File,readline);
BIND_METHOD(File,readlines);
BIND_METHOD(File,write);
BIND_METHOD(File,close);
BIND_METHOD(File,flush);
BIND_METHOD(File,read)->doc = "@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"
"@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.";
BIND_METHOD(File,__str__);
BIND_METHOD(File,__init__);
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.}";
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(
"Equivalent to @ref File but using @ref bytes instead of string @ref str."
);
BIND_METHOD(BinaryFile,read);
BIND_METHOD(BinaryFile,readline);
BIND_METHOD(BinaryFile,readlines);
@ -513,14 +529,18 @@ void _createAndBind_fileioMod(void) {
krk_finalizeClass(BinaryFile);
krk_makeClass(module, &Directory, "Directory", vm.baseClasses->objectClass);
Directory->docstring = S(
"Represents an opened file system directory."
);
Directory->allocSize = sizeof(struct Directory);
Directory->_ongcsweep = _dir_sweep;
BIND_METHOD(Directory,__repr__);
BIND_METHOD(Directory,__iter__);
BIND_METHOD(Directory,__call__);
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.";
BIND_METHOD(Directory,__enter__);
BIND_METHOD(Directory,__exit__);
BIND_METHOD(Directory,close);
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_finalizeClass(Directory);
/* Make an instance for stdout, stderr, and stdin */
@ -529,6 +549,13 @@ void _createAndBind_fileioMod(void) {
makeFileInstance(module, "stderr", stderr);
/* Our base will be the open method */
BIND_FUNC(module,open);
BIND_FUNC(module,opendir);
BIND_FUNC(module,open)->doc = "@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"
"@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.";
}

View File

@ -338,10 +338,15 @@ 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_defineNative(&gcModule->fields, "collect", krk_collectGarbage_wrapper);
krk_defineNative(&gcModule->fields, "generations", krk_generations);
krk_defineNative(&gcModule->fields, "pause", _gc_pause);
krk_defineNative(&gcModule->fields, "resume", _gc_resume);
krk_attachNamedObject(&gcModule->fields, "__doc__",
(KrkObj*)S("Namespace containing methods for controlling the garbge collector."));
(KrkObj*)S("@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 ";
}

View File

@ -158,55 +158,89 @@ KrkValue krk_module_onload_math(void) {
krk_attachNamedObject(&module->fields, "__doc__",(KrkObj*)
S("Provides access to floating-point mathematical functions from the system `libm`."));
bind(ceil)->doc = "Returns the smallest integer value not less than the input.";
bind(floor)->doc = "Returns the largest integer value not greater than the input.";
bind(ceil)->doc = "Returns the smallest integer value not less than the input.\n"
"@arguments x";
bind(floor)->doc = "Returns the largest integer value not greater than the input.\n"
"@arguments x";
#ifdef _math_trunc
bind(trunc)->doc = "Rounds the input towards zero to an integer.";
bind(trunc)->doc = "Rounds the input towards zero to an integer.\n"
"@arguments x";
#endif
bind(exp)->doc = "Returns the base-e exponentiation of the input.";
bind(exp)->doc = "Returns the base-e exponentiation of the input.\n"
"@arguments x";
#ifdef _math_expm1
bind(expm1)->doc = "Equivalent to `exp(x) - 1`.";
bind(expm1)->doc = "Equivalent to `exp(x) - 1`.\n"
"@arguments x";
#endif
bind(log2)->doc = "Calculates the base-2 logarithm of the input.";
bind(log10)->doc = "Calculates the base-10 logarithm of the input.";
bind(sqrt)->doc = "Calculates the square root of the input.";
bind(acos)->doc = "Calculates the arc-cosine of the radian input.";
bind(asin)->doc = "Calculates the arc-sine of the radian input.";
bind(atan)->doc = "Calculates the arc-tangent of the radian input.";
bind(cos)->doc = "Calculates the cosine of the radian input.";
bind(sin)->doc = "Calculates the sine of the radian input.";
bind(tan)->doc = "Calculates the tangent of the radian input.";
bind(log2)->doc = "Calculates the base-2 logarithm of the input.\n"
"@arguments x";
bind(log10)->doc = "Calculates the base-10 logarithm of the input.\n"
"@arguments x";
bind(sqrt)->doc = "Calculates the square root of the input.\n"
"@arguments x";
bind(acos)->doc = "Calculates the arc-cosine of the radian input.\n"
"@arguments x";
bind(asin)->doc = "Calculates the arc-sine of the radian input.\n"
"@arguments x";
bind(atan)->doc = "Calculates the arc-tangent of the radian input.\n"
"@arguments x";
bind(cos)->doc = "Calculates the cosine of the radian input.\n"
"@arguments x";
bind(sin)->doc = "Calculates the sine of the radian input.\n"
"@arguments x";
bind(tan)->doc = "Calculates the tangent of the radian input.\n"
"@arguments x";
#ifdef _math_acosh
bind(acosh)->doc = "Calculates the inverse hyperbolic cosine of the input.";
bind(asinh)->doc = "Calculates the inverse hyperbolic sine of the input.";
bind(atanh)->doc = "Calculates the inverse hyperbolic tangent of the input.";
bind(acosh)->doc = "Calculates the inverse hyperbolic cosine of the input.\n"
"@arguments x";
bind(asinh)->doc = "Calculates the inverse hyperbolic sine of the input.\n"
"@arguments x";
bind(atanh)->doc = "Calculates the inverse hyperbolic tangent of the input.\n"
"@arguments x";
#endif
bind(cosh)->doc = "Calculates the hyperbolic cosine of the input.";
bind(sinh)->doc = "Calculates the hyperbolic sine of the input.";
bind(tanh)->doc = "Calculates the hyperbolic tangent of the input.";
bind(cosh)->doc = "Calculates the hyperbolic cosine of the input.\n"
"@arguments x";
bind(sinh)->doc = "Calculates the hyperbolic sine of the input.\n"
"@arguments x";
bind(tanh)->doc = "Calculates the hyperbolic tangent of the input.\n"
"@arguments x";
#ifdef _math_erf
bind(erf)->doc = "Calculates the error function of the input.";
bind(erfc)->doc = "Calculates the complementary error function of the input.";
bind(erf)->doc = "Calculates the error function of the input.\n"
"@arguments x";
bind(erfc)->doc = "Calculates the complementary error function of the input.\n"
"@arguments x";
#endif
#ifdef _math_gamma
bind(gamma)->doc = "Calculates the gamma of the input.";
bind(lgamma)->doc = "Calculates the log gamma of the input.";
bind(gamma)->doc = "Calculates the gamma of the input.\n"
"@arguments x";
bind(lgamma)->doc = "Calculates the log gamma of the input.\n"
"@arguments x";
#endif
#ifdef _math_copysign
bind(copysign)->doc = "Copies the sign from one value to another.";
bind(copysign)->doc = "Copies the sign from @p x to @p y\n"
"@arguments x,y";
#endif
bind(fmod)->doc = "Returns the floating point remainder of the first input over the second.";
bind(fmod)->doc = "Returns the floating point remainder of @p x over @p y\n"
"@arguments x,y";
#ifdef _math_remainder
bind(remainder)->doc = "Somehow different from `fmod`.";
#endif
bind(log1p)->doc = "Equivalent to `log(x) + 1`";
bind(pow)->doc = "Calculates `x^p`";
bind(atan2)->doc = "Calculates the arctangent of `x` and `y`";
bind(frexp)->doc = "Converts a floating point input to a fractional and integer component pair, returned as a tuple.";
bind(log1p)->doc = "Equivalent to `log(x) + 1`\n"
"@arguments x";
bind(pow)->doc = "Calculates `x^p`\n"
"@arguments x,p";
bind(atan2)->doc = "Calculates the arctangent of `x` and `y`\n"
"@arguments x,y";
bind(frexp)->doc = "Converts a floating point input to a fractional and integer component pair, returned as a tuple.\n"
"@arguments x\n"
"@returns @ref tuple of two @ref int";
#ifdef isfinite
bind(isfinite)->doc = "Determines if the input is finite.";
bind(isinf)->doc = "Determines if the input is infinite.";
bind(isnan)->doc = "Determines if the input is the floating point `NaN`.";
bind(isfinite)->doc = "Determines if the input is finite.\n"
"@arguments x\n";
bind(isinf)->doc = "Determines if the input is infinite.\n"
"@arguments x\n";
bind(isnan)->doc = "Determines if the input is the floating point `NaN`.\n"
"@arguments x\n";
#endif
/**

145
src/os.c
View File

@ -355,7 +355,11 @@ KRK_FUNC(sync,{
KRK_FUNC(kill,{
FUNCTION_TAKES_EXACTLY(2);
return INTEGER_VAL(kill(AS_INTEGER(argv[0]), AS_INTEGER(argv[1])));
int result = kill(AS_INTEGER(argv[0]), AS_INTEGER(argv[1]));
if (result == -1) {
return krk_runtimeError(OSError, strerror(errno));
}
return INTEGER_VAL(result);
})
KRK_FUNC(fork,{
@ -454,7 +458,7 @@ KRK_FUNC(execle,{
})
KRK_FUNC(execv,{
FUNCTION_TAKES_AT_LEAST(1);
FUNCTION_TAKES_EXACTLY(2);
CHECK_ARG(0,str,KrkString*,filename);
CHECK_ARG(1,list,KrkList*,args);
char ** argp;
@ -467,7 +471,7 @@ KRK_FUNC(execv,{
})
KRK_FUNC(execvp,{
FUNCTION_TAKES_AT_LEAST(1);
FUNCTION_TAKES_EXACTLY(2);
CHECK_ARG(0,str,KrkString*,path);
CHECK_ARG(1,list,KrkList*,args);
char ** argp;
@ -486,7 +490,7 @@ void _createAndBind_osMod(void) {
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("os"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__",
(KrkObj*)S("Provides access to low-level system operations."));
(KrkObj*)S("@brief Provides access to low-level system operations."));
#ifdef _WIN32
krk_attachNamedObject(&module->fields, "name", (KrkObj*)S("nt"));
@ -546,51 +550,120 @@ void _createAndBind_osMod(void) {
#endif
krk_makeClass(module, &OSError, "OSError", vm.exceptions->baseException);
OSError->docstring = S(
"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);
BIND_FUNC(module,system);
BIND_FUNC(module,getcwd);
BIND_FUNC(module,chdir);
BIND_FUNC(module,getpid);
BIND_FUNC(module,strerror);
BIND_FUNC(module,abort);
BIND_FUNC(module,remove);
BIND_FUNC(module,truncate);
BIND_FUNC(module,dup);
BIND_FUNC(module,dup2);
BIND_FUNC(module,isatty);
BIND_FUNC(module,lseek);
BIND_FUNC(module,open);
BIND_FUNC(module,close);
BIND_FUNC(module,read);
BIND_FUNC(module,write);
BIND_FUNC(module,uname)->doc = "@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"
"@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"
"@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"
"@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"
"@arguments path\n\n"
"Attempts to delete the file at @p path.";
BIND_FUNC(module,truncate)->doc = "@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"
"@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"
"@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"
"@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"
"@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"
"@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"
"@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"
"@arguments fd,data\n\n"
"Writes the @ref bytes object @p data to the open file descriptor @p fd.";
BIND_FUNC(module,execl);
BIND_FUNC(module,execle);
BIND_FUNC(module,execlp);
BIND_FUNC(module,execv);
BIND_FUNC(module,execvp);
BIND_FUNC(module,execl)->doc = "@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"
"@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"
"@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"
"@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"
"@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.";
DO_INT(F_OK);
DO_INT(R_OK);
DO_INT(W_OK);
DO_INT(X_OK);
BIND_FUNC(module,access);
BIND_FUNC(module,access)->doc = "@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.";
#ifndef _WIN32
BIND_FUNC(module,pipe);
BIND_FUNC(module,kill);
BIND_FUNC(module,fork);
BIND_FUNC(module,symlink);
BIND_FUNC(module,sync);
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"
"@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"
"@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.";
BIND_FUNC(module,tcgetpgrp);
BIND_FUNC(module,tcsetpgrp);
BIND_FUNC(module,ttyname);
BIND_FUNC(module,tcgetpgrp)->doc = "@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"
"@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"
"@arguments fd\n\n"
"Returns a @ref str representing the path to the terminal device provided by the file descriptor @p fd.";
#endif
_loadEnviron(module);
}

View File

@ -39,8 +39,14 @@ void _createAndBind_timeMod(void) {
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("time"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__",
(KrkObj*)S("Provides timekeeping functions."));
BIND_FUNC(module,sleep);
BIND_FUNC(module,time);
(KrkObj*)S("@brief Provides timekeeping functions."));
BIND_FUNC(module,sleep)->doc = "@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"
"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.";
}

View File

@ -87,10 +87,12 @@ let modules = [
let docString = {}
def fixup(mod):
'''Escapes some characters in module names to make better page IDs.'''
if mod.startswith('__'): return '\\' + mod
return mod
def truncateString(s):
'''If @p s is longer than 100 characters, truncate it with an ellipsis.'''
s = s.strip()
if '\n' in s:
s = s.split('\n')[0]
@ -101,14 +103,15 @@ def truncateString(s):
return short
def fixupDoc(doc):
'''Cleans up docstring contents for display in the module list.'''
for line in doc.split('\n'):
if line.strip().startswith('@brief '):
doc = line.strip().replace('@brief ', '', 1).strip()
realPrint('derp:',doc)
break
return doc.replace(',','\\,').replace('<','&lt;').replace('>','&gt;')
def isExceptionType(cls):
'''Determines if @p cls is an @c Exception type by examining its superclass chain.'''
if cls == Exception: return True
let checked = []
while '__base__' in dir(cls) and cls.__base__ not in checked:
@ -118,6 +121,7 @@ def isExceptionType(cls):
return False
def getArgs(func):
'''Extract the arguments of either a managed (@c func.__args__) or native (from an `@arguments` docstring) function.'''
if func.__file__ == '<builtin>':
if '__doc__' in dir(func) and func.__doc__ and '@arguments ' in func.__doc__:
let before, after = func.__doc__.split('@arguments ',1)
@ -127,6 +131,7 @@ def getArgs(func):
return '\\,'.join([x for x in func.__args__ if x != 'self'])
def functionDoc(func):
'''Extracts the docstring from a function and removes markup that Doxygen will choke on.'''
let doc = func.__doc__ if ('__doc__' in dir(func) and func.__doc__) else ''
if '@arguments ' in doc:
doc = '\n'.join([x for x in doc.split('\n') if '@arguments' not in x])
@ -152,13 +157,13 @@ def processModules(modules):
else:
docString[modulepath] = 'TODO'
def outputFunction(name, func, prefix=None):
def outputFunction(name, func, prefix=None, paren=True):
# Build the function signature
let _args = getArgs(func)
let args = ('<i>' + _args + '</i>') if _args else ''
let body = functionDoc(func)
let maybePrefix = prefix + '.' if prefix else ''
let formatted = maybePrefix + '<b>' + name + '</b>(' + args + ')'
let formatted = maybePrefix + '<b>' + name + '</b>' + (f'({args})' if paren else args)
let maybeDetail = ''
if prefix and name in specialMethods:
maybeDetail = ',' + formatted
@ -183,6 +188,7 @@ def processModules(modules):
print('<p>' + cls.__doc__ + '</p>')
let seen = []
let methods = []
let properties = []
for member in dir(cls):
if member in blacklistedMethods: continue
realPrint(cls,member)
@ -195,10 +201,17 @@ def processModules(modules):
if isinstance(obj, function) and member not in seen:
seen.append(member)
methods.append(Pair(member,obj))
else if isinstance(obj, Property) and member not in seen:
seen.append(member)
properties.append(Pair(member,obj.__method__))
if methods:
methods.sort()
for methodName, method in methods:
outputFunction(methodName, method, prefix=name)
if properties:
properties.sort()
for propName, method in properties:
outputFunction(propName, method, prefix=name, paren=False)
print('\\methodend')
def dumpModule(name, thing):