summaryrefslogtreecommitdiff
path: root/more-types/src/types.adb
blob: 4e7590f27e28d57fab9bec945d7a4fb7ab1528f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
with Ada.Text_IO; use Ada.Text_IO;

procedure Types is

   -----------------------------------------------------------------------------
   -- Record initialization.
   -----------------------------------------------------------------------------
   procedure Test_Point is
      type Point is record
         X : Integer := 0;
         Y : Integer := 0;
      end record;

      Origin_1 : Point;                       -- Default initialization.
      Origin_2 : Point := (0, 0);             -- Explicit, unnamed.
      Origin_3 : Point := (X => 0, Y => 0);   -- Explicit, named.
      Origin_4 : Point := (X => <>, Y => <>); -- Explicit, using defaults.
      Origin_5 : Point := (X | Y => 0);       -- Initialize both values.
      Origin_6 : Point := Point'(0,0);        -- Qualified expression.
   begin
      Put_Line ("Origin: " & Integer'Image (Origin_5.X) & ", "
                & Integer'Image (Origin_5.Y));
   end Test_Point;

   -----------------------------------------------------------------------------
   -- Pointers.
   -----------------------------------------------------------------------------
   procedure Test_Pointer is
      type Month_Type is (Jan, Feb, Mar, Apr, May, Jun,
                          Jul, Aug, Sep, Oct, Nov, Dec);

      type Date is record
         Day : Integer range 1 .. 31;
         Month : Month_Type;
         Year : Integer;
      end record;

      -- Access types are nominally typed, not structurally typed.
      -- If we "own" a type X, we typically also declare an access type named
      -- X_Acc, so that there is a canonical name for the access type to X.
      type Date_Acc is access Date; -- Pointer to Date type.
      type Different_Date_Acc is access Date; -- Different type.

      Null_Date : Date_Acc := null;

      -- Allocate values of the access type using the 'new' keyword.
      D : Date_Acc := new Date;

      -- Constraints can be given when instantiating the type.
      Buffer : access String := new String(1 .. 5);

      -- We can also initialize along with the allocation.
      Hello_Str : access String := new String'("Hello");

      procedure Test_Null (D : Date_Acc; Name : String) is
      begin
         -- Dereferencing of D happens implicitly. Here we can treat D as an
         -- actual Date.
         if D = null then
            Put_Line (Name & " is null");
         else
            Put_Line (Name & " is not null");
         end if;
      end Test_Null;

   begin
      Test_Null (Null_Date, "Null_Date");
      Test_Null (D, "D");
   end Test_Pointer;

   -----------------------------------------------------------------------------
   -- Mutually recursive types.
   --
   -- Similar to C++, we can forward-declare a type to break the loop.
   -----------------------------------------------------------------------------

   procedure Test_MyList is
      type MyList;
      type MyList_Acc is access MyList;

      type MyList is record
         Value : Integer := 0;
         Next  : MyList_Acc := null;
      end record;

      function Cons (X : Integer; L : MyList_Acc) return MyList_Acc is
         Head : MyList_Acc := new MyList;
      begin
         Head.Value := X;
         Head.Next := L;
         return Head;
      end Cons;

      procedure Print_List (L : access constant MyList) is
         Node : access constant MyList := L;
      begin
         Put ("[");
         while Node /= null loop
            Put (Integer'Image (Node.Value) & " ");
            Node := Node.next;
         end loop;
         Put_Line ("]");
      end Print_List;

      InitialList : MyList_Acc := new MyList'(4, null);
      ModifiedList : MyList_Acc;
   begin
      ModifiedList := Cons (1, Cons (2, Cons (3, InitialList)));
      Print_List (ModifiedList);
   end Test_MyList;

begin
   Test_Point;
   Test_Pointer;
   Test_MyList;
end Types;