Aquefir

Massively multipurpose software.

Slick documentation format

Penned on the 2nd day of August, 2020. It was a Sunday.

This is an ASCII-compatible grammar for drafting and collating file-folder hierarchies in a single text file. The idea is simple: give structure to code documentation using a written pseudo-filesystem while retaining editability in text editors. Intelligent editors can take advantage of this structure to match documentation to the corresponding source, displaying it easily. The extension for these files is ‘.sli’.

The file format

Actual SLI files are arbitrary, and have no direct correspondence with any particular construct in the source code or the project repository. ADP 1 provides a protocol for placing SLI files inside the doc/ subfolder of a repository.

Similar to tarballs, SLI docs consist of a series of records. Each line that does not begin with a hard tab (\t) denotes the head of a record. Hard tabs prefix every line that contiguously forms a record’s contents. Customarily, a single tab is used for this, but the number of tabs does not matter. A record ends at the beginning of another record or at the EOF. The format of the record head is simply a relative pathname separated with forward slashes (/). A good convention is to start record paths with the project name.

For maximum compatibility with computers and human fingers, SLI files are restricted to be ASCII only. Files should end with a single newline, per Unix custom. Additionally, hard tab characters and newlines are insignificant to the composed output; both are are part of the grammar, and newlines may be inserted wherever necessary to display well on older terminals. However, through an exhaustive list of escape sequences in Appendix A, full output of Unicode in composition is supported.

Filetypes and expressions

File extensions are used to denote the ‘kind’ of expression being documented in a given file. These are the supported kinds of expressions:

For complex expressions that often include nontrivial children, such as classes, their contents can be placed in a subfolder of the same basename as the .class file sans the extension. So, foo.class’s members could be foo/bar.sub and foo/baz.var, for example. For the special constructor and destructor methods in classes, use foo/@.sub and foo/~@.sub, respectively. Getter methods are enclosed in angle brackets (e.g. foo/<myvar>.sub), while setter methods are enclosed the same but inverted (foo/>myvar<.sub). Operator overloads use the operator’s syntax literal as the name (e.g., foo/[].sub, or foo/<<.sub).

Tagging files

Often it is informative to list attributes or properties of a function subroutine or other expression to inform the user. For example, a function may be marked as pure, or marked to say it does not return. It could also be documented that it does not throw. To tag a file, simply list the tags at the beginning of the file with each tag in square brackets. These are the known tags:

File attributes

It is a common need to document a function’s parameters and return values, a variable’s valid values, or some combination thereof. Attributes are written as their own records with a special form; the file path remains the same, and a colon is appended to separate the path from the attribute portion, similar to the notation for file offsets or source code line numbers.

Return value

Used with: .sub

Denoted by the pound sign (#), e.g. foo/bar.sub:#.

Parameter

Used with: .sub

Denoted like shell arguments or regex groups, using a dollar sign and a number in decimal ($). $0 is used to represent member variables in class instances and is unused outside such context, so all parameters begin with $1. Example: foo/bar.sub:$2

Valid usage

Used with: .sub, .const, .var, parameters

Denoted by a single asterisk (*), following any other attributes if present, e.g. foo/bar.sub:* or foo/bla.sub:$1*. These records list out the constraints for a piece of data or code to be considered “valid”; for data, this entails specific restrictions on permitted values, shallow and deep, while for code this entails constraints beyond which the subroutine may exhibit undefined behaviour. This can include things like “such pointer must not be NULL” and “must point to a valid X object allocated with xyzallocator function”. RFC 2119 is useful for specifying normative terminology to these ends.

Appendix

A: Escape sequences

References & additional reading

  1. Network Working Group. “RFC 2119.” Key words for use in RFCs to Indicate Requirement Levels. <https://tools.ietf.org/html/rfc2119>
  2. Alexander Nicholi. “ADP 1.” Project repository filesystem schema. <https://aquefir.co/adp1>