yeelan
yeelan

Reputation: 1403

Ada generic package usage and compliation error "non-visible declaration"

I am new to Ada and I'm trying to make a generic quicksort package that can take an integer array of n numbers. The integers in the array must within 1 to 1000.

When I compile the following code, it told me

main.adb:: "Quicksort" is not visible
main.adb:: non-visible declaration at quick_sort.ads:6
main.adb:: "sort" is undefined

However, I cannot find the reason why it is like so and it just seems to be the same feeling that I can find on generic tutorial. I really appreciate that if someone can help me clear my mind why this is happening and how I can use generic correctly.

I wrote the following generic package declaration and body.

quick_sort.ads file

package quick_sort is
generic
    type element_type is private;
    type array_type is array(Natural range <>) of element_type;

    procedure Quicksort(arr: in out array_type);
end quick_sort;

quick_sort.adb file(snippet)

package body quick_sort is
    procedure Quicksort(arr: in out array_type) is
        left: integer := arr'First;
        right: integer := arr'Last;

        procedure partition is
        ....
        begin
            pivot := find_pivot(arr(left), arr((left+right)/2), arr(right));
            -- do the partition for the array
            while left <= right loop
                while arr(left) < pivot loop
                    left := left + 1;
                end loop;
                while arr(right) > pivot loop
                    right := right - 1;
                end loop;
                if left <= right then
                    swap(arr(left), arr(right));
                    left := left + 1;
                    right := right - 1;
                end if;
             end loop;
        end partition;
    begin
        if arr'Length > 1 then
            partition;
            Quicksort(arr(arr'First..right));
            Quicksort(arr(left..arr'Last));
         end if;
    end Quicksort;
end quick_sort;

main.adb

with quick_sort;
procedure main is

    subtype item is integer range 1..1000;
    arr: array(1..3) of item;
    input: item;
    package sort is new Quicksort(element_type => item);
begin
    for i in 1..3 loop
        get(input);
        arr(i) := input;
    end loop;
    sort(arr);
end main;

Edit:

I tried with/without the "use quick_sort" clause. Either way, the compiler will give me the following 2 errors

a generic package is not allowed in a use clause
"Quicksort" is not the name of a generic package

I cannot figure out if I used some wrong declarator. Any thought on it? Thanks!!!!!

Upvotes: 1

Views: 3282

Answers (1)

Simon Wright
Simon Wright

Reputation: 25501

Your Main begins with Quick_Sort;. This means that Main’s code has direct access to Quick_Sort but not to its contents - you have to qualify them by saying Quick_Sort.<whatever>.

You can either begin Main with

with Quick_Sort; use Quick_Sort;

or instantiate the generic with

package sort is new Quick_Sort.Quicksort(element_type => item);

That resolves the "Quicksort" is not visible problem. However as you report, the compiler now says "Quicksort" is not the name of a generic package; which is true, because it’s the name of a generic procedure.

Of course that last line above should read

procedure sort is new Quick_Sort.Quicksort(element_type => item);

which leads to the new error

missing actual "Array_Type"
in instantiation of "Quicksort" declared at yeelan.ada:6
instantiation abandoned

which means that instead of

arr: array(1..3) of item;

you need to write something like

type Item_Array is array (Natural range <>) of Item;
Arr : Item_Array (1 .. 3);

and then

procedure Sort is new Quicksort(Element_Type => Item,
                                Array_Type => Item_Array);

You’ll then get an error about Get being undefined, but the reason for that would be the answer to another question.

Upvotes: 1

Related Questions