Ada: package does not allow a body
Asked Answered
L

3

7

Using the GNAT compiler, when I try to compile or check semantic on the following files, I get some variation of the error package "Foo" does not allow a body. I'm new to the language and can't find an answer to this seemingly basic problem anywhere on the Internet. Please advise.

foo.ads

package Foo is
   type Shape_Enum is (Circle, Triangle, Rectangle);
end Foo;

foo.adb

package body Foo is
   procedure Foo is
      MyShape : Shape_Enum;
   begin
      MyShape := Rectangle;
   end Foo;   
end Foo;
Lanford answered 27/9, 2012 at 21:55 Comment(3)
Once you get it working, I'd suggest renaming it to "Adarocks". Compilers are sensitive, and you'll want to try to get back on its good side.Potluck
I've taken the liberty of editing the question to change the package name.Hellman
Whatever floats your boat. Thanks again for the answer. Accepted and upvoted.Lanford
H
10

A package is only allowed to have a body if the specification includes something that requires a body. (This avoid problems where an optional body might accidentally be left out of a build.)

You have a procedure in the body of the package (Foo.Foo), but there's no way to call it.

If you add a declaration:

procedure Foo;

to the specification, that should (a) fix the error, and (b) permit the procedure to be called by clients of the package. Or you can use pragma Elaborate_Body; to require it to have a body if you don't want the procedure to be visible to clients.

Incidentally, there's nothing special about a procedure with the same name as the package that contains it (unlike in C++, where such a function is a constructor for the containing class). It would probably be clearer to use a different name.

See section 7.2 of the Ada Reference Manual (I'm using a recent draft of the 2012 standard):

A package_body shall be the completion of a previous package_declaration or generic_package_declaration. A library package_declaration or library generic_package_declaration shall not have a body unless it requires a body; pragma Elaborate_Body can be used to require a library_unit_declaration to have a body (see 10.2.1) if it would not otherwise require one.

Hellman answered 27/9, 2012 at 22:16 Comment(3)
Thank you sincerely for your help. I'd consider a different name, but I've never spent so much time on such simple problems and found so little useful information on the Internet. I'm sure Ada is positively wonderful in some obscure way.Lanford
I typed <package does not allow a body> into Google and found adaic.org/resources/add_content/standards/05aarm/html/… as the top hit, which seems as though it might have helped. But I've been using Ada for a while now, so I'm not the person to judge!Intimate
This issue just came up at work. Note that there is a difference between the two. If your "unexpectedly required" package has begin...end body code you want run, it is quite possible that pragma elaborate_body may cause elaboration issues (even circularities). In this case, the fake procedure method is a better solution. In other words, Elaborate_Body has side effects that you may not find desirable, whereas the dummy routine method does not.Potluck
B
3

You could also declare the function to be private by adding:

private
    procedure Foo;

to the specification. Which will prevent it's use outside of the package.

Bower answered 29/9, 2012 at 2:24 Comment(0)
L
2

Apparently Ada needs you to explicitly force a package body with pragma elaborate_body. I found the answer here:

http://objectmix.com/ada/338459-erreur-de-compilation.html#post1225079 (thank God I speak French):

ORIGINAL

entier_paquetage.adb:4:01: spec of this package does not allow a body

Si la spec ne demande pas un corps, le corps n'est pas autorisé. On peut forcer un corps en mettant "pragma elaborate_body;" dans la spec.

English

If the spec doesn't demand (or ask for) a body, the body will not be authorize . We can force a body by putting "pragma elaborate_body;"

Lanford answered 27/9, 2012 at 22:39 Comment(10)
That's one way. Of course one could ask why you want a package body when nothing in there can be run, used, or invoked in any way. Isn't that all dead code?Potluck
That depends on what you mean by "dead code". All it does is set a variable value, which in and of itself is worthless; however, I've made my example as simple as possible so as to isolate the cause. Moreover, Ada seems extremely counter-intuitive and GNAT's errors are of little help, so it seems necessary to eliminate as much Ada-convolution as possible.Lanford
By "dead code" I mean code that cannot be reached from the program's entry point, or (in Ada's case) the entry point of any task. A subroutine in a package body that isn't in the spec, isn't called from the package's own "begin...end" code, isn't called directly or indirectly by another routine declared in the package spec, and isn't called from a task defined in that same package body, cannot be reached by anything. It's dead code.Potluck
I didn't realize Ada doesn't know how to execute code specified apart from the spec. Had I known that, I wouldn't have posted this question. ;)Lanford
It isn't really an Ada thing, its a simple matter of scope. You'd have this issue in any language that supports this kind of modularity (Modula-2, C++, etc). For example, the C++ equivalent would be creating a class with no public methods or constructors, and then being surprised when the linker optimizes away your private methods.Potluck
Though a valid case for Elaborate_Body could be a task that's not meant to be called by clients and has no public spec.Nailbiting
@T.E.D., not true, I don't have to declare a function in a c++ header file in order to use it in a program: pastebin.com/VtnAsEcJ I understand there is a difference between Ada spec files and .h files; however, that difference is the "Ada thing..." I was referring to.Lanford
@Lanford - I did not say anything about "header file"s. I was talking about C++ class declarations. "header files" are a hack that C programmers learned to use a long time ago to provide kind of a poor-man's modularity feature. I understand the C++ folks are looking at replacing them with a real module feature sometime in the future (https://mcmap.net/q/193652/-c-modules-why-were-they-removed-from-c-0x-will-they-be-back-later-on), but for now C++ users are stuck with #includePotluck
@Potluck I wasn't making a class in Ada; I was making a module with a function--the same as I demonstrated in C++. The fact that Ada requires me to declare a procedure in the specification is counter intuitive, and the fact that there is no decent online documentation (please don't point me to the Ada reference manual! :p ) is worse. I'm not arguing the merits of header files--generally I try to avoid both C++ and Ada in favor of languages that are easy to troubleshoot.Lanford
Agreed. Referring non-compiler engineers to the Ada Reference Manual should be a punishable offense. Unfortunately, there's not a lot of well written freely available Ada reference materials written for mere mortals.Eadie

© 2022 - 2024 — McMap. All rights reserved.