```-- Demonstrates using a record type as a parameter

procedure record_pairs is

type Pair is record   -- Records have Fields
x: Integer;
y: Integer;
end record;

-- Output a pair, with a label
procedure putPair(s: String; p: Pair) is
begin
put(s);
put(p.x);
put(p.y);
new_line;
end putPair;

-- Swap two pairs
-- In out parameters
-- Really swaps: value semantics
-- How else could we do this?
procedure swapPair(p1, p2: in out Pair) is
temp: constant Pair := p1;
begin
p1 := p2;
p2 := temp;
end swapPair;
procedure swapPair2(p1, p2: in out Pair) is
tx: constant Integer := p1.x;
ty: constant Integer := p1.y;
begin
p1.x := p2.x;
p1.y := p2.y;
p2.x := tx;
p2.y := ty;
end swapPair2;

function m_dist_to_origin(p: pair) return Natural is
begin
return abs p.x + abs p.y;
end m_dist_to_origin;

function m_dist(p1, p2: pair) return Natural is
begin
return abs (p1.x - p2.x) + abs (p1.y - p2.y);
end m_dist;

-- Declaration allocates
p1, p2, p3, p4: Pair;   -- Allocate 4 pairs

begin
put(p1.x);      -- Access fields
put(p1.y);      -- What values in fields?
new_line;

p1.x := 1;              -- Assign fields
p1.y := 2;

put(p1.x);   put(p1.y);    new_line;

p2.x := p1.x + 10;       -- Access fields
p2.y := p1.x + 10;

putPair("p2: ", p2);     -- Use IO routine

p3 := p1;
p1.x := 99;
if p1 = p3 then
put_line("p1 and p3 are the same");
else
put_line("p1 and p3 are different");
end if;
putPair("p1: ", p1);
putPair("p3: ", p3);

p4 := (33, 44);   -- Aggregate assignment (positional)
-- p4 := (y => 33, others => 44);   -- (keyword)

putPair("p1: ", p1);
putPair("p4: ", p4);

swapPair(p1, p4);

putPair("p1: ", p1);
putPair("p4: ", p4);
swapPair2(p1, p4);

putPair("p1: ", p1);
putPair("p4: ", p4);

p4 := (1, -1);
putPair("p1: ", p1);
putPair("p4: ", p4);
put(m_dist_to_origin(p4));
put(m_dist(p1, p4));

end record_pairs;
```