Author: chip Date: Tue Sep 5 15:00:42 2006 New Revision: 14432 Modified: trunk/docs/pdds/pdd07_codingstd.pod
Changes in other areas also in this revision: Modified: trunk/ (props changed) Log: Move pdd07 out of clip Modified: trunk/docs/pdds/pdd07_codingstd.pod ============================================================================== --- trunk/docs/pdds/pdd07_codingstd.pod (original) +++ trunk/docs/pdds/pdd07_codingstd.pod Tue Sep 5 15:00:42 2006 @@ -3,13 +3,9 @@ =head1 NAME -docs/pdds/pdd07_codingstd.pod - Conventions and Guidelines for Parrot Source +docs/pdds/pdd07_codingstd.pod - Conventions and Guidelines for Parrot Source Code -=head1 VERSION - -$Revision$ - =head1 ABSTRACT This document describes the various rules, guidelines and advice for those @@ -23,306 +19,316 @@ conventions, lack of comments in the source code, and so on. We don't intend to make the same mistake when writing Parrot. Hence this document. -We define three classes of conventions: +We define three classes of conventions. Those that say I<must> are mandatory, +and code will not be accepted (apart from in exceptional circumstances) unless +it follows these rules. Those that say I<should> are strong guidelines that +should normally be followed unless there is a sensible reason to do otherwise. +Finally, those that say I<may>, are tentative suggestions to be used at your +discretion. + +Note this particular PDD makes some recommendations that are specific to the C +programming language. This does not preclude Parrot (or Perl 6) being +implemented in other languages, but in this case, additional PDDs may need to +be authored for the extra language-specific features. + +=head1 IMPLEMENTATION + +=head2 Coding style + +The following I<must> apply: =over 4 -=item I<"must"> +=item * -Items labelled I<must> are mandatory; and code will not be accepted (apart -from in exceptional circumstances) unless it obeys them. +4 column indents for code and 2 column indents for nested CPP #directives. All +indentation must consist of spaces, no tabs (for ease of patching). -=item I<"should"> +There are two exceptions to the CPP indenting- neither PARROT_IN_CORE nor the +outermost _GUARD #ifdefs cause the level of indenting to increase. -Items labelled I<should> are strong guidelines that should normally be -followed unless there is a sensible reason to do otherwise. +To ensure that tabs aren't inadvertently used for indentation, the following +boilerplate code must appear at the bottom of each source file. (This rule may +be rescinded if I'm ever threatened with a lynching....) -=item I<"may"> + /* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ -Items labelled I<may> are tentative suggestions to be used at your discretion. -=back +=item * -Note that since Parrot is substantially implemented in C, these rules apply to -C language source code unless otherwise specified. +Any other tabs are assumed to be on an 8-character boundary. -=head1 IMPLEMENTATION +=item * +ANSI C function prototypes -=head2 Language Standards and Portability +=item * -=over 4 +"K&R" style for indenting control constructs: ie the closing C<}> should line +up with the opening C<if> etc. =item * -C code must generally depend on only those language and library features -specified by the ISO C89 standard. +When a conditional spans multiple lines, the opening C<{> must line up with the +C<if> or C<while>, or be at the end-of-line otherwise. -In addition, C code may assume that any pointer value can be coerced to an -integral type (no smaller than typedef C<INTVAL> in Parrot), then back to its -original type, without loss. +=item * + +Uncuddled C<else>s: ie avoid C<} else {> -C code that makes assumptions beyond these must depend on the configuration -system, either to not compile an entire non-portable source where it will not -work, or to provide an appropriate #ifdef macro. +=item * -{{ TODO: Enumerate all other non-C89 assumptions that Parrot depends on. }} +C-style comments only (C</* comment */>). Not all C compilers handle +C++-style comments. =item * -Perl code must be written for Perl 5.6.1 and all later versions. +Mark places that need to be revisited with XXX (and preferably your initials +too), and revisit often! -Perl code may use features not available in Perl 5.6.1 only if it is not vital -to Parrot, and if it uses C<$^O> and C<$]> to degrade or fail gracefully when -it is run where the features it depends on are not available. +=item * -=back +In function definitions, the name starts in column 0, with the return type on +the previous line. +=item * -=head2 Code Formatting +However, in function declarations (in header files) the return type is kept on +the same line. -The following I<must> apply: +=item * + +Variable names should be included for all function parameters in the function +declarations. These names should match the parameters in the function +definition. + +=item * + +Single space after keywords that are followed by C<()>, eg C<return (x+y)*2>, +but no space between function name and following C<()>, eg C<z = foo(x+y)*2> + +=back + +The following I<should> apply =over 4 =item * -Source line width is limited to 100 characters. Exceptions can be made for -technical requirements, but not for style reasons. And please bear in mind -that very long lines I<can> be hard to read. +Do not exceed 79 columns =item * -Indentation must consist only of spaces. (Tab characters just complicate -things.) +C<return foo;> rather than C<return (foo);> =item * -C and Perl code must be indented four columns per nesting level. +C<if (!foo) ...> rather than C<if (foo == FALSE) ...> etc. =item * -Preprocessor #directives must be indented two columns per nesting level, with -two exceptions: neither PARROT_IN_CORE nor the outermost _GUARD #ifdefs cause -the level of indenting to increase. +Avoid assignments in conditionals, but if they're unavoidable, use Extra paren, +e.g. C<if (a && (b = c)) ...> =item * -Labels (including case labels) must be outdented two columns relative to the -code they label. +Avoid double negatives, eg C<#ifndef NO_FEATURE_FOO> =item * -Closing braces for control structures must line up vertically with the start -of the control structures; e.g. C<}> that closes an C<if> must line up with the -C<if>. +Binary operators should have a space on either side; parentheses should not +have space immediately after the opening paren nor immediately before the +closing paren, commas should have space after but not before, eg + + x = (a + b) * f(c, d / e) =item * -Long lines, when split, must use at least one extra level of indentation on -the continued line. +Long lines should be split before an operator so that it is immediately obvious +when scanning the LHS of the code that this has happened, and two extra levels +of indent should be used. =item * -Cuddled C<else>s are forbidden: i.e. avoid C<} else {> . +and/or split on matching parens, with the content on separate line(s) and with +one extra indent: + + do_arbitrary_function( + list_of_parameters_with_long_names, or_complex_subexpression( + of_more_params, or_expressions + 1 + ) + ); =back +To enforce the spacing, indenting, and bracing guidelines mentioned above, the +following arguments to GNU Indent should be used: -The following I<should> apply: + -kr -nce -sc -cp0 -l79 -lc79 -psl -nut -cdw -ncs -lps -=over 4 +This expands out to: -=item * +=over -In function definitions, the function name must be on the left margin, with -the return type on the previous line. +=item -nbad -=item * +Do not force blank lines after declarations. -In function declarations (e.g. in header files), the function name must be on -the same line as the return type. +=item -bap -=item * +Force blank lines after procedure bodies. -There should be one space between C keywords and following open parentheses, -e.g. C<return (x+y)*2>. +=item -bbo -There should be no space between function names and following open parentheses, -e.g. C<z = foo(x+y)*2> +Prefer to break long lines before boolean operators. -=item * +=item -nbc -Use patterns of formatting to indicate patterns of semantics. Similar items -should look similar, as the language permits. Note that some dimensions of -similarity are incidental, not worth emphasizing; e.g. "these are all ints". +Do not force newlines after commas in declarations -=item * +=item -br -Binary operators (except C<.> and C<< -> >>) should have at least one space on -either side; there should be no space between unary operators and their -operands; parentheses should not have space immediately after the opening -parenthesis nor immediately before the closing parenthesis; commas should have -at least one space after, but not before; e.g.: +Put braces on line with if, etc. - x = (a-- + b) * f(c, d / e.f) +=item -brs -=item * +Put braces on struct declaration line. -Use vertical alignment for clarity of parallelism. Compare this (bad): +=item -c33 - foo = 1 + 100; - x = 100 + 1; - whatever = 100 + 100; +Put comments to the right of code in column 33 (not recommended) -... to this (good): +=item -cd33 - foo = 1 + 100; - x = 100 + 1; - whatever = 100 + 100; +Put declaration comments to the right of code in column 33 -=item * +=item -ncdb -Do not routinely put single statements in statement blocks. +Do not put comment delimiters on blank lines. -(Note that formatting consistency trumps this rule. For example, a long -C<if>/C<else if> chain is easier to read if all (or none) of the conditional -code is in blocks.) +=item -nce -=item * +Do not cuddle } and else. -Return values should not be parenthesized without need. It may be necessary -to parenthesize a long return expression so that a smart editor will properly -indent it. +=item -cdw -{{ TODO: Modify parrot.el so this rule is no longer required. }} +Do cuddle do { } while. -=item * +=item -ci4 -When assignming inside a conditional, use extra parentheses, -e.g. C<if (a && (b = c)) ...> or C<if ((a = b)) ...>. +Continuation indent of 4 spaces -=item * +=item -cli0 -When splitting a long line at a binary operator (other than comma), the split -should be I<before> the operator, so that the continued line looks like one. +Case label indent of 0 spaces -=item * +=item -ncs -When splitting a long line inside parentheses (or brackets), the continuation -should be indented to the right of the innermost unclosed punctuation, e.g.: +Do not put a space after a cast operator. - z = foo(bar + baz(something_very_long_here - * something_else_very_long), - corge); +=item -d0 -=back +Set indentation of comments not to the right of code to 0 spaces. +=item -di1 -=head2 Code Structure +Put declaration variables 1 space after their types -The following I<must> apply: +=item -nfc1 -=over 4 +Do not format comments in the first column as normal. -=item * +=item -nfca -C code must use C-style comments only, i.e. C</* comment */>. (Not all C -compilers handle C++-style comments.) +Do not format any comments -=item * +=item -hnl -All functions must have prototypes in scope at the point of use. Prototypes -for extern functions must appear only in header files. If static functions -are defined before use, their definitions serve as prototypes. +Prefer to break long lines at the position of newlines in the input. -=item * +=item -i4 -Parameters in function prototypes must be named. These names should match the -parameters in the function definition. +4-space indents -=item * +=item -ip0 -Variable names must be included for all function parameters in the function -declarations. +Indent parameter types in old-style function definitions by 0 spaces. -=back +=item -l79 +maximum line length for non-comment lines is 79 spaces. -The following I<should> apply +=item -lc79 -=over 4 +maximum line length for comment lines is 79 spaces. -=item * +=item -lp -Avoid double negatives, e.g. C<#ifndef NO_FEATURE_FOO>. +maximum line length for non-comment lines is 79 spaces. -=item * +=item -npcs -Do not compare directly against NULL, 0, or FALSE. Instead, write a boolean -test, e.g. C<if (!foo) ...>. +Do not put a space after the function in function calls. -(Note: C<PMC*> values should be checked for nullity with the C<PMC_IS_NULL> -macro, unfortunately leading to violations of the double-negative rule.) +=item -nprs -=item * +Do not put a space after every �(� and before every �)�. -Avoid dependency on "FIXME" and "TODO" labels; if a bug must be fixed soon, -use "XXX", else use the external bug tracking system. +=item -saf -=back +Put a space after each for. +=item -sai -=head2 Smart Editor Style Support +Put a space after each if. -All developers using Emacs must ensure that their Emacs instances load the -elisp source file F<tools/dev/parrot.el> before opening Parrot source files. -This may be done by adding this line to F<.emacs>: +=item -saw - (load-file "/<path-to-parrot>/tools/dev/parrot.el") +Put a space after each while. -All source files must end with an editor instruction block: +=item -sc -=over 4 +Put the `*� character at the left of comments. -=item * +=item -nsob -C source files, and files largely consisting of C (e.g. yacc, lex, PMC, and -opcode source files), must end with this block: +Do not swallow optional blank lines. - /* - * Local variables: - * c-file-style: "parrot" - * End: - * vim: expandtab shiftwidth=4: - */ +=item -nss -=item * +Do not force a space before the semicolon after certain statements -Perl source files must end with this block: +=item -nut - # Local Variables: - # mode: cperl - # cperl-indent-level: 4 - # fill-column: 100 - # End: - # vim: expandtab shiftwidth=4: +Use spaces instead of tabs. -=back +=item -lps -{{ XXX - Proper formatting and syntax coloring of C code under Emacs requires -that Emacs know about typedefs. We should provide a simple script to update a -list of typedefs, and parrot.el should read it or contain it. }} +Leave space between `#� and preprocessor directive. +=item -psl +Put the type of a procedure on the line before its name. (.c files), or -=head2 CHIP HAS EDITED THIS FAR INTO THE FILE +=item -npsl - +-------------------------------------------------------+ - Everything below this point must still be reviewed - +-------------------------------------------------------+ +Leave a procedure declaration's return type alone (.h files) +=back + +Please note that it is also necessary to include all typedef types with the +"-T" option to ensure that everything is formatted properly. +A script (F<tools/dev/run_indent.pl>) is provided which runs F<indent> +properly automatically. =head2 Naming conventions @@ -900,6 +906,8 @@ by Paolo Molaro <[EMAIL PROTECTED]>. Other snippets came from various P5Pers. The rest of it is probably my fault. +=head1 VERSION + =head2 CURRENT Maintainer: Dave Mitchell <[EMAIL PROTECTED]> @@ -919,9 +927,4 @@ None. First version -=cut -# Local Variables: -# fill-column:78 -# End: -# vim: expandtab shiftwidth=4: