-- Demonstrates using a record type as a parameter

with Ada.Integer_Text_IO; use  Ada.Integer_Text_IO;
with Ada.Text_IO;         use  Ada.Text_IO;

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;