nodesadasingly-linked-list

Ada Generic Linked List and Generic Package Access


I'm trying to build a generic linked list in Ada off of a generic Node class. However, I'm unable to access types and formal parameters of my Node inside of my Linked List, despite using a with clause and prefixing accordingly.

genericnode.ads:

generic
   type item_type is private;

package GenericNode is
   type Node is limited private;
   type NodePtr is access Node;
   
   procedure GetData(n : in Node; e : out item_type);
   procedure GetNext(n : in Node; x : out NodePtr);
   
   procedure SetData(n : in out Node; e : in item_type);
   procedure SetNext(n : in out Node; x : in NodePtr);
   
private
   type Node is
      record
         data : item_type;
         next : NodePtr;
      end record;

end GenericNode;

genericsll.ads:

with GenericNode;

generic
   size : Positive;
   type node_type is private;
package GenericSLL is
   
   type SLL is limited private;
   
   procedure Append(s : in out SLL; d : in GenericNode.item_type);
   
   procedure PrintTraversal(s : in SLL);
   
private
   type SLL is
      record
         head : NodePtr := null;
         length : Positive := 0;
      end record;

end GenericSLL;

Upon compilation, I'm told Invalid prefix in selected component "GenericNode" and "NodePtr" is not visible regarding genericsll.ads. Any suggestions? Thanks!


Solution

  • With generic packages in Ada, you need to first instantiate them. GenericNode is not a package; it is a recipe for packages, given a type item_type. Both errors are indicative of this problem; the compiler correctly states there is no such package and no such type NodePtr. ('invalid prefix in selected component GenericNode' just means I have no idea what you mean by 'GenericNode')

    Where in C++, you might expect indeed to make your singly linked list parameterized on the node type, and then tell the compiler 'just grab the X and Y members of this node type, even though I haven't told you what the node type actually is yet', the Ada compiler refuses this because it leads to error-prone code, where you cannot tell what the type should satisfy (contracts in C++20 are meant to patch over this problem).

    Ada does not allow this; every package must be instantiated before use, so that the parameters to each type are known. Unfortunately, this also means it is not possible to do arbitrary compile-time computation in Ada as in C++.

    If you parameterize GenericSLL on item_type and instead of on node_type, it can instantiate the specific GenericNode package it needs using that item_type. Only GenericSLL needs to be modified:

    with GenericNode;
    
    generic
       size : Positive;
       type item_type is private;
    package GenericSLL is
    
       package LinkedList_Node is new GenericNode(item_type);
       use LinkedList_Node;
    
       type SLL is limited private;
       
       procedure Append(s : in out SLL; d : in item_type);
       
       procedure PrintTraversal(s : in SLL);
       
    private
       type SLL is
          record
             head : NodePtr := null;
             length : Natural := 0; -- Positive starts at 1
          end record;
    
    end GenericSLL;