5

I have a main package with a normal spec and body file. I am trying to create child packages of the parent, but want them in a separate compilation file(s). I can easily get it done if it is just a package body, or if it is a subprogram/proc/func. However, I can't get it to let me make a child spec file.

The reason I am doing this is because I want to have information in a child that is available to other children of the same parent. I know I can do this by just including the spec portion in the parent, but that is making my parent file pretty big.

Is this even possible, or do I have no choice but to make another root unit? Or just leave everything spec wise in the parent?

I tried:

in parent: package Child1 is separate; (also tried Parent.Child1 but that gave compiles errors

in child:

separate(Parent)

package Parent.Child1 is
....
end Parent.Child1;

Ideas? Just not possible?

Update: I am compiling with Green Hills Multi Compiler. Ada95 language version, non-OO project.

Jacob Sparre Andersen
  • 6,733
  • 17
  • 22
Awaken
  • 1,243
  • 2
  • 14
  • 26
  • "is separate" is really meant for moving gigantic subroutines into their own source file. It isn't nessecary for packages. For routines, its usually a better idea to simplify the routine instead. Many projects I've worked on actually banned its use. As a user, I'd suggest you learn what it does so you can read code that uses it, but avoid using it yourself. – T.E.D. May 03 '13 at 18:29
  • Don't you end up with huge files? I'm trying to avoid having a monster sized file. If I put all the code in .ads and .adb, it is about 6000 lines with comments. – Awaken May 05 '13 at 11:36
  • If the file is huge, your package almost certainly needs to be broken up into multiple packages (which would each get their own files, solving the huge file problem too). Similarly, if one routine is huge, it almost certainly needs to be broken up into multiple routines (or even a whole package in extreme cases). – T.E.D. May 05 '13 at 13:30
  • So are you are fan of multiple "root level" packages or something else? – Awaken May 05 '13 at 13:42

2 Answers2

9

Noting that you're using the separate keyword I'm going to venture that your question is not about child units, but nested units.

Try the following:

Testing.adb

With
Ada.Text_IO,
Parent;

Procedure Testing is
Begin
    Ada.Text_IO.Put_Line("Starting Test:");

    Parent.Nested.Test_Procedure;

    Ada.Text_IO.Put_Line("Testing complete.");
End Test;

Parent.ads

Package Parent is

    Package Nested is
        Procedure Test_Procedure;
    End Nested;

End Parent;

Parent.adb

Package Body Parent is

    Package Body Nested is separate;

End Parent;

Parent-Nested.adb

(Note: you may have to use something slightly different for the file-name, I'm using GNAT with the default settings for "dot replacement".)

with Ada.Text_IO;

separate (Parent)

package body Nested is

    Procedure Test_Procedure is
    Message : Constant string:= ASCII.HT &
      "Hello from the separate, nested test-procedure.";
    begin
        Ada.Text_IO.Put_Line( Message );
    end Test_Procedure;

End Nested;

You should be able to compile and the output should be three lines as follows:

  1. Starting Test:
  2. Hello from the separate, nested test-procedure.
  3. Testing complete.

The problem here stems from a slight misunderstanding regarding the differences between nested and child packages. Both are accessed with the same method of dot-delimited-qualification: Parent.Nested and Parent.Child.

The subtle difference is that child-packages are always a separately compiled unit (in GNAT they are always in a different file, this is an implementation restriction due to how they [don't] implement the Library.. but some Ada compilers can put different compilation_units into the same file) -- but a nested-package must be compiled at the same time that its enclosing unit is compiled unless it is specifically tagged as separate.


In order to preserve the current nested structure and still use separates you can use the following method with a single Auxiliary package holding all the specs for the packages.

Parent.ads

Package Parent is

    -- Here's the magic of renaming. --'
    Package Nested renames Auxiliary.Delegate;

End Parent;

Auxiliary.ads

Package Auxiliary is

    Package Delegate is
        Procedure Test_Procedure;
    End Delegate;

End Auxiliary;

Auxiliary.adb

package body Auxiliary is

    Package Body Delegate is separate;

end Auxiliary;

Auxiliary-Delegate.adb

(Note: you may have to use something slightly different for the file-name, I'm using GNAT with the default settings for "dot replacement".)

with Ada.Text_IO;

separate (Auxiliary)

package body Delegate is

    Procedure Test_Procedure is
    Message : Constant string:= ASCII.HT &
      "Hello from the separate, nested test-procedure.";
    begin
        Ada.Text_IO.Put_Line( Message );
    end Test_Procedure;

End Delegate;
Shark8
  • 4,095
  • 1
  • 17
  • 31
  • You are correct in that is sort of what I am trying to do. The problem is that I have several "Nested" packages. And those "package Nested is" portion doesn't just include 1 procedure. It contains lots of procedures, but more importantly it contains tons of record types. So when you have 4 or 5 of them, you end up with 500+ lines of codes just declaring the nested packages even if I make the bodies separate. I actually did exactly what you showed above and have it working just fine. I just don't like the huge area of declaration inside the main file and want to move it out. – Awaken May 05 '13 at 11:34
  • Oh, well I know a way you could do that... I'm about to head off to church, but I can write it up and edit my answer later. – Shark8 May 05 '13 at 13:58
  • There you are, a method to hide away the specifications and have the bodies `separate` (and without drowning your `with`/`use` clauses). – Shark8 May 05 '13 at 20:16
5

Yes, this is totally fine. You can have your parent and child packages in separate files:

parent.ads

package Parent is
-- ...
end Parent;

parent-child.ads

package Parent.Child is
-- ...
end Parent.Child;

parent-other.ads:

limited with Parent.Child; --Need Ada 2005
package Parent.Other is
-- ...
end Parent.Other;

The parent.child package and the parent.other package have access to definitions in parent (with some limitations).

Notice how parent.other "withs" parent.child so that it has access to the definitions in parent.child.

I have an example of how it can be done. Also, here is an example from wikibooks.

Anthony
  • 12,177
  • 9
  • 69
  • 105
  • 1
    Your `limited with` example might be better done using private child packages, depending on the intention. In `private package Parent.Child`, `Parent.Child` can be seen by the body of any child and by the specs of other private children. This feature was in Ada95. – Simon Wright May 03 '13 at 05:38
  • Alright. When I tried to do that it works fine if I put the spec and body in the same file. When I tried to to put the spec in the .ads file and the body in the .adb file, it said it couldn't find the corresponding Spec. (I also added some more details in my original question) – Awaken May 03 '13 at 11:11
  • Also, I tried accessing a procedure from parent-child in parent and it tells me Direct Name Child is not visible. Do I need something in the parent that tells the parent it has a child? – Awaken May 03 '13 at 11:20
  • "spec in .ads and body in .adb doesn't work" -- does Green Hills have specific naming conventions for such files? in GNAT, they would be `parent-child.ads` and `parent-child.adb`. Perhaps the compiler will get the right idea if you compile the .ads first? – Simon Wright May 03 '13 at 12:05
  • "I tried accessing a procedure from parent-child in parent and it tells me Direct Name Child is not visible" - start a new question and show us the code. This statement is too vague for a sensible answer. – Simon Wright May 03 '13 at 18:02
  • @Awaken, The organisation of Ada sources is compiler dependent. As most of us use GNAT, it may be more helpful to read the manual for the Green Hills Ada compiler. – Jacob Sparre Andersen Nov 02 '17 at 05:42