-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathHello-Ada.tex
More file actions
159 lines (124 loc) · 7.69 KB
/
Copy pathHello-Ada.tex
File metadata and controls
159 lines (124 loc) · 7.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
\section{Hello, Ada}
\label{sec:hello-ada}
Whenever you begin to study a new language or software development environment, you should start
by writing the most trivial program possible in that language or environment. Thus, I will begin
this tutorial with a short but complete program that displays the string ``Hello, Ada!'' on the
console.
\label{lst:hello-ada}
\begin{lstlisting}
with Ada.Text_IO;
procedure Hello is
begin
Ada.Text_IO.Put_Line("Hello, Ada!");
end Hello;
\end{lstlisting}
\noindent The program starts with a \newterm{context clause} consisting of a |with| statement.
The context clause specifies the packages that will be used in this particular compilation unit.
Although the compilation unit above contains just a single procedure, most Ada code is in
packages. The standard library components are in child packages of the package |Ada|. In this
case, we use facilities in the child package |Ada.Text_IO|.
The main program is the procedure named |Hello|. The precise name used for the main program can
be anything; exactly which procedure is used as the program's entry point is specified when the
program is compiled. The procedure consists of two parts: the part between |is| and |begin| is
called the declarative part. Although empty in this simple case, it is here where you would
declare local variables and other things. The part between |begin| and |end| constitutes the
executable statements of the procedure. In this case, the only executable statement is a call to
procedure |Put_Line| in package |Ada.Text_IO|. As you can probably guess from its name,
|Put_Line| prints the given string onto the program's standard output device. It also terminates
the output with an appropriate end-of-line marker.
Notice how the name of the procedure is repeated at the end. This is optional but considered
good practice. In more complex examples, the readability is improved by making it clear exactly
what is ending. Notice also the semicolon at the end of the procedure definition. C family
languages do not require a semicolon here, so you might accidentally leave it out.
Spelling out the full name |Ada.Text_IO.Put_Line| is rather tedious. If you wish to avoid it,
you can include a |use| statement for the |Ada.Text_IO| package in the context clause (or in the
declarative part of |Hello|). Where the |with| statement makes the names in the withed package
\newterm{visible}, the |use| statement makes them \newterm{directly visible}. Such names can
then be used without qualification, as shown below:
\begin{lstlisting}
with Ada.Text_IO; use Ada.Text_IO;
procedure Hello is
begin
Put_Line("Hello, Ada!"); -- No need to specify Ada.Text_IO
end Hello;
\end{lstlisting}
\noindent Some Ada programmers do this to avoid having to write long package names everywhere.
However, indiscriminate use of |use| can make it difficult to understand your program because it
can be hard to tell in which package a particular name has been declared.
Ada is a case-insensitive language. Thus, identifiers such as |Hello|, |hello|, and |hElLo| all
refer to the same entity. It is traditional in modern Ada source code to use all lowercase
letters for reserved words. For all other identifiers, capitalize the first letter of each word
and separate multiple words with an underscore.\footnote{This style is often called
\newterm{title case}.} The Ada language does not enforce this convention, but it is a
well-established standard in the Ada community, so you should follow it.
\subsection{Building Ada Programs}
Before continuing, I should describe how to compile the program above. The modern approach uses
the Alire build and package manager. Although Alire is more powerful than is necessary for the
simple programs you will write as a beginning Ada programmer, it is worth learning to use it
early. Alire is quickly becoming the de facto standard for open source Ada development.
Begin by downloading Alire from \url{https://alire.ada.dev}. The precise installation
instructions depend on your development platform but are straightforward. Once you have
installed Alire, you must create a \newterm{crate} for your program. Every program should have
its own crate.
A crate is Alire's unit of deployment. Applications, both small and large, can exist in a crate,
but a crate can also contain a library with no main program. The ``crate'' terminology used by
Alire avoids ambiguity with ``package'' which, as you will see, is an important tool for
structuring Ada code and is something quite different from what Alire calls a crate.
Using a command prompt, navigate to the folder where you want to create your crate and enter the
following command:
\begin{Verbatim}
alr init --bin hello
\end{Verbatim}
\noindent This initializes a subfolder named \filename{hello} with the necessary material for a
new, empty application crate (as opposed to a library crate). The name ``hello'' is arbitrary,
but it must agree with the name of your program, and it should be all lowercase.
The first time you run Alire, it will ask you what \newterm{toolchain} you want to use. You can
choose the default, which should be a recent version of the GNAT compiler. You will also be
asked some questions about the new crate you are creating. The answers are not critical and can
be changed later.
Most of the files and folders created by Alire can be ignored for the simple programs you will
write at first. However, inside the \filename{hello} folder, you will find a file
\filename{src/hello.adb}. This is the file where you will put your Ada code, such as the
``Hello, Ada'' program show earlier.
To build the program, execute the following command in the root of the crate (not in the
\filename{src} folder):
\begin{Verbatim}
alr build
\end{Verbatim}
\noindent The executable file will be left in the \filename{bin} folder. You can also use the
command:
\begin{Verbatim}
alr run
\end{Verbatim}
\noindent This both compiles and runs the program in one step.
It is important that the procedure |Hello| be stored in a file named \filename{hello.adb}.
Notice that the file's name must be in lowercase letters and must agree with the name of the
procedure stored in that file. The \filename{adb} extension stands for ``Ada body.'' This
contrasts with Ada specification files that are given an extension of \filename{ads}. You will
see Ada specifications when I discuss packages in Section~\ref{sec:packages}. I will describe
other GNAT file naming requirements at that time.
You can use any text editor to write Ada programs, but many Ada programmers use GNAT Programming
Studio from AdaCore, which provides a full IDE experience. It is also common to use Visual
Studio Code with the Ada extension from AdaCore. The tricky part of using these tools is
ensuring they are run in an appropriate environment so they can see the Ada compiler you are
using. To do this, first tell Alire which editor you are using:
\begin{Verbatim}
alr edit --select-editor
\end{Verbatim}
\noindent Then, from the root of the crate, run the following command to launch the editor with
the correct environment:
\begin{Verbatim}
alr edit
\end{Verbatim}
\subsection*{Exercises}
\begin{enumerate}
\item Enter the trivial ``Hello, Ada'' program on page~\pageref{lst:hello-ada} into your system.
Compile and run it.
\item Make a minor modification to the trivial program that results in an error. Try compiling
the program again. Try several different minor errors. This will give you a feeling for the
kinds of error messages GNAT produces.
\item Experiment with the |use| statement. Try calling |Put_Line| without specifying its
package, both with and without the |use| statement. Try putting the |use| statement inside the
declarative part of the procedure. Try putting the |with| statement inside the declarative
part of the procedure.
\end{enumerate}