REBOL Technologies

Rebol's source style: function commenting, embedded documentation

Carl Sassenrath, CTO
REBOL Technologies
16-Oct-2012 15:09 GMT

Article #0515
Main page || Index || Prior Article [0514] || Next Article [0516] || 11 Comments || Send feedback

It's important to me that as R3 becomes open source that we continue with the style used for the C source. Those of you who've looked at the host-kit are familiar with it.

As the originator of source code auto-docs (Amiga, 1984), the method I used for documenting the multitasking kernel (Exec), I've continued to refine my embedded commenting practices, relaxing some of the extra typing and really focusing on the essence of what needs to be stated to understand each function.

Let me just pick a function at random as an example (actually, not so random... this is one is the very core of REBOL):

/***********************************************************************
**
*/  REBCNT Do_Next(REBSER *block, REBCNT index, REBFLG op)
/*
**      Evaluate the code block until we have:
**          1. An irreducible value (return next index)
**          2. Reached the end of the block (return END_FLAG)
**          3. Encountered an error
**
**      Index is a zero-based index into the block.
**      Op indicates infix operator is being evaluated (precedence);
**      The value (or error) is placed on top of the data stack.
**
***********************************************************************/

Notice that the comment wraps the actual function interface. It is embedded. This avoids duplication of the interface specification within the comment. (So, it is always accurate.)

The comment is also bold and stands out. Easy to spot, and all are identical in this form, without exception.

Also notice that the description is clear and concise. (And I don't go "overboard" with detail.) This is very helpful to understanding the purpose, intention, and design of the function... and, I will add, something you don't find in many other sources. (In fact... I think... none in my experience.)

So, this helps you understand how REBOL operates. It's very little extra work to include, and it has paid off many times over the years. I'd like you to continue with it.

Within a function, comments also appear, but they are not excessive. They draw out important points and help you understand what's happening.

For example:

/***********************************************************************
**
*/  void Compose_Block(REBVAL *block, REBFLG deep, REBFLG only, REBVAL *into)
/*
**      Compose a block from a block of un-evaluated values and
**      paren blocks that are evaluated. Stack holds temp values,
**      which also protects them from GC along the way.
**
**          deep - recurse into sub-blocks
**          only - parens that return blocks are kept as blocks
**
**      Returns result as a block on top of stack.
**
***********************************************************************/
{
    REBVAL *value;
    REBINT start = DSP + 1;

    for (value = VAL_BLK_DATA(block); NOT_END(value); value++) {
        if (IS_PAREN(value)) {
            // Eval the paren, and leave result on the stack:
            DO_BLK(value);
            DSP++; // !!!DSP temp
            if (THROWN(DS_TOP)) return;

            // If result is a block, and not /only, insert its contents:
            if (IS_BLOCK(DS_TOP) && !only) {
                // Append series to the stack:
                SERIES_TAIL(DS_Series) = DSP; // overwrites TOP value
                Append_Series(DS_Series, (REBYTE *)VAL_BLK_DATA(DS_TOP), VAL_BLK_LEN(DS_TOP));
                DSP = SERIES_TAIL(DS_Series) - 1;
                // Note: stack may have moved
            }
            else if (IS_UNSET(DS_TOP)) DS_DROP; // remove unset values
        }
        else if (deep) {
            if (IS_BLOCK(value)) Compose_Block(value, TRUE, only, 0);
            else {
                DS_PUSH(value);
                if (ANY_BLOCK(value)) // Include PATHS
                    VAL_SERIES(DS_TOP) = Copy_Block(VAL_SERIES(value), 0);
            }
        }
        else DS_PUSH(value);
    }

    Copy_Stack_Values(start, into);
}

Notice little comments like: "overwrites TOP value" and "stack may have moved." In a good design such critical elements should not be discovered the hard way (by falling into the hole.) So, it serves as a reminder. It didn't take any time to add that comment, and it will save others a whole lot of time in the long run.

11 Comments

Updated 8-Mar-2024   -   Copyright Carl Sassenrath   -   WWW.REBOL.COM   -   Edit   -   Blogger Source Code