Ada Language Fundamentals

Example 0: sayhi.adb

-- Simple Ada program -- in file sayhi.adb with Ada.Text_IO; procedure sayHi is begin Ada.Text_IO.put("Hi!"); -- Output some text! end sayHi;

Program Structure

In Java, to run a program you execute a

method



named main



that is nested in a class



In Ada, to run a program you execute a

procedure



that can have any name that you want



and that is not nested inside anything





Procedures and methods are similar

Comments

Comments are marked with -- to end of line

to end of line Only one kind



No multiline comment



Why? What happens here in Java?

/* This is a comment * / int x = a * b; // What about this line? /* Another comment */

Less of a problem with IDEs

Program Structure

Structure: procedure xxx is ... // Declarations go here begin // Execution begins here ... // Executable statements go here end xxx;

A procedure is similar to a method

is similar to a method Later we see functions which are also similar to methods

which are also similar to methods

Collectively called routines, subroutines, subprogram, (or even procedure)



procedure name xxx is chosen by user

is chosen by user

begin ... end marks a program block , like {...} in Java

marks a ,

Package Ada.Text_IO

ada.text_io : package that contains routines for i/o of text

: package that contains routines for i/o of text

put_line: procedure for string output

Outputs newline after string



Some other routines in Ada.Text_IO:

put: Outputs a string, without a newline



new_line: outputs a newline character



new_line(3): outputs 3 newline characters

With Statement

with Ada.Text_IO statement: allows procedure sayHi to refer to routines in package Ada.Text_IO

statement: allows procedure to refer to routines in package

If a routine accesses something that is in a package, the routine must have a with statement for that package

statement for that package

With is different from Java import , which causes the Java compiler to automatically search available classes for a feature

Use Statement

Consider saymore.adb:

with ada.text_io; use ada.text_io; procedure sayMore.adb is begin put_line("Hi"); put("Good to "); put("see you friends!"); new_line; end sayMore;

Use statement allows access to routines without using the fully qualified name

Compiler will automatically search ada.text_io for put_line, put, and new_line

with statement: tells compiler that the package will be used

use statement: tells compiler that the package should be automatically searched, and that the fully qualified name is not required, although it can be used

Similar to Java import

Make sure you understand the difference between with and use

Identifiers and Case Sensitivity

sayHi and sayMore: procedure names chosen by user



Identifiers: begin with letters and have any number of letters, digits, and underscores (underscores must appear between two non-underscores)



Reserved words cannot be used as identifiers

Predefined types and values can be used as identifiers (not recommended



donteverdothis.adb



Ada is NOT case sensitive: Example: sayhi, sayHi and SAYHI all refer to the same variable



Conventions:

Variable names: camel notation (eg someName)



Procedures and functions: camel notation (eg someProc)



Types: capitalized (eg Integer)



Packages: capitalized (eg Ada.Text_IO)



Warning: Operating systems can be case sensitive, so watch file names

For gnatmake, file name must be same as procedure name, but must be all lower case: sayhi.adb, not sayHi.adb

Literals

A Literal is a value that is expressed directly in a program

is a value that is expressed directly in a program Example: In the expression (2 + 3), the "2" and the "3" are literals that represent the obvious values. The expression itself represents the value 5, but the literal "5" does not itself appear in the expression.



String literal: enclosed in double quotes (eg "Hi Mom!", "")



Character literal: enclosed in single quotes (eg 'H')



Numeric Literals

Can contain underscores (eg 1_000_000_000, 1_000.000_1 )

)

Underscores must be between 2 digits





Floating point numbers require digits on each side of decimal point (eg 0.1, not .1 and not 0.





Bases 2 to 16:



binary: 2#0011_1010#







hexadecimal: 16#3A#





Exponents are represented using letter E:



10E3 is 10_000

is



1.0E3 is 1_000.0

is



2#110#E5 is 6 * 2**5

is

Enumerated types

Later we will see how to create new literals for a new type



Example:

type color is (red, blue, green); c: color := blue;

Some Java literals: Numbers.java

Example 1: Table of Squares and Cubes

This program prints a table of squares and cubes of the integers from 2 to 10: table1.adb (prettified version)



It shows the following concepts: if and for loop statements Variable declaration Assignment Integer output



Assignment Statement

Assignment symbol is :=



Equality represented by = , as in math

if a = b then c := d; elsif e /= f then g := h; end if;

Avoids assignment errors found in C/Java family

Assignment in Java and C

What is the value of d ?

boolean a = false; boolean b = true; d = 1; if (a = b) d = 2;

What about C?

i = 3; j = 4; d = 1; if (i = j) d = 2;

In C/Java, an assignment operator returns a value. The Ada assignment symbol does not return a value.

Initialization

The initial value of a variable is the current contents of its memory cell, unless it is initialized!

with ada.integer_text_io; procedure initialize is data1: Integer; begin put(data1); end initialize;

Outputs whatever value happens to be in memory at that location



No definite assignment as in java.



Watch out for subtle errors here: what happens to be in memory can vary from compiler to compiler and run to run!

Constants

An identifier that is declared to be a constant must be initialized cannot appear on the left side of an assignment



Example:

procedure constants is data1: Integer; data2: Constant Integer := 2; -- data3: Constant Integer; -- Compile error begin data1 := 1; -- data2 := 2; -- Compile error end initialize;

Is this true in Java?

For Loop Statement

No brackets: Mark end of loop with end loop;

end loop; is required even if the loop body contains only one statement

is required even if the loop body contains only one statement

Loop variable does not need to be declared

Loop variable hides variable with same name (Not recommended)



Loop variable cannot be modified



for loop includes range start .. finish

if start = finish, execute 1 time



if start > finish, execute 0 times



What does this do: for i in reverse 1 .. 10 loop



What happens here: JavaFor.java

What does the Ada version look like?

Three Kinds of Loops

For loop

for i in 1 .. 10 loop ... end loop;

While loop

i := 1; while i <= 10 loop ... i := i + 1; end loop;

General loop (infinite loop that can have an exit)

i := 1; loop exit when i = 10; ... i := i + 1; end loop;

Loop and a Half

Is exiting from the middle of a loop a good idea?



How to code input, test, process, input, test, process, input, ...



Contrast this:

input i while i /= flagValue loop process i input i end loop;

With this:

loop input i exit when i = flagValue; process i end loop;

Which is shorter, clearer, more error prone

Guidelines for using exit:

Use exit when rather than if C then exit

If possible, use only one exit statement

Keep multiple exit statements together

Named Loops

Loops can be named



Example:

Search: -- Name the loop for i in 1 .. 10 loop for j in 1 .. 20 loop ... exit when ... -- Exits inner loop ... exit Search when ... -- Exits outer loop end loop; end loop Search;

If Statements

No parens around condition



then required

required

end if; is required, even if body has only a single statement

is required, even if body has only a single statement

keyword elsif

allows multiple conditions in single if



avoids nesting



Can have as many elsif statements as desired

statements as desired

else statement optional

statement optional

Remember: if and for statements have end if; and end for;

and

Remember goal: concern for programmer

Case Statement - Multiway Selection

Java version - what is the output?

i = 3; switch (i){ case 4: System.out.println("****"); case 3: System.out.println("***"); case 2: System.out.println("**"); case 1: System.out.println("*"); default: ; }

Ada version - what is the output?

i := 3; case i is when 4 => put_line("****"); when 3 => put_line("***"); when 2 => put_line("**"); when 1 => put_line("*"); when others => null; end case;

Ada does not fall through to next case

when others required if all values not accounted for

Ada uses null; instead of solely ;

Case Statement - Multiple-Value Selection

Multiple value selection in Ada and Java:

-- Ada: case i is when 4|3 => put_line("****"); when 2|1 => put_line("**"); when others => null; end case; // Java switch (i){ case 4: case 3: System.out.println("****"); break; case 2: case 1: System.out.println("**"); break; default: ; } // End of break

Common Java Errors Avoided

When is g = h executed?

if (a == b) c = d; else e = f; g = h;

When is Sop(i) executed?

while (i++ <= 10); System.out.println(i);

Is the indentation correct on these? When is i = j executed?

if (a == b) c = d; if (e == f) g = h; else i = j; ///////////// ///////////// if (a == b) if (e == f) g = h; else i = j;

How to code these in Ada?

Example Program

Let's get some practice by writing a simple program



Let's start by reading and printing a name



Now let's sum a group of integers and calculate and print their average



First we'll input the number of numbers and read that many numbers



Can we format the average of the numbers



What if the numbers are floating point?



Let's make sure the number of numbers is non-negative



Now let's read until eof



Can we let the name be of any length?

Integer'Image - An Attribute of type Integer

Similar to Java toString() method

method

Resulting string includes a leading blank



'Image is an attribute of the type Integer

of the type Integer

Most built-in types have 'Image attribute

Package Ada.Integer_Text_IO

Integer input and output routines

Name comes from outputing an integer as text



Routine put is overloaded (ie same name but different parameters)

is overloaded (ie same name but different parameters) Ada.Text_IO.put("HI");



Ada.Integer_Text_IO.put(i);





If two packages have the same routine with the same parameter list, then the package name must be used to disambiguate the routines

parameter list, then the package name must be used to the routines

Can a single package have two routines with the same name and same parameter list?



Minimum width - eg put(i, 1)

If given 2 parameters, the second is the minimum width



Pads on left with blanks if needed



Examples:

i := 37; --12345678901 put(i, 5); -- 37 put(i, 1); --37 put(i); -- 37 -- Default width is 11

Integer Types

Type Integer is a primitive type

like java int



Variable stores a value, rather than a reference to a value



Sizes of Integer types:

Sizes of types are NOT defined by the language (unlike Java)



Values of type Integer are typically 32 bits



Values of type Long are typically 64 bits

Floating Point Types

Type Float - 32 bits on gnat

- 32 bits on gnat Type Long_Float - 64 bits on gnat

- 64 bits on gnat Primitive types



Floating point types trade precision for range

32 bit Integer has 10 significant digits in range ± 10 10



32 bit Float has about 7 significant digits for numbers as small as ± 10-44 and as large as ± 1038

Package Ada.Float_Text_IO

Contains routines for IO of floating point types



put(x)

default format: scientific notation



put(x, 3, 4, 1): fore, aft, exp

fore: minimum digits to left of decimal point



aft: digits to right of decimal point



exp: digits in exponent - 0 means no exponent

Primitive Types

Integer and Float are primitive types (ie built in)

(ie built in)

Other built in types include

Character: 8 bit (Wide_Characters are 16 bit Unicode)



Boolean: values true and false

and

Positive: range 1 .. Integer'Last



Natural: range 0 .. Integer'Last



String



Later we will see that

Character and Boolean are Enumerated types

types

Positive and Natural are actually subtypes of Integer

of Integer

String is an array of characters



Ada variables are not reference types (ie pointers) unless special steps are taken

Types and Type Checking

Ada has different and generally stronger type checking rules than Java

type checking rules than Java

Types of right and left sides of assignment must match



x: Float := 3; -- Compile error





Java would do an implicit conversion



Arithmetic operators must have the same types on both sides



y := 2 + 3.0; -- Compile error





Java would do an implicit conversion



Later we will see numeric subtypes that have more flexible rules: Ada will do implicit conversion on subtypes (eg from natural to integer)

Explicit Type Conversion

Example - this won't compile - it contains type mismatch:

i: Integer; f, g: Float; ... g := f + i;

Ada will not do an implicit conversion between integer and float

Example - will compile - the explicit type conversion fixes the type mismatch:

i: Integer; f, g: Float; ... i := 99; ... g := f + Float(i); -- float(i) returns the value of i as a float -- that is, it returns 99.0

In general, a type conversion uses the name of a type as if it were a function that takes a value of one type and returns a value of a different, related type

Similar to a java type cast (eg g = f (float) i;)

Implicit and Explicit Type Conversion

Ada will not do an implicit type conversion from integer to float



Java will do an implicit type conversion from integer to float



C will do an implicit type conversion from integer to float and float to integer



C++ will do an implicit type conversion from integer to float



C++ will do an implicit type conversion from float to integer and give a warning



Ada will do an implicit type conversion between a subtype of a type and the type (eg from natural to integer, and integer to natural)

A constraint error is raised if the value of the parent type is not valid for the subtype



Java has rules for subtypes and parent types with inheritance

Parent myP; Child myC;



myP = myC; //??



myC = myP; //??

Operators: Precedence and Associativity

Highest ** abs not exponent, absolute value, logical negation Multiplying * / mod rem mod and rem differ for negative numbers Unary adding + - Binary adding + - & & is string concatenation Relational = /= < <= > >= Note: not equal is /= rather than != Boolean (Lowest) and or xor xor is exclusive or

All operators are (generally) left associative (but sometimes parens are required)



Later we will see: in, and then, or else

They are used like operators but they are not called operators

Examples using Arithmetic Operators

6 / 2 yields 3



6.0 / 2.0 yields 3.0



6.0 / 2 does not compile

most operators require operands to be of the same type



2.0 ** 3 yields 8.0



2.0 ** (-3) yields 0.125 (ie 1/8)

Rem and Mod Operators

Summary of Behavior

x rem y and x mod y give the same result when x and y have the same sign



rem and mod differ when x and y have different signs :



Example:

13 mod 4 = 13 rem 4 = 1



-13 mod -4 = -13 rem -4 = -1





(-13) mod 4 yields 3



13 mod (-4) yields -3





(-13) rem 4 yields -1



13 rem (-4) yields 1



Sign and magnitude of the result:

The sign of the result:



sign of (x mod y) = sign of y;





sign of (x rem y) = sign of x;





The magnitude of the result - the results make these formula true:



x = y * floor(x/y) + (x mod y)





floor truncates toward negative infinity (eg trunc(-1.1) = -2)







eg -13 = 4 * floor(-13/4) + -13 mod 4 = -16 + 3







Another desired characteristic of mod: 0 ≤ x/y - floor(x/y) = (x mod y)/y < 1







x = y * trunc(x/y) + (x rem y)





trunc truncates toward zero (eg trunc(-1.1) = -1)







eg -13 = 4 * trunc(-13/4) + -13 rem 4 = -12 + -1



Motivation:

rem is useful because computer arithmetic operates like trunc (ie it rounds toward 0)



mod gives the behavior we want for modular arithmetic (eg clock arithmetic) such as this:

(X1 + X2) mod Y = ((X1 mod Y) + (X2 mod Y)) mod Y

How about Java?

Finally, note that rem and mod have higher precedence than unary minus so -3 mod 4 means -(3 mod 4)

Examples using Relational and Boolean Operators

When and and or are mixed, parens are required (ie user must specify order of evaluation)

and are mixed, parens (ie user must specify order of evaluation)

Example: if (a < b or c < d) and e < f then



Parens are also required if multiple relational operators are used:

Example: if (a < b) = true then

Example using String Concatenation Operator

put_line("Hello, this certainly is a " & "really long line!");

Short Circuit: and then, or else

and then and or else are short circuit versions of and and or

and are short circuit versions of and

Short circuit control forms don't evaluate the right operand if the result is known from the left operand



Non-Short circuit operators always evaluate both operands



Examples:

if d /= 0 and then (n / d) > 3 then ... if x = null or else x.value = probe then ...

Good for processing linked data structures!

Java: What do these do?

if (a == b && c++ == d) ... if (a == b & c++ == d) ...

in Membership Test

if i in 1 .. 10 then