Comments on: Rebol's source style: function commenting, embedded documentation
REBOL Technologies

Comments on: 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] || 10 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.

10 Comments

Comments:

Brian Hawley
16-Oct-2012 9:41:27
Nice code. Based on this, it should be simple to add the long-requested /into option to map-each.
Fork
16-Oct-2012 10:25:23
I note that you're not intermingling the initializations with the code as C99 (and C++) permit, so you didn't write:

REBINT start = DSP + 1;
for (REBVAL* value = VAL_BLK_DATA(block); NOT_END(value); value++) 

But you are using // style comments so it's not pure C89 (=C90). Random example of someone's complaint of why it's a bad idea even if a compiler silently supports it in C89 mode (or whatever hodgepodge "mode" it decides to use when it sees a .c file):

int a = 20 //* comment */ 2
      + 79;

Does it matter if programs will silently compile differently in "pseudo-C89" vs. C99? I dunno. But I do think it's nice to not be forced to tease out all the locals so they're at the head of the function (or block). It's better for readability and maintenance. And I'm also attached to C++ style comments, as we've established before. :-P

Here's the situation with Microsoft Visual C++ and C99...basically their priorities are only to implement the parts that are a subset of C++11:

http://stackoverflow.com/questions/146381/visual-studio-support-for-new-c-c-standards

Point being: if there are esoteric compilers that remain relevant to the project but have fewer features, it's important to know what the lowest common denominator is for contributions to the trunk.

Steven White
16-Oct-2012 10:29:12
Nice idea. I have tried some ideas over the years for producing documentation by extracting comments out of source code, but I never thought of the idea of putting source code into the comments so the source code itself can be part of the documentation. I am impressed.
Carl Sassenrath
16-Oct-2012 11:18:58
Fork, the compiler will be the subject of another blog. In the past it's been determined by practicality: what actually works over the widest range. (I can usually port REBOL3/core to any target machine in 5 minutes.)

This hasn't been easy, and it's why there are various C restrictions. I agree... many of the C++isms are nice, but can dramatically reduce portability to older boxes. It's a balancing act.

Let's get back to this topic in a new blog.

Joe Latone
16-Oct-2012 12:09:32
Cool, we're down to commenting now about comments, which means we're close and I'll soon be able to press Enter:

git clone https://github.com/rebol/r3-source

Champing at the bit...

Arnold
16-Oct-2012 14:12:07
I like the documentation trick :)

Sure nice to see this post and good to see you around here so much Carl! You must have been on the Jazz today. (The wine resting in the barrel's for the winter now so you have some spare time).

I say forget the license and join the Red development team ;-)

shadwolf
17-Oct-2012 5:40:51
Clear and short code.

As a community of co-workers (several code writers) it will take alot of time to get our own new modules as polished and simplified as your code Carl.

It is not impossible but it is a long and delicate process. My fear is that the ones you put in charge of this task or lack competences to do that kind of task or lack time to focus serriously on that task and in the end rebol3 will not evolve any more than it evolves actually because of the bottle neck of the selected few oversighters. I'm trying to figure out how will be organised things to fit your high coding standard and quality requierements.

My best guess is to create larger possible groups and the most open possible. instead of giving the polishing touch to a bunch of selected individuals I would make you the one that have the last word and the community will have the task to bring code, discuss it, trim and polish it and then propose the final version of the code to your aproval, with maybe a short version of the discussions around that new module to allow you to get a glimpse over how the work have been wraped up.

Maxim Olivier-Adlhoch
17-Oct-2012 11:01:12
shad, you'd be surprised to know that some rebolers are even MORE picky than Carl. ;-)

Whoever has the same level of authority as Carl on the official distro will most definitely have the same bloat intolerance and because this is a DVCS, Carl can very easily just go and fix any blunders if it ever really comes to that.

John
22-Oct-2012 17:51:11
Anyone in Australia want to catch up when the conference is on in Nice? We could find a venue and potentially join in via video conference?
Scot
29-Nov-2012 9:46:06
Great stuff. I've been wrapping comments around function headers ever since I saw it in the Amiga code, though not very religiously. I love the ability to comment naturally within Rebol.

Post a Comment:

You can post a comment here. Keep it on-topic.

Name:

Blog id:

CS-0515


Comment:


 Note: HTML tags allowed for: b i u li ol ul font p br pre tt blockquote
 
 

This is a technical blog related to the above topic. We reserve the right to remove comments that are off-topic, irrelevant links, advertisements, spams, personal attacks, politics, religion, etc.

Updated 12-Dec-2017   -   Copyright Carl Sassenrath   -   WWW.REBOL.COM   -   Edit   -   Blogger Source Code