Friday, September 14, 2012

warm-up exercise refactoring

10-09-12
(them)


Could you give us a short assessment of where you are in the introductory example that we gave you as a warm-up exercise? In order for you to spend some time on the real container library, it would be good to complete this exercise this week if possible.

I see you committed the exercise code+text in hi-lite/libs/containers/ada/intro, thanks. Could you create a different version of Stacks for each extension? So the original Stacks is the simplest one, and then you can have Unbounded_Stacks and Indefinite_Stacks, etc. That will help reviewing your code.

14-09-12
(I)

I already this structure to the sources:

indefinite_stacks
stacks
unbounded_integer_stacks
unbounded_stacks

Now I'm using one main for each test:
main_indefinite_stacks.adb
main_stacks.adb
main_unbounded_integer_stacks.adb
main_unbounded_stacks.adb

but I don't know if you refer to this kind of organization
or maybe you refer a hierarchical one
maybe in the simplest stacks
I can define base operations like

   function Is_Empty
   function Is_Full 

and then on the others stacks make extends the basic operation.
also maybe I can just code one larger main for testing
#main_indefinite_stacks right now is just a copy of unbounded_stacks
#and main.adb is the old one that currently I'm not using anymore

14-09-12
(them)

This organization of code is fine.


maybe in the simplest stacks
I can define base operations like

    function Is_Empty
    function Is_Full

and then on the others stacks make extends the basic operation.
The code is not yet clean. Could you restart from stack.ads/stack.adb and remove all unneeded operations? Just stick to the API that Johannes indicated (see INTRO.txt), which is sufficient to see and discuss issues. Remember this is just an exercise that should allow us to communicate, so the simpler the better.

also maybe I can just code one larger /main/ for testing
/#main_indefinite_stacks /right now is just a copy of /unbounded_stacks/
#and /main.adb /is the old one that currently I'm not using anymore

Please keep separate /main/ for each stack. That's easier to follow.

code style warnings

3-09-12

(I)


a)
I think that autofix option is just available for gnat pro.
Do you have a "coding standard file" already generated?
Theoretically I can use it to "check coding standard" option

Anyway I already fixed my sources, 
also if when I added the "-gnatyg" flag on my test.gpr gps don't show any (style) messages


But now I have a copyright issue, it yields:

[panzon@baleada intro]$ git push
Counting objects: 17, done.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (13/13), 193.76 KiB, done.
Total 13 (delta 3), reused 0 (delta 0)
remote: main.adb:70:10: Copyright notice missing, must occur before line 24
remote: Style check failed for trunk/hi-lite/libs/containers/ada/intro/src/main.adb
remote: error: hook declined to update refs/heads/master
 ! [remote rejected] master -> master (hook declined)
error: failed to push some refs to 'git+ssh://panzon@scm.forge.open-do.org//scmrepos/git/hi-lite/hi-lite.git'


I took a look and I saw that hi-lite have different copyright headers

b)
Do I should use this one?

------------------------------------------------------------------------------
--                                                                          --
--                            INTRO COMPONENTS                           --
--                                                                          --
--                     W H Y - G E N - N A M E _ G E N                      --
--                                                                          --
--                                 B o d y                                  --
--                                                                          --
--                       Copyright (C) 2010-2012, AdaCore                   --
--                                                                          --
-- intro is  free  software;  you can redistribute  it and/or  modify it --
-- under terms of the  GNU General Public License as published  by the Free --
-- Software  Foundation;  either version 3,  or (at your option)  any later --
-- version.  gnat2why is distributed  in the hope that  it will be  useful, --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public --
-- License for  more details.  You should have  received  a copy of the GNU --
-- General  Public License  distributed with  gnat2why;  see file COPYING3. --
-- If not,  go to  http://www.gnu.org/licenses  for a complete  copy of the --
-- license.                                                                 --
--                                                                          --
-- intro is maintained by AdaCore (http://www.adacore.com)               --
--                                                                          --
------------------------------------------------------------------------------


I just substitute intro instead WHY
or maybe you already have some script that generate this header.

3-09-12
(them)

On 09/03/2012 04:28 PM, Ricardo Aguirre wrote:
a)
I think that autofix option is just available for gnat pro.
No, when you compile inside GPS with the option -gnatyg, and if you get style warnings like the ones you sent us, then you should have a small icon on the left side of the warning *and* the same icon on the left side of the line with a warning that allows you to autofix the problem by clicking on the icon.


Do you have a "coding standard file" already generated?
Didn't you see the attachment in my previous email? This is the coding standard we use at AdaCore.


Theoretically I can use it to "check coding standard" option
Do you mean an input file to gnatcheck?


Anyway I already fixed my sources,
ok, good.


also if when I added the "-gnatyg" flag on my test.gpr gps don't show
any (style) messages
good, keep it then in your project file.

But now I have a copyright issue, it yields:
    /[panzon@baleada intro]$ git push/
    /Counting objects: 17, done./
    /Compressing objects: 100% (12/12), done./
    /Writing objects: 100% (13/13), 193.76 KiB, done./
    /Total 13 (delta 3), reused 0 (delta 0)/
    /remote: main.adb:70:10: Copyright notice missing, must occur before
    line 24/
    /remote: Style check failed for
    trunk/hi-lite/libs/containers/ada/intro/src/main.adb/
    /remote: error: hook declined to update refs/heads/master/
    /To
    git+ssh://panzon@scm.forge.open-do.org//scmrepos/git/hi-lite/hi-lite.git
    <http://panzon@scm.forge.open-do.org//scmrepos/git/hi-lite/hi-lite.git>/
    / ! [remote rejected] master -> master (hook declined)/
    /error: failed to push some refs to
    'git+ssh://panzon@scm.forge.open-do.org//scmrepos/git/hi-lite/hi-lite.git
    <http://panzon@scm.forge.open-do.org//scmrepos/git/hi-lite/hi-lite.git>'/


I took a look and I saw that hi-lite have different copyright headers

Ah yes, you should not bother about copyright at this stage.
I have committed a change to .gitattributes so that you don't have this problem anymore (you can see my change after you update your repository). Retry committing now (after doing a "git pull --rebase" and checking you have no conflicts of course).

14-09-12
(them)

On Fri 14 Sep 2012 01:34:57 AM CEST, Ricardo Aguirre wrote:
>>Do you mean an input file to gnatcheck?

Maybe yes, I'm not pretty sure

When I click the right button on the editor
it appears "check coding standard" option
if I click it
then it appears this message (attached image).
I meant that file.
You are trying to use GNATcheck. This is not what I meant by using our coding style. Most rules in our coding style have to do with spacing/indentation/naming of entities and do not require GNATcheck. They are simple enough that you can follow them easily while developing, if you take the time to read the coding style pdf that I sent you.

BTW, I just tried to compile your code, and I get various warnings related to style problems, that should be corrected:

$ gnatmake -P test
unbounded_stacks.ads:40:36: (style) space required
main_stacks.adb:33:03: (style) incorrect layout
main_stacks.adb:41:03: (style) incorrect layout
stacks.ads:11:80: (style) this line is too long
stacks.ads:48:04: (style) horizontal tab not allowed
stacks.ads:54:80: (style) this line is too long

hook problems

3-09-12
(them)

 it is important that you concentrate now on being able to commit your work in git. I give you below the reason for the error you got so far, that should be easy to correct.


On 09/02/2012 10:52 PM, Ricardo Aguirre wrote:
I already solved the 13)

My error was incredible stupid!

Now I have problems with git
last week I setup my global git configuration on my pc, I used this email:
panzon@scm.forge.open-do.org <mailto:panzon@scm.forge.open-do.org>

now I'm getting this errors:
http://pastebin.com/ST85qZnj

Ok, you're having hook problems. We have a hook that checks that the code you commit complies to GNAT style checks before allowing you to commit them. You can check these rules on your computer by compiling with switch -gnatyg. Many of these rules are so simple (indentation, spacing) that you can correct them in GPS by clicking on a small icon on the side that says "autofix". BTW, you can set up GPS so that it does the indentation automatically for you. I am joining the Ada Coding Style that we use at AdaCore.


12)
at first it yields
raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed precondition from stacks.ads:39

Then I removed the old push precondition (not Is_Full(S))
now is running
I guess it's ok, but here it would really help that you commit the questions and your current answers in a file that I can inspect.


13)
I'm stocked with generics, I already read many chapters of ada book, but I'm doing something wrong, I hope I'll solve it during this weekend.
Now I see that stack example is really classic, and book talk about it in many chapters, actually I feel little embarrassed cause I'm having problems with really basic stuffs. However I'm working in.
Don't worry, the goal of this exercise is precisely to help you figure out the problems in a simplified setting, so that we can help you more easily before you attack the real library.


14)
To solve this point I have to ideas:
a) do not use anymore the array instead use a list, like the Cell example
Yes, that's what we had in mind.


b) Use a type base, and then all objects inserted on the array should be
subtype of this base type. Doing an analogy with java that each object
extends implicitly from Object Class.
We have the same notion of derivation in Ada: an object of type T'Class can be dynamically of any type derived from T. Except you cannot put T'Class objects in an array, because they do not have a fixed size. So the solution is really to use pointers.

8)
When I tried to use your suggested postcondition
it yields:
/raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed postcondition from
stacks.ads:49 instantiated at main.adb:5/


I'm not pretty sure about the reason of this message.

Either your postcondition is wrong, or your implementation of Push is wrong. At least they do not match. Try inspecting values by debugging or printing to see which one it is.

My homework doubts

1-09-12
(I)


Since yesterday I tried to push some changes  and at first it yields error on web (when I tried to verify, if my changes was really commited)
this morning also the console
[panzon@baleada intro]$ git pull
ssh: connect to host scm.forge.open-do.org port 22: Connection timed out
fatal: The remote end hung up unexpectedly
12)
at first it yields
raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed precondition from stacks.ads:39

Then I removed the old push precondition (not Is_Full(S))
now is running

13) 
I'm stocked with generics, I already read many chapters of ada book, but I'm doing something wrong, I hope I'll solve it during this weekend.
Now I see that stack example is really classic, and book talk about it in many chapters, actually I feel little embarrassed cause I'm having problems with really basic stuffs. However I'm working in.

2-09-12
(I)


I already solved the 13)

My error was incredible stupid!

Now I have problems with git
last week I setup my global git configuration on my pc, I used this email:
panzon@scm.forge.open-do.org
now I'm getting this errors:
14)
To solve this point I have to ideas:
a) do not use anymore the array instead use a list, like the Cell example
b) Use a type base, and then all objects inserted on the array should be subtype of this base type. Doing an analogy with java that each object extends implicitly from Object Class.

What do you think?

8)
When I tried to use your suggested postcondition 
it yields:
raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed postcondition from stacks.ads:49 instantiated at main.adb:5

my homework (reply)

29-08-12

(them)




However I'm back, I have not finished yet my homework but I hope I can
finish tomorrow.
I found this observations:
I wrote code but I don't know if I should submit in git cause this is
not really part of hi-lite, so I attach in this mail.
Please add a directory where I indicated, to put all your code there. It will be much easier to work together, and we can remove the code afterwards if we feel this is not useful to leave it in the repository. Also, could you add there a file with Johannes instructions/questions, and your answers? This way, we can reply by updating this file, and have it evolve as you make progress.

a)
with the "lighter introduction to hi-lite" I observed that I need /gnat
pro/ in order to use /codePeer/

maybe I won't need it but I'd say it

No, you don't need CodePeer.


4)
At first it yields run-time error
raised CONSTRAINT_ERROR : stacks.adb:47 index check failed
correct, this is the expected behavior when you try to Pop from an empty stack.


then I add an "if not empty validation"
and now pop returns -2 (a constant Error_Value) when it pop an element
from an empty stack list.
That's precisely what we want to avoid. We want Pop to be called only in a context where the stack is not empty, which you can express by adding a precondition to Pop (see point (5) in instructions).


5)
it yields run-time error
raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed precondition from
stacks.ads:26
correct, this is now better, you get a precondition failure when the context to call Pop is not adequate.


Is better cause this is an assertion failure and not an error
This assertion is defined on the specification.
Is better cause we're giving more util information to the compiler.
And we have not to write post condition on each caller code
so please remove the special defensive code that you have added to Pop.


6)
I wrote another precondition for the push procedure, but I have doubts
on this point.
If you're talking of
  Pre => not Is_Full (S)
then, that's the correct precondition that we expected. I see there is code commented out where you try to call Peek. I don't think that's useful here.


I saw that gnat gpl do not include GNATcoverage
I'm reading how to use gcov but still don't understand
don't go into that. That's not useful for this exercise.


Right know I have just 2 tests but I'm not sure if you refer to these
kind of tests
You should have a test where you call Push on a full stack, so that it raises an exception, that you can catch in an exception block:

  begin
     Push (S, 1);
     Put_Line ("Error: Push on full stack does not raise exception");
  exception
     when Assert_Failure =>
        Put_Line ("Ok: Push on full raises exception");
  end;


8)
I don't know how to use Peek on the Pop precondition
Johannes said to use Peek in the postcondition of Push, not the precondition of Pop.


I think to save the Peeked value on the pre condition in a variable
and in the post condition compare the poped value with the previous peeked.
but I'm not sure if I should define variables used just for this kind of
proofs.
Maybe exist a way to define vars just for  pre/post scope.

--I wrote this at first, now I'm using S'old
You can write the following postcondition of Pop:

  function Pop (S : in out Stack) return Integer with
    Post => Pop'Result = Peek (S'Old);

10)
when I compile code I get these warnings:
/stacks.ads:35:27: warning: call to "Push" may occur before body is seen/
/stacks.ads:35:27: warning: Program_Error may be raised at run time/
/stacks.ads:35:27: warning:  called at stacks.adb:44/

You are calling the Push recursively in its postcondition, which is not a good idea: it leads to infinite recursion. Hence the message of the compiler. Notice that Johannes asked you to call in the postcondition of the *procedure* Push a *function* also called Push that he tells you about in point (9) of the instructions.


12)
I'm not sure what is the goal of this point
now I'm reading the chapter 10 - Access Types
I suppose that you refer to use a list instead than array
no. You can simply have a stack be a record holding a pointer to the underlying array. When the array is full, you can then reallocate a bigger one and copy all the values, then change the value of the internal pointer component.

My test are not really invasive I  think probably I'm not doing well
I remember that on the "lighter introduction to hi-lite"
exists tests on the specification
         Test_1 => (*if*  X = 10*and*  Y < 9_990*then*  Add'Result = X + Y),
         Test_2 => (*if*  X = 11*and*  Y = 9_990*then*  Add'Result = 10_000);


I'm almost sure that you didn't refer of above kind of test cause you
said on Main.adb

Yes, just use tests like Johannes started in main.adb

I suggest you first add the code and a file for instructions/answers to the git repository, before we continue by email.

my homework

26-08-12
(I)

However I'm back, I have not finished yet my homework but I hope I can finish tomorrow.
I found this observations:
I wrote code but I don't know if I should submit in git cause this is not really part of hi-lite, so I attach in this mail.
 
a)
with the "lighter introduction to hi-lite" I observed that I need gnat pro in order to use codePeer
maybe I won't need it but I'd say it

4)
At first it yields run-time error
raised CONSTRAINT_ERROR : stacks.adb:47 index check failed
then I add an "if not empty validation"
and now pop returns -2 (a constant Error_Value) when it pop an element from an empty stack list.

5)
it yields run-time error
raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed precondition from stacks.ads:26

Is better cause this is an assertion failure and not an error
This assertion is defined on the specification. 
Is better cause we're giving more util information to the compiler.
And we have not to write post condition on each caller code

6) 
I wrote another precondition for the push procedure, but I have doubts on this point.

I saw that gnat gpl do not include GNATcoverage
I'm reading how to use gcov but still don't understand

Right know I have just 2 tests but I'm not sure if you refer to these kind of tests

8)
I don't know how to use Peek on the Pop precondition
I think to save the Peeked value on the pre condition in a variable
and in the post condition compare the poped value with the previous peeked.
but I'm not sure if I should define variables used just for this kind of proofs.
Maybe exist a way to define vars just for  pre/post scope. 

--I wrote this at first, now I'm using S'old

10)
when I compile code I get these warnings:
stacks.ads:35:27: warning: call to "Push" may occur before body is seen
stacks.ads:35:27: warning: Program_Error may be raised at run time
stacks.ads:35:27: warning:  called at stacks.adb:44

12)
I'm not sure what is the goal of this point
now I'm reading the chapter 10 - Access Types
I suppose that you refer to use a list instead than array

My test are not really invasive I  think probably I'm not doing well
I remember that on the "lighter introduction to hi-lite" 
exists tests on the specification
        Test_1 => (if X = 10 and Y < 9_990 then Add'Result = X + Y),
        Test_2 => (if X = 11 and Y = 9_990 then Add'Result = 10_000);
I'm almost sure that you didn't refer of above kind of test cause you said on Main.adb
Right know my test are just these  two: 

--test push
--  For N in 1 .. Max_Size +1 loop
--    Push (S, N);
--  end loop;

-- test pop
--  X := Pop (S);

I changed the first when I create a stack of a different size.
all pre/post continue hold.


To compile:
gnatmake -P test.gpr

To run:
./main

get your hands dirty and write some code

9-08-12
(them)

So indeed it's a good time to get your hands dirty and write some code,
play with the containers, Ada 2012, contracts ...

The "lighter introduction to hi-lite" is a good start, but it shouldn't
take you too long. By the way, you can find the code in

  testsuite/gnatprove/tests/intro

After that, here is a homework assignment to get you started with contracts.

1) Write a stack package whose spec (stacks.ads) looks a bit like that:

package Stacks is
  --  A stack package that holds integers

  Max_Size : constant Integer := 1000;
  --  the maximal number of elements in the stack

  type Content_Type is array (1 .. Max_Size) of Integer;
  --  the array that holds the elements

  type Stack is record
    Content : Content_Type;
    Index   : Integer;
  end record;

  function Create return Stack;

  function Is_Empty (S : Stack) return Boolean;

  function Is_Full (S : Stack) return Boolean;

  procedure Push (S : in out Stack; X : Integer);
  --  push a new element on the stack

  procedure Pop (S : in out Stack; X : out Integer);
  --  remove the topmost element from the stack, and return it in X

  function Pop (S : in out Stack) return Integer;
  --  same as the above procedure, but return the topmost element,
  --  instead of having an out parameter
  --  note that only in Ada 2012 functions can have in out parameters.
end Stacks;

2) Write an implementation for this package (stacks.adb). The Stack is
an array, together with an index that points to the first empty cell, or
to last used cell, as you wish.

3) Write a main program that tests your stack implementation. It could
look as follows (main.adb):

with Stacks; use Stacks;

procedure Main is
  S : Stack := Create;
  X : Integer;
begin
  pragma Assert (Is_Empty (S));
  Push (S, 1);
  pragma Assert (not (Is_Empty (S)));
  Pop (S, X);
  pragma Assert (X = 1);
  pragma Assert (Is_Empty (S));
  Push (S, 2);
  Push (S, 3);
  Push (S, 4);
  X := Pop (S);
  pragma Assert (X = 4);
  X := Pop (S);
  pragma Assert (X = 3);
  X := Pop (S);
  pragma Assert (X = 2);
  pragma Assert (Is_Empty (S));
end Main;

Obviously, when you run your program, none of the assertions should
fail! Be sure to compile with option "-gnata".

Best is to write a project file, such as "test.gpr", with the following
contents:

project Test is

   for Object_Dir use "obj";
   for Exec_Dir use ".";
   for Main use ("main.adb");

   package Compiler is
      for Default_Switches ("ada") use ("-gnat12", "-gnata");
   end Compiler;

end Test;


You can now compile your project with

  $ gnatmake -P test.gpr

4) What happens when you add the following line at the end of the Main
procedure:

  X := Pop (S);

5) You can protect yourself against what happens in (4) if you add a
precondition to Pop:

  procedure Pop (S : in out Stack; X : out Integer)
  with Pre => (not Is_Empty (S));

What happens now if you run the main program of (4)? In what way is that
better than what happened in (4)?

6) Write more preconditions, so that any runtime error in your stacks
package is impossible. Write a few tests in main.adb to check that.

7) Write postconditions that you know are true after executing a
subprogram. For example, you know that after a "push", the stack is not
empty, and after a "pop", it is not full.

8) Pre/ and Postconditions should never have side effects. There is a
problem with that, because it means you cannot use Push and Pop in
pre/post. A way to solve this is to write functions without side
effects, that do something similar to push and pop, but without changing
the stack. For example, you can write a function Peek that returns the
topmost element of the stack without removing it. You can then write in
the postcondition of push:

  Peek (S) = X

to express that the topmost element is the one we just pushed.

Write the function Peek and use it in the pre/post.

9) The proposed solution in (8) solves only half of the problem, it
gives an alternative to Pop, but not to Push. For Push, what we need is
a *function* Push that leaves the current Stack alone and returns a new
stack with the new element on top:

function Push (S : Stack; X : Integer) return Stack;

Note that "S" is an "in" parameter and is not modified. So Push must
make a copy of S, modify the copy, and then return that modified copy.

10) Use the function of (9) in your pre/post. For example, a complete
contract of the procedure Push is now the following:

procedure Push (S : in out Stack; X : Integer)
with Pre => (not Is_Full (S)),
with Post => (S = Push(S'Old, X));

we have used S'Old to refer to the previous value of S, ie the stack S
before pushing.

11) With the package, one can only create stacks that all have the same
fixed size. How can you change it to create stacks that have a different
maximal size? You need to change the type definition, and the function
Create, which now has an argument for the maximal size.
Hint: use discriminant records.
Change your tests and run them to see if all assertions and
pre/postconditions still hold.

12) Write a version of stacks that can hold any number of integers. This
means that at some point you need to reallocate memory. It also means
that you probably need to use pointers (access).
Change your tests and run them to see if all assertions and
pre/postconditions still hold.

13) Write a version of stacks that can hold any definite object (whose
size is statically known), not just Integer. Use the Ada feature of
generic packages for that.
Change your tests and run them to see if all assertions and
pre/postconditions still hold.

14) Write a version of stacks that can hold any object, even objects of
mixed size. You probably need to use pointers again.
Change your tests and run them to see if all assertions and
pre/postconditions still hold.

15) Feel free to write an Ada program that uses your stack, and does
something useful, add pre/post to your own program ...

16) I forgot another aspect of the example. Make the type Stack private.
Does this change anything for the implementation of the stack, and for
the clients of the stack?



I'm not sure how long this may take you, this assignment is really just
to get you started, feel free to abandon this whenever you think you
have understood the point. You can then look at the code of the Ada 2005
containers, to see how things are done "in real code". You can start
thinking what kinds of pre/post you would write for the Ada 2005
containers. You can also start writing functions without side effects
that correspond to the procedures that modify a container, as in
exercise 9 and 10.