Thursday, August 7, 2025

Autodoc

The opposite of pseudocode is autodoc. If pseudocode is about generating code from a text description, then autodoc is about generating a text description from code. We shadow the usual Common Lisp defining symbols that take docstrings, such as defun, defgeneric, defvar, etc. and check if the docstring was supplied. If so, it is used as is, but if the docstring is missing, we ask the LLM to generate one for us. Your code becomes self-documenting in the truest sense of the word.

I have added autodoc as an adjunct to the pseudo system. It uses the same LLM client (at the moment Gemini) but the system instructions are tailored to generate docstrings. Here are some examples of source code and the generated docstrings:

(defclass 3d-point ()
  ((x :initarg :x :initform 0)
   (y :initarg :y :initform 0)
   (z :initarg :z :initform 0)))

;;; Generated docstring:
"A class representing a point in 3D space with x, y, and z coordinates."

(defconstant +the-ultimate-answer+ 42)

;;; Generated docstring:
"A constant representing the ultimate answer to life, the universe, and everything."

(defgeneric quux (a b)
  (:method ((a int) (b int))
    (declare (ignore a b))
    0)
  (:method ((a string) (b string))
    (declare (ignore a b))
    "Hello, world!"))

;;; Generated docstring:
"A generic function that takes two arguments of type int or string.

The int method returns 0, and the string method returns 'Hello, world!'."

(defmacro bar (a b)
  `(foo ,a ,b))

;;; Generated docstring:
"A macro that expands to a call to the function foo with arguments a and b."

(defparameter *screen-width* 640)

;;; Generated docstring:
"A global variable representing the width of the screen in pixels."  

(defstruct point
  (x 0)
  (y 0))

;;; Generated docstring:
"A structure representing a point in 2D space with x and y coordinates."

(defun foo (a b)
  (+ a b))

;;; Generated docstring:
"A function that takes two arguments a and b and returns their sum."

(defvar *current-foo* nil)

;;; Generated docstring:
"A global variable that holds the current value of foo, initialized to nil."

As you can see, the generated docstrings aren't bad. They describe the purpose of the class, constant, generic function, macro, global variable, and structure. The docstrings are not perfect, but they are better than nothing, which is what you start with.

No comments: