PONY λ M2 Modula-2

Pascal.CodeCompared.To/Ada

An interactive executable cheatsheet comparing Pascal and Ada

Free Pascal 3.2.2 Ada 2022 (GNAT 16.1)
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.