diff --git a/docs/Doxyfile b/docs/Doxyfile index 6b644d2..f1a8664 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -28,7 +28,8 @@ HTML_COLORSTYLE_SAT = 200 # Doxygen will enable latex by default, so let's turn that off. GENERATE_LATEX = NO -ALIASES += methodstart{4}="\htmlonly<\3 class=\"memtitle \4\" id=\"\1\">_\2
\endhtmlonly" +ALIASES += methodstart{4}="\anchor \1 \htmlonly<\3 class=\"memtitle \4\">_\2
\endhtmlonly" +ALIASES += methodstart{5}="\anchor \1 \htmlonly<\3 class=\"memtitle \4\">_\2
\5
\endhtmlonly" ALIASES += methodend="\htmlonly
\endhtmlonly" ALIASES += bsnote{1}="\htmlonly
\endhtmlonly\1\htmlonly
\endhtmlonly" diff --git a/src/builtins.c b/src/builtins.c index 072acc8..209c51c 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -405,13 +405,16 @@ void _createAndBind_builtins(void) { krk_finalizeClass(vm.baseClasses->propertyClass); krk_makeClass(vm.builtins, &Helper, "Helper", vm.baseClasses->objectClass); - BIND_METHOD(Helper,__call__); + 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."; 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); - BIND_METHOD(LicenseReader,__call__); + 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."; BIND_METHOD(LicenseReader,__repr__); krk_finalizeClass(LicenseReader); krk_attachNamedObject(&vm.builtins->fields, "license", (KrkObj*)krk_newInstance(LicenseReader)); diff --git a/src/obj_bytes.c b/src/obj_bytes.c index e5e6069..fb7cbe6 100644 --- a/src/obj_bytes.c +++ b/src/obj_bytes.c @@ -215,7 +215,10 @@ _corrupt: _noexport void _createAndBind_bytesClass(void) { KrkClass * bytes = ADD_BASE_CLASS(vm.baseClasses->bytesClass, "bytes", vm.baseClasses->objectClass); - BIND_METHOD(bytes,__init__); + BIND_METHOD(bytes,__init__)->doc = + "@arguments iter=None\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."; BIND_METHOD(bytes,__repr__); BIND_METHOD(bytes,__len__); BIND_METHOD(bytes,__contains__); diff --git a/src/threads.c b/src/threads.c index f460f6b..3eea1e8 100644 --- a/src/threads.c +++ b/src/threads.c @@ -207,26 +207,37 @@ void _createAndBind_threadsMod(void) { krk_attachNamedObject(&threadsModule->fields, "__name__", (KrkObj*)S("threading")); krk_attachNamedValue(&threadsModule->fields, "__file__", NONE_VAL()); krk_attachNamedObject(&threadsModule->fields, "__doc__", - (KrkObj*)S("Methods for dealing with threads.")); + (KrkObj*)S("Methods and classes for creating platform threads.")); - BIND_FUNC(threadsModule, current_thread); + BIND_FUNC(threadsModule, current_thread)->doc = "@arguments \nReturns the @ref Thread object associated with the calling thread, if one exists."; krk_makeClass(threadsModule, &ThreadError, "ThreadError", vm.exceptions->baseException); + ThreadError->docstring = S( + "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( + "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); - BIND_METHOD(Thread,join); - BIND_METHOD(Thread,is_alive); - BIND_PROP(Thread,tid); + 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_finalizeClass(Thread); krk_makeClass(threadsModule, &Lock, "Lock", vm.baseClasses->objectClass); + Lock->docstring = S( + "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__); - BIND_METHOD(Lock,__enter__); - BIND_METHOD(Lock,__exit__); + 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."; BIND_METHOD(Lock,__repr__); krk_finalizeClass(Lock); } diff --git a/tools/gendoc.krk b/tools/gendoc.krk index 76d5564..ea70568 100755 --- a/tools/gendoc.krk +++ b/tools/gendoc.krk @@ -23,9 +23,17 @@ let blacklistedMethods = [ ] let specialMethods = { - '__contains__': lambda cls, args: f'{args} in {cls}', - '__init__': lambda cls, args: f'{cls}({args})', - '__get__': lambda cls, args: f'{cls}[{args}]', + '__contains__': lambda cls, args: f'{args or "needle"} in {cls}', + '__init__': lambda cls, args: f'let x = {cls}({args})', + '__get__': lambda cls, args: f'{cls}[{args or "key"}]', + '__delitem__': lambda cls, args: f'del {cls}[{args or "key"}]', + '__add__': lambda cls, args: f'{cls} + {args or "other"}', + '__len__': lambda cls, args: f'len({cls})', + '__call__': lambda cls, args: f'{cls}({args})', + '__iter__': lambda cls, args: f'for x in {cls}:', + '__eq__': lambda cls, args: f'{cls} == {args or "other"}', + '__lt__': lambda cls, args: f'{cls} < {args or "other"}', + '__gt__': lambda cls, args: f'{cls} > {args or "other"}', } class Pair(): @@ -33,12 +41,19 @@ class Pair(): def __init__(left,right): self.left = left self.right = right + def __eq__(other): + if not isinstance(other,Pair): return False + return self.left == other.left def __lt__(other): - if self.left == '__init__': return True + if self.left == '__init__' and other.left != '__init__': return True + if other.left == '__init__': return False return self.left < other.left def __gt__(other): if self.left == '__init__': return False + if other.left == '__init__': return True return self.left > other.left + def __repr__(): + return f'Pair({self.left!r},{self.right!r})' def __iter__(): let x = -1 def _(): @@ -108,7 +123,7 @@ def getArgs(func): let before, after = func.__doc__.split('@arguments ',1) let line, rest = after.split('\n',1) if '\n' in after else (after,None) return line.strip().replace(',','\\,') - return '...' + return '' return '\\,'.join([x for x in func.__args__ if x != 'self']) def functionDoc(func): @@ -139,15 +154,16 @@ def processModules(modules): def outputFunction(name, func, prefix=None): # Build the function signature - let args = '' + getArgs(func) + '' + let _args = getArgs(func) + let args = ('' + _args + '') if _args else '' let body = functionDoc(func) - let formatted let maybePrefix = prefix + '.' if prefix else '' + let formatted = maybePrefix + '' + name + '(' + args + ')' + let maybeDetail = '' if prefix and name in specialMethods: + maybeDetail = ',' + formatted formatted = specialMethods[name](prefix,args) - else: - formatted = maybePrefix + '' + name + '(' + args + ')' - print('\\methodstart{' + maybePrefix + name + ',' + formatted + ',' + ('h4,methodDef' if prefix else 'h3,functionDef') + '}') + print('\\methodstart{' + (maybePrefix + name).replace('.','_') + ',' + formatted + ',' + ('h4,methodDef' if prefix else 'h3,functionDef') + maybeDetail + '}') if body: print(body) print('\n\\methodend') print('')