Question

I am developping a genereic program which filters data with Ada. I tried to do that with a list and with a tree.

The program with lists implementation works perfectly. My probleme is with the tree.

I have different generic packages :

Arbre_Binaire_Recherche_g.ads

generic
   TYPE Element IS PRIVATE;
   WITH FUNCTION "="(E1,E2 : IN Element) RETURN Boolean;
   WITH FUNCTION "<"(E1,E2 : IN Element) RETURN Boolean;
   WITH PROCEDURE Liberer_Element(E : IN OUT Element);
   WITH FUNCTION Element_To_String(E : IN Element) RETURN String;

package Arbre_Binaire_Recherche_g is

[...]

with function critere(E : in element) return Boolean;
 procedure Filtrer(A : in Arbre; B : out Arbre);
private
    TYPE Noeud;

  TYPE Arbre IS ACCESS Noeud;

  TYPE Noeud IS RECORD
     Info : Element;
     Gauche : Arbre;
     Droite : Arbre;
  END RECORD;

END Arbre_Binaire_Recherche_g;

This is the filter procedure, with the generic function critere :

Arbre_Binaire_Recherche_g.adb

 procedure Filtrer(A : in Arbre ; B : out Arbre) is
  begin
 if not Est_Vide(A) then
    Filtrer(A.Gauche, B);
    if critere(A.all.Info) then
       Inserer_element(B, A.all.info);
    end if;
    Filtrer(A.Droite, B);
 end if;
  end Filtrer;

abr_acteurs.ads

WITH Arbre_Binaire_Recherche_G, Acteurs;  
USE Acteurs;


package ABR_acteurs is new Arbre_Binaire_Recherche_G(acteur,"=","<",Liberer_acteur,Acteur_To_String);

There are also acteurs.ads and acteurs.adb but it's not important here.

And then, the client : Tester_ABR_Acteur :

WITH ABR_Acteurs, Acteurs, Ada.Text_Io, Arbre_Binaire_Recherche_G;
use Ada.Text_Io, Abr_Acteurs;


PROCEDURE Tester_ABR_Acteurs is

 function Filtrage (Act : Acteurs.Acteur) return Boolean is
 begin
    return true;
 end Filtrage;

 procedure Filtrer_acteur is new Arbre_Binaire_Recherche_G.Filtrer(Filtrage);
[...]

But, at compilation, there is the error : invalid prefix in selected component "Arbre_Binaire_Recherche_G"
At line :

procedure Filtrer_acteur is new Arbre_Binaire_Recherche_G.Filtrer(Filtrage);  

In client file.


There is the error, if I do this instanciation. But if I put my generic critere function with an other generic procedure / function, like this :

Arbre_Binaire_Recherche_g.ads

generic
   TYPE Element IS PRIVATE;
   WITH FUNCTION "="(E1,E2 : IN Element) RETURN Boolean;
   WITH FUNCTION "<"(E1,E2 : IN Element) RETURN Boolean;
   WITH PROCEDURE Liberer_Element(E : IN OUT Element);
   WITH FUNCTION Element_To_String(E : IN Element) RETURN String;
   with function critere(E : in element) return Boolean;

Then I instantiate like this :

abr_acteurs.ads

package ABR_acteurs is new Arbre_Binaire_Recherche_G(acteur,"=","<",Liberer_acteur,Acteur_To_String, Critere_acteur);

There is no error, and everything works correctly!

I can't find out where the problem is !

================================================================
I do exactly the same with my list implementation, with generic function at the end of my generic package, and it works correctly! I don't understand..

Does anyone have an idea?

[Update]

  • My generic function : with function critere(E : in element) return Boolean; is in the procedure : procedure Filtrer(A : in Arbre; B : out Arbre);, like that :

    procedure Filtrer(A : in Arbre ; B : out Arbre) is  
       begin  
     if not Est_Vide(A) then  
        Filtrer_hihi(A.Gauche, B);
    

Here there is critere(A.all.Info)

        if critere(A.all.Info) then  
           Inserer_element(B, A.all.info);  
        end if;  
        Filtrer_hihi(A.Droite, B);  
     end if;  
      end Filtrer;    

So, it's normal if I instantiated my procedure in this way, because (Refer to 2.)

  • That's how I proceeded with my generic list :

package liste_ordonnee_g.ads

with Ada.Unchecked_Deallocation;

generic
   type Element is private;
   with function "<"(E1, E2 : in Element) return Boolean;
   with function "="(E1, E2 : in Element) return Boolean;
   with procedure Liberer_Element(E : in out Element);
   with function Element_To_String(E : in Element) return String;

package Liste_Ordonnee_G is

    type Liste is private;

 [...]

generic
    with function Critere(E:Element) return Boolean;

function Filtrer(L : Liste) return Liste;

private

type Cellule;
type Lien is access Cellule;
type Cellule is record
    Info : Element;
    Suiv : Lien;
end record;

type Liste is record
    Debut : Lien;
    Cardinal : Natural;
end record;

-- procedure de liberation de la memoire occupee par la cellule
procedure Liberer_Cellule is new Ada.Unchecked_Deallocation(Cellule, Lien);

end Liste_Ordonnee_G;

liste_ordonnee_g.adb

function Filtrer(L : Liste) return Liste is
   New_Liste : Liste;
   Aux :Lien ;
begin
   Creer_Liste(New_Liste);
   Aux := L.Debut;
   while Aux /= null loop

Here there is critere(A.all.Info)

      if Critere(Aux.all.Info) then
     Inserer(Aux.all.Info, New_Liste);
      end if;
      Aux := Aux.all.Suiv;
   end loop;
   return New_Liste;
end Filtrer;

Here, I instantiate my generic package WITHOUT the function critere :

liste_ordonnee_acteurs.ads

with Acteurs, Liste_Ordonnee_G;
use Acteurs;

PACKAGE Liste_Ordonnee_Acteurs IS new Liste_Ordonnee_G(Acteur, "<", "=", Liberer_Acteur, Acteur_To_String);

And in my client file : I instanciate my generic procedure filtrer with the critere :

Test_Liste_Ordonnee_Acteurs.adb

 function Filtrage (A : Acteurs.Acteur) return Boolean is
   begin
      return Acteurs.Annee(A) = 2000;
   end Filtrage;

   function Filtrer is new Liste_Ordonnee_Acteurs.filtrer(Filtrage); 

List implementation works correctly! I don't understand why tree implementation doesn't work :( ..

Was it helpful?

Solution

For the list version, you have

with Acteurs, Liste_Ordonnee_G;
use Acteurs;
PACKAGE Liste_Ordonnee_Acteurs
   IS new Liste_Ordonnee_G(Acteur, "<", "=", Liberer_Acteur, Acteur_To_String);

which results (effectively) in a new generic function Liste_Ordonnee_Acteurs.Filtrer like

generic
   with function Critere(E:Acteur) return Boolean;
function Filtrer(L : Liste) return Liste;

which you instantiate successfully as

function Filtrage (A : Acteurs.Acteur) return Boolean is
begin
   return Acteurs.Annee(A) = 2000;
end Filtrage;

function Filtrer is new Liste_Ordonnee_Acteurs.filtrer(Filtrage);

What you've done in the tree version is the equivalent of

function Filtrer is new Liste_Ordonnee_G.filtrer(Filtrage);

so you need to change

procedure Filtrer_acteur is new Arbre_Binaire_Recherche_G.Filtrer(Filtrage);

to

procedure Filtrer_acteur is new ABR_Acteurs.Filtrer(Filtrage);

OTHER TIPS

Arbre_Binaire_Recherche_G is the name of your generic package. A generic package is not a package; it's a template from which you can create a package by instantiating it (defining an instance).

And Filtrer is a non-generic procedure declared in the generic package.

When you write:

procedure Filtrer_acteur is new Arbre_Binaire_Recherche_G.Filtrer(Filtrage);

you're trying to refer to the .Filtrer name from something that's not a package -- and Filtrer itself isn't even a generic.

If you instantiate your Arbre_Binaire_Recherche_G package, you can then refer to the Filtrer function defined in that instance (which is a package):

package Actual_Package is new Arbre_Binaire_Recherche_G(...);
...
... Actual_Package.Filtrer ...

(But from within a generic package, the name of the generic package refers to the current instance, not to the generic, so Arbre_Binaire_Recherche_G.Filtrer is a valid procedure name in that context. I'm not sure whether that's relevant to your problem.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top