+ - * / & < = > /= <= >= := => | .. : <>
Default_String : constant String := "This is the long string returned by" & " default. It is broken into multiple" & " Ada source lines for convenience."; type Signed_Whole_16 is range -2**15 .. 2**15 - 1; type Address_Area is array (Natural range <>) of Signed_Whole_16; Register : Address_Area (16#7FF0# .. 16#7FFF#); Memory : Address_Area ( 0 .. 16#7FEC#); Register(Pc) := Register(A); X := Signed_Whole_16(Radius * Sin(Angle)); Register(Index) := Memory(Base_Address + Index * Element_Length); Get(Value => Sensor); Error_Term := 1.0 - (Cos(Theta)**2 + Sin(Theta)**2); Z := X**3; Y := C * X + B; Volume := Length * Width * Height;
However, many of the delimiters (commas, semicolons, parentheses, etc.) are familiar as normal punctuation marks. It is distracting to see them spaced differently in a computer program than in normal text. Therefore, they should be spaced the same (no spaces before commas and semicolons, no spaces inside of parentheses, etc.).
Language Ref Manual references: 2.2 Lexical Elements, Separators, and Delimiters, 2.6 String Literals, 3.6.3 The Type String, 4.4 Expressions, 4.5 Operators and Expression Evaluation, 4.5.2 Relational Operators and Membership Tests, 4.5.3 Binary Adding Operators, 6.4 Subprogram Calls, 6.5 Function Subprograms
begin <<label>> | <long statement with line break> <statement> | <trailing part of same statement> end;
The if statement and the plain loop:
if <condition> then | <name>: <statements> | loop elsif <condition> then | <statements> <statements> | exit when <condition>; else | <statements> <statements> | end loop <name>; end if; |
Loops with the for and while iteration schemes:
<name>: | <name>: for <scheme> loop | while <condition> loop <statements> | <statements> end loop <name>; | end loop <name>;
The block and the case statement as recommended in the Ada Language Reference Manual (Department of Defense 1983):
<name>: | case <expression> is declare | when <choice> => <declarations> | <statements> begin | when <choice> => <statements> | <statements> exception | when others => when <choice> => | <statements> <statements> | end case; --<comment> when others => | <statements> | end <name>; |
These case statements save space over the the Ada Language Reference Manual (Department of Defense 1983) recommendation and depend on very short statement lists, respectively. Whichever you choose, be consistent.
case <expression> is | case <expression> is when <choice> => | when <choice> => <statements> <statements> | <statements> when <choice> => | when <choice> => <statements> <statements> | when others => <statements> when others => | end case; <statements> | end case; |
The various forms of selective wait and the timed and conditional entry calls:
select | select when <guard> => | <entry call>; <accept statement> | <statements> <statements> | or or | delay <interval>; <accept statement> | <statements> <statements> | end select; or | when <guard> => | delay <interval>; | <statements> | or | select when <guard> => | <entry call>; terminate; | <statements> else | else <statements> | <statements> end select; | end select;
The accept statement and a subunit:
accept <specification> do | separate (<parent unit>) <statements> | <proper body> end <name>; |
Proper bodies of program units:
procedure <specification> is | package body <name> is <declarations> | <declarations> begin | begin <statements> | <statements> exception | exception when <choice> => | when <choice> => <statements> | <statements> end <name>; | end <name>; | function <specification> | task body <name> is return <type name> is | <declarations> <declarations> | begin begin | <statements> <statements> | exception exception | when <choice> => when <choice> => | <statements> <statements> | end <name>; end <name>; |
Context clauses on compilation units are arranged as a table. Generic formal parameters do not obscure the unit itself. Function, package, and task specifications use standard indentation:
with <name>; | function <specification> with <name>; | return <type>; with <name>; | | package <name> is use <name>; | <declarations> | private <compilation unit> | <declarations> | end <name>; | generic | task type <name> is <formal parameters> | <entry declarations> <compilation unit> | end <name>;
Instantiations of generic units and record indentation:
procedure <name> is |type ... is new <generic name> <actuals> | record | <component list> function <name> is | case <discriminant name> is new <generic name> <actuals>| when <choice> => | <component list> package <name> is | when <choice> => new <generic name> <actuals> | <component list> | end case; | end record;
Indentation for record alignment:
for <name> use record <alignment clause> <component clause> end record;
Default_String : constant String := "This is the long string returned by" & " default. It is broken into multiple" & " Ada source lines for convenience."; loop if Input_Found then Count_Characters; else --not Input_Found Reset_State; Character_Total := First_Part_Total * First_Part_Scale_Factor + Second_Part_Total * Second_Part_Scale_Factor + Default_String'Length + Delimiter_Size; end if; end loop;
While there is much discussion on the number of spaces to indent, the reason for indentation is code clarity. The fact that the code is indented consistently is more important than the number of spaces used for indentation.
Additionally, in Section 1.5, the Ada Language Reference Manual says that the layout shown in the examples and syntax rules in the Ada Language Reference Manual is the recommended code layout to be used for Ada programs. "The syntax rules describing structured constructs are presented in a form that corresponds to the recommended paragraphing. ... Different lines are used for parts of a syntax rule if the corresponding parts of the construct described by the rule are intended to be on different lines. ... It is recommended that all indentation be by multiples of a basic step of indentation (the number of spaces for the basic step is not defined)."
It is important to indent continuation lines differently from nested control structures to make them visually distinct. This prevents them from obscuring the structure of the code as the user scans it.
Indenting with spaces is more portable than indenting with tabs because tab characters are displayed differently by different terminals and printers.
Language Ref Manual references: 1.5 Method of Description and Syntax Notation, 2.6 String Literals, 3.7 Record Types, 5 Statements, 6.1 Subprogram Declarations, 7 Packages, 9.7 Select Statements, 10.1.1 Context Clauses - With Clauses, 11.2 Exception Handlers, 12.1 Generic Declarations, 12.3 Generic Instantiation, 13.4 Record Representation Clauses
if Slot_A >= Slot_B then Temporary := Slot_A; Slot_A := Slot_B; Slot_B := Temporary; end if; Numerator := B**2 - 4.0 * A * C; Denominator := 2.0 * A; Solution_1 := -B + Square_Root(Numerator / Denominator); Solution_2 := B + Square_Root(Numerator / Denominator); X := A * B + C * D + E * F; Y := (A * B + C) + -- basic equation (2.0 * D - E) - -- 3.5; -- account for error factor
The use of lines and spacing on long expressions can emphasize terms, precedence of operators, and other semantics. It can also leave room for highlighting comments within an expression.
Language Ref Manual references: 4.4 Expressions, 4.5 Operators and Expression Evaluation, 5.2 Assignment Statement
Prompt_Column : constant := 40; Question_Mark : constant String := " ? "; -- prompt on error input Prompt_String : constant String := " ==> ";
If this results in lines that are too long, they can be laid out with each part on a separate line with its unique indentation level.
subtype User_Response_Text_Frame is String (1 .. 72); -- If the declaration needed a comment, it would fit here. Input_Line_Buffer : User_Response_Text_Frame := Prompt_String & String'(1 .. User_Response_Text_Frame'Length - Prompt_String'Length => ' ');
Declarations of enumeration literals can be listed in one or more columns as:
type Op_Codes_In_Column is (Push, Pop, Add, Subtract, Multiply, Divide, Subroutine_Call, Subroutine_Return, Branch, Branch_On_Zero, Branch_On_Negative);
or, to save space:
type Op_Codes_Multiple_Columns is (Push, Pop, Add, Subtract, Multiply, Divide, Subroutine_Call, Subroutine_Return, Branch, Branch_On_Zero, Branch_On_Negative);
or, to emphasize related groups of values:
type Op_Codes_In_Table is (Push, Pop, Add, Subtract, Multiply, Divide, Subroutine_Call, Subroutine_Return, Branch, Branch_On_Zero, Branch_On_Negative);
Language Ref Manual references: 2.6 String Literals, 2.7 Comments, 3.5.1 Enumeration Types, 3.9 Declarative Parts, 3 Declarations and Types
procedure Display_Menu (Title : in String; Options : in Menus; Choice : out Alpha_Numerics);
or
procedure Display_Menu_On_Primary_Window (Title : in String; Options : in Menus; Choice : out Alpha_Numerics);
or
procedure Display_Menu_On_Screen ( Title : in String; Options : in Menus; Choice : out Alpha_Numerics );
Aligning parentheses makes complicated relational expressions more clear:
if not (First_Character in Alpha_Numerics and then Valid_Option(First_Character)) then
The third example is a format commonly used to reduce the amount of editing required when parameter lines are added, deleted, or reordered. The parentheses don't have to be moved from line to line. However, the last parameter line is the only one without a semicolon.
if ... then for ... loop ... end loop; end if;
This example separates different kinds of declarations with blank lines:
type Employee_Record is record Legal_Name : Name; Date_Of_Birth : Date; Date_Of_Hire : Date; Salary : Money; end record; type Day is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday); subtype Weekday is Day range Monday .. Friday; subtype Weekend is Day range Saturday .. Sunday;
Language Ref Manual references: 3 Declarations and Types, 5 Statements
with Basic_Types; package body SPC_Numeric_Types is ... --------------------------------------------------------------------- function Max (Left : in Basic_Types.Tiny_Integer; Right : in Basic_Types.Tiny_Integer) return Basic_Types.Tiny_Integer is begin if Right < Left then return Left; else return Right; end if; end Max; --------------------------------------------------------------------- function Min (Left : in Basic_Types.Tiny_Integer; Right : in Basic_Types.Tiny_Integer) return Basic_Types.Tiny_Integer is begin if Left < Right then return Left; else return Right; end if; end Min; --------------------------------------------------------------------- use Basic_Types; begin -- SPC_Numeric_Types Max_Tiny_Integer := Min(System_Max, Local_Max); Min_Tiny_Integer := Max(System_Min, Local_Min); -- ... end SPC_Numeric_Types;
Language Ref Manual references: 2.7 Comments, 6.3 Subprogram Bodies, 7.2 Package Specifications and Declarations, 7.3 Package Bodies, 9.1 Abort Statements
if End_Of_File then Close_File; else Get_Next_Record; end if;
rather than
if End_Of_File then Close_File; else Get_Next_Record; end if; exceptional case Put("A="); Natural_IO.Put(A); New_Line; Put("B="); Natural_IO.Put(B); New_Line; Put("C="); Natural_IO.Put(C); New_Line;
According to the Ada Language Reference Manual (Department of Defense 1983), "The preferred places for other line breaks are after semicolons."
Language Ref Manual references: 1.5 Method of Description and Syntax Notation, 3 Declarations and Types, 5 Statements
Source code must sometimes be published for various reasons, and letter-size paper is not as forgiving as a computer listing in terms of the number of usable columns.
In addition, there are human limitations in the width of the field of view for understanding at the level required for reading source code. These limitations correspond roughly to the 70 to 80 column range.