File: unitmanager-unitstore.adb

package info (click to toggle)
spark 2012.0.deb-9
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 29,260 kB
  • ctags: 3,098
  • sloc: ada: 186,243; cpp: 13,497; makefile: 685; yacc: 440; lex: 176; ansic: 119; sh: 16
file content (149 lines) | stat: -rw-r--r-- 5,826 bytes parent folder | download | duplicates (3)
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset is free software; you can redistribute it and/or modify it
-- under terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 3, or (at your option) any later
-- version. The SPARK toolset is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-- Public License for more details. You should have received a copy of the GNU
-- General Public License distributed with the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

with Ada.Characters.Handling;
with E_Strings;
with E_Strings.Not_SPARK;
with GNAT.HTable;

package body UnitManager.UnitStore is
   ---------------------------------------------------------------------------
   -- This package body is NOT SPARK, and should not be                     --
   -- presented to the Examiner                                             --
   ---------------------------------------------------------------------------

   Max_Units : constant := 1000;
   type Index is range 1 .. Max_Units;

   function Hash (Id : Unit.Id) return Index;

   package Unit_Table is new GNAT.HTable.Simple_HTable (
                                                        Header_Num => Index,
                                                        Element => Unit.Object,
                                                        No_Element => Unit.Null_Object,
                                                        Key => Unit.Id,
                                                        Hash => Hash,
                                                        Equal => Unit.Are_Equal);

   ---------------------------------------------------------------------------

   function Key (From_Id : Unit.Id) return E_Strings.T
   --
   -- Returns a unique key (string) for the unit.
   is
      Result : E_Strings.T := E_Strings.Empty_String;
   begin
      E_Strings.Append_Examiner_String (E_Str1 => Result,
                                        E_Str2 => From_Id.The_Name);
      E_Strings.Append_String (E_Str => Result,
                               Str   => Unit.Kind'Image (From_Id.The_Kind));
      return Result;
   end Key;

   --------------------------------------------------------------------------------

   function Hash (Id : Unit.Id) return Index is
      The_Key : E_Strings.T;

      function Raw_Hash (Key : String) return Index is
         type Uns is mod 2 ** 32;

         -- GNAT-Specific Import here
         function Rotate_Left (Value  : Uns;
                               Amount : Natural) return Uns;
         pragma Import (Intrinsic, Rotate_Left);

         Tmp : Uns := 0;
      begin
         for J in Key'Range loop
            Tmp := Rotate_Left (Value  => Tmp,
                                Amount => 1) + Character'Pos (Ada.Characters.Handling.To_Upper (Key (J)));
         end loop;

         return Index'First + Index'Base (Tmp mod Index'Range_Length); -- also GNAT-defined attrib
      end Raw_Hash;

   begin
      The_Key := Key (From_Id => Id);
      return Raw_Hash (Key => E_Strings.Not_SPARK.Get_String (E_Str => The_Key));
   end Hash;

   --------------------------------------------------------------------------------

   procedure Add (The_Unit : in     Unit.Object;
                  Added    :    out Boolean) is
   begin
      if Get (The_Unit.The_Id) = Unit.Null_Object then
         Added := True;
         Unit_Table.Set (K => The_Unit.The_Id,
                         E => The_Unit);
      else
         Added := False;
      end if;
   end Add;

   --------------------------------------------------------------------------------

   function Get (The_Unit : Unit.Id) return Unit.Object is
   begin
      return Unit_Table.Get (K => The_Unit);
   end Get;

   --------------------------------------------------------------------------------

   function Get_Body_Unit (With_Name : in E_Strings.T) return Unit.Object is
      The_Unit : Unit.Object;
   begin
      for Kind in Unit.Kind range Unit.Main_Program_Unit .. Unit.Separate_Body_Unit loop
         The_Unit := Get (The_Unit => Unit.Id'(The_Name => With_Name,
                                               The_Kind => Kind));
         exit when The_Unit /= Unit.Null_Object;
      end loop;
      return The_Unit;
   end Get_Body_Unit;

   --------------------------------------------------------------------------------

   function Get_Specification_Unit (With_Name : in E_Strings.T) return Unit.Object is
      The_Unit : Unit.Object;
   begin
      for Kind in Unit.Specification_Unit loop
         The_Unit := Get (The_Unit => Unit.Id'(The_Name => With_Name,
                                               The_Kind => Kind));
         exit when The_Unit /= Unit.Null_Object;
      end loop;
      return The_Unit;
   end Get_Specification_Unit;

   --------------------------------------------------------------------------------

   function Get_All_Units return  Units.Stack is
      CurrentUnit : Unit.Object;
      The_Units   : Units.Stack := Units.NullStack;
   begin
      CurrentUnit := Unit_Table.Get_First;
      while CurrentUnit /= Unit.Null_Object loop
         Units.Push (TheStack => The_Units,
                     TheUnit  => CurrentUnit.The_Id);
         CurrentUnit := Unit_Table.Get_Next;
      end loop;
      return The_Units;
   end Get_All_Units;

begin
   Unit_Table.Reset;
end UnitManager.UnitStore;