Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile error when implementing interface

Tags:

ada

I am experimenting a bit (out of academic interest, no tangible use-case) with protected interfaces and have come-up with the following code:

procedure Protected_Map is
   type Key is new Character range 'A' .. 'K';
   type Value is range -10 .. 10;
   
   package Maps is
      type Map is protected interface;
      procedure Insert(M: out Map; K: in Key; V: in Value) is abstract;
      procedure Find(M: in out Map; K: in Key; V: out Value) is abstract;
   end Maps;
   use Maps;
   
   -- protected type implementation
   protected type A_Map is new Map with
      overriding
      procedure Insert(K: in Key; V: in Value);
      not overriding
      function Get(K: in Key) return Value;       
   end A_Map;
   
   protected body A_Map is
      procedure Insert(K: in Key; V: in Value) is null; -- dummy
      function Get(K: in Key) return Value is (0); -- dummy
   end A_Map;
   
   overriding
   procedure Find(M: in out A_Map; K: in Key; V: out Value) is
   begin
      V:= M.Get(K);
   end Find;
begin
   null;
end Protected_Map;

The idea is to implement a task-safe Map by declaring a protected interface type with the associated procedures of inserting and finding values by some key. A protected type is then declared in order to implement the interface which only partly implements it (i.e. Insert(..)) and introduces a Get(..) function to retrieve a value by some key. The second required procedure (Find(..)) is implemented in an independent full-blown way. The reason for this is so that writers continue to access the map in a mutually exclusive way whilst readers are able to access it concurrently.

However, compilation is failing for Find(..) with the compiler complaining that no selector "Get" for type derived from A_Map. Why can it not see Get which is clearly in the protected type declaration? Is it a scoping issue i.e. do the protected type declaration and the independent implementation need to be in the same package? (or some other unit?)

like image 947
Sidisyom Avatar asked Jul 27 '26 18:07

Sidisyom


1 Answers

The problem is your compiler has a bug with the error message. The actual error you are making is trying to declare an overriding operation of your A_Map type after specifying a body for the protected type. Ada wants you to declare all your overrides before the type "freezes" and making a body for the protected type freezes it. If you add in a declaration for your Find procedure before the body of the protected type, then all is good. It's a bad error message.

See example

with Ada.Text_IO; use Ada.Text_IO;

procedure jdoodle is
    procedure Protected_Map is
       type Key is new Character range 'A' .. 'K';
       type Value is range -10 .. 10;
       
       package Maps is
          type Map is protected interface;
          procedure Insert(M: out Map; K: in Key; V: in Value) is abstract;
          procedure Find(M: in out Map; K: in Key; V: out Value) is abstract;
       end Maps;
       use Maps;
       
       -- protected type implementation
       protected type A_Map is new Map with
          overriding
          procedure Insert(K: in Key; V: in Value);
          not overriding
          function Get(K: in Key) return Value;       
       end A_Map;
       
       -- Notice the declaration I added here before the body code.
       overriding
       procedure Find(M: in out A_Map; K: in Key; V: out Value);
       
       protected body A_Map is
          procedure Insert(K: in Key; V: in Value) is null; -- dummy
          function Get(K: in Key) return Value is (0); -- dummy
       end A_Map;
       
       procedure Find(M: in out A_Map; K: in Key; V: out Value) is
       begin
          V:= M.Get(K);
       end Find;
    begin
       null;
    end Protected_Map;
begin
    null;
end jdoodle;

at https://www.jdoodle.com/ia/K4h

like image 143
Jere Avatar answered Jul 30 '26 08:07

Jere