ada - declarations must come before begin? - ada

Question: why and how to fix this error message about ADA? Thax
12:04 declarations must come before "begin"
29:01 statement expected
With Ada.Text_IO; Use Ada.Text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
With Ada.Strings.Unbounded; Use Ada.Strings.Unbounded;
With Ada.Strings.Bounded;
procedure polynomial is
begin
function evaluate (x: Integer) return Integer is
type i is new Integer;
type p is new Integer;
type x is new Integer;
begin
for i in reverse 0..10 loop
i:= i-1;
p:= coef(i)+x*p;
end loop;
return p;
end evaluate;
end polynomial;

As the error message says, declarations must come before begin. Thus, if you have a declaration, it must come before the begin of the construct that encloses it. For example, the type declarations of i, x, and p (which should not be type declarations, but that's another problem) are directly enclosed in the evaluate function. Therefore, they must appear before the begin of the evaluate function, as they are.
The thing is that this applies to function and procedure declarations, too--and a complete function body, such as evaluate, counts as a declaration for this rule. evaluate is directly enclosed in polynomial. Therefore, it must appear before the begin line belonging to polynomial, whereas your code puts it right after the begin line, which is illegal.
There are actually two ways to fix it: (1) Move evaluate before the begin line. (2) Add a block that begins with declare:
procedure polynomial is
begin
declare
function evaluate (x: Integer) return Integer is
i : Integer;
-- etc.
begin
-- etc.
end evaluate;
begin -- this is the BEGIN line of the block
-- Now put some code here!
end; -- this is the end of the block
end polynomial;
Now the evaluate function is directly enclosed in the block, not in polynomial, and it must occur before the begin line of the block, but it doesn't have to occur before the begin line of polynomial.
A couple other things: This declaration:
type i is new Integer;
does not mean that "the type of i is an integer". It means you're declaring a new type named i. You don't want that, you want a variable.
i : Integer;
Second: note the part of the block where I said "now put some code here". That's necessary. Declaring the function evaluate does not run the function. You have to put in a statement that calls it, if you ever want your function to run. Your original incorrect code didn't have any statements that called evaluate, which is why I am not sure whether you understood that concept.

Related

Does Ada have any idiomatic rules on when to use a function versus a procedure with an output parameter?

You can assign to a variable by having a function return a value to it:
My_Int : Integer := My_Math_Func [(optional params)];
Or you can do it like this with a procedure (assuming My_Int has already been declared):
My_Math_Proc ([optional params;] [in] out My_Int);
Obviously a procedure can't initialize a variable like the function does in the first example, but I'm hoping for some concrete, practical rules on when and why to pick one over the other.
Two to get you started...
When more than one result is to be returned, a procedure with several OUT parameters is often a good choice.
When the size of the object is unknown prior to the subprogram call, an OUT parameter cannot be used because it would have to be declared precisely the right size, but a function return can set the size by initialising the variable in the caller. This is commonly used with a variable declared in a Declare block, which can hold a different sized string each time it is invoked.
This example shows the variable "text" initialised by calling a Read_File function, to hold the contents of a different file on each iteration of the loop. Safe, no "malloc" or "free" or pointers necessary. (Filename is an array of filenames in this example)
for i in 1 .. last_file loop
declare
text : String := Read_File(Filename(i));
-- the size of "text" is determined by the file contents
begin
-- process the text here.
for j in text'range loop
if text(j) = '*' then
...
end loop;
end
end loop;
Edit : And I suppose I'd better mention the underlying mathematical principle, since Ada is based more closely on mathematical logic than many other languages.
Functions and procedures are both subprograms, but for different purposes:
a function is an abstraction over an expression : like a mathematical operator (and an operator in Ada is just a function). Ideally, it provides a result from a number of operands and nothing else, leaving them unchanged and having no state and no side effects. This ideal is called a "pure function" (and applying "pragma pure" asks the compiler to check its purity) - similar restrictions apply in functional programming (FP) languages. Pure functions allow a whole bunch of optimisation (because reordering them doesn't change results). In practice Ada is not that strict, allowing impure functions too.
a procedure is an abstraction over a statement. It generally has some physical effect (such as changing state) since it doesn't deliver a result.
So the logical separation between expressions and statements is carried over into subprograms (abstractions) as the separation between functions and procedures.
And this is probably the best way to decide which to use.
Brian Drummond already answered your question directly, but I wanted to add some additional info: If your type has some sort of initializing procedure, in Ada2005/Ada2012 you can convert it to an initializing function using extended return syntax. It will even work for limited types.
Say you have a package with a type like this:
package Example is
type My_Type is limited private;
procedure Initialize(Self : in out My_Type; Value : Integer);
procedure Print(Self : My_Type);
private
type My_Type is limited record
Value : Integer := 0;
end record;
end Example;
package body Example is
procedure Initialize(Self : in out My_Type; Value : Integer) is
begin
Self.Value := Value;
end Initialize;
procedure Print(Self : My_Type) is
begin
Ada.Text_IO.Put_Line(Self.Value'Image);
end Print;
end Example;
You can then make your own initializing function out of that procedure doing something like this:
function Make_My_Type (Value : Integer) return Example.My_Type is
begin
return Result : Example.My_Type do
Example.Initialize(Result,Value);
end return;
end Make_My_Type;
and you can initialize variables easily using the procedure hidden in your function underneath:
procedure Test
Thing : Example.My_Type := Make_My_Type(21);
begin
Example.Print(Thing);
end Test;
This is different than just making a variable and returning it. You are not able to do that with a limited type, but with extended return syntax, you can do it for any type.
Here is some additional info for extended return statements as well.

Ada : custom type in range 1..var?

I'm a very beginner of Ada code. I use GPS from AdaCore.
I would create a variable sized by the user.
I write this :
-- My ada program --
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure main is
wanted : Integer := 10;
type custom is range 0..wanted;
...
But something went wrong in line 8 :
Builder results
C:\Users\**********\Desktop\ada project\src\main.adb
8:26 "wanted" is not static constant or named number (RM 4.9(5))
8:26 non-static expression used for integer type bound
I really don't understand what this mean... Can someone help me ?
Variable wanted is not a constant, it may change its value during program execution, therefore this variable is not allowed to be used as range constraint when declaring new types. You may however make it constant by using constant keyword (Wanted : constant Integer := 10;). It should resolve your problem.
As said by Timur, wanted has to be constant in its scope. This allows you some nice things such as declaring a type inside a procedure. Look at this, it might be of interest :)
-- My ada program --
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure Main is
procedure Test (Wanted : Integer) is
type custom is new Integer range 0..wanted;
begin
Put_Line("First value " & Custom'Image (Custom'First)
& " Last value " & Custom'Image (Custom'Last));
end Test;
begin
Test (10);
Test (12);
end Main;
Output is
First value 0 Last value 10
First value 0 Last value 12
In this case, your type is different from one call to another but it works as wanted is constant within the procedure. The only thing is that the type defined has to be a new derived type of the type of your parameter.
I let you think about the possibilities :)

subprogram declarative section order of evaluation Ada

With the declarative section of subprograms in Ada, is the order in which variable assignments is evaluated the order in which they are declared? For example if I write
procedure Foo() is
I: Integer := 4;
J: Integer := I * 2;
begin
--do stuff
end Foo;
can I say for certain that I will always be evaluated before J?
It seems to me like declarative items are indeed evaluated in order, according to ARM 3.11(7):
The elaboration of a declarative_part consists of the elaboration of the declarative_items, if any, in the order in which they are given in the declarative_part.
Edited: Source of ARM

raised CONSTRAINT_ERROR : polynom.adb:85 index check failed

I created an array like this one:
type coef_list is array(Integer range 0..50) of Integer;
But the message appears when I call this function:
t:= times(r,q); --that multiply two polynoms.
Why? I need a dynamic array? with Ada.Vectors but how to used it? if there is any simple example to guide me, please share? Thx
Ada procedures (and similar for functions) require this structure:
procedure Foo is
-- declarations goes here
begin
-- code goes here
end Foo;
In your code, both polynomials and Main is missing the begin.
You have also put declarations (value1 : integer := 1; etc) after begin in print_polynoms, which is illegal.
Other problems with your code:
You redefine the built-in type String.
The type zero is not defined anywhere.
The type String_Pointer is not defined anywhere.
This syntax makes no sense: type Polynom is new Integer(p,p1,p2,p3,p4,q,q1,q2); And the type Polynom is never used. Why declare it?
The variable zero is not defined anywhere.
Why have an inner procedure Main here? It does nothing anyway. And is never called. Probably better to move print_polynoms out of Main, as an inner function of polynomials directly.
The polynomials procedure does nothing, print_polynoms will never be called.
Also, the code you pasted seems to not be the same as the code you tried to compile. (main is not declared at line 9)

How do I use “separate" keyword

I am unable to figure out keyword separate in Ada and its depth concept. Please help me to understand by giving a small example?
Lets say I have a nested procedure
with ada.text_io; use ada.text_io;
procedure main is
procedure proc is
begin
put_line ("i am proc");
end proc;
begin
put_line ("main");
end main;
How to use separate keyword ?
You primarily use the separate keyword to achieve one of 2 effects.
OS specific actions. (Put 2 versions of the procedure / functions in different directories, and compile for 2 different targets)
Separation of a lengthy procedure from surrounding code.
Here is an example to show the syntax.
package_x.ads
package Package_X is
procedure Foo;
procedure Sep;
end Package_X;
package_x.adb
package body Package_X is
procedure Foo is
begin
null;
end Foo;
procedure Sep is separate;
end Package_X;
package_x-sep.adb
separate (Package_X) procedure Sep is
begin
null;
end Sep;
The separate keyword creates a unit of compilation, a subunit, that is compiled independently. The parameter of separate refers to the package in which the subunit is a sub unit of.
So if you had a package body X, then you remove procedure Y from it, you create a sub unit of X by creating a new file in which you place Y, and put "separate(X)" at the start of the file, to indicate that Y is really part of X.

Resources