Hello World & Structure
Hello, World
program Hello;
begin
writeln('Hello, World!');
end. with Ada.Text_IO; use Ada.Text_IO;
procedure Example is
begin
Put_Line("Hello, World!");
end Example; Ada packages replace Pascal's implicit I/O. The main unit is a
procedure, not a program. On Compiler Explorer the file is always example.adb, so the main procedure must be named Example.Compiling
{ fpc hello.pas }
{ ./hello } -- gnatmake example.adb
-- ./example gnatmake compiles and links in one step. Individual phases use gcc -c, gnatbind, and gnatlink.Printing integers and floats
program PrintDemo;
begin
writeln(42);
writeln(3.14:8:2);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Float_Text_IO;
procedure Example is
begin
Ada.Integer_Text_IO.Put(42, Width => 0); New_Line;
Ada.Float_Text_IO.Put(3.14, Fore => 1, Aft => 2, Exp => 0); New_Line;
end Example; Put_Line accepts only strings. Numeric output goes through Ada.Integer_Text_IO.Put and Ada.Float_Text_IO.Put. Using them fully qualified (no use) avoids overload ambiguity when both packages are imported.Importing packages
{ Pascal: uses makes all names directly visible }
program Demo;
uses SysUtils;
begin
writeln(IntToStr(42));
writeln(UpperCase('hello'));
end. -- with only: all names are qualified
-- with Ada.Text_IO;
-- Ada.Text_IO.Put_Line("qualified");
-- with + use: names visible directly (like Pascal uses)
with Ada.Text_IO; use Ada.Text_IO;
procedure Example is
begin
Put_Line("unqualified, from use Ada.Text_IO");
Ada.Text_IO.Put_Line("qualified still works too");
end Example; with makes a package visible (you can qualify its names). use additionally brings names into direct scope — equivalent to Pascal's uses. You may with without use to keep namespaces explicit.Variables & Types
Variable declarations
program Demo;
var
count : Integer;
ratio : Real;
flag : Boolean;
begin
count := 10;
ratio := 3.14;
flag := True;
writeln(count, ' ', ratio:4:2, ' ', flag);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Float_Text_IO;
procedure Example is
Count : Integer := 10;
Ratio : Float := 3.14;
Flag : Boolean := True;
begin
Ada.Integer_Text_IO.Put(Count, Width => 0); New_Line;
Ada.Float_Text_IO.Put(Ratio, Fore => 1, Aft => 2, Exp => 0); New_Line;
Put_Line(Boolean'Image(Flag));
end Example; Ada declarations live between
is and begin. Variables may carry an initializer (:= value) inline. Using Ada.Integer_Text_IO fully qualified avoids overload conflicts with Ada.Text_IO.Put.Integer types
program Demo;
var
small : ShortInt; { -128..127 }
medium : Integer; { 32-bit }
big : Int64; { 64-bit }
pos : Word; { 0..65535 }
begin
medium := 1000000;
writeln(medium);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
Small : Short_Integer := 0;
Medium : Integer := 1_000_000;
Big : Long_Long_Integer := 0;
Natural_N : Natural := 0; -- >= 0
Positive_N : Positive := 1; -- >= 1
begin
Ada.Integer_Text_IO.Put(Medium, Width => 0); New_Line;
end Example; Ada provides
Natural (≥ 0) and Positive (≥ 1) as predefined subtypes of Integer. Assigning a negative value to Natural raises Constraint_Error at runtime.Boolean & logical operators
program Demo;
var
ready, done: Boolean;
begin
ready := True;
done := False;
if ready and not done then
writeln('Go!')
else
writeln('Wait');
end. with Ada.Text_IO; use Ada.Text_IO;
procedure Example is
Ready : Boolean := True;
Done : Boolean := False;
begin
if Ready and then not Done then
Put_Line("Go!");
else
Put_Line("Wait");
end if;
end Example; Ada keeps Pascal's
and/or/not keywords but adds and then and or else for short-circuit evaluation. and then is idiomatic Ada; bare and always evaluates both sides.Constants
program Demo;
const
MaxSize = 100;
Pi = 3.14159;
Greeting = 'Hello';
begin
writeln(MaxSize);
writeln(Greeting);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
Max_Size : constant Integer := 100;
Pi : constant := 3.14159;
Greeting : constant String := "Hello";
begin
Ada.Integer_Text_IO.Put(Max_Size, Width => 0); New_Line;
Put_Line(Greeting);
end Example; Ada constants use
constant as a modifier on the type annotation. A constant without a type (constant := 3.14159) is a universal numeric constant that adapts to context — like a Pascal untyped constant.Named type declarations
program Demo;
type
Color = (Red, Green, Blue);
Score = 0..100;
var
hue : Color;
grade: Score;
begin
hue := Green;
grade := 87;
writeln(Ord(hue));
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
type Color is (Red, Green, Blue);
type Score is new Integer range 0..100;
Hue : Color := Green;
Grade : Score := 87;
begin
Ada.Integer_Text_IO.Put(Color'Pos(Hue), Width => 0); New_Line;
Ada.Integer_Text_IO.Put(Integer(Grade), Width => 0); New_Line;
end Example; type Score is new Integer range 0..100 creates a derived type — a distinct type that cannot be mixed with plain Integer without an explicit conversion. Pascal's type Score = 0..100 creates a subrange that still interoperates freely with Integer.Strings
Fixed-length strings
program Demo;
var
name: String[10];
begin
name := 'Alice';
writeln(name, ' len=', Length(name));
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
Name : String(1..10) := "Alice ";
begin
Put_Line(Name);
Ada.Integer_Text_IO.Put(Name'Length, Width => 0); New_Line;
end Example; Ada's
String type is a fixed-length array of Character. The bounds are part of the type — String(1..5) and String(1..10) are incompatible. Use Unbounded_String when the length varies at runtime.Variable-length strings
program Demo;
var
name: AnsiString;
begin
name := 'Alice';
name := name + '!';
writeln(name, ' len=', Length(name));
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
procedure Example is
Name : Unbounded_String := To_Unbounded_String("Alice");
begin
Append(Name, "!");
Put_Line(To_String(Name));
Ada.Integer_Text_IO.Put(Length(Name), Width => 0); New_Line;
end Example; Unbounded_String from Ada.Strings.Unbounded is the variable-length string type, analogous to Pascal's AnsiString. To_String converts back to a fixed String when needed.String concatenation
program Demo;
var
first, last, full: AnsiString;
begin
first := 'Ada';
last := 'Lovelace';
full := first + ' ' + last;
writeln(full);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
procedure Example is
First : Unbounded_String := To_Unbounded_String("Ada");
Last : Unbounded_String := To_Unbounded_String("Lovelace");
Full : Unbounded_String;
begin
Full := First & " " & Last;
Put_Line(To_String(Full));
end Example; Ada uses
& for string concatenation instead of Pascal's +. With Unbounded_String, concatenation extends the string dynamically. With fixed String, the result length must be known at compile time.String attributes & slices
program Demo;
var
word: AnsiString;
sub : AnsiString;
begin
word := 'Hello';
sub := Copy(word, 2, 3); { 'ell' }
writeln(sub, ' len=', Length(word));
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
Word : constant String := "Hello";
Sub : constant String := Word(2..4); -- "ell"
begin
Put_Line(Sub);
Ada.Integer_Text_IO.Put(Word'Length, Width => 0); New_Line;
end Example; Ada strings support array slicing with
(Low..High) notation. Attributes like 'Length, 'First, and 'Last replace Pascal's Length() function and manual indexing.Subtypes & Constraints
Subrange types
program Demo;
type
MonthRange = 1..12; { type and var names must differ: }
ScoreRange = 0..100; { Pascal is case-insensitive! }
var
month: MonthRange;
grade: ScoreRange;
begin
month := 6;
grade := 87;
writeln(month, ' ', grade);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
subtype Month_Type is Integer range 1..12;
subtype Score_Type is Integer range 0..100;
Month : Month_Type := 6;
Grade : Score_Type := 87;
begin
Ada.Integer_Text_IO.Put(Month, Width => 0); New_Line;
Ada.Integer_Text_IO.Put(Grade, Width => 0); New_Line;
end Example; Ada's
subtype is semantically identical to Pascal's subrange type. Assigning a value outside the range raises Constraint_Error at runtime — or earlier if the compiler can prove the violation statically.Derived types (distinct units)
program Demo;
{ Pascal: type aliases still interoperate freely }
type
Metres = Real;
Seconds = Real;
var
distance: Metres;
time : Seconds;
begin
distance := 100.0;
time := distance; { no error -- same base type }
writeln(time:4:1);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_Text_IO;
procedure Example is
type Metres is new Float;
type Seconds is new Float;
Distance : Metres := 100.0;
-- Time : Seconds := Distance; -- compile error: incompatible types
Same : Metres := Distance;
begin
Ada.Float_Text_IO.Put(Float(Same), Fore => 1, Aft => 1, Exp => 0);
New_Line;
end Example; Ada's
type T is new Base creates a genuinely distinct type. Metres and Seconds cannot be mixed arithmetically — accidental unit errors become compile errors. Pascal's type declarations create aliases that still freely interoperate.Constraint_Error at runtime
program Demo;
uses SysUtils;
type Month = 1..12;
var m: Month;
begin
try
m := 13;
except
on E: ERangeError do
writeln('Range error: ', E.Message);
end;
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
subtype Month_Type is Integer range 1..12;
Month : Month_Type := 6;
begin
begin
Month := 13;
exception
when Constraint_Error =>
Put_Line("Constraint_Error: value out of range");
end;
Ada.Integer_Text_IO.Put(Month, Width => 0); New_Line;
end Example; Ada raises
Constraint_Error for any range or type constraint violation. Exception handlers use exception when E => at the end of any begin...end block — no separate try keyword needed.Control Flow
If / elsif
program Demo;
var score: Integer;
begin
score := 75;
if score >= 90 then
writeln('A')
else if score >= 80 then
writeln('B')
else if score >= 70 then
writeln('C')
else
writeln('F');
end. with Ada.Text_IO; use Ada.Text_IO;
procedure Example is
Score : Integer := 75;
begin
if Score >= 90 then
Put_Line("A");
elsif Score >= 80 then
Put_Line("B");
elsif Score >= 70 then
Put_Line("C");
else
Put_Line("F");
end if;
end Example; Ada uses
elsif (not else if or elseif) and closes the whole chain with end if;. No begin/end pair is needed inside branches.Case statement
program Demo;
var month: Integer;
begin
month := 6;
case month of
12, 1, 2 : writeln('Winter');
3..5 : writeln('Spring');
6..8 : writeln('Summer');
9..11 : writeln('Autumn');
end;
end. with Ada.Text_IO; use Ada.Text_IO;
procedure Example is
Month : Integer := 6;
begin
case Month is
when 12 | 1 | 2 => Put_Line("Winter");
when 3..5 => Put_Line("Spring");
when 6..8 => Put_Line("Summer");
when 9..11 => Put_Line("Autumn");
when others => Put_Line("Invalid");
end case;
end Example; Ada uses
when clauses with | for multiple values, closes with end case;, and requires when others => if not all values are covered. Pascal uses commas and colons instead.Short-circuit operators
{ and then / or else require {$mode delphi} in FPC;
use and / or in {$mode objfpc} }
program Demo;
var
numbers: array[1..5] of Integer;
index : Integer;
begin
numbers[1] := 42;
index := 1;
if (index >= 1) and (index <= 5) and
(numbers[index] > 0) then
writeln('Valid positive: ', numbers[index]);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
Numbers : array(1..5) of Integer := (42, 0, 0, 0, 0);
Index : Integer := 1;
begin
if Index >= 1 and then Index <= 5 and then
Numbers(Index) > 0 then
Ada.Integer_Text_IO.Put(Numbers(Index), Width => 0); New_Line;
end if;
end Example; Ada's
and then and or else are short-circuit operators — the right side is not evaluated if the left side determines the result. Bare and/or always evaluate both sides. Ada also uses parentheses () for array indexing instead of [].Loops
For loop
program Demo;
var i: Integer;
begin
for i := 1 to 5 do
write(i, ' ');
writeln;
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
begin
for Index in 1..5 loop
Ada.Integer_Text_IO.Put(Index, Width => 0);
Put(" ");
end loop;
New_Line;
end Example; Ada uses
in instead of :=/to, and closes with end loop;. The loop variable is declared implicitly, is read-only inside the loop, and does not exist after the loop ends.Counting down
program Demo;
var i: Integer;
begin
for i := 5 downto 1 do
write(i, ' ');
writeln;
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
begin
for Index in reverse 1..5 loop
Ada.Integer_Text_IO.Put(Index, Width => 0);
Put(" ");
end loop;
New_Line;
end Example; Ada uses
in reverse to count down; downto does not exist. The range is still written low..high — the reverse keyword drives iteration backwards.While loop
program Demo;
var count: Integer;
begin
count := 1;
while count <= 5 do
begin
write(count, ' ');
Inc(count);
end;
writeln;
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
Count : Integer := 1;
begin
while Count <= 5 loop
Ada.Integer_Text_IO.Put(Count, Width => 0);
Put(" ");
Count := Count + 1;
end loop;
New_Line;
end Example; Ada replaces Pascal's
begin/end pair inside while with loop...end loop;. There is no Inc builtin — increment is written as Count := Count + 1.Repeat-until / loop-exit
program Demo;
var count: Integer;
begin
count := 1;
repeat
write(count, ' ');
Inc(count);
until count > 5;
writeln;
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
Count : Integer := 1;
begin
loop
Ada.Integer_Text_IO.Put(Count, Width => 0);
Put(" ");
Count := Count + 1;
exit when Count > 5;
end loop;
New_Line;
end Example; Ada has no
repeat...until. The idiom is loop ... exit when Cond; end loop;. The exit when can appear anywhere in the body, not just at the end.Iterating over an array
program Demo;
var
numbers: array[1..5] of Integer;
i: Integer;
begin
numbers[1] := 10; numbers[2] := 20;
numbers[3] := 30; numbers[4] := 40;
numbers[5] := 50;
for i := 1 to 5 do
write(numbers[i], ' ');
writeln;
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
Numbers : array(1..5) of Integer := (10, 20, 30, 40, 50);
begin
for Index in Numbers'Range loop
Ada.Integer_Text_IO.Put(Numbers(Index), Width => 0);
Put(" ");
end loop;
New_Line;
end Example; Ada arrays use parentheses for indexing —
Numbers(Index) not Numbers[Index]. The 'Range attribute yields the array's declared bounds, so the loop automatically covers all elements.Procedures & Functions
Procedures
program Demo;
procedure Greet(name: String);
begin
writeln('Hello, ', name, '!');
end;
begin
Greet('Alice');
end. with Ada.Text_IO; use Ada.Text_IO;
procedure Example is
procedure Greet(Name : String) is
begin
Put_Line("Hello, " & Name & "!");
end Greet;
begin
Greet("Alice");
end Example; Ada procedures are declared in the declarative region between
is and begin. The body starts with is (not a semicolon) and the end repeats the procedure name. Parameters default to in mode (read-only).Functions
program Demo;
function Square(n: Integer): Integer;
begin
result := n * n;
end;
begin
writeln(Square(7));
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
function Square(N : Integer) return Integer is
begin
return N * N;
end Square;
begin
Ada.Integer_Text_IO.Put(Square(7), Width => 0); New_Line;
end Example; Ada uses
return in both the signature (return Integer) and the body (return N * N). Pascal's result := (or FunctionName :=) becomes an explicit return statement.In / out parameters
program Demo;
procedure Swap(var a, b: Integer);
var temp: Integer;
begin
temp := a;
a := b;
b := temp;
end;
var x, y: Integer;
begin
x := 5; y := 10;
Swap(x, y);
writeln(x, ' ', y);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
procedure Swap(A : in out Integer; B : in out Integer) is
Temp : Integer := A;
begin
A := B;
B := Temp;
end Swap;
X : Integer := 5;
Y : Integer := 10;
begin
Swap(X, Y);
Ada.Integer_Text_IO.Put(X, Width => 0); Put(" ");
Ada.Integer_Text_IO.Put(Y, Width => 0); New_Line;
end Example; Pascal's
var parameter becomes Ada's in out mode. Ada also distinguishes in (read-only, the default) and out (write-only — the parameter's initial value is not readable).Nested subprograms
program Demo;
procedure Outer;
procedure Inner(n: Integer);
begin
writeln('Inner: ', n);
end;
begin
Inner(42);
end;
begin
Outer;
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
procedure Outer is
procedure Inner(N : Integer) is
begin
Put("Inner: ");
Ada.Integer_Text_IO.Put(N, Width => 0); New_Line;
end Inner;
begin
Inner(42);
end Outer;
begin
Outer;
end Example; Ada fully supports nested subprograms just as Pascal does. Inner subprograms can access outer variables and may themselves contain further nested declarations.
Records
Record types
program Demo;
type
Point = record
x, y: Integer;
end;
var origin: Point;
begin
origin.x := 0;
origin.y := 0;
writeln(origin.x, ' ', origin.y);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
type Point is record
X, Y : Integer;
end record;
Origin : Point;
begin
Origin.X := 0;
Origin.Y := 0;
Ada.Integer_Text_IO.Put(Origin.X, Width => 0); Put(" ");
Ada.Integer_Text_IO.Put(Origin.Y, Width => 0); New_Line;
end Example; Ada's
record...end record is nearly identical to Pascal's record...end. Field access uses the same dot notation. Ada convention capitalises field names (X, Y).Record aggregates
program Demo;
type
Point = record x, y: Integer; end;
var
p1, p2: Point;
begin
p1.x := 3; p1.y := 4; { field-by-field init }
p2.x := 0; p2.y := 0;
writeln(p1.x, ' ', p1.y);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
type Point is record X, Y : Integer; end record;
P1 : Point := (X => 3, Y => 4); -- named aggregate
P2 : Point := (0, 0); -- positional aggregate
begin
Ada.Integer_Text_IO.Put(P1.X, Width => 0); Put(" ");
Ada.Integer_Text_IO.Put(P1.Y, Width => 0); New_Line;
Ada.Integer_Text_IO.Put(P2.X, Width => 0); Put(" ");
Ada.Integer_Text_IO.Put(P2.Y, Width => 0); New_Line;
end Example; Ada record aggregates use named associations (
Field => Value) or positional order. Named form is preferred — it is self-documenting and immune to field reordering.Procedures operating on records
program Demo;
type
Person = record
name: String[20];
age : Integer;
end;
procedure PrintPerson(p: Person);
begin
writeln(p.name, ' age ', p.age);
end;
var alice: Person;
begin
alice.name := 'Alice';
alice.age := 30;
PrintPerson(alice);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
type Person is record
Name : String(1..5);
Age : Integer;
end record;
procedure Print_Person(P : Person) is
begin
Put_Line(P.Name & " age" & Integer'Image(P.Age));
end Print_Person;
Alice : Person := (Name => "Alice", Age => 30);
begin
Print_Person(Alice);
end Example; Ada records are passed by value to
in parameters (the default), just like Pascal. Use in out to allow modification. The Integer'Image attribute converts an integer to its string representation.Packages
Package structure
{ Pascal unit: one file }
unit Geometry;
interface
type Point = record x, y: Real; end;
function Distance(a, b: Point): Real;
implementation
uses Math;
function Distance(a, b: Point): Real;
begin
result := Sqrt((b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y-a.y));
end;
end. -- geometry.ads (spec)
package Geometry is
type Point is record X, Y : Float; end record;
function Distance(A, B : Point) return Float;
end Geometry;
-- geometry.adb (body)
with Ada.Numerics.Elementary_Functions;
package body Geometry is
function Distance(A, B : Point) return Float is
DX : Float := B.X - A.X;
DY : Float := B.Y - A.Y;
begin
return Ada.Numerics.Elementary_Functions.Sqrt(DX*DX + DY*DY);
end Distance;
end Geometry; Ada splits every package into a spec file (
.ads — the public interface) and a body file (.adb — the implementation). The spec is visible to callers; the body is private. This is a stricter version of Pascal's interface/implementation split.Qualified vs unqualified names
{ Pascal: uses makes all names directly visible }
{ uses SysUtils; }
{ writeln(IntToStr(42)); -- unqualified } -- with only: all names are qualified
with Ada.Text_IO;
procedure Example is
begin
Ada.Text_IO.Put_Line("qualified");
end Example;
-- with + use: names visible directly
-- with Ada.Text_IO; use Ada.Text_IO;
-- procedure Example is
-- begin
-- Put_Line("unqualified");
-- end Example; with makes a package visible (you can qualify its names). use additionally brings names into direct scope — equivalent to Pascal's uses. You may with without use to keep namespaces explicit.Access Types
Access types (pointers)
program Demo;
var
ptr: ^Integer;
begin
New(ptr);
ptr^ := 42;
writeln(ptr^);
Dispose(ptr);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
type Int_Access is access Integer;
Ptr : Int_Access := new Integer'(42);
begin
Ada.Integer_Text_IO.Put(Ptr.all, Width => 0); New_Line;
Ptr.all := 55;
Ada.Integer_Text_IO.Put(Ptr.all, Width => 0); New_Line;
end Example; Ada uses
access T instead of Pascal's ^T, and .all to dereference instead of ^. new Integer'(42) allocates and initialises in one step. No Dispose is needed — the runtime manages access object lifetimes.Access to records
program Demo;
type
PersonPtr = ^Person;
Person = record
name: String[5];
age : Integer;
end;
var ptr: PersonPtr;
begin
New(ptr);
ptr^.name := 'Bob';
ptr^.age := 25;
writeln(ptr^.name, ' ', ptr^.age);
Dispose(ptr);
end. with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Example is
type Person is record
Name : String(1..3);
Age : Integer;
end record;
type Person_Access is access Person;
Ptr : Person_Access := new Person;
begin
Ptr.Name := "Bob";
Ptr.Age := 25;
Put_Line(Ptr.Name);
Ada.Integer_Text_IO.Put(Ptr.Age, Width => 0); New_Line;
end Example; Ada automatically dereferences access values for record field access —
Ptr.Name is shorthand for Ptr.all.Name. No ^. or -> needed. The compiler inserts the dereference transparently.Exception Handling
Exception handling
program Demo;
uses SysUtils;
var n, d: Integer;
begin
d := 0;
try
n := 10 div d;
except
on E: EDivByZero do
writeln('Division by zero: ', E.Message);
on E: Exception do
writeln('Error: ', E.Message);
end;
end. with Ada.Text_IO; use Ada.Text_IO;
procedure Example is
N : Integer;
D : Integer := 0;
begin
begin
N := 10 / D;
exception
when Constraint_Error =>
Put_Line("Numeric error (div by zero)");
when others =>
Put_Line("Unexpected error");
end;
end Example; Ada exception handlers live at the end of any
begin...end block, introduced by the exception keyword — no separate try. Multiple when clauses name specific exceptions; when others is the catch-all.Raising exceptions
program Demo;
uses SysUtils;
procedure CheckAge(age: Integer);
begin
if age < 0 then
raise Exception.Create('Negative age: ' + IntToStr(age));
end;
begin
try
CheckAge(-1);
except
on E: Exception do writeln(E.Message);
end;
end. with Ada.Text_IO; use Ada.Text_IO;
procedure Example is
procedure Check_Age(Age : Integer) is
begin
if Age < 0 then
raise Constraint_Error with "Negative age: " & Integer'Image(Age);
end if;
end Check_Age;
begin
begin
Check_Age(-1);
exception
when Constraint_Error =>
Put_Line("Caught: negative age");
end;
end Example; Ada's
raise ExceptionName with "message" attaches a detail string without needing an exception object. The optional with clause provides the message that appears in Exception_Message(E).Custom exceptions
program Demo;
uses SysUtils;
type
EValueError = class(Exception);
procedure Validate(n: Integer);
begin
if n > 100 then
raise EValueError.Create('Too large: ' + IntToStr(n));
end;
begin
try
Validate(200);
except
on E: EValueError do writeln('Value error: ', E.Message);
end;
end. with Ada.Text_IO; use Ada.Text_IO;
procedure Example is
Value_Error : exception;
procedure Validate(N : Integer) is
begin
if N > 100 then
raise Value_Error with "Too large: " & Integer'Image(N);
end if;
end Validate;
begin
begin
Validate(200);
exception
when Value_Error =>
Put_Line("Value error: value out of range");
end;
end Example; Declaring a custom exception in Ada is a single line — no class definition needed. The identifier is just a constant of type
Exception. Pascal (FPC) uses class declarations (class(Exception)) for the same purpose.