-------------------------------------------------------------------------------
-- (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 E_Strings;

separate (Sem)
procedure Check_Priority_Range
  (Error_Sym   : in     Dictionary.Symbol;
   Scope       : in     Dictionary.Scopes;
   Pragma_Kind : in     Dictionary.RavenscarPragmas;
   Err_Pos     : in     LexTokenManager.Token_Position;
   Value       : in     Maths.Value;
   Value_Rep   :    out LexTokenManager.Lex_String)
is
   type Lookup_Token_Table is array (Dictionary.RavenscarPragmas) of LexTokenManager.Lex_String;

   Lookup_Token : constant Lookup_Token_Table :=
     Lookup_Token_Table'
     (Dictionary.Priority          => LexTokenManager.Priority_Token,
      Dictionary.InterruptPriority => LexTokenManager.Any_Priority_Token,
      Dictionary.AttachHandler     => LexTokenManager.Interrupt_Priority_Token);

   System_Sym         : Dictionary.Symbol;
   Priority_Sym       : Dictionary.Symbol;
   Result             : Maths.Value;
   Unused             : Maths.ErrorCode;
   Lower_OK, Upper_OK : Boolean;
begin
   Value_Rep := LexTokenManager.Null_String;
   -- do we have a value to check?
   if Maths.IsIntegerValue (Value) then
      -- is System shadowed or declared in config file?
      System_Sym :=
        Dictionary.LookupItem
        (Name              => LexTokenManager.System_Token,
         Scope             => Dictionary.GlobalScope,
         Context           => Dictionary.ProgramContext,
         Full_Package_Name => False);

      if not Dictionary.Is_Null_Symbol (System_Sym) then
         -- System exists, what about the subtype we need?
         Priority_Sym :=
           Dictionary.LookupSelectedItem
           (Prefix   => System_Sym,
            Selector => Lookup_Token (Pragma_Kind),
            Scope    => Dictionary.GetScope (System_Sym),
            Context  => Dictionary.ProgramContext);
         if not Dictionary.Is_Null_Symbol (Priority_Sym) then
            -- we can do a range check
            --# accept Flow, 10, Unused, "Expected ineffective assignment";
            Maths.GreaterOrEqual
              (Value,
               Maths.ValueRep (Dictionary.GetScalarAttributeValue (False, LexTokenManager.First_Token, Priority_Sym)),
               Result,
               Unused);

            Maths.ValueToBool (Result, Lower_OK, Unused);

            Maths.LesserOrEqual
              (Value,
               Maths.ValueRep (Dictionary.GetScalarAttributeValue (False, LexTokenManager.Last_Token, Priority_Sym)),
               Result,
               Unused);

            Maths.ValueToBool (Result, Upper_OK, Unused);
            --# end accept;

            if not (Upper_OK and Lower_OK) then
               ErrorHandler.Semantic_Error_Sym2
                 (Err_Num   => 881,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Err_Pos,
                  Sym       => Error_Sym,
                  Sym2      => Priority_Sym,
                  Scope     => Scope);
            else
               -- valid value
               Maths.StorageRep (Value, Value_Rep);
            end if;
         end if; -- no Priority subtype
      else
         -- no System so we can't check the range but we can still add it to the dictionary
         Maths.StorageRep (Value, Value_Rep);
      end if;
   end if;
   --# accept Flow, 33, Unused, "Expected to be neither referenced nor exported";
end Check_Priority_Range;
