comp.lang.ada
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* Re: Recursive algebraic data types
  @ 2018-03-06 20:54  5%   ` Jeffrey R. Carter
  0 siblings, 0 replies; 70+ results
From: Jeffrey R. Carter @ 2018-03-06 20:54 UTC (permalink / raw)


On 03/06/2018 09:28 PM, Randy Brukardt wrote:
> 
> A "recursive data type" is illegal in Ada: a type can never depend on
> itself, directly or indirectly. You have to break this sort of thing with an
> intervening access type, which brings a world of complications in storage
> management.

You have to break it with something, but that doesn't need to be an access type. 
Consider S expressions (usually shortened to sexes), which are either an atom or 
a list of zero or more sexes:

    type Sex (Is_Atom : Boolean := False) is tagged private;
private
    type Root is interface;

    package Sex_Lists is new
       Ada.Containers.Indefinite_Vectors (Positive, Root'Class);

    type Sex (Is_Atom : Boolean := False) is new Root with record
       case Is_Atom is
       when False =>
          List : Sex_Lists.Vector;
       when True =>
          Atom : Atom_Value;
       end case;
    end record;

The only downside of this is that any element you obtain from S.List has to be 
converted to Sex, which is just noise. Better would be if we could instantiate 
Indefinite_Vectors with type Sex directly, before it's full definition is seen.

-- 
Jeff Carter
"He that hath no beard is less than a man."
Much Ado About Nothing
132

^ permalink raw reply	[relevance 5%]

* Re: gettext for Ada
  @ 2017-11-23 16:02  4%             ` Shark8
  0 siblings, 0 replies; 70+ results
From: Shark8 @ 2017-11-23 16:02 UTC (permalink / raw)


On Thursday, November 23, 2017 at 1:25:50 AM UTC-7, G. B. wrote:
> Shark8 wrote:
> 
> > Er... "The strings come from a freely available ISO standard, so they will never change"
> > 
> > So why not enumerate the strings, that way proper cases can be done on
> > either languages and/or locales?
> 
> 
> The set of locales may grow. ‘Last etc. would change.

Why would you use 'Last or 'Succ on languages? -- If you're talking about setting up a generic-system, you'd make special values formal parameters:

Generic
  Type Language is (<>);
  Default,
  Unknown : in Language;
Package Translation_Base is
 --...
End Translation_Base;


Using enumerations also means that you can leverage discriminated records, making a solid foundation for true multilingual applications:

Type Language_String( Language : Ada.Locale.Language; Length : Natural ) is record
  Data : String( 1..Length );
end record;

--...

Package Language_String_Vector is new Ada.Containers.Indefinite_Vectors(
    Index   => Positive,
    Element => Language_String
  );

Subtype Multi_Lingual_Text is Language_String_Vector.Vector;

--...

Procedure Render( Text : Multi_Lingual_Text; Display : Some_Text_Device );


^ permalink raw reply	[relevance 4%]

* Re: Is Ada.Containers.Vectors.Reference_Type a constrained view?
  2017-10-28 11:10  4% Is Ada.Containers.Vectors.Reference_Type a constrained view? Stephen Leake
@ 2017-11-15  0:38  0% ` Randy Brukardt
  0 siblings, 0 replies; 70+ results
From: Randy Brukardt @ 2017-11-15  0:38 UTC (permalink / raw)


"Stephen Leake" <stephen_leake@stephe-leake.org> wrote in message 
news:fad2c15c-52e5-416a-b133-a3674afc318c@googlegroups.com...
>I have the following vector type:
>
>   type Indent_Labels is (Not_Set, Int, Anchor, Anchored, Nested_Anchor);
>
>   type Indent_Type (Label : Indent_Labels := Not_Set) is record
>      case Label is
>      when Not_Set =>
>         null;
>
>      when Int =>
>         Int_Offset : Integer;
>
>      ...
>
>      end case;
>   end record;
>
>   package Indent_Vectors is new Ada.Containers.Vectors
>     (Line_Number_Type, Indent_Type);
>
> Then I have code like this:
>
>      for Line in First_Line .. Last_Line loop
>         declare
>            Indent : Indent_Type := Data.Indents (Line);
>         begin
>            case Delta_Indent.Label is
>            when Int =>
>               Indent_Apply_Int (Indent, Delta_Indent.Offset);
>            ...
>            end case;
>
>            Data.Indents.Replace_Element (Line, Indent);
>         end;
>      end loop;
>
> The body of Indent_Apply_Int may change the Label from Not_Set to Int; the 
> other branches of the case statement change Not_Set to the other label 
> values.
>
> I'd like to avoid copying Indent (mostly on general principle; this is not 
> a large object). However, if I use:
>
>   Indent : Indent_Type renames Data.Indents.Reference (Line).Element.all;
>
> and drop the Replace_Element call, then Constraint_Error is raised at the 
> point in Indent_Apply_Int that changes the Label (I'm using GNAT GPL 
> 2017).
>
> I'm not clear if that Constraint_Error is allowed by the ARM. Reference 
> returns a Reference_Type object:
>
>   type Reference_Type (Element : not null access Element_Type) is private
>   with
>      Implicit_Dereference => Element;
>
> Note that Element is of an access type. AARM 4.8 (6) says that allocated 
> objects are constrained by their initial value. AARM 3.10 (26.d/2) says 
> most non-allocated objects accessed via an access-to-object type are not 
> constrained.
>
> So is the type of discriminant Element an access to object type? It 
> doesn't have 'all' in it, so I guess not. Note that the syntax of 
> discriminants does not allow 'all'.

Of course it is an access-to-object type; the only alternative is an 
access-to-subprogram type, and it surely isn't that.

But your question really is, is the object designated by the reference 
object allowed to be constrained (that is, allowed to be an allocated 
object). This doesn't seem to be answered by the RM.

The question IS answered for Update_Element (see A.18.2(142/2)).

I'd argue that the same rule is intended for Reference_Type, but since there 
is no wording requiring it in the RM, it's hard to say that the GNAT 
implementation is wrong. You might try two things:
(1) Try using Update_Element rather than Reference. (A pain, I know.) If 
that does not work either, then GNAT is wrong, file a bug report.
(2) Send a question to Ada-Comment so that the ARG considers the question. I 
don't think we ever intended Update_Element and Reference to work 
differently, but it ought to be discussed.

Note that the answer would be different had you been using 
Indefinite_Vectors. (Those definitely allow the elements to be constrained, 
as those pretty much have to be allocated individually when they are 
created.)

                                         Randy.





> This seems to be a flaw; it would be nice to be able to use Reference in 
> the code above, especially if the copy operation is slow. I guess I could 
> use Update_Element in that case.
>
> In Ada.Containers.Indefinite_Vectors, the Element parameter of 
> Update_Element is allowed to be constrained (AARM A.18.11 (8/2)); that 
> statement is not made in Ada.Containers.Vectors, so the actual Element in 
> a Vector cannot be constrained.
>
> -- Stephe
> 



^ permalink raw reply	[relevance 0%]

* Is Ada.Containers.Vectors.Reference_Type a constrained view?
@ 2017-10-28 11:10  4% Stephen Leake
  2017-11-15  0:38  0% ` Randy Brukardt
  0 siblings, 1 reply; 70+ results
From: Stephen Leake @ 2017-10-28 11:10 UTC (permalink / raw)


I have the following vector type:

   type Indent_Labels is (Not_Set, Int, Anchor, Anchored, Nested_Anchor);

   type Indent_Type (Label : Indent_Labels := Not_Set) is record
      case Label is
      when Not_Set =>
         null;

      when Int => 
         Int_Offset : Integer;

      ...

      end case;
   end record;

   package Indent_Vectors is new Ada.Containers.Vectors 
     (Line_Number_Type, Indent_Type);

Then I have code like this:

      for Line in First_Line .. Last_Line loop
         declare
            Indent : Indent_Type := Data.Indents (Line);
         begin
            case Delta_Indent.Label is
            when Int =>
               Indent_Apply_Int (Indent, Delta_Indent.Offset);
            ...
            end case;

            Data.Indents.Replace_Element (Line, Indent);
         end;
      end loop;

The body of Indent_Apply_Int may change the Label from Not_Set to Int; the other branches of the case statement change Not_Set to the other label values.

I'd like to avoid copying Indent (mostly on general principle; this is not a large object). However, if I use:

   Indent : Indent_Type renames Data.Indents.Reference (Line).Element.all;

and drop the Replace_Element call, then Constraint_Error is raised at the point in Indent_Apply_Int that changes the Label (I'm using GNAT GPL 2017).

I'm not clear if that Constraint_Error is allowed by the ARM. Reference returns a Reference_Type object:

   type Reference_Type (Element : not null access Element_Type) is private
   with
      Implicit_Dereference => Element;

Note that Element is of an access type. AARM 4.8 (6) says that allocated objects are constrained by their initial value. AARM 3.10 (26.d/2) says most non-allocated objects accessed via an access-to-object type are not constrained.

So is the type of discriminant Element an access to object type? It doesn't have 'all' in it, so I guess not. Note that the syntax of discriminants does not allow 'all'.

This seems to be a flaw; it would be nice to be able to use Reference in the code above, especially if the copy operation is slow. I guess I could use Update_Element in that case.

In Ada.Containers.Indefinite_Vectors, the Element parameter of Update_Element is allowed to be constrained (AARM A.18.11 (8/2)); that statement is not made in Ada.Containers.Vectors, so the actual Element in a Vector cannot be constrained.

-- Stephe


^ permalink raw reply	[relevance 4%]

* Re: Array of Unbounded_String vs Indefinite_Vectors(Natural, String)
  2017-10-21 21:48  4% Array of Unbounded_String vs Indefinite_Vectors(Natural, String) Victor Porton
  2017-10-22  0:51  0% ` Shark8
@ 2017-10-22 12:30  0% ` Victor Porton
  1 sibling, 0 replies; 70+ results
From: Victor Porton @ 2017-10-22 12:30 UTC (permalink / raw)


Victor Porton wrote:

> I need to develop an API which return a list of strings.
> 
> I have two possible design choices for the result type:
> 
> 1. type T is array(Natural range <>) of Unbounded_String;
> 
> 2. package V is new Ada.Containers.Indefinite_Vectors(Natural, String);
> 
> Which one of the two to choose?
> 
> The first has the advantage that it is a regular array not a fancy
> container. The second one has the advantage that the element type is
> String not a fancy Unbounded_String.
> 
> Please help me to make the choice!

"2" is preferred, because it is more flexible: String can be replaced with 
some another type without big code changes.

-- 
Victor Porton - http://portonvictor.org


^ permalink raw reply	[relevance 0%]

* Re: Array of Unbounded_String vs Indefinite_Vectors(Natural, String)
  2017-10-22  0:51  0% ` Shark8
@ 2017-10-22 10:52  0%   ` Victor Porton
  0 siblings, 0 replies; 70+ results
From: Victor Porton @ 2017-10-22 10:52 UTC (permalink / raw)


Shark8 wrote:

> On Saturday, October 21, 2017 at 3:48:48 PM UTC-6, Victor Porton wrote:
>> I need to develop an API which return a list of strings.
>> 
>> I have two possible design choices for the result type:
>> 
>> 1. type T is array(Natural range <>) of Unbounded_String;
>> 
>> 2. package V is new Ada.Containers.Indefinite_Vectors(Natural, String);
>> 
>> Which one of the two to choose?
>> 
>> The first has the advantage that it is a regular array not a fancy
>> container. The second one has the advantage that the element type is
>> String not a fancy Unbounded_String.
>> 
>> Please help me to make the choice!
> 
> Personally I like the vector option.

Why?

-- 
Victor Porton - http://portonvictor.org

^ permalink raw reply	[relevance 0%]

* Re: Array of Unbounded_String vs Indefinite_Vectors(Natural, String)
  2017-10-21 21:48  4% Array of Unbounded_String vs Indefinite_Vectors(Natural, String) Victor Porton
@ 2017-10-22  0:51  0% ` Shark8
  2017-10-22 10:52  0%   ` Victor Porton
  2017-10-22 12:30  0% ` Victor Porton
  1 sibling, 1 reply; 70+ results
From: Shark8 @ 2017-10-22  0:51 UTC (permalink / raw)


On Saturday, October 21, 2017 at 3:48:48 PM UTC-6, Victor Porton wrote:
> I need to develop an API which return a list of strings.
> 
> I have two possible design choices for the result type:
> 
> 1. type T is array(Natural range <>) of Unbounded_String;
> 
> 2. package V is new Ada.Containers.Indefinite_Vectors(Natural, String);
> 
> Which one of the two to choose?
> 
> The first has the advantage that it is a regular array not a fancy 
> container. The second one has the advantage that the element type is String 
> not a fancy Unbounded_String.
> 
> Please help me to make the choice!

Personally I like the vector option.
There's a third choice, an array of unconstrained Holder container -- http://www.ada-auth.org/standards/12rat/html/Rat12-8-5.html -- You could overload your array-type with an operator to directly return the string.

Assuming you've instantiated String_Holder, you could do something like this.

Type String_List is Array(Positive range <>) of String_Holder.Holder;
Function "/"( List : String_List; Index : Positive ) return String is
( String_Holder.Element( List(Index) ) )
with Pre => Index in List'Range;


^ permalink raw reply	[relevance 0%]

* Array of Unbounded_String vs Indefinite_Vectors(Natural, String)
@ 2017-10-21 21:48  4% Victor Porton
  2017-10-22  0:51  0% ` Shark8
  2017-10-22 12:30  0% ` Victor Porton
  0 siblings, 2 replies; 70+ results
From: Victor Porton @ 2017-10-21 21:48 UTC (permalink / raw)


I need to develop an API which return a list of strings.

I have two possible design choices for the result type:

1. type T is array(Natural range <>) of Unbounded_String;

2. package V is new Ada.Containers.Indefinite_Vectors(Natural, String);

Which one of the two to choose?

The first has the advantage that it is a regular array not a fancy 
container. The second one has the advantage that the element type is String 
not a fancy Unbounded_String.

Please help me to make the choice!

-- 
Victor Porton - http://portonvictor.org


^ permalink raw reply	[relevance 4%]

* Re: Convert between different container types
  2017-09-11 21:20  0% ` Victor Porton
@ 2017-10-02 23:29  0%   ` Randy Brukardt
  0 siblings, 0 replies; 70+ results
From: Randy Brukardt @ 2017-10-02 23:29 UTC (permalink / raw)


You can use stream operations Read and Write to convert between two similar 
containers, including between an unbounded and bounded container of the same 
kind (vector, list, map, etc.). Other containers are too different 
internally to be convertable; you'll have to write your own conversion 
routine as suggested by someone else.

                                Randy.

"Victor Porton" <porton@narod.ru> wrote in message 
news:op6uo0$suu$1@gioia.aioe.org...
> Victor Porton wrote:
>
>> What is the easiest way to convert between different container types, for
>> example between Ada.Containers.Doubly_Linked_Lists and
>> Ada.Containers.Indefinite_Vectors as well as between these types and 
>> plain
>> old Ada arrays?
>
> Sorry, typo: I would instead consider the case when both containers are
> indefinite or both are not indefinite.
>
> -- 
> Victor Porton - http://portonvictor.org 



^ permalink raw reply	[relevance 0%]

* Re: Convert between different container types
  2017-09-11 21:19  5% Convert between different container types Victor Porton
  2017-09-11 21:20  0% ` Victor Porton
@ 2017-09-11 21:36  0% ` Simon Wright
  1 sibling, 0 replies; 70+ results
From: Simon Wright @ 2017-09-11 21:36 UTC (permalink / raw)


Victor Porton <porton@narod.ru> writes:

> What is the easiest way to convert between different container types, for 
> example between Ada.Containers.Doubly_Linked_Lists and 
> Ada.Containers.Indefinite_Vectors as well as between these types and plain 
> old Ada arrays?

for El of A loop
   B.Append (El);
end loop;


^ permalink raw reply	[relevance 0%]

* Re: Convert between different container types
  2017-09-11 21:19  5% Convert between different container types Victor Porton
@ 2017-09-11 21:20  0% ` Victor Porton
  2017-10-02 23:29  0%   ` Randy Brukardt
  2017-09-11 21:36  0% ` Simon Wright
  1 sibling, 1 reply; 70+ results
From: Victor Porton @ 2017-09-11 21:20 UTC (permalink / raw)


Victor Porton wrote:

> What is the easiest way to convert between different container types, for
> example between Ada.Containers.Doubly_Linked_Lists and
> Ada.Containers.Indefinite_Vectors as well as between these types and plain
> old Ada arrays?

Sorry, typo: I would instead consider the case when both containers are 
indefinite or both are not indefinite.

-- 
Victor Porton - http://portonvictor.org


^ permalink raw reply	[relevance 0%]

* Convert between different container types
@ 2017-09-11 21:19  5% Victor Porton
  2017-09-11 21:20  0% ` Victor Porton
  2017-09-11 21:36  0% ` Simon Wright
  0 siblings, 2 replies; 70+ results
From: Victor Porton @ 2017-09-11 21:19 UTC (permalink / raw)


What is the easiest way to convert between different container types, for 
example between Ada.Containers.Doubly_Linked_Lists and 
Ada.Containers.Indefinite_Vectors as well as between these types and plain 
old Ada arrays?

-- 
Victor Porton - http://portonvictor.org

^ permalink raw reply	[relevance 5%]

* Getting the index for an element in mutually referencing containers
@ 2017-03-09 13:45  6% Mart van de Wege
  0 siblings, 0 replies; 70+ results
From: Mart van de Wege @ 2017-03-09 13:45 UTC (permalink / raw)



I am missing another thing: I managed to boil down the problem to the
PoC code below. I want to have two objects, each with a container as a
record attribute, referring to each other, and then merely get the index
value of one of the two containers. Yet if I do, I get a Storage_Error
exception.

Code:

with Ada.Containers.Indefinite_Vectors;
with Ada.Containers.Indefinite_Doubly_Linked_Lists;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Test_Container is
   type Abstract_Person is abstract tagged null record;
   package Offspring is new Ada.Containers.Indefinite_Vectors
     (Index_Type => Positive,
      Element_Type => Abstract_Person'Class);
   package Group is new Ada.Containers.Indefinite_Doubly_Linked_Lists
     (Element_Type => Abstract_Person'Class);
   type Person is new Abstract_Person with record
      Children : Offspring.Vector := Offspring.To_Vector(4);
      Parents : Group.List;
   end record;
   Father : Person;
   Child : Person;
begin
   Child.Parents.Prepend(Father);
   Father.Children.Append(Child);
   Put(Integer(Father.Children.Find_Index(Child)));
end Test_Container;

This compiles OK, but on runtime throws an exception:

raised STORAGE_ERROR : stack overflow or erroneous memory access

Now, cyclic dependencies are tricky, so I am sure I am doing something
wrong, but I can't for the life of me see what.

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.

^ permalink raw reply	[relevance 6%]

* Re: Ada.Numerics.Long_Real_Arrays
  2017-01-26 14:52  3%       ` Ada.Numerics.Long_Real_Arrays Simon Wright
@ 2017-01-26 15:03  6%         ` Simon Wright
  0 siblings, 0 replies; 70+ results
From: Simon Wright @ 2017-01-26 15:03 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> I'm not sure whether one could get something less clumsy by using
> Ada.Containers.Indefinite_Vectors to hold the R_Vectors.

with Ada.Containers.Indefinite_Vectors;
with Ada.Numerics.Long_Real_Arrays;
package Nmc is
   package Matrices is new Ada.Containers.Indefinite_Vectors
     (Positive,
      Ada.Numerics.Long_Real_Arrays.Real_Vector,
      "=" => Ada.Numerics.Long_Real_Arrays."=");
   subtype Matrix is Matrices.Vector;
end Nmc;

with Nmc;
procedure Test_Nmc is
   M : Nmc.Matrix;
begin
   M (1) := (1.0, 2.0);
   M (2) := (3.0, 4.0);
   M (3) := (5.0, 6.0);
end Test_Nmc;


^ permalink raw reply	[relevance 6%]

* Re: Ada.Numerics.Long_Real_Arrays
  @ 2017-01-26 14:52  3%       ` Simon Wright
  2017-01-26 15:03  6%         ` Ada.Numerics.Long_Real_Arrays Simon Wright
  0 siblings, 1 reply; 70+ results
From: Simon Wright @ 2017-01-26 14:52 UTC (permalink / raw)


This will compile, and preserve visibility of the underlying Vectors.
I'm not sure whether one could get something less clumsy by using
Ada.Containers.Indefinite_Vectors to hold the R_Vectors.

with Ada.Numerics.Long_Real_Arrays;
generic
   Np : Positive;
package Nm_G is
   subtype R_Vector
     is Ada.Numerics.Long_Real_Arrays.Real_Vector (1 .. Np);
   type R_Matrix is array (1 .. Np + 1) of R_Vector;
end Nm_G;

with Nm_G;
package Nm is
   --  I assume there's more than just Fnm here; if not, Fnm could be a
   --  library-level generic subprogram.
   --
   --  Of course, if there _is_ more than just Fnm, it's likely the
   --  other components will also need to know which instantiation of
   --  Nm_G they have to deal with, and the 'with package' bit would
   --  need to be placed on the Nm (which itself has to be generic).
   generic
      --  This generic needs to know which instantiation of Nm_G it is
      --  to deal with.
      with package Nm_I is new Nm_G (<>);
      --  Now we know what type the parameter of the actual F has to
      --  be.
      with function F (R : Nm_I.R_Vector) return Long_Float;
   procedure Fnm (P : in out Nm_I.R_Matrix);
end Nm;

package body Nm is
   procedure Fnm (P : in out Nm_I.R_Matrix) is
   begin
      null;
   end Fnm;
end Nm;

with Nm;
with Nm_G;
procedure Test_Nm is
   package Nm_Inst is new Nm_G (Np => 2);
   function Actual_F (R : Nm_Inst.R_Vector) return Long_Float is (42.0);
   procedure Actual_Fnm is new Nm.Fnm (Nm_I => Nm_Inst,
                                       F    => Actual_F);
   P : Nm_Inst.R_Matrix := ((1.0, 2.0), (3.0, 4.0), (5.0, 6.0));
begin
   Actual_Fnm (P);
end Test_Nm;

^ permalink raw reply	[relevance 3%]

* Re: New to Ada need help implementing Warshall's algorithm
  2016-09-23  4:31  5% ` Shark8
@ 2016-09-23 14:54  0%   ` James Brewer
  0 siblings, 0 replies; 70+ results
From: James Brewer @ 2016-09-23 14:54 UTC (permalink / raw)


On Thursday, September 22, 2016 at 11:31:53 PM UTC-5, Shark8 wrote:
> On Wednesday, September 21, 2016 at 4:05:12 PM UTC-6, James Brewer wrote:
> > Hello I hope this is right forum for this question. I have been asked to write a program that implements Warshall's algorithm using Ada. The problem, I have never written an Ada program and I a limited time frame to put this together.
> > I have have the IDE installed and am in the process of writing some rudimentary programs to familiarize myself with the language but I'm afraid that I may run out of time. 
> > 
> > The input data I have is a series of connections between 7 to 9 entities that would be stored in a file.
> > 
> > examples: A->B  A->D  C->D 
> >           alice->bob  alice->larry bob -> larry
> >            1 -> 3  1 -> 5  2 -> 5
> > 
> > Any help you could offer would be greatly appreciated.
> > Thanks
> 
> 
> This sounds kind of like homework, is it?
> 
> In any case, what you could do is use Ada.Containers to handle the problem:
> * Create an enumeration for nodes, perhaps Node_01 to Node_10.
> * Instantiate Ada.Containers.Indefinite_Vectors with that enumeration as key and element as string. (This is to associate your input-variables w/ the enumeration.)
> * Instantiate Ada.Containers.Ordered_Sets with the enumeration; this is to represent node-connections.
> * Instantiate Ada.Containers.Indefinite_Ordered_Maps with the Set-type from the above as the element and the enumeration as the key. 
> 
> The rest is left to you.

It is a homework of sorts, but not in the way you'd normally think.  The instructor uses Ada when teaching algorithms for the examples but he expects you to teach yourself Ada on your own while trying to learn the algorithms. This is a bit daunting when you don't know what the language can and cannot do.

Thanks for the help, I appreciate it.  

^ permalink raw reply	[relevance 0%]

* Re: New to Ada need help implementing Warshall's algorithm
  @ 2016-09-23  4:31  5% ` Shark8
  2016-09-23 14:54  0%   ` James Brewer
  0 siblings, 1 reply; 70+ results
From: Shark8 @ 2016-09-23  4:31 UTC (permalink / raw)


On Wednesday, September 21, 2016 at 4:05:12 PM UTC-6, James Brewer wrote:
> Hello I hope this is right forum for this question. I have been asked to write a program that implements Warshall's algorithm using Ada. The problem, I have never written an Ada program and I a limited time frame to put this together.
> I have have the IDE installed and am in the process of writing some rudimentary programs to familiarize myself with the language but I'm afraid that I may run out of time. 
> 
> The input data I have is a series of connections between 7 to 9 entities that would be stored in a file.
> 
> examples: A->B  A->D  C->D 
>           alice->bob  alice->larry bob -> larry
>            1 -> 3  1 -> 5  2 -> 5
> 
> Any help you could offer would be greatly appreciated.
> Thanks


This sounds kind of like homework, is it?

In any case, what you could do is use Ada.Containers to handle the problem:
* Create an enumeration for nodes, perhaps Node_01 to Node_10.
* Instantiate Ada.Containers.Indefinite_Vectors with that enumeration as key and element as string. (This is to associate your input-variables w/ the enumeration.)
* Instantiate Ada.Containers.Ordered_Sets with the enumeration; this is to represent node-connections.
* Instantiate Ada.Containers.Indefinite_Ordered_Maps with the Set-type from the above as the element and the enumeration as the key. 

The rest is left to you.

^ permalink raw reply	[relevance 5%]

* Re: Are mutually dependant and possibly recursive types using Containers possible?
  2016-09-09 20:24  4% Are mutually dependant and possibly recursive types using Containers possible? Shark8
@ 2016-09-09 20:40  0% ` Jeffrey R. Carter
  0 siblings, 0 replies; 70+ results
From: Jeffrey R. Carter @ 2016-09-09 20:40 UTC (permalink / raw)


On 09/09/2016 01:24 PM, Shark8 wrote:
> 
> We could add Strings easily enough:
>  Package String_Holder is new Ada.Containers.Indefinite_Holders( String );
>  
>  Type Type_Indicator is ( TI_Integer, TI_Real, TI_String );
>  
>  Type Item( Indicator : Type_Indicator ) is record
>     case Indicator is
>         when TI_Integer => Integer_Value : Integer;
>         when TI_Real    => Real_Value    : Float;
>         when TI_String  => String_Value  : String_Holder.Holder;
>     end case;
>  end record;
> 
> But with adding arrays things break down:
> we can't instantiate Ada.Containers.Indefinite_Vectors for use in Item because Item isn't defined at that point, yet we absolutely need it in order to make it (the structure/definition) simple.

Somebody named Shark8 asked this July 30:

https://groups.google.com/forum/#!msg/comp.lang.ada/Brf7vvOLvrQ/fQB6RUzZAgAJ;context-place=forum/comp.lang.ada

I'm not sure what was wrong with the solution you got there then, since you
didn't respond to any of the replies, but my solution is still to make Item a
type extension of a dummy tagged type Root, and instantiate Indefinite_Vectors
with Root'Class.

-- 
Jeff Carter
"In the frozen land of Nador they were forced to
eat Robin's minstrels, and there was much rejoicing."
Monty Python & the Holy Grail
70

^ permalink raw reply	[relevance 0%]

* Are mutually dependant and possibly recursive types using Containers possible?
@ 2016-09-09 20:24  4% Shark8
  2016-09-09 20:40  0% ` Jeffrey R. Carter
  0 siblings, 1 reply; 70+ results
From: Shark8 @ 2016-09-09 20:24 UTC (permalink / raw)


Alright, let's say we're implementing a programming a programming language  -- because the problem becomes very apparent there -- and it has a simple set of two primitive types, Real and Integer, and two complex ones, Array and String.

If it were just the primitive-types, we could use:
 Type Primitive(Is_Real : Boolean) is record
    case Is_Real is
        when True  => Real_Value    : Float;
        when False => Integer_Value : Integer;
    end case;
 end record;


We could add Strings easily enough:
 Package String_Holder is new Ada.Containers.Indefinite_Holders( String );
 
 Type Type_Indicator is ( TI_Integer, TI_Real, TI_String );
 
 Type Item( Indicator : Type_Indicator ) is record
    case Indicator is
        when TI_Integer => Integer_Value : Integer;
        when TI_Real    => Real_Value    : Float;
        when TI_String  => String_Value  : String_Holder.Holder;
    end case;
 end record;

But with adding arrays things break down:
we can't instantiate Ada.Containers.Indefinite_Vectors for use in Item because Item isn't defined at that point, yet we absolutely need it in order to make it (the structure/definition) simple.

True, we could avoid this if arrays of arrays aren't required/allowed, but the problem comes back if the language introduces/requires references and, arguably, pointers. (The difference being that the empty-holder would not be allowed in a reference, but would in a pointer [whose null value would be the no_element constant].)

^ permalink raw reply	[relevance 4%]

* Re: Base64 encoding and decoding (preferably public domain)
  @ 2016-08-22  2:48  3% ` Shark8
  0 siblings, 0 replies; 70+ results
From: Shark8 @ 2016-08-22  2:48 UTC (permalink / raw)


On Saturday, August 20, 2016 at 12:23:30 PM UTC-6, jo...@peppermind.com wrote:
> Hi!
> 
> Does anybody happen to have a source package for Base64 encoding and decoding of in-memory strings?
> 
> I'm writing a small package that I intend to release under an MIT license and therefore don't want to use any of the large libraries like Ada.utils or GNATcoll.

Pragma Ada_2012;
Pragma Assertion_Policy( Check );

With
Ada.Containers.Indefinite_Vectors,
Interfaces;

Package Base_64 is

    Type Base_64_Character is
      (	'A',	'B',	'C',	'D',	'E',
       	'F',	'G',	'H',	'I',	'J',
	'K',	'L',	'M',	'N',	'O',
	'P',	'Q',	'R',	'S',	'T',
	'U',	'V',	'W',	'X',	'Y',
	'Z',	'a',	'b',	'c',	'd',
	'e',	'f',	'g',	'h',	'i',
	'j',	'k',	'l',	'm',	'n',
	'o',	'p',	'q',	'r',	's',
	't',	'u',	'v',	'w',	'x',
	'y',	'z',	'0',	'1',	'2',
	'3',	'4',	'5',	'6',	'7',
	'8',	'9',	'+',	'/',	'='
      ) with Size => 8, Object_Size => 8;

    Subtype Nonpad_Character is Base_64_Character range
      Base_64_Character'First..Base_64_Character'Pred(Base_64_Character'Last);

    type Base_64_String is Array(Positive range <>) of Base_64_Character
      with Dynamic_Predicate =>
	-- Base64 Strings always have a length that is a multiple of 4.
	(Base_64_String'Length mod 4 = 0 or else raise Constraint_Error with "Illegal Base64 length:" & Natural'Image(Base_64_String'Length))
--        and then
--  	-- Only the last two characters can be padding.
--  	(for all Index in Base_64_String'First..Base_64_String'Last - 2 =>
--             Base_64_String(Index) in Nonpad_Character --or else raise Constraint_Error with "Malformed Base64 string."
--           )
       and then
        -- Pad characters must come at the end, if present.
    (if Base_64_String'Length > 1 and then Base_64_String(Base_64_String'Last-1) = '=' then
	 (if Base_64_String(Base_64_String'Last) /= '=' then raise Constraint_Error with "Nonterminal pad character detected."
	  else True)
    );
    
    
    Function Encode( Data : String ) return Base_64_String;
    Function Decode( Data : Base_64_String ) return String;
    
    -- Converts a Base_64_String to a String.
    -- NOTE: This does NOT entail decoding.
    Function To_String( Data : Base_64_String ) return String;

    Type Encoder is private;
    Procedure Feed( State : in out Encoder; Data : Interfaces.Integer_8 );
    Function  Get_Data( State : in Encoder ) return Base_64_String;
    Function  Reset( State : in out Encoder) return Base_64_String;
    Procedure Reset( State : in out Encoder; Data : Base_64_String );
    Procedure Reset( State : in out Encoder );

Private
    
    Package Internals is
	
	----------------------
	--  INTERNAL TYPES  --
        ----------------------
 
	Type Base_64_Chunk  is array(Positive range 1..4) of Base_64_Character;
	
	Type Internal_Count is range 1..3;

	Type Internal_Character is new Nonpad_Character
	  with Size => 6;

	Type Quad    is record 
	    A, B, C, D : Internal_Character;
	end record
	  with Size => 24, Object_Size => 24, Pack; --, Bit_Order => System.Low_Order_First; --, alignment => 0, Pack, 
	
	For Quad use record at mod 8;
	    D at 0 range 0..5;
	    C at 0 range 6..11;
	    B at 0 range 12..17;
	    A at 0 range 18..23;
	end record;
	
	
	Type Tripple is record
	    A, B, C : Interfaces.Integer_8;
	end record
	  with Size => 24, Object_Size => 24, Pack;--, Bit_Order => System.High_Order_First;
    
	For Tripple use record at mod 8;
	    A at 2 range 0..7;
	    B at 1 range 0..7;
	    C at 0 range 0..7;
	end record;
	
	-------------------------
	--  INTERNAL PACKAGES  --
        -------------------------
	
	Package Internal_Data_Vector is new Ada.Containers.Indefinite_Vectors(
	    Index_Type   => Positive,
 	    Element_Type => Quad,
	    "="          => "="
	);
	
	--------------------------
	--  INTERNAL FUNCTIONS  --
        --------------------------
	
	
	Function Convert( Source : Quad ) return Tripple with Inline, Pure_Function;
	Function Convert( Source : Tripple ) return Quad with Inline, Pure_Function;
	Function Convert( Source : Base_64_Chunk) return Quad with Inline, Pure_Function;
	Function Convert( Source : Quad) return Base_64_Chunk with Inline, Pure_Function;
    End Internals;
    
    Type Encoder is record -- new Ada.Finalization.Controlled with record
	Result : Internals.Internal_Data_Vector.Vector;
	B1, B2 : Interfaces.Integer_8:= Interfaces.Integer_8'First;

	Current : Internals.Internal_Count := Internals.Internal_Count'First;
    end record;


End Base_64;

-------------------------------
-------------------------------

Pragma Ada_2012;
Pragma Assertion_Policy( Check );

With
System,
Unchecked_Conversion;

Package Body Base_64 is

    Package Body Internals is
	
	Function Internal_Convert is new Unchecked_Conversion(
	    Source => Tripple,
	    Target => Quad
	   );
	
	Function Internal_Convert is new Unchecked_Conversion(
	    Source => Quad,
 	    Target => Tripple
	   );
	
	Function Convert( Source : Quad ) return Tripple is
	  ( Internal_Convert(Source) );
	Function Convert( Source : Tripple ) return Quad is
	  ( Internal_Convert(Source) );
	
	Function Convert (Source : Base_64_Chunk) return Quad is
	(if (for all C of Source => C in Nonpad_Character) then
	  (  Internal_Character( Source(1) ),
	     Internal_Character( Source(2) ),
	     Internal_Character( Source(3) ),
	     Internal_Character( Source(4) )
	  ) else raise Program_Error with "Cannot convert a chunk with padding."
	);
    
    
	Function Convert (Source : Quad) return Base_64_Chunk is
	  (Base_64_Character( Source.A ),
	   Base_64_Character( Source.B ),
	   Base_64_Character( Source.C ),
	   Base_64_Character( Source.D )
	  );
	
	Function Internal_Convert is new Unchecked_Conversion(
	    Source => Interfaces.Integer_8,
	    Target => Character
	   );
	
    end Internals;
    
    
    Function Convert is new Unchecked_Conversion(
       Source => Character,
       Target => Interfaces.Integer_8
      );

    Function Convert is new Unchecked_Conversion(
       Source => Interfaces.Integer_8,
       Target => Character
      );
    

    Function Encode( Data : String ) return Base_64_String is
	State : Encoder;
    begin
	for Item of Data loop
	    Feed( State, Convert(Item) );
	end loop;

	Return Get_Data( State );
    end Encode;

    Function Decode( Data : Base_64_String ) return String is
	Local_Encoder : Encoder;
	Chunk_Size : Constant := 3;
    begin
	if Data'Length not in Positive then
	    Return "";
	end if;

	Reset( Local_Encoder, Data );
	
	Decode_Process:
	Declare
	    Has_Pad : Constant Boolean := Data(Data'Last)   not in Nonpad_Character;
	    Two_Pad : Constant Boolean := Data(Data'Last-1) not in Nonpad_Character;
	    
	    Subtype Chunk_Range is Positive range 1 .. Data'Length/4
	        + (if Has_Pad then -1 else 0);
	    
	    Padding : Constant Natural := (
	       if    Two_Pad then 1
	       elsif Has_Pad then 2
	       else               0
	      );
	    
	    Result_Length : Constant Natural := Chunk_Range'Last*3 + Padding;
	Begin
	    Return Result : String(1..Result_Length) := (others => '?') do
		Handle_Nonpad_Characters:
		For Index in Chunk_Range loop
		    declare
			Use Internals;
			Chunk_Start : Constant Positive := Positive'Succ(Natural'Pred(Index)*4);
			Subtype Chunk is Positive range Chunk_Start..Chunk_Start+Chunk_Size;
			Start : Constant Positive := Natural'Pred(Index)*Chunk_Size + Result'First;
			Stop  : Constant Positive := Start + Chunk_Size - 1;
			
			Temp : Constant Base_64_Chunk := Base_64_Chunk(Data(Chunk));
			Four : Quad renames Convert( Temp );
			Three: Tripple renames Convert( Four );
		    begin
			Result(Start..Stop):= 
			  (Convert(Three.A),
			   Convert(Three.B),
			   Convert(Three.C)
			  );
		    end;
		End Loop Handle_Nonpad_Characters;
		
		if Has_Pad then
		    Handle_Padding:
		    Declare
			Use Internals;
			Tail : Base_64_String renames Data(Data'Last-3..Data'Last);
			B64C : Constant Base_64_Chunk := Base_64_Chunk(Tail);
			Q    : Constant Quad := 
			  (   Internal_Character( B64C(1) ),
			      Internal_Character( B64C(2) ),
			      (if Two_Pad then Internal_Character'First
			       else Internal_Character( B64C(3) )),
			      Internal_Character'First
			  );
			Three : Tripple renames Convert( Q );
		    Begin
			Result(Result'Last-1):= Convert(Three.A);
			Result(Result'Last  ):= Convert(Three.B);
		    End Handle_Padding;
		end if;
	    End return;
	End Decode_Process;
    End Decode;


    Function To_String( Data : Base_64_String ) return String is
    Begin
	Return Result : String( Data'Range ) do
	    for Index in Data'Range loop
		declare
		    B64C  : Base_64_Character renames Data(Index);
		    Pos   : Constant Natural := Base_64_Character'Pos( B64C );
		    Image : String renames Base_64_Character'Image( Base_64_Character'Val(Pos) );
		    CI    : Character renames Image(2);
		begin
		    Result(Index):= CI;
		end;
	    end loop;
	End return;
    End To_String;


    -------


    Procedure Feed( State : in out Encoder; Data : Interfaces.Integer_8 ) is
	Use Internals;
    begin
	case State.Current is
	when 1 =>
	    State.B1:= Data;
	    State.Current:= Internal_Count'Succ( State.Current );
	when 2 =>
	    State.B2:= Data;
	    State.Current:= Internal_Count'Succ( State.Current );
	when 3 =>
	    Process:
	    Declare
		Three_Bytes : Constant Tripple := (State.B1, State.B2, Data);
		Four_Chars  : Quad renames Convert(Three_Bytes);
	    Begin
		State.Result.Append( Four_Chars );
		State.Current:= Internal_Count'First;
	    End Process;
	end case;
    End Feed;

    Function  Get_Data( State : in Encoder ) return Base_64_String is
	Use Ada.Containers, Internals.Internal_Data_Vector, Internals;
	Chunk_Size : Constant := Base_64_Chunk'Length;
	Padding : Constant Natural := (if State.Current = 1 then 0 else 1);
	Subtype Result_Range is Positive range 1..Natural(State.Result.Length);
	Subtype Padded_Range is Positive range 1..(Result_Range'last+Padding)*Chunk_Size;
    begin
	Return Result : Base_64_String(Padded_Range) := (others => '=') do
	    Transpose_Result:
	    For Index in Result_Range loop
		declare
		    Offset : Constant Natural := Chunk_Size*Natural'Pred(Index);
		    Start  : Constant Positive:= Offset+1;
		    Stop   : Constant Positive:= Positive'Pred(Start+Chunk_Size);
		    Temp   : Base_64_Chunk renames Convert(State.Result(Index));
		begin
		    Result(Start..Stop):= Base_64_String( Temp );
		end;
	    End Loop Transpose_Result;

	    Handle_Tail:
	    declare
	    begin
		case State.Current is
		when 1 => null;
		when others =>
		    declare
			Three : Constant Tripple := (State.B1, State.B2, 0);
			Four  : Base_64_Chunk renames Convert(Convert(Three));
		    begin
			Result(Padded_Range'Last-3):= Four(1);
			Result(Padded_Range'Last-2):= Four(2);
			if State.Current = 3 then
			    Result(Padded_Range'Last-1):= Four(3);
			end if;
		    end;
		end case;
	    End Handle_Tail;
	end return;
    end Get_Data;

    Function  Reset( State : in out Encoder) return Base_64_String is
    Begin
	Return Result : constant Base_64_String := Get_Data(State) do
	    Reset(State);
	End return;
    End Reset;
    
    Procedure Reset( State : in out Encoder; Data : Base_64_String ) is
    begin
	Reset(State);
	if Data'Length not in Positive then
	    Return;
	else
	    Decode:
	    declare
		Use Internals;
		Has_Pad     : Constant Boolean := Data(Data'Last) not in Nonpad_Character;
		Two_Pad     : Constant Boolean := Data(Data'Last-1) not in Nonpad_Character;
		Data_Length : Constant Integer := Data'Length / 4 - (if Has_Pad then 1 else 0);
		Subtype Chunk_Index is Positive range Data'First..Data_Length;
	    begin
		Common_Portion:
		For Index in Chunk_Index loop
		    declare
			C : Constant Base_64_Chunk := Base_64_Chunk(Data(Index*4..Index*4+3));
			Q : Quad renames Convert(C);
		    begin			
			State.Result.Append( Q );
		    end;
		End Loop Common_Portion;
		
		if Has_Pad then
		    Handle_Padding:
		    Declare
			Tail : Base_64_String renames Data(Data'Last-3..Data'Last);
			B64C : Constant Base_64_Chunk := Base_64_Chunk(Tail);
			Q    : Constant Quad := 
			  (
			    Internal_Character( B64C(1) ),
			    Internal_Character( B64C(2) ),
			    (if Two_Pad then Internal_Character'First
			     else Internal_Character( B64C(3) )),
			    Internal_Character'First
			  );
			Three : Tripple renames Convert( Q );
		    Begin
			State.B1 := Three.A;
			if Two_Pad then 
			    State.B2:= Three.B;
			    State.Current:= 3;
			else
			    State.Current:= 2;
			end if;
		    End Handle_Padding;
		end if;
	    End Decode;
	end if;
    end Reset;
    
    Procedure Reset( State : in out Encoder ) is
    Begin
	State.Result.Clear;
	State.Current:= 1;
	State.B1 := Interfaces.Integer_8'First;
	State.B2 := Interfaces.Integer_8'First;
    End Reset;

End Base_64;


^ permalink raw reply	[relevance 3%]

* Re: Is it possible to make a possibly self-referential type using containers?
  2016-07-31  0:31  4% Is it possible to make a possibly self-referential type using containers? Shark8
  2016-07-31  2:41  3% ` Randy Brukardt
  2016-07-31  5:36  4% ` Jeffrey R. Carter
@ 2016-07-31  7:00  4% ` Dmitry A. Kazakov
  2 siblings, 0 replies; 70+ results
From: Dmitry A. Kazakov @ 2016-07-31  7:00 UTC (permalink / raw)


On 2016-07-31 02:31, Shark8 wrote:

> Type Executable_Code(<>) is private; -- The type in which we store executable code.
> Type Word(<>);
>
> Package Word_List is new Ada.Containers.Indefinite_Vectors
>   (Element_Type => Word, Index_Type => Positive);
>
> Type Word( Is_List ) is record
>   case Is_List is
>     when True  => List : Word_List.Vector;
>     when False => Item : Executable_Code;
> end record;
>
> The above would be nicely elegant insofar as maintenance goes as
> it's  simple and straightforward.

Nothing elegant in this, but anyway...

> * Word: a chunk of code to execute or a list of words [to execute].
> ** Something like SEQUENCE OF INTEGER is fundamental in IDL and ASN.1.

    type Word is interface;
    type Executable_Code (<>) is new Word with private;
    package Lists is
       new Ada.Containers.Indefinite_Vectors
           (  Index_Type   => Positive,
              Element_Type => Word'Class
           );
    type List is new Lists.Vector and Word with null record;

P.S. Type recursion is inconsistent if not resolved, as in the example 
which splits self-referential Word into Word interface and Word'Class.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[relevance 4%]

* Re: Is it possible to make a possibly self-referential type using containers?
  2016-07-31  0:31  4% Is it possible to make a possibly self-referential type using containers? Shark8
  2016-07-31  2:41  3% ` Randy Brukardt
@ 2016-07-31  5:36  4% ` Jeffrey R. Carter
  2016-07-31  7:00  4% ` Dmitry A. Kazakov
  2 siblings, 0 replies; 70+ results
From: Jeffrey R. Carter @ 2016-07-31  5:36 UTC (permalink / raw)


On 07/30/2016 05:31 PM, Shark8 wrote:
> Consider something like Forth, IDL, and ASN.1 where there recursion plays a big part in the underlying ideas: the former in its definition of "Word"*, and in the latter two in the defining of types**.
> 
> So, given that the most straightforward way to implement these would be in a self-referencing type it would be nice to be able to use containers for this, perhaps like:

There was a discussion of this on here about a year ago in the context of having
a private type that is self-referential using a container. See

https://groups.google.com/d/msg/comp.lang.ada/SO9olMGfF4o/aGrCFMsVCwAJ

The advantage of using a container is that one doesn't have to deal with the
error-prone aspects of using access types and doing memory management.

I presented a solution there that used a tagged type, an indefinite container of
the 'Class of that type, and a type extension to achieve this:

with Ada.Containers.Indefinite_Vectors;

package P is
   type T (<>) is private;
private
   type Root is tagged null record;

   package Lists is new Ada.Containers.Vectors
      (Index_Type => Positive, Element_Type => Root'Class);

   type T is new Root with record
      List : Lists.Vector;
   end T;
end P;

The intention here is that only values of type T will be stored in such a
vector, so Root and the type extension for T are noise. You also have to
explicitly convert anything retrieved from the list to type T, which is more
noise. But it beats messing with access values.

-- 
Jeff Carter
"I was either in love, or I had smallpox."
Take the Money and Run
137


^ permalink raw reply	[relevance 4%]

* Re: Is it possible to make a possibly self-referential type using containers?
  2016-07-31  0:31  4% Is it possible to make a possibly self-referential type using containers? Shark8
@ 2016-07-31  2:41  3% ` Randy Brukardt
  2016-07-31  5:36  4% ` Jeffrey R. Carter
  2016-07-31  7:00  4% ` Dmitry A. Kazakov
  2 siblings, 0 replies; 70+ results
From: Randy Brukardt @ 2016-07-31  2:41 UTC (permalink / raw)


You could, of course, create a container using a formal incomplete type 
(which does match incomplete types). The issue(*) is that you'd need to pass 
in a constructor function and a destructor procedure (since you can't 
allocate an object of an incomplete type). That would look something like:

    generic
         type Index_Type is range <>;
         type Element_Type;
         with function "=" (Left, Right : Element_Type)  return Boolean is 
<>;
         with function Copy_Constructor (Obj : Element_Type) return access 
Element_Type;
         with procedure Destructor (Value : access Element_Type);
    package Incomplete_Vectors is
      ....

Then the operations that add elements to the container would use 
Copy_Constructor to allocate a copy, and the clean-up code would use 
Destructor. (It might be better to use a named access for this purpose, the 
problem with that is that you'd have to declare it visible before the 
instance, while that type is really an implementation artifact best kept 
private to this usage.)

                 Randy Brukardt.

(*) It's *almost* possible to create a container of pre-existing objects 
using a formal incomplete type. The problem is that you're not allowed to 
take 'Access of a parameter of such a type (that violates 3.10.1(10/3) - 
even though there's no real problem with that particular operation). I've 
suggested "fixing" this issue in the Ada Standard, but that hasn't gotten 
any traction as most see it as a curiosity rather than the realistic 
technique. If you'd like to see this work, send something to Ada-Comment!


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:18dfc647-ef22-4052-b6ad-ce3516124085@googlegroups.com...
Consider something like Forth, IDL, and ASN.1 where there recursion plays a 
big part in the underlying ideas: the former in its definition of "Word"*, 
and in the latter two in the defining of types**.

So, given that the most straightforward way to implement these would be in a 
self-referencing type it would be nice to be able to use containers for 
this, perhaps like:

Type Executable_Code(<>) is private; -- The type in which we store 
executable code.
Type Word(<>);

Package Word_List is new Ada.Containers.Indefinite_Vectors
  (Element_Type => Word, Index_Type => Positive);

Type Word( Is_List ) is record
  case Is_List is
    when True  => List : Word_List.Vector;
    when False => Item : Executable_Code;
end record;

The above would be nicely elegant insofar as maintenance goes as it's simple 
and straightforward. However, we cannot use that because Element_Type cannot 
be a incomplete-type, but it needs to be because the full type declaration 
requires the instantiation of the container. -- It also seems that 
Limited/private with clauses cannot help.

* Word: a chunk of code to execute or a list of words [to execute].
** Something like SEQUENCE OF INTEGER is fundamental in IDL and ASN.1. 


^ permalink raw reply	[relevance 3%]

* Is it possible to make a possibly self-referential type using containers?
@ 2016-07-31  0:31  4% Shark8
  2016-07-31  2:41  3% ` Randy Brukardt
                   ` (2 more replies)
  0 siblings, 3 replies; 70+ results
From: Shark8 @ 2016-07-31  0:31 UTC (permalink / raw)


Consider something like Forth, IDL, and ASN.1 where there recursion plays a big part in the underlying ideas: the former in its definition of "Word"*, and in the latter two in the defining of types**.

So, given that the most straightforward way to implement these would be in a self-referencing type it would be nice to be able to use containers for this, perhaps like:

Type Executable_Code(<>) is private; -- The type in which we store executable code.
Type Word(<>);

Package Word_List is new Ada.Containers.Indefinite_Vectors
  (Element_Type => Word, Index_Type => Positive);

Type Word( Is_List ) is record
  case Is_List is
    when True  => List : Word_List.Vector;
    when False => Item : Executable_Code;
end record;

The above would be nicely elegant insofar as maintenance goes as it's simple and straightforward. However, we cannot use that because Element_Type cannot be a incomplete-type, but it needs to be because the full type declaration requires the instantiation of the container. -- It also seems that Limited/private with clauses cannot help. 

* Word: a chunk of code to execute or a list of words [to execute].
** Something like SEQUENCE OF INTEGER is fundamental in IDL and ASN.1.


^ permalink raw reply	[relevance 4%]

* Re: Confused about class-wide types
  2016-03-20 13:18  5% ` Shark8
  2016-03-20 13:56  0%   ` Mart van de Wege
@ 2016-03-21 21:54  0%   ` Randy Brukardt
  1 sibling, 0 replies; 70+ results
From: Randy Brukardt @ 2016-03-21 21:54 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:c5f5d5ac-89c4-4b60-9388-f461ed69eb0e@googlegroups.com...
>On Sunday, March 20, 2016 at 5:16:24 AM UTC-6, Mart van de Wege wrote:
>>    package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
>> Element_Type => Event_Ptr);
>
>If you are using Ada 2012, then you can change "Events" to 
>Ada.Containers.Indefinite_Vectors ...

Indefinite_Vectors was actually introduced with the original containers 
library in Ada 2005; you don't need Ada 2012 to use it. (Since there are a 
number of non-GNAT compilers that claim to support Ada 2005, using it 
doesn't lock you in quite as much.)

                                                 Randy.



^ permalink raw reply	[relevance 0%]

* Re: Confused about class-wide types
  2016-03-20 13:18  5% ` Shark8
@ 2016-03-20 13:56  0%   ` Mart van de Wege
  2016-03-21 21:54  0%   ` Randy Brukardt
  1 sibling, 0 replies; 70+ results
From: Mart van de Wege @ 2016-03-20 13:56 UTC (permalink / raw)


Shark8 <onewingedshark@gmail.com> writes:

> On Sunday, March 20, 2016 at 5:16:24 AM UTC-6, Mart van de Wege wrote:
>>    package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
>> 						 Element_Type => Event_Ptr);
>
>
> If you are using Ada 2012, then you can change "Events" to
> Ada.Containers.Indefinite_Vectors with an Element_Type of
> Event'Class... which should, in turn, eliminate the need for any
> pointer-types in the test. (It also has the advantage of not needing
> to check the vector for Null.)

So *that* is what Indefinite_Vectors is for. That would solve my issues,
yes.

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.


^ permalink raw reply	[relevance 0%]

* Re: Confused about class-wide types
  @ 2016-03-20 13:18  5% ` Shark8
  2016-03-20 13:56  0%   ` Mart van de Wege
  2016-03-21 21:54  0%   ` Randy Brukardt
  0 siblings, 2 replies; 70+ results
From: Shark8 @ 2016-03-20 13:18 UTC (permalink / raw)


On Sunday, March 20, 2016 at 5:16:24 AM UTC-6, Mart van de Wege wrote:
>    package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
> 						 Element_Type => Event_Ptr);


If you are using Ada 2012, then you can change "Events" to Ada.Containers.Indefinite_Vectors with an Element_Type of Event'Class... which should, in turn, eliminate the need for any pointer-types in the test. (It also has the advantage of not needing to check the vector for Null.)


^ permalink raw reply	[relevance 5%]

* Re: working with diferent instances of the same generic interface
  @ 2015-09-10 12:22  4%     ` Jacob Sparre Andersen
  0 siblings, 0 replies; 70+ results
From: Jacob Sparre Andersen @ 2015-09-10 12:22 UTC (permalink / raw)


Aitor Alcrudo Sangros wrote:

> Hi, I'm not really specifically tring to make that code work as
> is. What I want to know is how can I work with different instances of
> the same generic interface, doing things like iterating over a
> collection of them. This is a minimal example of how I am
> (unsuccessfully ) tring to do so. Anyway this code compiles, then has
> a runtime exception.

Your problem is that you instantiate the same package much too often.
Here is a working "solution":

package Intro is
      type Data_type is interface;

      generic
         type Readable_Data is abstract new Data_type with private;
      package Readable is
         type    Readable_Element is interface;
         subtype Readable_Class   is Readable_Element'Class ;
         function Get_Values (this : Readable_Element ) return Readable_Data'Class
                           is abstract;
      end Readable;

      type state is (OK,KO);

      generic
         with package Readable_Reporting is new Readable(<>);
         use Readable_Reporting ;
      package Reporting is
         type    Reporting_Element is interface and Readable_Element ;
         subtype Reporting_Class   is Reporting_Element'Class;
         function Report (This :Reporting_Element  ) return state is Abstract;
         overriding function Get_Values (this : Reporting_Element ) return
           Readable_Data'Class is abstract;
      end Reporting;
   end Intro;
with Intro;

package Instantiations is
   package Readable_Basic  is new Intro.Readable  (Intro.Data_Type);
   package Reporting_Basic is new Intro.Reporting (Readable_Basic);
end Instantiations;
with Intro,
     Instantiations;

package A is
   type SomeData is new Intro.Data_type with record
      a :float;
   end record;

   package Readable_Some  renames Instantiations.Readable_Basic;
   package Reporting_Some renames Instantiations.Reporting_Basic;

   type Element_type_A is
     new Readable_Some.Readable_Element and Reporting_Some.Reporting_Element
     with
      record
         data : SomeData := SomeData'(a => 0.0 );
      end record;

   subtype Element_type_A_Class is Element_type_A'Class;
   overriding function Report(This : Element_Type_A ) return Intro.state is ( Intro.KO);

   overriding
   function Get_Values (this : Element_type_A ) return Intro.Data_Type'Class is
      (this.data);
end A;
with Intro,
     Instantiations;

package B is
   type OtherData is new Intro.Data_type with record
      a :float;
   end record;

   package Readable_Other  renames Instantiations.Readable_Basic;
   package Reporting_Other renames Instantiations.Reporting_Basic;

   type Element_type_B is new Readable_Other.Readable_Element
     and Reporting_Other.Reporting_Element
     with record
        data :OtherData;
   end record;
   subtype Element_type_B_Class is Element_type_B'Class;
   function Get_Values (this : Element_type_B ) return Intro.Data_Type'Class is
      (this.data);
      function Report(This : Element_type_B ) return Intro.state is ( Intro.KO);
end B;
with Ada.Containers.Indefinite_Vectors;

with Intro,
     Instantiations;

package Manager is
   package Reporting_Basic renames Instantiations.Reporting_Basic;
   use Reporting_Basic;

   package Element_Vector is new
     Ada.Containers.Indefinite_Vectors
     (Index_Type   => Natural,
      Element_Type => Reporting_Basic.Reporting_Class);
   use Element_Vector;

   type Manager is tagged record
      elements :  Element_Vector.Vector;
   end record;
   procedure Add_Element(this : in out Manager ;
                         Element : in Reporting_Class );
end Manager;

   package body Manager is
      procedure Add_Element(this : in out Manager ;
                            Element : in Reporting_Class ) is
      begin
         this.elements.Append(Element);
      end Add_Element;
   end Manager;
with Ada.Text_IO;

with A, B, Manager;

procedure Test is
   Man      : Manager.Manager;
   Elm1_ptr : A.Element_Type_A_Class := A.Element_Type_A'(Data => (A => 1.0));
   Elm2_ptr : B.Element_Type_B_Class := B.Element_Type_B'(Data => (A => 2.0));
begin
   Man.Add_Element (Manager.Reporting_basic.Reporting_Class(Elm1_ptr));
   Ada.Text_IO.Put_Line ("1 worked.");

   Man.Add_Element (Manager.Reporting_basic.Reporting_Class(Elm2_ptr));
   Ada.Text_IO.Put_Line ("2 worked.");
end Test;

Notice how there's no need for access types.

Greetings,

Jacob
-- 
"Universities are not part of the nation's security organisation,
 they are not the nation's research laboratory either: they are
 the nation's universities."                     -- E.W. Dijkstra

^ permalink raw reply	[relevance 4%]

* Re: Indefinite Containers of Indefinite Private Types
  @ 2015-08-07 20:45  4%       ` Jeffrey R. Carter
  0 siblings, 0 replies; 70+ results
From: Jeffrey R. Carter @ 2015-08-07 20:45 UTC (permalink / raw)


On 08/07/2015 01:13 PM, Bob Duff wrote:
> "Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> writes:
> 
>> Yes, of course. The examples are simplified from a more complex case where the
>> container is used in the full type definition. This can be achieved by adding
>> some additional code that is essentially noise, or by using access types.
>> Avoiding access types is worth adding noise, but it would be nice if the noise
>> were unnecessary.
> 
> I'm curious what the "noise" looks like in your case.
> 
> Last time I ran into this problem I think I ended up using a workaround
> that involved access types.  I don't remember the details.

It involves using tagged types, type extension, and a container of a class-wide
type:

with Ada.Containers.Indefinite_Vectors;

package P is
   type T (<>) is private;
private
   type Root is tagged null record;

   package Lists is new Ada.Containers.Vectors
      (Index_Type => Positive, Element_Type => Root'Class);

   type T is new Root with record
      List : Lists.Vector;
   end T;
end P;

The only reason for the type extension is to get the instantiation that can be
used in the full declaration of T. The only objects that will be stored in a
vector are of type T. In addition to the noise of the Root type and the
extension for T, there are type conversions required that are part of the noise.

-- 
Jeff Carter
"From this day on, the official language of San Marcos will be Swedish."
Bananas
28


^ permalink raw reply	[relevance 4%]

* Re: Indefinite Containers of Indefinite Private Types
  2015-08-04  2:23  7% Indefinite Containers of Indefinite Private Types Jeffrey R. Carter
@ 2015-08-04  5:40  0% ` Niklas Holsti
    0 siblings, 1 reply; 70+ results
From: Niklas Holsti @ 2015-08-04  5:40 UTC (permalink / raw)


On 15-08-04 05:23 , Jeffrey R. Carter wrote:
> This is legal:
>
> package Indefinite1 is
>     type T (<>) is private;
> private -- Indefinite1
>     type T is new String;
> end Indefinite1;
>
> with Indefinite1;
> with Ada.Containers.Indefinite_Vectors;
>
> package Indefinite2 is
>     use type Indefinite1.T;
>
>     package Lists is new Ada.Containers.Indefinite_Vectors
>        (Index_Type => Positive, Element_Type => Indefinite1.T);
> end Indefinite2;
>
> But this isn't:
>
> with Ada.Containers.Indefinite_Vectors;
>
> package Indefinite1 is
>     type T (<>) is private;
> private -- Indefinite1
>     package Lists is new Ada.Containers.Indefinite_Vectors
>        (Index_Type => Positive, Element_Type => T);
>
>     type T is new String;
> end Indefinite1;
>
> It seems to me that both instantiations have all the information they need.
> Probably I'm missing something, but why is the latter illegal?

I'm not sure that I have understood your question correctly -- are you 
asking for the RM rule that makes this illegal, or for the reason behind 
that rule?

At the point of instantiation in the second case, "T" is a partial view 
of the type. RM 7.3(5) says "... Similarly, before the full declaration, 
the name of the partial view cannot be used in a generic_instantiation 
or in a representation item."

As to why this rule exists, I suspect it has to do with the "rechecks" 
discussed in the annotated RM 12.3(11) where the legality of an 
instantiation is checked by comparing the actual types with the _full_ 
declaration of the generic (not only with the declarations of the 
generic formals). It might be difficult to apply these rechecks if the 
actual type is only a partial view.

The second case becomes legal if the full declaration of type T is moved 
to occur before the instantiation -- as happens in the first case -- but 
you probably knew that.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


^ permalink raw reply	[relevance 0%]

* Indefinite Containers of Indefinite Private Types
@ 2015-08-04  2:23  7% Jeffrey R. Carter
  2015-08-04  5:40  0% ` Niklas Holsti
  0 siblings, 1 reply; 70+ results
From: Jeffrey R. Carter @ 2015-08-04  2:23 UTC (permalink / raw)


This is legal:

package Indefinite1 is
   type T (<>) is private;
private -- Indefinite1
   type T is new String;
end Indefinite1;

with Indefinite1;
with Ada.Containers.Indefinite_Vectors;

package Indefinite2 is
   use type Indefinite1.T;

   package Lists is new Ada.Containers.Indefinite_Vectors
      (Index_Type => Positive, Element_Type => Indefinite1.T);
end Indefinite2;

But this isn't:

with Ada.Containers.Indefinite_Vectors;

package Indefinite1 is
   type T (<>) is private;
private -- Indefinite1
   package Lists is new Ada.Containers.Indefinite_Vectors
      (Index_Type => Positive, Element_Type => T);

   type T is new String;
end Indefinite1;

It seems to me that both instantiations have all the information they need.
Probably I'm missing something, but why is the latter illegal?

-- 
Jeff Carter
"English bed-wetting types."
Monty Python & the Holy Grail
15


^ permalink raw reply	[relevance 7%]

* Re: array of string
  @ 2014-10-04  1:07  4%   ` Brad Moore
  0 siblings, 0 replies; 70+ results
From: Brad Moore @ 2014-10-04  1:07 UTC (permalink / raw)


On 2014-10-03 6:50 PM, Jerry wrote:
> On Friday, October 3, 2014 4:29:15 PM UTC-7, Stribor40 wrote:
>> is there way to declare array of strings to contain something like this..
>>
>> a(1)="london"
>>
>> a(2)""toronto"
>>
>> how would i create this?
>
> The two examples you give, london and toronto, are of different lengths. The elememts of an array have to be the same (or compatible *) type(s), so you would have to make the strings the same length and then waste some of the length for shorter names, and hope that you have declared the string length long enough for your longest city name.
>
> A better way is to make an array of unbounded strings whereby Ada things each element of the array is the same (an unbounded string) but yet unbounded strings can be of any length. The only thing you'll have to watch out for is that it is likely that other places will expect to see string, not unbounded string, for example, Put. This is easy as Ada provides conversion functions between strings and unbounded strings.
>
> When I was first learning Ada (still am, really), learning about the three different kinds of strings was one of the most useful things to know. Another was to understand subtypes *.
>
> Jerry
>

Some other options include;

1. Create an array type of access to string
eg.

type String_Array is array (Natural range <>) of access constant String;
S1 : aliased constant String := "Toronto";
S2 : aliased constant String := "London";

S : String_Array := (1 => S1'Access, 2 => S2'Access);


2. You could use an indefinite container, such as an indefinite vector.

eg.

package S_Vectors is new Ada.Containers.Indefinite_Vectors
     (Index_Type   => Natural,
      Element_Type => String);

S_Vector : S_Vectors.Vector;

...
S_Vector.Append ("Toronto");
S_Vector.Append ("London");




^ permalink raw reply	[relevance 4%]

* Re: Can anyone build AWS on Windows?
       [not found]     <8ac0299b-1935-46f9-962a-57fb710e8cf7@googlegroups.com>
@ 2014-10-01 18:16  3% ` Björn Lundin
  0 siblings, 0 replies; 70+ results
From: Björn Lundin @ 2014-10-01 18:16 UTC (permalink / raw)


On 2014-10-01 18:34, David Botton wrote:
> Since I haven't found a volunteer to try gnoga on windows I setup a Win box and... AWS doesn't compile. Makefile issues. I am using CygWin and GNAT-GPL 2014.
> 
> Has anyone managed to get it to compile and run?
> 
> Thanks
> David Botton
> 

I run mingw

from a cmd-prompt, I start bash

c:\bnl\tmp>bash
I set the prefix in makefile.conf to

prefix	 = /c/bnl/tools/aws/3.1.0w

mkdir -p c:/bnl/tools/aws/3.1.0w

make setup
make
make install


this is with gnat pro 7.1.1


then I - in cmd-prompt

set ADA_PROJECT_PATH=%ADA_PROJECT_PATH%;c:\bnl\tools\aws\3.1.0w
cd to gnoga dir
make


>make
mkdir bin
mkdir obj
mkdir lib
cd src && gprbuild -Pgnoga.gpr
gcc -c -gnatyabcefhiklmnprst -E gnoga.adb
gnoga.adb:86:07: (style) misplaced "then"
gcc -c -gnatyabcefhiklmnprst -E gnoga-types.adb
gnoga-types.adb:111:15: warning: "Index" is only defined in Ada 2005
gnoga-types.ads:41:17: warning: "Ada.Strings.Hash" is an Ada 2005 unit
gnoga-types.ads:42:20: warning: "Ada.Containers.Indefinite_Vectors" is
an Ada 20
05 unit
gnoga-types.ads:43:20: warning: "Ada.Containers.Indefinite_Hashed_Maps"
is an Ad
a 2005 unit
gcc -c -gnatyabcefhiklmnprst -E gnoga-server.ads
gcc -c -gnatyabcefhiklmnprst -E gnoga-server-model.adb
gnoga-server-model.ads:49:20: access-to-constant is an Ada 2005 extension
gnoga-server-model.ads:49:20: unit should be compiled with -gnat05 switch
gnoga-server-model.ads:53:04: overriding indicator is an Ada 2005 extension
gnoga-server-model.ads:53:04: unit must be compiled with -gnat05 switch
gnoga-server-model.ads:121:20: access-to-constant is an Ada 2005 extension
gnoga-server-model.ads:121:20: unit should be compiled with -gnat05 switch
gprbuild: *** compilation phase failed
make: *** [gnoga] Error 4


added "-gnat05" in all .gpr files



>make
cd src && gprbuild -Pgnoga.gpr
cd demo/snake && gprbuild
using project file snake.gpr
gcc -c -E -gnat05 snake-main.adb
gcc -c -E -gnat05 snake.ads
gcc -c -E -gnat05 snake-connection.adb
gprbind snake-main.bexch
gnatbind snake-main.ali
gcc -c b__snake-main.adb
gcc snake-main.o -o snake.exe
cd demo/adablog && gprbuild
using project file adablog.gpr
gcc -c -E -gnat05 adablog-main.adb
gcc -c -E -gnat05 adablog.ads
gcc -c -E -gnat05 adablog-controller.adb
gcc -c -E -gnat05 adablog-migrations.adb
gcc -c -E -gnat05 adablog-model.ads
gcc -c -E -gnat05 adablog-view.adb
gprbind adablog-main.bexch
gnatbind adablog-main.ali
gcc -c b__adablog-main.adb
gcc adablog-main.o -o adablog.exe
c:/bnl/tools/gnat/7.1.1/bin/../libexec/gcc/i686-pc-mingw32/4.7.3/ld.exe:
cannot
find -lsqlite3
collect2.exe: error: ld returned 1 exit status
gprbuild: link of adablog-main.adb failed
make: *** [adablog] Error 4

well, I do not have sql-lite installed

I get snake.exe though.
Running that, it works - but I do have the same issues as Niklas Holsti
described, arrow keys are not working.
Score of 40...


I know that git is the coolest thing ever, but I've seen some projects
where one can choose between git and svn.

It would be nice to access the code via svn too.
I now got a tar.gz snapshot, that won't update easy



-- 
--
Björn


^ permalink raw reply	[relevance 3%]

* Re: A bad counterintuitive behaviour of Ada about OO
  2014-08-07 19:41  0%                       ` Dmitry A. Kazakov
@ 2014-08-07 20:53  0%                         ` Robert A Duff
  0 siblings, 0 replies; 70+ results
From: Robert A Duff @ 2014-08-07 20:53 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On Thu, 07 Aug 2014 14:14:52 -0400, Robert A Duff wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>> 
>>>...you cannot have one of class-wide
>>> elements.
>> 
>> ...but that's not one of them.  Ada.Containers.Indefinite_Vectors
>> supports class-wide element types, for example.
>
> But you must have class-wide "elementary types" first. There is none, which
> was the point.

Oh, now I see what you mean.  That's not a restriction on generics, it's
a restriction on non-tagged types.  We tried to add 'Class on non-tagged
types in Ada 9X, but the idea was rejected.

universal_integer is something like root_integer'Class, but since you
can't name those types, you can't do something like:

    function Image(X: universal_integer; Base: Integer range 2..16 := 10) return String;

> -----------
> Generics (parametric polymorphism) does not add anything to the language.
> Anything you want to parametrize, must be in the language first, e.g. to
> have a generic package the language must have plain packages.

I think types should be generic, instead.  See Eiffel.

- Bob


^ permalink raw reply	[relevance 0%]

* Re: A bad counterintuitive behaviour of Ada about OO
  2014-08-07 18:14  5%                     ` Robert A Duff
@ 2014-08-07 19:41  0%                       ` Dmitry A. Kazakov
  2014-08-07 20:53  0%                         ` Robert A Duff
  0 siblings, 1 reply; 70+ results
From: Dmitry A. Kazakov @ 2014-08-07 19:41 UTC (permalink / raw)


On Thu, 07 Aug 2014 14:14:52 -0400, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>>...you cannot have one of class-wide
>> elements.
> 
> ...but that's not one of them.  Ada.Containers.Indefinite_Vectors
> supports class-wide element types, for example.

But you must have class-wide "elementary types" first. There is none, which
was the point.

-----------
Generics (parametric polymorphism) does not add anything to the language.
Anything you want to parametrize, must be in the language first, e.g. to
have a generic package the language must have plain packages.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[relevance 0%]

* Re: A bad counterintuitive behaviour of Ada about OO
  @ 2014-08-07 18:14  5%                     ` Robert A Duff
  2014-08-07 19:41  0%                       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 70+ results
From: Robert A Duff @ 2014-08-07 18:14 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> Generics do not work for containers:

There are various annoying limitations, but...

>...you cannot have one of class-wide
> elements.

...but that's not one of them.  Ada.Containers.Indefinite_Vectors
supports class-wide element types, for example.

- Bob


^ permalink raw reply	[relevance 5%]

* Re: Problem with indefinite discriminant records in container
  2014-08-05 13:06  5% Problem with indefinite discriminant records in container john
@ 2014-08-05 16:05  5% ` Simon Wright
  0 siblings, 0 replies; 70+ results
From: Simon Wright @ 2014-08-05 16:05 UTC (permalink / raw)


john@peppermind.com writes:

> How can I store different versions of an indefinite record with
> discriminants such as Rt_Class in some array or vector?

You should be able to do this. I made a compilable program with
mocked-up versions of the omitted types, and it compiles and runs with
every version of GNAT I have here.

with Ada.Containers.Indefinite_Vectors;
procedure John is

   subtype Methodid is Natural range 0 .. 10;
   subtype Classid is Natural range 0 .. 10;
   type Rt_Methods is array (Natural range <>) of Integer;
   type Rt_Class_Ids is array (Natural range <>) of Integer;

   type Rt_Class (Method_Table_Size : MethodId;
                  Superclass_Count  : ClassId)
     is record
        Id              : ClassId;
        Is_Interface    : Boolean;
        Methods         : Rt_Methods (1 .. Method_Table_Size);
        Superclasses    : Rt_Class_Ids (1 .. Superclass_Count);
        Inst_Prop_Count : Natural;
        Method_Count    : Natural;
     end record;

   package Class_Vectors is new Ada.Containers.Indefinite_Vectors
     (Index_Type => ClassId,
      Element_Type => Rt_Class);
   use Class_Vectors;
   type Rt_Classes is new Class_Vectors.Vector with null record;

   C :  Rt_Classes;

begin
   C.Append (Rt_Class'(Method_Table_Size => 1,
                       Superclass_Count => 1,
                       Id => 4,
                       Is_Interface => False,
                       Methods => (1 => 42),
                       Superclasses => (1 => 43),
                       Inst_Prop_Count => 44,
                       Method_Count => 45));
end John;

========================================================================

On a separate front, it seems to me that

   use Class_Vectors;
   type Rt_Classes is new Class_Vectors.Vector with null record;

are nudging the edge of current GNAT; indexing on the LHS, eg
   C (0) := ...
confused the heck out of the compiler, in differing ways for GNAT GPL
2014 and FSF GCC 4.9.0; something to do with Cursors, I think.

^ permalink raw reply	[relevance 5%]

* Problem with indefinite discriminant records in container
@ 2014-08-05 13:06  5% john
  2014-08-05 16:05  5% ` Simon Wright
  0 siblings, 1 reply; 70+ results
From: john @ 2014-08-05 13:06 UTC (permalink / raw)


I want to store records of different size in Ada.Containers.Indefinite_Vectors:

 type Rt_Class (Method_Table_Size : MethodId;
                  Superclass_Count  : ClassId) is record
      Id              : ClassId;
      Is_Interface    : Boolean;
      Methods         : Rt_Methods (1 .. Method_Table_Size);
      Superclasses    : Rt_Class_Ids (1 .. Superclass_Count);
      Inst_Prop_Count : Natural;
      Method_Count    : Natural;
   end record;

   package Class_Vectors is new Ada.Containers.Indefinite_Vectors
     (Index_Type => ClassId,
      Element_Type => Rt_Class);
   use Class_Vectors;
   type Rt_Classes is new Class_Vectors.Vector with null record;

it compiles but I get a *runtime* error "instantiation error" with explanation 
"invalid constraint: type has no discriminant" when the above package is instantiated.

Rt_Methods and Rt_Class_Ids are array types and all of this occurs in the private part of a package. 

How can I store different versions of an indefinite record with discriminants such as Rt_Class in some array or vector? Using access types would be very hard if not impossible in this case because of the associated scope restrictions. Somewhat annoying in this case is also that this table/array only needs to be created *once* in the beginning of program execution and otherwise is completely static and read-only ... and access should be as fast as possible.

Any ideas or suggestions?


^ permalink raw reply	[relevance 5%]

* Re: How can I declare a collection of an interface?
  @ 2013-08-02 18:28  5% ` Adam Beneschan
  0 siblings, 0 replies; 70+ results
From: Adam Beneschan @ 2013-08-02 18:28 UTC (permalink / raw)


On Friday, August 2, 2013 9:39:14 AM UTC-7, Graham Stark wrote:
> Hi,
> 
>    if I have (say):
> 
> type Person is interface;
> 
> and I want to declare a collection of Person, how can I declare the type I'd need? I've tried:
> 
> type PA is array(1..2) of Person;

Assuming you want the array elements to be possibly different types that are derived from Person, you'll need to declare an access type:

  type Person_Acc is access all Person'Class;
  type PA is array(1..2) of Person_Acc;

Since an object of type Person'Class could be lots of other types, possibly of different sizes, Ada can't create an array of Person'Class.  Arrays are only useful when all the elements are the same type.  That's why you have to use an access type.  If you're coming from another language such as Java or C#, those languages will automatically give you a pointer if you declare an array of some class type.  Ada doesn't.  You have to tell it you want an access type (i.e. pointer).  'Class means "an object of this type or some type derived from it"; this is something else that Java/C# give you automatically, but in Ada you have to be explicit about this because sometimes you don't want that automatically.

> or
> 
> package PV is new Ada.Containers.Vectors( Positive, Person );
>  
> and the same with 'Class.

You could use Person_Acc in the same way:

  package PV is new Ada.Containers.Vectors (Positive, Person_Acc);

However, the Ada.Containers packages are able to handle "indefinite types" themselves, and they should take care of the pointer stuff for you.  To do this, you have to use Indefinite_Vectors instead of Vectors:

  package PV is new Ada.Containers.Indefinite_Vectors (Positive, Person'Class);

Person'Class is an "indefinite" type because we don't know beforehand what the actual type of the object will be.

                              -- Adam

^ permalink raw reply	[relevance 5%]

* Re: Depth First Search of a Char_Matrix?
  2013-04-27 15:35  3% ` Shark8
@ 2013-04-27 17:25  0%   ` Jeffrey Carter
  0 siblings, 0 replies; 70+ results
From: Jeffrey Carter @ 2013-04-27 17:25 UTC (permalink / raw)


On 04/27/2013 08:35 AM, Shark8 wrote:
>
>      SubType Board_Range is Positive Range 1..5;
>      Type Board_Type is Array(Board_Range,Board_Range) of Access Piece;
>
>      Board : Board_Type:= (others => (others => Null));
>
>      Function Is_Alive(	Board	: Board_Type;
> 			X, Y	: Board_Range
> 		      ) return Boolean is
> 	Use Type System.Address;
> 	Package Address_List_Package is New Ada.Containers.Indefinite_Vectors(
> 		Index_Type	=> Positive,
> 		Element_Type	=> System.Address);

There is absolutely no reason to use access types (especially not anonymous 
access types) or addresses for this problem.

-- 
Jeff Carter
"Sheriff murdered, crops burned, stores looted,
people stampeded, and cattle raped."
Blazing Saddles
35



^ permalink raw reply	[relevance 0%]

* Re: Depth First Search of a Char_Matrix?
  @ 2013-04-27 15:35  3% ` Shark8
  2013-04-27 17:25  0%   ` Jeffrey Carter
  0 siblings, 1 reply; 70+ results
From: Shark8 @ 2013-04-27 15:35 UTC (permalink / raw)


On Saturday, April 27, 2013 8:09:10 AM UTC-6, Alex wrote:
> Below is Char_Matrix representation of the board game "Go".  A 'W' represents a white piece, a 'B' represents a black piece, and a '.' represents a empty space.  Each black or white piece can either be alive or dead.  A piece is Alive is if it horizontally or vertically next to a '.' OR if it is horizontally or vertically next to another piece that is alive. You can think of aliveness as being contagious.  How can I use depth first search to count the number of alive black pieces and alive white pieces?  
> 
> 
> WW.BB
> .WWWW
> WWBBB
> BBBWW
> WWBW.
> 
> 
> In this example there are 11 alive white piece and 2 alive black pieces.
> 
> Can anyone provide any insight into this problem?

According to your definition though all of the pieces should be alive; you forgot to add in the condition that the alive piece next to them has to be the same color to transmit 'alive'.

Anyway, here's the basic layout for a DFS function on determining if they're alive... the solution is simple, instead of merely returning a boolean you want to increment a counter. Note that this is coded as you said about alive being transmitted via another alive piece sou you'll have to add that logic in, too. 
    
    Type Piece_Color is (Black, White);
    Type Piece is record
	Color : Piece_Color;
    end record;
    
    SubType Board_Range is Positive Range 1..5;
    Type Board_Type is Array(Board_Range,Board_Range) of Access Piece;

    Board : Board_Type:= (others => (others => Null));
    
    Function Is_Alive(	Board	: Board_Type;
			X, Y	: Board_Range
		      ) return Boolean is
	Use Type System.Address;
	Package Address_List_Package is New Ada.Containers.Indefinite_Vectors(
		Index_Type	=> Positive,
		Element_Type	=> System.Address);

	Address_List : Address_List_Package.Vector;
	Function Recursion(X,Y : Board_Range) Return Boolean is
	begin
	    if Board(X,Y) = null then
		Return True;
	    elsif Address_List.Contains( Board(x,Y)'Address ) then
		Return False;
	    else
		Address_List.Append( Board(X,Y).all'Address );
		Return Result : Boolean := False do
		    declare
			xs : Array (1..2) of Natural:= (x - 1, x + 1);
			ys : Array (1..2) of Natural:= (y - 1, y + 1);
		    begin
			for index_1 of ys loop
			    for index_2 of xs loop
				if index_1 in Board_Range and index_2 in Board_Range then
				    Result:= Recursion(index_2, index_1);
				end if;
				if Result then Return; end if;
			    end loop;
			end loop;
		    end;
		end return;
	    end if;
	end Recursion;
	  
    begin
	Return Recursion(x,y);
    End Is_Alive;



^ permalink raw reply	[relevance 3%]

* Interresting, possibly buggy behavior in GNAT generics w/ expression function.
@ 2013-03-28 17:34  6% Shark8
  0 siblings, 0 replies; 70+ results
From: Shark8 @ 2013-03-28 17:34 UTC (permalink / raw)


Lately I've been interested in perhaps getting Ada as a script-tag language, much like JavaScript. I figured I'd need a DOM library or somesuch and was looking into XMLAda (which, oddly fails compile on DOTNET-Gnat and seems oblivious to --target=JVM) so I was tinkering with it in native-code hoping to be able to get to a point where I could seek-out and alter attributes [for a node] on a DOM-Document and was surprised to find there's no functionality for altering attributes via XMLAda DOM-package (at least nothing obvious).

So I decided to play around and see about my own DOM-library (which I would rather not do, as there are several DOM-ish Ada packages about) and found this interesting tidbit: behavior changes when the parameter of image is changed from positive to natural. {Actually it only happens when Attribute_Values is instantiated with Integer[-type].}
----------------------------------------------------------------------------
With Ada.Containers.Indefinite_Vectors, Ada.Strings.Fixed;
Use  Ada.Containers;

Generic
    Attribute_Name : String;
    Type Attribute_Values is (<>);

    With Function Img(Value : Attribute_Values) Return String is Attribute_Values'Image;
    With Package Units is New Indefinite_Vectors(
		Index_Type => Positive,
		Element_Type => String );

    Attribute_Units : Units.Vector:= Units.Empty_Vector;

Package Generic_Attribute_Set is

    Type Attribute(Has_Units : Boolean:= Attribute_Units.Length /= 0) is record
	Value : Attribute_Values;
	case Has_Units is
	When True  => Unit : Positive;
	When False => Null;
	end case;
    end record;

    -- The 'Image Attribute, when applied to numeric types, leaves a leading
    -- space for non-negative numbers (for uniform columnuar display); this is
    -- undesirable for our use, so we wrap it in a call to trim.
    Function Image(Value : Attribute_Values) Return String is
	( Ada.Strings.Fixed.Trim(Img(Value), Side => Ada.Strings.Left) );
    
    -- Getting the string stored in the position for out units-vector is a
    -- simple index into the proper position in the vector containing the units.
    Function Image(Value : Positive) Return String is
      ( --if Value not in positive then "" else 
        Units.Constant_Reference( Attribute_Units, Value ) );
    
    Function To_String( Attr : Attribute ) Return String is
      ( Attribute_Name & "=""" & 
	 Image(Attr.Value) & (if Attr.Has_Units then Image(Attr.Unit) else "") &
	 '"'
      );
    
End Generic_Attribute_Set;
----------------------------------------------------------------------------
With
Generic_Attribute_Set,
Ada.Streams,
Ada.Text_IO.Text_Streams,
Ada.Containers.Indefinite_Vectors;

Procedure Test is
    Package Units is New Ada.Containers.Indefinite_Vectors(
		Index_Type => Positive,
		Element_Type => String );

    Use Units;
    Screen : Units.Vector:= Vector'("en" & "ex") & Vector'("px" & "%");
    
    Type J is (Alpha, Beta, 'K', Fred);
    
    Package Margins is new Generic_Attribute_Set(
	Attribute_Name   => "margin-left",
	Attribute_Values => Integer,
	Units            => Units,
	Attribute_Units  => Screen);
Begin
    Declare
      Use Margins;
      K : Attribute;
    begin
	K.Value:= 88; --J'Succ(Beta);
	K.Unit:= 4;
	Ada.Text_IO.Put_Line( To_String(K) );
    end;
End Test;
----------------------------------------------------------------------------

As I understand it this shouldn't *ever* happen because in the generic there's supposed to be no knowledge of what the parameters are actually instantiated with.


^ permalink raw reply	[relevance 6%]

* Re: asynchronous task communication
  @ 2013-01-07 10:49  3%                                 ` Brian Drummond
  0 siblings, 0 replies; 70+ results
From: Brian Drummond @ 2013-01-07 10:49 UTC (permalink / raw)


On Sun, 06 Jan 2013 14:55:05 -0800, Charles Hixson wrote:

> On 01/05/2013 12:48 AM, Niklas Holsti wrote:
>> On 13-01-05 07:18 , Charles Hixson wrote:
>>>> "Charles Hixson"<charleshixsn@earthlink.net>   wrote in message
>>>> news:MY2dnX5O5NO_TXnNnZ2dnUVZ_hudnZ2d@earthlink.com...
>>>> ....
>>>>> And I'm sure there must be some reasonable way to deallocate a
>>>>> Vector.

>> If your ordinary array holds accesses to other objecs, nothing happens
>> to those other objects when the array is discarded (there is no
>> automatic "deep" deallocation). The same holds for Vectors: if the
>> Vector holds accesses to other objecs, only the accesses are discarded
>> when the Vector is discarded; nothing happens to those other accessed
>> objects.
>>
>>> But all I really want is a variable size array. ....

> It has been suggested that my intended use of Vectors is a mistake. That
> it is unreasonable to store access variables into vectors.  This is a
> pity, as I know of no other Ada construct that would suit my needs. 

I think the message may have been to avoid if possible, use of access 
types rather than vectors! 

For example, Ada.Containers.Indefinite_Vectors allows variable-sized 
objects (not just pointers to them) to be stored in the vectors. It's 
probably implemented internally using access types, but that's another 
matter...

Then how do you maintain links from one such object to others, to build a 
network or graph? You can access a vector element via a cursor - is it 
safe and reasonable to store and use cursors to maintain references to an 
object as the vector grows?

As an alternative, wrap the access type in a controlled type, so that the 
controlled object can take care of deallocating the accessed resources 
when it is finalised - and store controlled objects in the vector.

When you create such a controlled type, you can specify its Finalize 
operation (overriding a default) in which you can free its contents 
however is appropriate - decrement its reference count, 
Unchecked_Deallocate etc.


> (I  *do* need to deallocate the vectors, though.  

No ... when you are done with the contents, you need to *clear* the 
vectors.

This will free their contents. If the contents are controlled types, 
these will be Finalized to free their own contents in turn - see above. 
The Barnes 2005 book mentions Clear in connection with Lists, and goes on 
to say that Lists and Vectors have a lot in common, so it's easy to miss 
that point.

- Brian



^ permalink raw reply	[relevance 3%]

* Re: Tasking troubles, unexpected termination.
  @ 2012-10-31  2:17  3%     ` Shark8
  0 siblings, 0 replies; 70+ results
From: Shark8 @ 2012-10-31  2:17 UTC (permalink / raw)


Here's the updated code:

---- Scheduling.adb ------------------------------------------
with
Ada.Text_IO,
Ada.Calendar,
Ada.Containers.Indefinite_Vectors,
Ada.Task_Termination,
Ada.Task_Identification,
Task_Debugging;

Procedure Scheduling is

    -- Introduce shorthand so convert Strings to access strings.
    Function "+" (Item : String) Return Not Null Access String is
      ( New String'(Item) );
    
    -- Forward declare the Notification type; indicate it has discriminants.
    Type Notification(<>);
    
    -- Declare Handle for Notifications.
    Type Notification_Handle is Not Null Access Notification;
    
    Type Notification(	Message	: Not Null Access String;
			Expiry	: Not Null Access Ada.Calendar.Time
		     ) is null record;
    
    -- Declare the Timing-task.
    Task Type Timing ( Resolution : Not Null Access Duration ) is
	Entry Add( Event : Notification_Handle );
    end Timing;

    
    -- Implementation for the timing-task.
    Task body Timing is

	-- Package for showing Duration.
	Package Decimal_Display is new Ada.Text_IO.Fixed_IO( Duration );
	
	-- Internal package, defining Vectors holding notification handles.
	Package Notification_Vector is New Ada.Containers.Indefinite_Vectors
	  ( Index_Type => Positive, Element_Type => Notification_Handle );
	Use Notification_Vector;
	
	-- Handle expired messages.
	Procedure Handle_Expiration( List : in out Vector ) is
	    Use Ada.Calendar, Ada.Text_IO;
	    Length : Positive:= Positive(List.Length);
	    Now    : Time:= Clock;

	    -- We flag everything to be deleted, as tampering with the cursor is
	    -- not good.
	    Type Deletion_Flags is Array(1..Length) of Boolean;
	    Deletion_Marks : Deletion_Flags:= (Others => False);
	    
	    
	    procedure Execute(Position : Cursor) is
		Item	: Constant Notification_Handle:= Element(position);
		Index	: Constant Positive:= Positive( To_Index(position) );
	    begin
		Deletion_Marks(Index):= Now >= Item.Expiry.All;
		--
		Ada.Text_IO.Put( ASCII.HT & "Exipration: " );
		Decimal_Display.Put( Item.Expiry.All - Now, Fore => 2, Aft => 3 );
		Ada.Text_IO.New_Line;
	    end Execute;

	begin
	    -- Iterate through the vector's elements; old-style iterator.
	    List.Reverse_Iterate( Process => Execute'Access );

	    -- Delete flagged elements; iteration bckwards to preserve indicies.
	    For Index in reverse Deletion_Marks'Range loop
		if Deletion_Marks(Index) then
		    
		    Put_Line( "Message: " & List(Index).Message.All);
		    List.Delete( Index );
		end if;
	    end loop;
	    
	    -- Render a report on the new length, if it was altered.
	    declare
		Post_op_length : Natural:= Natural(List.Length);
	    begin
		if Length /= post_op_length then
		    Put_Line( "Deleted items; New Length:" &  post_op_length'Img);
		end if;
	    end;
	end Handle_Expiration;

	-- Declare a Vector to hold all the nofifications.
	Notification_List : Vector:= Empty_Vector;
	
	Use Ada.Task_Termination, Task_Debugging, Ada.Containers, Ada.Calendar;
	
	-- Mark the start-time.
	Start : Time:= Clock;
	
--	Function Elapsed Return String is
--	  ( Duration'Image(Clock - Start)(1..7) );
	Function Elapsed Return Duration is
	  ( Clock - Start );

    begin
	-- Set our debugging-handler for this task.
	Ada.Task_Termination.Set_Specific_Handler(
		T       => Ada.Task_Identification.Current_Task,
		Handler => Debug.Termination'Access );

	-- When there are no items in our internal vector, then we need can only
	-- accept Add or terminate the task.
	-- When we add an item, then we can either add another item or when the
	-- time expires iterate the vector and handling Notifications as needed.
	loop
	    select 
		accept Add( Event : Notification_Handle ) do
		    Notification_List.Append( Event );
		end add;
		while not Notification_List.Is_Empty loop
		    Ada.Text_IO.Put( "Elapsed:" );
		    Decimal_Display.Put( Elapsed, Fore => 2, Aft => 3 );
		    Ada.Text_IO.New_Line;
		    Handle_Expiration( List => Notification_List );
		    select
			accept Add( Event : Notification_Handle ) do
			    Notification_List.Append( Event );
			    Ada.Text_IO.Put_Line( "New Length: " & Notification_List.Length'Img );
			    Ada.Text_IO.Put( ASCII.HT & "Exipration: " );
			    Decimal_Display.Put( Event.Expiry.All - Clock, Fore => 2, Aft => 3 );
			    Ada.Text_IO.New_Line;
			end add;
		    or
			delay Timing.Resolution.All;
		    end select;
		end loop;
		Ada.Text_IO.Put_Line( "EMPTY." );
	    or
		terminate;
	    end select;
	end loop;
    end Timing;
    
    
      
    K : Timing( Resolution => New Duration'(2.0) ); -- 2 second resolution.
    Now : Ada.Calendar.Time:= Ada.Calendar.Clock;
begin
    For Index in 1..10 loop
	declare
	    Use Ada.Calendar;
	    Item : Notification(
			 Message => + ("DD"&Positive'Image(Index)),
			 -- Expire at Now and 3*Index seconds.
			 Expiry  => New Time'( Now + Duration(Index) )
			);
	begin
	    K.Add( Event => New Notification'(Item) );
	end;
    end loop;
    
    -- Add an element in the past... it should immediately be operated on.
    K.Add( Event => New Notification'(
	Message => + ("Last."),
	Expiry  => New Ada.Calendar.Time'( Now )
	)
    );

end Scheduling;

---- Task_Debugging.ads ----------------------------------------------
-- The following are not strictly nessacary, but used in this example for 
-- debugging purposes.
With
System.Address_To_Access_Conversions,
Ada.Unchecked_Conversion,
Ada.Exceptions.Traceback,
Ada.Task_Identification,
Ada.Task_Termination;

Package Task_Debugging is
    Pragma Elaborate_Body;
    
    Protected Type Debugging is
	-- Termination debugging function.
	procedure Termination(
				 Cause : Ada.Task_Termination.Cause_Of_Termination;
				 T     : Ada.Task_Identification.Task_Id;
				 X     : Ada.Exceptions.Exception_Occurrence);

    End Debugging;
    
    -- Debug, an instance of our debugging object.
    Debug : Debugging;
    
End Task_Debugging;

---- Task_Debugging.adb ----------------------------------------------
With Ada.Text_IO;

Package Body Task_Debugging is

    Protected body Debugging is
	-- Termination debugging function.
	procedure Termination(
		       Cause : Ada.Task_Termination.Cause_Of_Termination;
		       T     : Ada.Task_Identification.Task_Id;
		       X     : Ada.Exceptions.Exception_Occurrence) is
	    Use Ada.Text_IO, Ada.Task_Termination, Ada.Exceptions;
	begin
	    Put_Line("Termination: "& Cause'Img);
	    case Cause is
	    When Normal | Abnormal => Null;
	    When Unhandled_Exception =>
		Put_Line( Exception_Name(X)&": "&Exception_Message(X) );
	    end case;
	end Termination;	
    end Debugging;

End Task_Debugging;
---------------------------------------------------------------------------

I've fixed the original problems (first the "tampering", and second a constraint_error) but there's still something strange going on. The discriminants for notifications seem to be being ignored (or rather the latest one being used).

Here's the output:
C:\Programming\Projects\Scheduler>scheduling.exe
Elapsed: 0.000
        Exipration:  0.984
New Length:  2
        Exipration:  1.983
Elapsed: 0.002
        Exipration:  1.982
        Exipration:  1.982
New Length:  3
        Exipration:  2.981
Elapsed: 0.004
        Exipration:  2.980
        Exipration:  2.980
        Exipration:  2.980
[...]
Message: Last.
Deleted items; New Length: 10
Elapsed: 2.047
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
Elapsed: 4.051
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
Elapsed: 6.061
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
Elapsed: 8.086
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
Elapsed:10.106
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
Message: DD 10
Message: DD 9
Message: DD 8
Message: DD 7
Message: DD 6
Message: DD 5
Message: DD 4
Message: DD 3
Message: DD 2
Message: DD 1
Deleted items; New Length: 0
EMPTY.
Termination: NORMAL

As you can see, instead of each element being different they're all tagged as having the same expiration.



^ permalink raw reply	[relevance 3%]

* Tasking troubles, unexpected termination.
@ 2012-10-30 22:03  4% Shark8
    0 siblings, 1 reply; 70+ results
From: Shark8 @ 2012-10-30 22:03 UTC (permalink / raw)


with
Ada.Text_IO,
Ada.Calendar,
Ada.Containers.Indefinite_Vectors;

Procedure Scheduling is

    -- Introduce shorthand so convert Strings to access strings.
    Function "+" (Item : String) Return Not Null Access String is
      ( New String'(Item) );
    
    -- Forward declare the Notification type; indicate it has discriminants.
    Type Notification(<>);
    
    -- Declare Handle for Notifications.
    Type Notification_Handle is Not Null Access Notification;
    
    Type Notification(	Message	: Not Null Access String;
			Expiry	: Not Null Access Ada.Calendar.Time
		     ) is null record;
    
    -- Declare the Timing-task.
    Task Type Timing ( Resolution : Not Null Access Duration ) is
	Entry Add( Event : Notification_Handle );
    end Timing;


    -- Implementation for the timing-task.
    Task body Timing is
	-- Internal package, defining Vectors holding notification handles.
	Package Notification_Vector is New Ada.Containers.Indefinite_Vectors
	  ( Index_Type => Positive, Element_Type => Notification_Handle );
	Use Notification_Vector;
	
	-- Declare a Vector to hold all the notifications.
	Notification_List : Vector:= Empty_Vector;
	
	Procedure Handle_Expiration is
	    Use Ada.Calendar, Ada.Text_IO;
	    Length : Positive:= Positive(Notification_List.Length);
	    Now    : Time:= Clock;
	begin
	    -- Iterate through the vector's elements; reversed so that deletion
	    -- does not intefere with the iteration.
	    for Index in reverse 1..Length loop
		declare
		    Item : Notification_Handle Renames Notification_List(Index);
		begin
		    -- If it's reached the expiry, then we display the message
		    -- and remove the item.
		    if Now > Item.Expiry.All then
			Put_Line( "Message: " & Item.Message.All);
			Notification_List.Delete(Index);
		    end if;
		end;
	    end loop;
	    
	    declare
		Post_op_length : Positive:= Positive(Notification_List.Length);
	    begin
		if Length /= post_op_length then
		    Put_Line( "Deleted items; New Length:" &  post_op_length'Img);
		end if;
	    end;
	end Handle_Expiration;

	Use Ada.Containers;
    begin
	-- When there are no items in our internal vector, then we need can only
	-- accept Add or terminate the task.
	-- When we add an item, then we can either add another item or when the
	-- time expires iterate the vector and handling Notifications as needed.
	loop
	    select 
		accept Add( Event : Notification_Handle ) do
		    Notification_List.Append( Event );
		end add;
		while not Notification_List.Is_Empty loop
		    Handle_Expiration;
		    select
			accept Add( Event : Notification_Handle ) do
			    Notification_List.Append( Event );
			    Ada.Text_IO.Put_Line( "New Length: " & Notification_List.Length'Img );
			end add;
		    or
			delay Timing.Resolution.All;
		    end select;
		end loop;
		Ada.Text_IO.Put_Line( "EMPTY. Length: " & Notification_List.Length'Img );
	    or
		terminate;
	    end select;
	end loop;
    end Timing;
    
    
    K : Timing( Resolution => New Duration'(2.0) );
    
begin
    For Index in 1..10 loop
	declare
	    Use Ada.Calendar;
	    Expire : Time:= Clock + (Index*2.0); -- Now and 2*Index seconds.
	    Item : Notification(
			 Message => + ("DD"&Positive'Image(Index)),
			 Expiry  => New Time'( Expire )
			);
	begin
	    K.Add( Event => New Notification'(Item) );
	end;
    end loop;
end Scheduling;

----------------------------------

Output:
C:\Programming\Projects\Scheduler>scheduling.exe
New Length:  2
New Length:  3
New Length:  4
New Length:  5
New Length:  6
New Length:  7
New Length:  8
New Length:  9
New Length:  10
Message: DD 10


As you can see there's something happening to force termination -- there should at the least be an new-length message -- this leads me to believe [or, more accurately, guess] that there's some exception happening in the task which is blowing everything up.

Is that the case?
Also, if there is some tasking-exceptions interaction, how do I force them to display [and/or handle them] instead of falling off a cliff?



^ permalink raw reply	[relevance 4%]

* Re: String_Holder ?
  @ 2011-12-19 11:12  4% ` Martin
  0 siblings, 0 replies; 70+ results
From: Martin @ 2011-12-19 11:12 UTC (permalink / raw)


On Dec 18, 12:34 pm, Natasha Kerensikova <lithium...@gmail.com> wrote:
> Hello,
>
> in my few Ada projects so far, I have quite often encountered the need
> of storing a string along with other information in records. So I went
> for discriminants containing the string size, and putting the string
> directly in the record.
>
> This works well when there is only one or two strings, but with several
> of them, or in variant records, I find it quite heavy. So I was thinking
> about something like that:
>
> type String_Holder is still to be defined;
>
> function Hold (S : String) return String_Holder;
>
> function To_String (Holder : String_Holder) return String;
>
> procedure Query (Holder : String_Holder;
>                  Process : not null access procedure (S : String));
>
> I'm still unsure on what kind of type String_Holder should be (private,
> tagged private or interface). It would basically be a constant-size
> reference to an immutable string that is stored "somewhere".
>
> The simplest implementation would be an Unbounded_String, though if
> needed it could be improved reference counting to make assignments
> cheaper, or with a hash table to deduplicate identical strings, etc.
>
> So my question is, does it make sense to have such objects? Or am I
> getting blinded by my C past, where strings are always manipulated
> through a char* object?
>
> Assuming it does make sense, am I right in thinking it's better to have
> such a type, even if it's a thin wrapper around Unbounded_String,
> instead of using directly Unbounded_String?
>
> Assuming it does make sense to have a String_Holder, would it be better
> to have it private, tagged private or interface?
> My guess is that tagged private has no advantage over interface,
> especially with a default implementation around Unbounded_String, which
> doesn't need to be controlled, but then controlled extension would be
> heavier. Then the choice between private and interface amounts to
> whether or not it could be useful to use simultaneously several
> implementations of String_Holder in the same project. I cannot think of
> any project where it would be the case, so I would lean towards private,
> but maybe I'm lacking imagination here.
>
> Still under the same assumption, is the above specification sane, or am
> I missing something? Query procedure is probably not absolutely
> necessary, but I guess it can be occasionally useful to save a string
> copy compared to To_String, and it seems to be a very small
> implementation burden anyway.
>
> Still under the same assumption, can it be useful to provide unary "+"
> functions to tersely convert String_Holder to String, and maybe
> vice-versa, or would it do more harm (obfuscation) than good?
>
> And lastly, is there any trick to allow a String_Holder object or
> similar to be pre-elaborable?
>
> Thanks in advance for your insights,
> Natasha

Have you considered a "Flyweight"?

Here's an example in Ada2012 (which is soooo much easier to acheive
than in previous Ada versions).

The coffee flavour string is repeated in each order but only unique
strings are stored and each order context contains a reference to the
string.

In a real application, you'd want probably want to add finalization.

-- Martin



-- main.adb
with Applications; use Applications;
procedure Main is
   App : Application := Create;
begin
   App.Execute;
end Main;

-- applications.ads
        private with Ada.Containers.Vectors;
        private with Coffee_Orders.Flavours;
        private with Coffee_Orders.Flavours.Factories;
limited private with Coffee_Order_Contexts;
package Applications is
   type Application (<>) is tagged limited private;
   function Create return Application;
   procedure Execute (A : in out Application);
private
   use Coffee_Orders.Flavours.Factories;
   type Order is record
      Context : access Coffee_Order_Contexts.Coffee_Order_Context;
      Flavour : access Coffee_Orders.Flavours.Flavour;
   end record;
   package Order_Vectors is
      new Ada.Containers.Vectors (Natural, Order);
   type Application is tagged limited record
      Orders          : Order_Vectors.Vector;
      Flavour_Factory : Coffee_Orders.Flavours.Factories.Factory;
   end record;
   procedure Take_Orders (A       : in out Application;
                          Flavour :        String;
                          Table   :        Integer);
end Applications;

-- applications.adb
with Ada.Text_IO;            use Ada.Text_IO;
with Coffee_Order_Contexts;  use Coffee_Order_Contexts;
with Coffee_Orders.Flavours; use Coffee_Orders.Flavours;
package body Applications is
   function Create return Application is
   begin
      return Result : Application do
         null;
      end return;
   end Create;
   procedure Take_Orders (A       : in out Application;
                          Flavour :        String;
                          Table   :        Integer) is
   begin
      A.Orders.Append ((Context => new Coffee_Order_Context'(Create
(Table)),
                        Flavour =>
Flavour_Ref'(A.Flavour_Factory.Get_Flavour (Flavour))));
   end Take_Orders;
   procedure Execute (A : in out Application) is
   begin
      A.Take_Orders ("Cappuccino", 2);
      A.Take_Orders ("Cappuccino", 2);
      A.Take_Orders ("Frappe", 1);
      A.Take_Orders ("Frappe", 1);
      A.Take_Orders ("Xpresso", 1);
      A.Take_Orders ("Frappe", 897);
      A.Take_Orders ("Cappuccino", 97);
      A.Take_Orders ("Cappuccino", 97);
      A.Take_Orders ("Frappe", 3);
      A.Take_Orders ("Xpresso", 3);
      A.Take_Orders ("Cappuccino", 3);
      A.Take_Orders ("Xpresso", 96);
      A.Take_Orders ("Frappe", 552);
      A.Take_Orders ("Cappuccino", 121);
      A.Take_Orders ("Xpresso", 121);
      for Order of A.Orders loop
         Order.Flavour.Serve_Coffee (Order.Context.all);
      end loop;
      Put_Line ("Total Coffee_Flavor objects made:" & Integer'Image
(A.Flavour_Factory.Total_Flavours_Made));
   end Execute;
end Applications;

-- coffee_order_contexts.ads
package Coffee_Order_Contexts is
   type Coffee_Order_Context (<>) is tagged private;
   function Create (Table : Integer) return Coffee_Order_Context;
   function Table_No (COC : Coffee_Order_Context) return Integer;
private
   type Coffee_Order_Context is tagged record
      Table : Integer := 0;
   end record;
end Coffee_Order_Contexts;

-- coffee_order_contexts.adb
package body Coffee_Order_Contexts is
   function Create (Table : Integer) return Coffee_Order_Context is
   begin
      return Result : Coffee_Order_Context do
         Result.Table := Table;
      end return;
   end Create;
   function Table_No (COC : Coffee_Order_Context) return Integer is
   begin
      return COC.Table;
   end Table_No;
end Coffee_Order_Contexts;

-- coffee_order_contexts-vectors.ads
with Ada.Containers.Indefinite_Vectors;
package Coffee_Order_Contexts.Vectors is
   new Ada.Containers.Indefinite_Vectors (Natural,
Coffee_Order_Context);

-- coffee_orders.ads
with Coffee_Order_Contexts; use Coffee_Order_Contexts;
package Coffee_Orders is
   type Coffee_Order is interface;
   procedure Serve_Coffee (CO  : Coffee_Order;
                           COC : Coffee_Order_Context) is abstract;
end Coffee_Orders;

-- coffee_orders-flavours.ads
private with Ada.Strings.Unbounded;
        with Coffee_Order_Contexts; use Coffee_Order_Contexts;
package Coffee_Orders.Flavours is
   type Flavour (<>) is new Coffee_Order with private;
   type Flavour_Ref is access all Flavour'Class;
   function Create (Name : String) return Flavour;
   function "=" (L, R : Flavour) return Boolean;
   overriding
   procedure Serve_Coffee (F   : Flavour;
                           COC : Coffee_Order_Context);
private
   use Ada.Strings.Unbounded;
   type Flavour is new Coffee_Order with record
      Name : Unbounded_String;
   end record;
end Coffee_Orders.Flavours;

-- coffee_orders-flavours.adb
with Ada.Strings.Equal_Case_Insensitive;
with Ada.Text_IO; use Ada.Text_IO;
package body Coffee_Orders.Flavours is
   function Create (Name : String) return Flavour is
   begin
      return Result : Flavour do
         Result.Name := To_Unbounded_String (Name);
      end return;
   end Create;
   function "=" (L, R : Flavour) return Boolean is
   begin
      return Ada.Strings.Equal_Case_Insensitive (To_String (L.Name),
To_String (R.Name));
   end "=";
   procedure Serve_Coffee (F   : Flavour;
                           COC : Coffee_Order_Context) is
   begin
      Put_Line ("Serving Coffee flavor " & To_String (F.Name)
                & " to table number " & Integer'Image (COC.Table_No));
   end Serve_Coffee;
end Coffee_Orders.Flavours;

-- coffee_orders-flavours-vectors.ads
with Ada.Containers.Vectors;
package Coffee_Orders.Flavours.Vectors is
   new Ada.Containers.Vectors (Natural, Flavour_Ref);

-- coffee_orders-flavours-factories.ads
private with Ada.Containers.Indefinite_Hashed_Maps;
private with Ada.Strings.Equal_Case_Insensitive;
private with Ada.Strings.Hash_Case_Insensitive;
private with Ada.Strings.Unbounded;
package Coffee_Orders.Flavours.Factories is
   type Factory is tagged private;
   function Get_Flavour (F    : in out Factory;
                         Name :        String)
                         return not null access Flavour;
   function Total_Flavours_Made (F : Factory) return Natural;
private
   use Ada.Strings.Unbounded;
   package Maps is
     new Ada.Containers.Indefinite_Hashed_Maps (Key_Type        =>
String,
                                                Element_Type    =>
Flavour,
                                                Hash            =>
Ada.Strings.Hash_Case_Insensitive,
                                                Equivalent_Keys =>
Ada.Strings.Equal_Case_Insensitive);
   type Factory is tagged record
      Flavours : Maps.Map;
   end record;
end Coffee_Orders.Flavours.Factories;

-- coffee_orders-flavours-factories.adb
package body Coffee_Orders.Flavours.Factories is
   function Get_Flavour (F    : in out Factory;
                         Name :        String) return not null access
Flavour is
      use type Maps.Cursor;
      C : constant Maps.Cursor := F.Flavours.Find (Name);
   begin
      if C /= Maps.No_Element then
         return F.Flavours.Constant_Reference (Name).Element;
      end if;
      F.Flavours.Insert (Name, Create (Name));
      return F.Flavours.Constant_Reference (Name).Element;
   end Get_Flavour;
   function Total_Flavours_Made (F : Factory) return Natural is
   begin
      return Natural (F.Flavours.Length);
   end Total_Flavours_Made;
end Coffee_Orders.Flavours.Factories;



^ permalink raw reply	[relevance 4%]

* Re: Use of abstract tagged types without access types -- again and complete
  2011-06-10 15:43  4%     ` Prof. Dr. Carl Weierstrass
@ 2011-06-12 12:05  0%       ` Alex R. Mosteo
  0 siblings, 0 replies; 70+ results
From: Alex R. Mosteo @ 2011-06-12 12:05 UTC (permalink / raw)


Prof. Dr. Carl Weierstrass wrote:

> On 9 Jun., 23:06, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
>> "Ludovic Brenta" <ludo...@ludovic-brenta.org> wrote in message
>>
>> news:87hb7yn4fs.fsf@ludovic-brenta.org...
>>
>> > "Prof. Dr. Carl Weierstrass" writes on comp.lang.ada:
>> >> type Parent_Type is new Ada.Finalization.Controlled with record
>> >> Child : Child_Type'Class;
>> >> end record;
>>
>> >> This doesn't work, because:
>> >> class-wide subtype with unknown discriminants in component declaration
>>
>> >> Of course I could use an access type to avoid the error but is there a
>> >> way to do something like this without access types.
>>
>> > No.  The reason is that the size of Child is unknown, so you cannot
>> > encapsulate a Child into a Parent_Type, which has a fixed size.  In
>> > contrast, the size of an access value is fixed at comile time, so you
>> > can encapsulate an access value in the Parent_Type.
>>
>> Not quite accurrate -- an access type is necessary somewhere, but it
>> doesn't have to be visible.
>>
>> Specifically, use the Holder container for this purpose:
>>
>> package Child_Holder is new Ada.Containers.Indefinite_Holders
>> (Child_Type'Class);
>>
>> type Parent_Type is new Ada.Finalization.Controlled with record
>> Child : Child_Holder.Holder;
>> end record;
>>
>> This is a slight complication when using the component (you have to use
>> Element and Replace_Element to access the contents), but it is usually
>> better than writing all of this storage management yourself.
>>
>> The only downside is whether your Ada compiler supports this container
>> (it was added after Ada 2005 was finished, early in the Ada 2012
>> process). It's used in the latest ASIS (that's why it was invented), so a
>> compiler supporting ASIS for Ada 2005 probably supports the container.
>>
>> If your compiler doesn't yet support this container, it's easy enough to
>> create it yourself rather than using explicit access types.
>>
>> Randy.
> 
> Thank you very much. I think that this could be the solution that I
> was looking for.
> In case of many children I considered using an
> Ada.Containers.Indefinite_Vectors type,
> but I was looking for a solution when the is only one child.
> Unfortunately I'am using
> GNAT GPL 2010 and can't find that container in the library.
> 
> Any idea, where I can find an implementation? I hope it will be in the
> next GNAT GPL 2011
> version.

I've been using this 'holder' approach for years. If you don't have the 
official, the simplest way is to make your own with any other of the 
standard containers, and a simplified spec.

Migration to the true Holder would later be a matter of seconds with a 
single search/replace if you take care to respect the subprogram names.

> 
> Regards




^ permalink raw reply	[relevance 0%]

* Re: Use of abstract tagged types without access types -- again and complete
  @ 2011-06-10 15:43  4%     ` Prof. Dr. Carl Weierstrass
  2011-06-12 12:05  0%       ` Alex R. Mosteo
  0 siblings, 1 reply; 70+ results
From: Prof. Dr. Carl Weierstrass @ 2011-06-10 15:43 UTC (permalink / raw)


On 9 Jun., 23:06, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
> "Ludovic Brenta" <ludo...@ludovic-brenta.org> wrote in message
>
> news:87hb7yn4fs.fsf@ludovic-brenta.org...
>
> > "Prof. Dr. Carl Weierstrass" writes on comp.lang.ada:
> >>    type Parent_Type is new Ada.Finalization.Controlled with record
> >>          Child : Child_Type'Class;
> >>    end record;
>
> >> This doesn't work, because:
> >> class-wide subtype with unknown discriminants in component declaration
>
> >> Of course I could use an access type to avoid the error but is there a
> >> way to do something like this without access types.
>
> > No.  The reason is that the size of Child is unknown, so you cannot
> > encapsulate a Child into a Parent_Type, which has a fixed size.  In
> > contrast, the size of an access value is fixed at comile time, so you
> > can encapsulate an access value in the Parent_Type.
>
> Not quite accurrate -- an access type is necessary somewhere, but it doesn't
> have to be visible.
>
> Specifically, use the Holder container for this purpose:
>
>      package Child_Holder is new Ada.Containers.Indefinite_Holders
> (Child_Type'Class);
>
>      type Parent_Type is new Ada.Finalization.Controlled with record
>            Child : Child_Holder.Holder;
>      end record;
>
> This is a slight complication when using the component (you have to use
> Element and Replace_Element to access the contents), but it is usually
> better than writing all of this storage management yourself.
>
> The only downside is whether your Ada compiler supports this container (it
> was added after Ada 2005 was finished, early in the Ada 2012 process). It's
> used in the latest ASIS (that's why it was invented), so a compiler
> supporting ASIS for Ada 2005 probably supports the container.
>
> If your compiler doesn't yet support this container, it's easy enough to
> create it yourself rather than using explicit access types.
>
>                                              Randy.

Thank you very much. I think that this could be the solution that I
was looking for.
In case of many children I considered using an
Ada.Containers.Indefinite_Vectors type,
but I was looking for a solution when the is only one child.
Unfortunately I'am using
GNAT GPL 2010 and can't find that container in the library.

Any idea, where I can find an implementation? I hope it will be in the
next GNAT GPL 2011
version.

Regards



^ permalink raw reply	[relevance 4%]

* Order of execution of subprogram parameters
@ 2011-03-19 17:10  4% Syntax Issues
  0 siblings, 0 replies; 70+ results
From: Syntax Issues @ 2011-03-19 17:10 UTC (permalink / raw)


Across ada compilers what is the order of execution for subprogram
parameters? Is it left-to-right, right-to-left, and does it matter if
I use labels out of order?

Example:
...
type Record_Joint
	is record
		Name   : String(1..64);
		Flags  : Integer_1_Unsigned;
		Parent : Integer_4_Signed;
		Start  : Integer_4_Signed;
	end record;
package Container_Record_Joint
	is new Ada.Containers.Indefinite_Vectors
	(Integer_4_Unsigned, Record_Joint);
...
Animation    : Record_Md5_Animation;
...
Animation.Joints.Append(
	(Name   => Remove_Quotes(Next_String(File, Current_Line)),
	 Parent => Next_Integer_4_Signed(File, Current_Line),
	 Flags  => Next_Integer_1_Unsigned(File, Current_Line),
	 Start  => Next_Integer_4_Signed(File, Current_Line));
...
function Next_X
	(File : in out File_Type;
	 Line : in out String)
	return X;



^ permalink raw reply	[relevance 4%]

* Re: Little tutorial about streams
  @ 2011-03-05  1:08  2% ` Shark8
  0 siblings, 0 replies; 70+ results
From: Shark8 @ 2011-03-05  1:08 UTC (permalink / raw)


I was debating on whether or not to submit to you a little 'toy' LISP
interpreter I've started. I've only got the reading and writing here,
no eval or special-forms like 'if', but since they're Stream-based it
might be appropriate.


---------------------------------
-- Lisp Interpreter in Ada.
-- By Joey Fish

---------------
-- LISP.ADS  --
---------------
With
Ada.Containers.Indefinite_Vectors,
Ada.Streams;

Package LISP is

 
-----------------------------------------------------------------------
   --	In LISP a List is defined as either a single element or an	--
   --	element followed by a lisr; as a consequence of this
definition	--
   --	there is no such thing as an "Empty List."			--
 
-----------------------------------------------------------------------


   Type List is Private;
   -- ToDo: Add primitive functions for list construction/
manipulation.
   -- ToDo: Add primitive functions for determining if it is an
executable list.

Private
   -- Alias Ads.Streams.Root_Stream_Type for ease of use.
   SubType Stream_Root is Ada.Streams.Root_Stream_Type;

   -- Element_Type describes the possible types of an Atom
   --	Note: Empty_Type is the NULL-element.
   Type Element_Type is
     ( Empty_Type, Boolean_Type, Integer_Type, Real_Type,
String_Type );

   -- Type Atom is a record containing the type and value of an
element.
   Type Atom( Element : Element_Type:= Empty_Type ) is record
      Case Element is
         When Empty_Type	=> Null;
         When Boolean_Type	=> Boolean_Value : Boolean:= False;
         When Integer_Type	=> Integer_Value : Integer:= 0;
         When Real_Type		=> Real_Value	 : Float  := 0.0;
         When String_Type	=> Is_Name	 : Boolean:= False;
				   String_Value	 : Not Null Access String;
      End Case;
   end record;

   Procedure Write_Atom( Stream	: Not Null Access Stream_Root'Class;
			 Item	: In Atom
                       );

   For Atom'Write Use Write_Atom;

   Type Atom_Array is Array (Positive Range <>) of Atom;
   Type Elementry_List( Terminal : Boolean:= True ) is record
      Head : Atom:=		( Element => Empty_Type );
      Case Terminal is
	When False => Tail : Not Null Access Elementry_List;
	When True  => Null;
      End Case;
   end record;

   Procedure Append( Head : In Out Elementry_List; Tail : In
Elementry_List );
   Function  Convert( List : Elementry_List ) Return Atom_Array;
   Function  Convert( List : Atom_Array ) Return Elementry_List;

   Procedure Write_EList( Stream	: Not Null Access Stream_Root'Class;
			  Item		: In Elementry_List
                       );
   Procedure Read_EList( Stream	: Not Null Access Stream_Root'Class;
			 Item	: Out Elementry_List
                       );


   For Elementry_List'Read  Use Read_EList;
   For Elementry_List'Write Use Write_EList;

   Type List_Element_Type is ( Atom_Element, EList_Type,
Recursive_List );
   Type List_Element( Element : List_Element_Type:= Atom_Element ) is
record
      Case Element is
	When Atom_Element	=> Atom_Data	: Atom;
	When EList_Type		=> EList_Data	: Elementry_List;
	When Recursive_List	=> RList_Data	: Not Null Access List;
      end case;
   end record;
   Function As_List( Input : in List_Element ) Return List;

   Package Elements is New Ada.Containers.Indefinite_Vectors
	( Index_Type => Positive, Element_Type => List_Element );

   Type List is Tagged record
      Data : Elements.Vector:= Elements.Empty_Vector;
   end record;

   Procedure Write_List( Stream	: Not Null Access Stream_Root'Class;
			  Item	: In List
                       );
   Procedure Read_List( Stream	: Not Null Access Stream_Root'Class;
			 Item	: Out List
                       );

   For List'Read  Use Read_List;
   For List'Write Use Write_List;


End LISP;

---------------
-- LISP.ADB  --
---------------

With
Ada.Strings.Fixed;

Package Body LISP is

   FALSE_Text	: Constant String:= Boolean'Image( False );
   TRUE_Text	: Constant String:= Boolean'Image( True  );
   NULL_Text	: Constant String:= "NULL";

   Function Trim_Image( Input : In Float ) Return String is
      Use Ada.Strings, Ada.Strings.Fixed;
   Begin
      Return Result: String:=
        Trim( Side => Left, Source => Float'Image( Input ) );
   End Trim_Image;


   ------------------
   --  WRITE_ATOM  --
   ------------------
   Procedure Write_Atom(	Stream	: Not Null Access Stream_Root'Class;
				Item	: In Atom ) is
      Text : Access String;
   begin
      Case Item.Element is
	 When Empty_Type	=>
		Text:= New String'( NULL_Text );
         When Boolean_Type	=>
		Text:= New String'( Boolean'Image(Item.Boolean_Value) );
         When Integer_Type	=>
		Text:= New String'( Integer'Image(Item.Integer_Value) );
         When Real_Type		=>
		Text:= New String'( Float'Image( Item.Real_Value ) );
         When String_Type	=>
            If Not Item.Is_Name then
		Text:= New String'( '"' & Item.String_Value.All & '"' );
            else
		Text:= New String'( Item.String_Value.All );
            end if;
      End Case;
      String'Write(	Stream, Text.All	);
   end Write_Atom;


   --------------
   --  Append  --
   --------------
   Procedure Append( Head : In Out Elementry_List; Tail : In
Elementry_List ) is
   begin
      If Head.Terminal then
         Declare
            Result : Elementry_List:= Elementry_List'( Terminal =>
False,
		Head => Head.Head, Tail => New Elementry_List'(Tail) );
            For Result'Address Use Head'Address;
         Begin		-- Here the initialization of Result changes the value
            Null;	-- of Head because they are overlaid; further, we
are
         End;		-- guarenteed that the sizes are both the same because
      else		-- Elementry_List is a simple varient record and cannot
         Declare	-- be extended because it is not a tagged-type.
            This : Access Elementry_List:= Head.Tail;
         Begin
            While Not This.Terminal loop	-- If Head is not terminal
then
               This:= This.Tail;		-- we must traverse the list
            end loop;				-- until the end to append Tail.
            Append( This.All, Tail );
         End;
      end if;
   end Append;

   Function  Convert( List : Elementry_List ) Return Atom_Array is

      Function Get_Element( Item : Elementry_List ) Return Atom_Array
is
      begin
         if Item.Terminal then
            Return Result : Atom_Array:= ( 1 => Item.Head );
         else
            Return Result : Atom_Array:= Atom_Array'( 1 => Item.Head )
		& Get_Element( Item.Tail.All );
         end if;
      end Get_Element;

   begin
      Return Get_Element( List );
   end Convert;

   Function Create( Input : Atom ) Return Elementry_List is
   begin
      Return Result: Elementry_List:= ( Terminal => True, Head =>
Input );
   end;


   Function  Convert( List : Atom_Array ) Return Elementry_List is
   begin
      if List'Length = 0 then
         Raise Program_Error;
      end if;

      Declare
	Working : Elementry_List:= Create( Input => List(List'First) );
      Begin
	For Index in Positive'Succ(List'First)..List'Last loop
            Append( Head => Working, Tail => Create( List(Index) ) );
	end loop;
       Return Working;
      End;
   end Convert;


   ---------------------------------------------------
   --  Elementry_List's  'Read & 'Write Attributes  --
   ---------------------------------------------------

   Procedure Write_EList( Stream	: Not Null Access Stream_Root'Class;
			  Item		: In Elementry_List
                       ) is

   begin
      Character'Write( Stream, '(' );		-- When saving to a Stream
every
      Declare					-- elementry-list begins with an
         This : Elementry_List:= Item;		-- opening parenthisis,
followed
      Begin					-- by list of Atoms (whitespace
         List:					-- separated), terminated by a
         loop					-- closing parenthisis.
            Atom'Write( Stream, This.Head );
            Exit List When This.Terminal;
            This:= This.Tail.All;
            Character'Write( Stream, ',' );
         end loop List;
         Character'Write( Stream, ')' );
      End;
   end Write_EList;

   Procedure Read_EList( Stream	: Not Null Access Stream_Root'Class;
			 Item	: Out Elementry_List
                        ) is
      Function Parse_Atom( S : String ) Return Atom is
         Function Get_Type_Indicator(Input : String) Return
Element_Type is
            SubType Digit is Character Range '0'..'9';
         begin
            Case Input(Input'First) is		-- A floating-point numeric is
               When Digit =>			-- distinguished from an integer
                  For Index in Input'Range loop	-- by the decimal
point or the
                     Case Input(Index) is	-- exponent notation.
                        When 'e' | 'E' | '.' => Return Real_Type;
                        When Others => null;
                     End case;
                  end loop;
                  Return Integer_Type;
               When Others =>
                  if Input = NULL_Text then	-- NULL, TRUE, & FALSE are
texts
                     Return Empty_Type;		-- which are not String_Type.
                  elsif Input = TRUE_Text or Input = FALSE_Text then
                     Return Boolean_Type;
                  else				-- Everything else, however, is
                     Return String_Type;	-- either a String_Type or a
                  end if;			-- name. Strings start w/ '"'.
            end case;
         end Get_Type_Indicator;

       Use Ada.Strings, Ada.Strings.Fixed;			-- Parse_Atom
         Input : String:= Ada.Strings.Fixed.Trim( S, Both );	-- starts
here.
      begin
         Return Result : Atom(Get_Type_Indicator(Input)) do
            Case Result.Element is
            When Empty_Type	=> Null;
            When String_Type	=>
               Result.Is_Name:= Input(Input'First) = '"';
               if Not Result.Is_Name then
               Result.String_Value:= New String'(
		  Input(Positive'Succ(Input'First)..Positive'Pred(Input'Last))
						);
               else
                  Result.String_Value:= New String'(Input);
               end if;
            When Integer_Type	=> Result.Integer_Value:=
Integer'Value(Input);
            When Real_Type	=> Result.Real_Value:= Float'Value(Input);
            When Boolean_Type	=> Result.Boolean_Value:= Input =
TRUE_Text;
            End case;
         End Return;
      end Parse_Atom;

         WhiteSpace : Constant Array(Character) Of Boolean:=
           ( ASCII.VT | ASCII.HT | ASCII.LF | ASCII.CR | ' ' => True,
             Others => False );

	Type Index_Vector is Array (Positive Range <>) of Positive;
	Seperators	: Not Null Access Index_Vector:=
					New Index_Vector'( 2..1 => 1 );
	Working		: Not Null Access String:= New String'( "" );
	C		: Character;
	Result		: Elementry_List;
	In_String	: Boolean:= False;
	Is_Terminated	: Boolean:= False;

   begin
      Loop
	Character'Read( Stream, C );
	Case C is
	 When '"'	=>	In_String:= Not In_String;
				Is_Terminated:= False;
         When ')'	=>	Exit When Not In_String;
         When Others	=>
	    If WhiteSpace(C) then
		if Is_Terminated then
			GoTo Bypass;
		else
			Is_Terminated:= True;
		end if;
	    else
		Is_Terminated:= False;
	    end if;
	End Case;
	Working:= New String'( Working.All & C );	-- We update "working."
	if WhiteSpace(C) then			-- and delimit with whitespace.
	   Seperators:= New Index_Vector'( Seperators.All & Working'Last );
	end if;
	<<Bypass>>
	Null;
      End Loop;

	-- We simulate a terminating space by appending one more
	-- than the last index to Seperators.
	Seperators:= New Index_Vector'(Seperators.All & (Working'Last+1));

      Declare
	-- We use one more than Working'First to ignore the '(' that starts
	-- this list, just like we terminated the string just before
	-- copying the trailing ')' into Working.
	Start : Positive:= Working'First+1;
	Stop  : Positive;
      Begin
	for Index in Seperators'Range loop	-- Here is where we create an
	    Stop:= Seperators( Index )-1;	-- atom from every interval we
	    Append(Result,			-- recorded in "seperators".
		(Terminal => True, Head => Parse_Atom(Working(Start..Stop)))
		  );
	    Start:= Seperators( Index )+1;
	end loop;
      End;
					-- And we return everything we
      Item:= Result.Tail.All;		-- previously appended to result.
   end Read_EList;

   ---------------
   --  As_List  --
   ---------------
   Function As_List( Input : in List_Element ) Return List is
   Begin
      Return Result : List do
         Case Input.Element is
            When Atom_Element	=> Result.Data.Append( New_Item =>
Input );
            When Recursive_List	=> Result:= Input.RList_Data.All;
            When EList_Type	=>
               Declare
		Data : Elementry_List:= Input.EList_Data;
               Begin
		loop
		   Result.Data.Append( New_Item => (Atom_Element, Data.Head) );
		   Exit When Data.Terminal;
		   Data:= Data.Tail.All;
		end loop;
               End;
         End Case;
      End Return;
   End As_List;



   Procedure Write_List( Stream	: Not Null Access Stream_Root'Class;
			  Item	: In List
                       ) is
      SubType ELIST is Elementry_List;
   begin
      Character'Write( Stream, '(' );
      Declare
         Procedure Process_Data( Position : Elements.Cursor ) is
            Item : List_Element Renames Elements.Element( Position );
         begin
            Case Item.Element is
            When Atom_Element	=> Atom'Write( Stream, Item.Atom_Data );
            When EList_Type	=> ELIST'Write(Stream, Item.EList_Data);
            When Recursive_List	=> List'Write( Stream,
Item.RList_Data.All );
            end case;
         end Process_Data;
      Begin
         Item.Data.Iterate( Process_Data'Access );
      End;
      Character'Write( Stream, ')' );
   end Write_List;

   Procedure Read_List( Stream	: Not Null Access Stream_Root'Class;
			 Item	: Out List
                      ) is
   begin
      null;
   end Read_List;


End LISP;



^ permalink raw reply	[relevance 2%]

* Re: Properties
  2010-12-03 21:14  4%                     ` Properties Randy Brukardt
  2010-12-04  5:35  0%                       ` Properties Shark8
@ 2010-12-13 15:10  0%                       ` Brian Drummond
  1 sibling, 0 replies; 70+ results
From: Brian Drummond @ 2010-12-13 15:10 UTC (permalink / raw)


On Fri, 3 Dec 2010 15:14:09 -0600, "Randy Brukardt" <randy@rrsoftware.com>
wrote:

>"Shark8" <onewingedshark@gmail.com> wrote in message 
>news:75475874-cd6c-4e75-8a2f-7675ecf0864a@f20g2000vbc.googlegroups.com...
>...
>>It is somewhat irritating that you cannot initialize element to
>>GUI_Base'Class directly.
...
>>instantiation error at a-convec.ads:321
>>"unconstrained element type in array declaration actual for
>>"Element_Type" must be a definite subtype"
>
>Right, but you are using the wrong container for this. Try the indefinite 
>containers (designed specifically for this purpose):
>
>Package GUI_Vector is New Ada.Containers.Indefinite_Vectors
>   ( Element_Type => GUI_Base'Class, Index_Type => Positive );
>
>This will work fine.

Excellent! 
But perhaps the error message could be improved to suggest this, e.g.

>>"unconstrained element type in array declaration actual for
>>"Element_Type" must be a definite subtype, or container must be indefinite"

- Brian



^ permalink raw reply	[relevance 0%]

* Re: Properties
  2010-12-03 21:14  4%                     ` Properties Randy Brukardt
@ 2010-12-04  5:35  0%                       ` Shark8
  2010-12-13 15:10  0%                       ` Properties Brian Drummond
  1 sibling, 0 replies; 70+ results
From: Shark8 @ 2010-12-04  5:35 UTC (permalink / raw)


On Dec 3, 2:14 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
> Right, but you are using the wrong container for this.
> Try the  indefinite containers (designed specifically for
> this purpose):
>
> Package GUI_Vector is New Ada.Containers.Indefinite_Vectors
>   ( Element_Type => GUI_Base'Class, Index_Type => Positive );
>
> This will work fine.
>
>                              Randy.

Oh wow! / Nice... As I've admitted I'm a newcomer to Ada, so there's a
lot to [still] learn.

I kept thinking "there's GOT to be some reason that it won't let me do
that... maybe I'm just not understanding something here..."

Just a quick question, but why was it necessary to have two sets of
containers, one for the indefinates and one for the definites?



^ permalink raw reply	[relevance 0%]

* Re: Properties
  @ 2010-12-03 21:14  4%                     ` Randy Brukardt
  2010-12-04  5:35  0%                       ` Properties Shark8
  2010-12-13 15:10  0%                       ` Properties Brian Drummond
  0 siblings, 2 replies; 70+ results
From: Randy Brukardt @ 2010-12-03 21:14 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:75475874-cd6c-4e75-8a2f-7675ecf0864a@f20g2000vbc.googlegroups.com...
...
>It is somewhat irritating that you cannot initialize element to
>GUI_Base'Class directly.

You can do this with the Ada containers.

>Attempting the following
>   Package GUI_Vector is New Ada.Containers.Vectors
>( Element_Type => GUI_Base'Class, Index_Type => Positive );
>yields
>instantiation error at a-convec.ads:321
>"unconstrained element type in array declaration actual for
>"Element_Type" must be a definite subtype"

Right, but you are using the wrong container for this. Try the indefinite 
containers (designed specifically for this purpose):

Package GUI_Vector is New Ada.Containers.Indefinite_Vectors
   ( Element_Type => GUI_Base'Class, Index_Type => Positive );

This will work fine.

                              Randy.



What's wrong with say initializing Ada.Containers.Vector with Positive
=> Index and Element => Access_GUI_Base_Class*?

*Type Access_GUI_Base_Class is Access GUI_Base'Class;

It would be nice to throw a "Not null" in because storing a 'pointer'
to "not an object" is pretty dumb... but that gives this error-set:
warning: in instantiation at a-convec.adb:1196
warning: (Ada 2005) null-excluding objects must be initialized
warning: "Constraint_Error" will be raised at run time
warning: in instantiation at a-convec.adb:1209
warning: (Ada 2005) null-excluding objects must be initialized
warning: "Constraint_Error" will be raised at run time

It's almost as if it's saying that we couldn't ever use the container
exclusively like this:

Vector : GUI_Vector.Vector:= GUI_Vector.Empty_Vector;
Component_1 : Aliased GUI_Base'Class:= Make_Component( ... );
--...
Component_n : Aliased GUI_Base'Class:= Make_Component( ... );
begin
 Vector.Add( Component_1'Access );
--...
 Vector.Add( Component_n'Access );
--the work
end;

>This raises another question. Ada
> does not support abstract access types. You want a reference to the widget
> be a fat pointer transparent to all widget operations with automatic
> collection of widget objects. This almost works in Ada, but it is 
> extremely
> boring to do.

[snip]
> The bottom line, interfaces must be removed from Ada.
> Instead of that an interface must be made inheritable
> from any concrete type. This is the same idea as with
> abstract record, array etc types.

Wouldn't this be alleviated by two things:
Allowing INTERFACE [keyword] objects to have fields (properties as
I've described, or somesuch)?
Allowing objects some sort of self/this/me attribute where the result
is a Not Null Access to its classwide-type*? (Or am I misunderstanding
what you mean by the need for "a fat pointer transparent to all widget
operations"?)

*Or is this the equivalent of requiring all such variables to be
Aliased?

>
> type Widget_Handle is private Widget; -- Like the widget, but isn't
> private
> type Widget_Handle is new Ada.Limited_Controlled with record
> Ptr : access Widget;
> end record;
>
> For access types there must be delegation support, which should eliminate
> need in wrappers. There are other issues as well, like that "access 
> Widget"
> is purposely not "access Widget'Class."
>
> > Finally, I've been quite impressed with Delphi's Visual Component
> > Library (VCL).
>
> That's interesting, because we are using the VCL quite heavily. One of our
> customers explicitly ordered that. Now, my impression is opposite to 
> yours:
> it is safer, *quicker*, cleaner, an far more maintainable to develop GUI 
> in
> *raw* Windows API than in VCL. As a bonus, you can get rid of that awful
> Borland C++, use VC++ or gcc instead.

Oh, right, the VCL *WAS* ported-over-to/interfaced-with Borland's C
Builder. I'm utterly unfamiliar with that incarnation of the VCL as my
experience with it has been on the Delphi (Object Pascal) side.

But the problem is that wrapping the API calls, and management of the
returned references, in objects yields something similar-in-structure
to the VCL, no?

I'm not saying that things couldn't have been done better; they could
have. But for being a useful object-oriented GUI library tied to a
singular API (Windows) I think it's done pretty well.

The idea we've been kicking around about a truly portable GUI library
with attention to type-safety and [hopefully] prevention of Bad Things
(insofar as they can be prevented, thus your desire for a statically-
checked GUI library) is an order of magnitude more complex. -- Though
I myself would like to see just such a portable GUI library done in
Ada.

>
> > Microsoft's MFC and Java's JFC seem to have been
> > 'inspired' [or copied] from the VCL, but neither presents itself as
> > uniform & usable/mature [if you will] as the VCL.
>
> We dropped MFC long ago and never returned to it. We didn't use JFC, so I 
> cannot say anything about it.

Imagine the VCL, then take away all the inherited handling of events
and make them all purely java-interfaces (so in order to handle events
you have to create some class which implements the interface; this is
usually cone in-line/via-anonymous-class), and you basically have
something similar to the JFC. 





^ permalink raw reply	[relevance 4%]

* Re: Limited use for limited with?
  2010-09-28 15:15  4%     ` Ludovic Brenta
@ 2010-09-28 22:04  0%       ` Maciej Sobczak
  0 siblings, 0 replies; 70+ results
From: Maciej Sobczak @ 2010-09-28 22:04 UTC (permalink / raw)


On 28 Wrz, 17:15, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:

> Do you mean you don't like this one:
>
>    procedure Start
>      (Web_Server : in out HTTP;
>       Dispatcher : Dispatchers.Handler'Class;
>       Config     : AWS.Config.Object);
>
> Personally it is the one I prefer. Why do you not like it?

See my answer to Dmitry for code example. The above construct, by
implicitly leaking references out of its execution, obstructs the
scoping of object lifetime.

> > 1. Object is an interface type for the callback that will be
> > implemented by user.
> > 2. Object_Access is a type that will be used for declaring and passing
> > around callback references. I don't want everybody to define their own
> > types for what is a common functionality.
>
> I don't think this functionality is that common; ideally the only
> things you have to do with such references is record them in a
> registry and then dereference them to call the callbacks. You wouldn't
> "pass around" such references very often, I think. Especially if your
> callbacks are allocated at elaboration and not dynamically on the
> heap.

That's right. Still, I need to express it somehow and I think that
having an explicitly defined access type is a good practice.
Unfortunately it does not seem to be compatible with the "limited
with" feature.

> I would probably use an instance of Ada.Containers.Indefinite_Vectors
> or Indefinite_Doubly_Linked_Lists to hold an ordered list of class-
> wide callback objects. Is that the language feature you were looking
> for? Granted, such a container would duplicate the callback objects
> ("functors") in memory; using access values would avoid that.

Exactly, but copying is not the only problem. There are also
dependencies.
Note that my construct is not dependent on Ada.Containers and it
allows the user to write programs without any use of dynamic memory.
It is perfectly possible to create a callback object at the package
level or local in a subprogram.

> I would define the access type in the package that defines the
> registry of callback objects, e.g.
>
> limited with Objects;
> package Registry is
>    type Callback is access all Objects.Object'Class;
>    procedure Register (C : in Callback);
>    procedure Call_All_Callbacks_In_Registration_Order;
> end Registry;

Interesting. I will have to meditate on this possibility.

--
Maciej Sobczak * http://www.inspirel.com



^ permalink raw reply	[relevance 0%]

* Re: Limited use for limited with?
  @ 2010-09-28 15:15  4%     ` Ludovic Brenta
  2010-09-28 22:04  0%       ` Maciej Sobczak
  0 siblings, 1 reply; 70+ results
From: Ludovic Brenta @ 2010-09-28 15:15 UTC (permalink / raw)


Maciej Sobczak wrote on comp.lang.ada:
> So let's say that I already did the thinking and the most prevalent
> use case for access types is callback registration.
>
> Think about AWS dispatchers for the closest analogy.
> In fact, the AWS.Server.Start procedure has a version that takes the
> callback by access. It is an access to function, but I need it to be
> object-oriented.

OK, functors then (I believe this word is C++ jargon).

> Hiding the use of access values behind the scenes (by virtue of tagged
> types being always passed by reference) would obstruct the code
> without clear benefit. This is what AWS does in its other versions of
> Start, but I don't like it.

Do you mean you don't like this one:

   procedure Start
     (Web_Server : in out HTTP;
      Dispatcher : Dispatchers.Handler'Class;
      Config     : AWS.Config.Object);

Personally it is the one I prefer. Why do you not like it?

> I want to express this:
>
> 1. Object is an interface type for the callback that will be
> implemented by user.
> 2. Object_Access is a type that will be used for declaring and passing
> around callback references. I don't want everybody to define their own
> types for what is a common functionality.

I don't think this functionality is that common; ideally the only
things you have to do with such references is record them in a
registry and then dereference them to call the callbacks. You wouldn't
"pass around" such references very often, I think. Especially if your
callbacks are allocated at elaboration and not dynamically on the
heap.

> I totally agree that in Ada the pressure for using access values is
> much smaller than in C++, but object registration (in a map, perhaps)
> is not addressed by any other language feature.

I would probably use an instance of Ada.Containers.Indefinite_Vectors
or Indefinite_Doubly_Linked_Lists to hold an ordered list of class-
wide callback objects. Is that the language feature you were looking
for? Granted, such a container would duplicate the callback objects
("functors") in memory; using access values would avoid that.

> Should I drop the Object_Access type altogether and mess with locally-
> defined access types in other parts of the code?

I would define the access type in the package that defines the
registry of callback objects, e.g.

limited with Objects;
package Registry is
   type Callback is access all Objects.Object'Class;
   procedure Register (C : in Callback);
   procedure Call_All_Callbacks_In_Registration_Order;
end Registry;

--
Ludovic Brenta.



^ permalink raw reply	[relevance 4%]

* Re: S-expression I/O in Ada
  2010-08-18 10:49  0%     ` Natasha Kerensikova
@ 2010-08-18 11:14  0%       ` Ludovic Brenta
  0 siblings, 0 replies; 70+ results
From: Ludovic Brenta @ 2010-08-18 11:14 UTC (permalink / raw)


Natasha Kerensikova wrote on comp.lang.ada:
> I have indeed forgotten about Ada containers. However after having read
> A.18.2 and A.18.3, it seems to me that Doubly_Linked_Lists are more
> appropriate than vectors: the recursive structure of S-expressions can
> make assignment (i.e. deep copies) quite expensive, and
> Doubly_Linked_Lists seem designed primarily to avoid copy of contained
> objects (though I may be mistaken).

I think you are mistaken:

ARM A.18.3(159/2):
  The execution of an assignment_statement for a list shall have the
effect of copying the elements from the source list object to the
target list object.

However, if the elements contain access values, then whether _they_
perform a deep or shallow copy is your decision; the Element_Type may
be controlled or not.

[...]

>>     generic -- Object_Conversions
>>        type Element (<>) is limited private;
>>     package Object_Conversions is
>>        function To_Atom (Value : in Element) return Atom;
>>        function To_Object (Value : in Atom) return Element;
>>     end Object_Conversions;
>
> I'm not fond of that part, because it's actually a memory dump, while
> atom contents are supposed to be a serialized representation of
> (atomic) objects.
>
> I'm aware that it's best to hide as much as possible about type
> definitions, but I think in that particular case having Atom definition
> public is justified.
>
> The idea is that my other objects, clients of S_Expressions, will be
> able to make a S-expression representing themselves. So they will need
> subprograms to make S-expressions. Complex objects will only have to use
> the container aspect of S-expressions, assembling S-expression
> representation provided by their sub-objects. But at some point some
> objects will be simple enough to be represented as atoms, and knowledge
> about how to serialize these atomic objects into atom objects can't be
> part of S_Expressions. Which means S_Expressions has to expose details
> of atom type.
>
> On the other hand, there will be relatively few atomic objects compared
> to complex objects. Would it possible to hide atom type definition in a
> subpackage or something, that would only be with'ed in atomic object
> packages?

Yes; in my implementation I resolved that problem by providing a
generic package Serialization containing the To_Atom and From_Atom
operations, for any discrete type. For other, arbitrary types, I
provide From_Blob and To_Blob; a client of my S_Expression package can
thus hex-encode any object by overlaying it with a Storage_Array, e.g.

function To_Atom (Object : Arbitrary_Type) return S_Expression.T is
   Blob : Storage_Array (1 .. Object'Size / System.Storage_Unit);
   for Blob'Address use Object'Address;
begin
   return S_Expression.To_Atom (Blob);
end To_Atom;

All this without exposing the internals of an atom.

In my implementation, it is also possible to turn any kind of object
into an atom by providing a pair of To_String, From_String operations,
but these operations actually perform the serialization you were
trying to hide ;/

> Maybe something like:
> private with S_Expressions.Atoms;
> package S_Expressions is
>    type Atom is private;
>    ...
>
> It doesn't seem to work due to a circular dependency. But there anything
> to do along that line of thoughts?
>
>>     type Root is tagged null record;
>>
>>     package Lists is new Ada.Containers.Indefinite_Vectors (Index_Type =>
>> Positive, Element_Type => Root'Class);
>>
>>     type S_Expression (Is_Atom : Boolean) is new Root with record
>>        case Is_Atom is
>>        when False =>
>>           List : Lists.Vector;
>>        when True =>
>>           Value : Atom;
>>        end case;
>>     end record;
>
> I don't understand why you need Indefinite_Vectors here. They have been
> presented to me as heterogeneous vector containers, but here Lists would
> be homogeneous, containing only S_Expression items.
> I'm not sure about the need of Root either, but my guess is that it's to
> provide a common root to all objects contained in the
> Indefinite_Vectors.
>
> But what makes S_Expression an indefinite type?

The type S_Expression is definite but Root'Class, being class-wide, is
indefinite. (It is considered to have at least one unknown
discriminant, which is the tag).

This is also the reason why Lists.Vector, in the example above, is
really heterogeneous; it can contain objects of different types that
extend Root.

--
Ludovic Brenta.



^ permalink raw reply	[relevance 0%]

* Re: S-expression I/O in Ada
  2010-08-17 19:00  4%   ` Jeffrey Carter
@ 2010-08-18 10:49  0%     ` Natasha Kerensikova
  2010-08-18 11:14  0%       ` Ludovic Brenta
  0 siblings, 1 reply; 70+ results
From: Natasha Kerensikova @ 2010-08-18 10:49 UTC (permalink / raw)


On 2010-08-17, Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> wrote:
> It seemed to me that you could implement this without any access types or 
> values, so I gave it a shot. The following has been compiled:
>
> private with Ada.Containers.Indefinite_Vectors;
> private with Ada.Containers.Vectors;

I have indeed forgotten about Ada containers. However after having read
A.18.2 and A.18.3, it seems to me that Doubly_Linked_Lists are more
appropriate than vectors: the recursive structure of S-expressions can
make assignment (i.e. deep copies) quite expensive, and
Doubly_Linked_Lists seem designed primarily to avoid copy of contained
objects (though I may be mistaken). Usual operations on S-expressions
are append and traversal, on which Vectors don't provide a significant
improvement (unlike e.g. random access).

Does it make sense or am I missing something?

Btw reading A.18 I discovered the idea of Cursor types, which I find
very nice: I'm used (in C) to hand over Nodes because they also contain
enough information to progress in the S-expression structure, but it
looks like Cursor would do it in a more Ada-ish way.

>     generic -- Object_Conversions
>        type Element (<>) is limited private;
>     package Object_Conversions is
>        function To_Atom (Value : in Element) return Atom;
>        function To_Object (Value : in Atom) return Element;
>     end Object_Conversions;

I'm not fond of that part, because it's actually a memory dump, while
atom contents are supposed to be a serialized representation of
(atomic) objects.

I'm aware that it's best to hide as much as possible about type
definitions, but I think in that particular case having Atom definition
public is justified.

The idea is that my other objects, clients of S_Expressions, will be
able to make a S-expression representing themselves. So they will need
subprograms to make S-expressions. Complex objects will only have to use
the container aspect of S-expressions, assembling S-expression
representation provided by their sub-objects. But at some point some
objects will be simple enough to be represented as atoms, and knowledge
about how to serialize these atomic objects into atom objects can't be
part of S_Expressions. Which means S_Expressions has to expose details
of atom type.

On the other hand, there will be relatively few atomic objects compared
to complex objects. Would it possible to hide atom type definition in a
subpackage or something, that would only be with'ed in atomic object
packages?

Maybe something like:
private with S_Expressions.Atoms;
package S_Expressions is
   type Atom is private;
   ...

It doesn't seem to work due to a circular dependency. But there anything
to do along that line of thoughts?

>     type Root is tagged null record;
>
>     package Lists is new Ada.Containers.Indefinite_Vectors (Index_Type => 
> Positive, Element_Type => Root'Class);
>
>     type S_Expression (Is_Atom : Boolean) is new Root with record
>        case Is_Atom is
>        when False =>
>           List : Lists.Vector;
>        when True =>
>           Value : Atom;
>        end case;
>     end record;

I don't understand why you need Indefinite_Vectors here. They have been
presented to me as heterogeneous vector containers, but here Lists would
be homogeneous, containing only S_Expression items.
I'm not sure about the need of Root either, but my guess is that it's to
provide a common root to all objects contained in the
Indefinite_Vectors.

But what makes S_Expression an indefinite type?



Thanks a lot for your review,
Natacha



^ permalink raw reply	[relevance 0%]

* Re: S-expression I/O in Ada
  @ 2010-08-17 19:00  4%   ` Jeffrey Carter
  2010-08-18 10:49  0%     ` Natasha Kerensikova
  0 siblings, 1 reply; 70+ results
From: Jeffrey Carter @ 2010-08-17 19:00 UTC (permalink / raw)


On 08/17/2010 10:01 AM, Natasha Kerensikova wrote:
>
> Even though I'm much more used to C than to Ada, I have the feeling it's
> horribly ugly and that using access types all over the place like I did
> is extremely poor. Yet I just can't find out exactly how it's wrong, nor
> how to get it right.

I would agree. Access types and values should not appear in the visible part of 
a package specification if at all possible.

> Would any other you be kind enough to have a look at it, and point me
> where I did wrong and explain me how wrong it is, be it on high-level
> package design to low-level implementation choice and anything in
> between including code style.

It seemed to me that you could implement this without any access types or 
values, so I gave it a shot. The following has been compiled:

private with Ada.Containers.Indefinite_Vectors;
private with Ada.Containers.Vectors;

package S_Expressions is
    type Atom is private;

    function To_Atom (Value : in String) return Atom;
    function To_String (Value : in Atom) return String;

    generic -- Object_Conversions
       type Element (<>) is limited private;
    package Object_Conversions is
       function To_Atom (Value : in Element) return Atom;
       function To_Object (Value : in Atom) return Element;
    end Object_Conversions;

    type S_Expression (<>) is tagged private; -- An Atom or a list of S_Expression.

    function Make (Item : in Atom) return S_Expression;

    function Is_Atom (Expression : in S_Expression) return Boolean;

    Not_An_Atom : exception;

    function To_Atom (Expression : in S_Expression) return Atom;
    -- Raises Not_An_Atom if not Is_Atom (Expression);

    Empty_List : constant S_Expression;

    Not_A_List : exception;

    function Append (Onto : in S_Expression; Value : in S_Expression) return 
S_Expression;
    -- Returns a list consisting of the exisiting list Onto with Value appended 
to it.
    -- Raises Not_A_List if Is_Atom (Onto);

    procedure Iterate
       (Over : in S_Expression; Process : not null access procedure (Expression 
: in S_Expression; Continue : in out Boolean) );
    -- Passes each element of Over to Process in turn, with Continue => True.
    -- Returns immediately if Process sets Continue to False; remaining elements 
will not be processed.
    -- Raises Not_A_List if Is_Atom (Over).
private -- S_Expressions
    Byte_Size : constant := 8;

    type Byte_Value is mod 2 ** Byte_Size;

    package Byte_Lists is new Ada.Containers.Vectors (Index_Type => Positive, 
Element_Type => Byte_Value);

    type Atom is record
       Value : Byte_Lists.Vector;
    end record;

    type Root is tagged null record;

    package Lists is new Ada.Containers.Indefinite_Vectors (Index_Type => 
Positive, Element_Type => Root'Class);

    type S_Expression (Is_Atom : Boolean) is new Root with record
       case Is_Atom is
       when False =>
          List : Lists.Vector;
       when True =>
          Value : Atom;
       end case;
    end record;

    Empty_List : constant S_Expression := (Is_Atom => False, List => 
Lists.Empty_Vector);
end S_Expressions;

with Ada.Unchecked_Conversion;

package body S_Expressions is
    function To_Atom (Value : in String) return Atom is
       Result : Atom;
    begin -- To_Atom
       All_Characters : for I in Value'range loop
          Result.Value.Append (New_Item => Character'Pos (Value (I) ) );
       end loop All_Characters;

       return Result;
    end To_Atom;

    function To_String (Value : in Atom) return String is
       Result : String (Value.Value.First_Index .. Value.Value.Last_Index);
    begin -- To_String
       All_Bytes : for I in Result'range loop
          Result (I) := Character'Val (Value.Value.Element (I) );
       end loop All_Bytes;

       return Result;
    end To_String;

    package body Object_Conversions is
       type Byte_List is array (Positive range <>) of Byte_Value;

       function To_Atom (Value : in Element) return Atom is
          Num_Bytes : constant Positive := (Value'Size + Byte_Size - 1) / Byte_Size;

          subtype Element_List is Byte_List (1 .. Num_Bytes);

          function Convert is new Ada.Unchecked_Conversion (Source => Element, 
Target => Element_List);

          Byte : Element_List renames Convert (Value);

          Result : Atom;
       begin -- To_Atom
          All_Bytes : for I in Byte'range loop
             Result.Value.Append (New_Item => Byte (I) );
          end loop All_Bytes;

          return Result;
       end To_Atom;

       function To_Object (Value : in Atom) return Element is
          subtype Element_List is Byte_List (Value.Value.First_Index .. 
Value.Value.Last_Index);

          function Convert is new Ada.Unchecked_Conversion (Source => 
Element_List, Target => Element);

          Byte : Element_List;
       begin -- To_Object
          All_Bytes : for I in Byte'range loop
             Byte (I) := Value.Value.Element (I);
          end loop All_Bytes;

          return Convert (Byte);
       end To_Object;
    end Object_Conversions;

    function Make (Item : in Atom) return S_Expression is
       -- null;
    begin -- Make
       return S_Expression'(Is_Atom => True, Value => Item);
    end Make;

    function Is_Atom (Expression : in S_Expression) return Boolean is
       -- null;
    begin -- Is_Atom
       return Expression.Is_Atom;
    end Is_Atom;

    function To_Atom (Expression : in S_Expression) return Atom is
       -- null;
    begin -- To_Atom
       if not Expression.Is_Atom then
          raise Not_An_Atom;
       end if;

       return Expression.Value;
    end To_Atom;

    function Append (Onto : in S_Expression; Value : in S_Expression) return 
S_Expression is
       Result : S_Expression (Is_Atom => False);
    begin -- Append
       if Onto.Is_Atom then
          raise Not_A_List;
       end if;

       Result.List := Onto.List;
       Result.List.Append (New_Item => Value);

       return Result;
    end Append;

    procedure Iterate
       (Over : in S_Expression; Process : not null access procedure (Expression 
: in S_Expression; Continue : in out Boolean) )
    is
       Continue : Boolean := True;
    begin -- Iterate
       if Over.Is_Atom then
          raise Not_A_List;
       end if;

       All_Expressions : for I in Over.List.First_Index .. Over.List.Last_Index loop
          Process (Expression => S_Expression (Over.List.Element (I) ), Continue 
=> Continue);

          exit All_Expressions when not Continue;
       end loop All_Expressions;
    end Iterate;
end S_Expressions;

I think this includes all necessary functionality to build and process 
S-expressions, though you might have some additional operations you might like 
to add. Reading it might prove instructional, whether you like this approach or not.

-- 
Jeff Carter
"I'm a lumberjack and I'm OK."
Monty Python's Flying Circus
54

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---



^ permalink raw reply	[relevance 4%]

* Re: S-expression I/O in Ada
  @ 2010-08-13 10:30  5%     ` Georg Bauhaus
  0 siblings, 0 replies; 70+ results
From: Georg Bauhaus @ 2010-08-13 10:30 UTC (permalink / raw)


On 13.08.10 10:56, Natacha Kerensikova wrote:

> Ada arrays are statically sized,

Not quite, but I think you mean that once an array is allocated, you
can't add more components than are declared by the index constraint?
Example:

procedure Uses_Array (N : Positive; ...) is

   X : array (1 .. N) of Character;  -- now fixed to N compoments

begin...

But Ada's Container packages can provide for the desired flexibility.
There are containers of homogeneous components and containers of
heterogeneous components.  The latter have _Indefinite in their
package's names.  Example:

 package Vecs is new Ada.Containers.Indefinite_Vectors
     (Element_Type => Types.Heterogenous'Class,
      Index_Type => Positive,
      "=" => Types.Eq);

(Vecs.Vector objects will grow as needed.)

Another option is to instantiate a "definite" container generic with
a pointer type, which is definite.  Its access values will point
to any object in some hierarchy.  (This can mean pointers to
any objects that share the same interface (Ada 2005 keyword),
so types need not even be rooted at the same one parent type,
I think). For example

   package S_Lists is new Ada.Containers.Doubly_Linked_Lists
     (Element_Type => Some_Hier_Ptr,
      "=" => ...);


Georg



^ permalink raw reply	[relevance 5%]

* Re: Problems with Scope of aliased Objects
  @ 2009-04-16 19:12  4%   ` sjw
  0 siblings, 0 replies; 70+ results
From: sjw @ 2009-04-16 19:12 UTC (permalink / raw)


On Apr 16, 4:47 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> Fourth solution could be to use a container of unconstrained objects or a
> container of smart pointers if the objects are limited.

ie, instantiate Ada.Containers.Indefinite_Vectors (http://
www.adaic.com/standards/05rm/html/RM-A-18-10.html) .. or lists, maps,
sets, as needed .. with type Foo'Class.

Of course this has to do heap allocation behind the scenes, but you
don't have to worry about it yourself unless performance is really an
issue. If you think it might be an issue, write a performance spec and
do some measurements before you start optimising!



^ permalink raw reply	[relevance 4%]

* Re: Array of Strings
  @ 2008-09-14  9:45  6% ` Per Sandberg
  0 siblings, 0 replies; 70+ results
From: Per Sandberg @ 2008-09-14  9:45 UTC (permalink / raw)


You could also go for the Ada containers approach and get vector 
semantics's.

with Ada.Containers.Indefinite_Vectors;
procedure Demo is
    package String_Vectors is new Ada.Containers.Indefinite_Vectors 
(Natural, String);
    V : String_Vectors.Vector;
begin
    V.Append ("Tell Me");
    V.Append ("Tell You");
end Demo;

/Per


jedivaughn wrote:
> Hi everyone,
> 
> I'm having trouble making a array of type string. can some one show me
> how to do this. I've tried type letters is array (Integer range <>) of
> String; but I get error "unconstrained element type in array
> declaration". what am I doing wrong?
> 
> Thanks,
> 
> John



^ permalink raw reply	[relevance 6%]

* Re: Deallocating list of polymorphic objects?
  2006-12-01  4:11  6% ` Matthew Heaney
@ 2006-12-01  6:12  0%   ` Michael Rohan
  0 siblings, 0 replies; 70+ results
From: Michael Rohan @ 2006-12-01  6:12 UTC (permalink / raw)


Matthew Heaney wrote:
> "Michael Rohan" <mrohan@ACM.ORG> writes:
>
> > I would like to construct a list of polymorphic objects that,
> > as part of the list's finalization, deallocates the objects on
> > the list.  Basically, I have a vector of pointers to Object'Class.
> > The objects are added to the list via procedures defined for
> > the list, e.g., append an integer, append a floating point.
> > These append procedures allocate objects derived from the
> > base Object type for the type being appended, e.g.,
> > Integer_Object, which is private to the list package.
>
>
> Here's one way to do it:
>
> --STX
> with Ada.Containers.Indefinite_Vectors;
> pragma Elaborate_All (Ada.Containers.Indefinite_Vectors);
>
> package Lists is
>
>    type List_Type is tagged limited private;
>
>    procedure Append (L : in out List_Type; I : Integer);
>    procedure Append (L : in out List_Type; F : Float);
>
> private
>
>    type Object is interface;
>    procedure Print (O : Object) is abstract;
>
>    package List_Vectors is
>       new Ada.Containers.Indefinite_Vectors (Natural, Object'Class);
>
>    type List_Type is tagged limited record
>       V : List_Vectors.Vector;
>    end record;
>
>
>    type Integer_Object is new Object with record
>       I : Integer;
>    end record;
>
>    procedure Print (O : Integer_Object);
>
>    type Float_Object is new Object with record
>       F : Float;
>    end record;
>
>    procedure Print (O : Float_Object);
>
> end Lists;
>
>
> package body Lists is
>
>    procedure Append (L : in out List_Type; I : Integer) is
>    begin
>       L.V.Append (Integer_Object'(I => I));
>    end;
>
>    procedure Append (L : in out List_Type; F : Float) is
>    begin
>       L.V.Append (Float_Object'(F => F));
>    end;
>
>    procedure Print (O : Integer_Object) is
>    begin
>       null;
>    end;
>
>    procedure Print (O : Float_Object) is
>    begin
>       null;
>    end;
>
> end Lists;

Hi,

This looks really tidy and clean.

Thank you,
Michael.




^ permalink raw reply	[relevance 0%]

* Re: Deallocating list of polymorphic objects?
    2006-12-01  3:52  6% ` Matthew Heaney
@ 2006-12-01  4:11  6% ` Matthew Heaney
  2006-12-01  6:12  0%   ` Michael Rohan
  1 sibling, 1 reply; 70+ results
From: Matthew Heaney @ 2006-12-01  4:11 UTC (permalink / raw)


"Michael Rohan" <mrohan@ACM.ORG> writes:

> I would like to construct a list of polymorphic objects that,
> as part of the list's finalization, deallocates the objects on
> the list.  Basically, I have a vector of pointers to Object'Class.
> The objects are added to the list via procedures defined for
> the list, e.g., append an integer, append a floating point.
> These append procedures allocate objects derived from the
> base Object type for the type being appended, e.g.,
> Integer_Object, which is private to the list package.


Here's one way to do it:

--STX
with Ada.Containers.Indefinite_Vectors;
pragma Elaborate_All (Ada.Containers.Indefinite_Vectors);

package Lists is

   type List_Type is tagged limited private;

   procedure Append (L : in out List_Type; I : Integer);
   procedure Append (L : in out List_Type; F : Float);

private

   type Object is interface;
   procedure Print (O : Object) is abstract;

   package List_Vectors is
      new Ada.Containers.Indefinite_Vectors (Natural, Object'Class);

   type List_Type is tagged limited record
      V : List_Vectors.Vector;
   end record;


   type Integer_Object is new Object with record
      I : Integer;
   end record;

   procedure Print (O : Integer_Object);

   type Float_Object is new Object with record
      F : Float;
   end record;

   procedure Print (O : Float_Object);

end Lists;


package body Lists is

   procedure Append (L : in out List_Type; I : Integer) is
   begin
      L.V.Append (Integer_Object'(I => I));
   end;

   procedure Append (L : in out List_Type; F : Float) is
   begin
      L.V.Append (Float_Object'(F => F));
   end;

   procedure Print (O : Integer_Object) is
   begin
      null;
   end;

   procedure Print (O : Float_Object) is
   begin
      null;
   end;

end Lists;



^ permalink raw reply	[relevance 6%]

* Re: Deallocating list of polymorphic objects?
  @ 2006-12-01  3:52  6% ` Matthew Heaney
  2006-12-01  4:11  6% ` Matthew Heaney
  1 sibling, 0 replies; 70+ results
From: Matthew Heaney @ 2006-12-01  3:52 UTC (permalink / raw)


"Michael Rohan" <mrohan@ACM.ORG> writes:

> I would like to construct a list of polymorphic objects that,
> as part of the list's finalization, deallocates the objects on
> the list.  Basically, I have a vector of pointers to Object'Class.

The easiest way to do that is using the indefinite form:

with Ada.Containers.Indefinite_Vectors;

package Object_Vectors is
  new Ada.Containers.Indefinite_Vectors (Object'Class);

As others have pointed out, the Ada run-time properly handles deallocation of
objects having a class-wide type, so there's nothing special you need to do.



^ permalink raw reply	[relevance 6%]

* Re: Basic Explaination of OO in Ada
  2006-09-19 16:06  5%           ` Ludovic Brenta
@ 2006-09-19 16:14  0%             ` Alex R. Mosteo
  0 siblings, 0 replies; 70+ results
From: Alex R. Mosteo @ 2006-09-19 16:14 UTC (permalink / raw)


Ludovic Brenta wrote:

> Alex R. Mosteo wrote:
>> Just a note: although what Ludovic writes is right, and you can only have
>> vanilla arrays of definite types, you can have more sophisticated
>> containers (for example Ada.Containers.Indefinite_Vectors) that store
>> class-wide types in Ada 2005:
>>
>> package Pak_Vectors is
>>   new Ada.Containers.Indefinite_Vectors (Positive, Pak.T'Class);
>>
>> In this case, however, you store copies so some overhead can occur, but
>> in many cases it can be more convenient than starting to play with
>> pointers.
> 
> Doesn't Ada.Containers.Indefinite_Vectors have to declare a class-wide
> access type for its internal use? I'd guess so. But, it hides the
> access type from the user, and that's encapsulation at its best.

Yep, I suppose so (but I didn't looked for it).

> In Ada, one rarely needs access types at all. The only justification
> for declaring one is because you're doing some kind of dynamic data
> structure and allocating dynamically on the heap. With the standard
> Ada.Containers, you'd need access types even less often.

Agreed.

> That's why in my examples I did not declare an access type along with
> the tagged type (in package P); instead, I declared an access type in
> another package (package Collection) because that package absolutely
> needed one.

Ok, I missed your intention with the example here, so I was trying to make
clear that one shouldn't be too keen on jumping to access types :)




^ permalink raw reply	[relevance 0%]

* Re: Basic Explaination of OO in Ada
  2006-09-19 15:56  6%         ` Alex R. Mosteo
@ 2006-09-19 16:06  5%           ` Ludovic Brenta
  2006-09-19 16:14  0%             ` Alex R. Mosteo
  0 siblings, 1 reply; 70+ results
From: Ludovic Brenta @ 2006-09-19 16:06 UTC (permalink / raw)


Alex R. Mosteo wrote:
> Just a note: although what Ludovic writes is right, and you can only have
> vanilla arrays of definite types, you can have more sophisticated
> containers (for example Ada.Containers.Indefinite_Vectors) that store
> class-wide types in Ada 2005:
>
> package Pak_Vectors is
>   new Ada.Containers.Indefinite_Vectors (Positive, Pak.T'Class);
>
> In this case, however, you store copies so some overhead can occur, but in
> many cases it can be more convenient than starting to play with pointers.

Doesn't Ada.Containers.Indefinite_Vectors have to declare a class-wide
access type for its internal use? I'd guess so. But, it hides the
access type from the user, and that's encapsulation at its best.

In Ada, one rarely needs access types at all. The only justification
for declaring one is because you're doing some kind of dynamic data
structure and allocating dynamically on the heap. With the standard
Ada.Containers, you'd need access types even less often.

That's why in my examples I did not declare an access type along with
the tagged type (in package P); instead, I declared an access type in
another package (package Collection) because that package absolutely
needed one.

-- 
Ludovic Brenta.




^ permalink raw reply	[relevance 5%]

* Re: Basic Explaination of OO in Ada
  @ 2006-09-19 15:56  6%         ` Alex R. Mosteo
  2006-09-19 16:06  5%           ` Ludovic Brenta
  0 siblings, 1 reply; 70+ results
From: Alex R. Mosteo @ 2006-09-19 15:56 UTC (permalink / raw)


Ludovic Brenta wrote:

> Access types come in handy if you want a collection of class-wide
> objects; the collection is said to be polymorphic:
> 
> with Pak;
> package Collection is
>    type Ref is access Pak.T'Class; -- access-to-class-wide-objects
>    type Vector is array (Positive range <>) of Ref; -- polymorphic
> vector
>    procedure Traverse (V : in Vector);
> end Collection;
> 
> package body Collection is
>    procedure Traverse (V : in Vector) is
>    begin
>       for J in V'Range loop
>          if V (J) /= null then
>             Pak.P (V (J).all); -- dispatches on the specific type of
> the object
>          end if;
>       end loop;
>    end Traverse;
> end Collection;

Just a note: although what Ludovic writes is right, and you can only have
vanilla arrays of definite types, you can have more sophisticated
containers (for example Ada.Containers.Indefinite_Vectors) that store
class-wide types in Ada 2005:

package Pak_Vectors is 
  new Ada.Containers.Indefinite_Vectors (Positive, Pak.T'Class);

In this case, however, you store copies so some overhead can occur, but in
many cases it can be more convenient than starting to play with pointers.



^ permalink raw reply	[relevance 6%]

* Re: memory management and productivity
  2004-06-21 15:22  0%             ` Hyman Rosen
@ 2004-06-21 16:47  0%               ` Martin Krischik
  0 siblings, 0 replies; 70+ results
From: Martin Krischik @ 2004-06-21 16:47 UTC (permalink / raw)


Hyman Rosen wrote:

> Martin Krischik wrote:
>> For example C++ std::vector<> can't store polymorvic objects - Ada soon
>> to come Ada.Containers.Indefinite_Vectors can.
> 
> That seems like a neat trick, given that a vector is
> intended to work like an array,
> that is, to have a 
> contiguous block of equal-sized objects.

It only has to work like it - internally it might be implemented differently
i.E. using dynamic memory.

> How is the 
> container going to work?

The trick is that Ada can "clone ()" objects without:

class Base
{
   virtual Base* clone();
}

That's because Ada knows (by hidden size attribute) how large any object is.
Including polymorvic objects. Write any indefinite object to a Stream via
'Output and look at it with hex editor.

In that respect Ada is even cooler then Java: You can serialise any object
without a Serialiseable interface.

So, the truth is that the object is copied into dynamic memory. However, you
will never know about it.

With Regards

Martin

-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com




^ permalink raw reply	[relevance 0%]

* Re: memory management and productivity
  2004-06-21  8:14  5%           ` Martin Krischik
@ 2004-06-21 15:22  0%             ` Hyman Rosen
  2004-06-21 16:47  0%               ` Martin Krischik
  0 siblings, 1 reply; 70+ results
From: Hyman Rosen @ 2004-06-21 15:22 UTC (permalink / raw)


Martin Krischik wrote:
> For example C++ std::vector<> can't store polymorvic objects - Ada soon to
> come Ada.Containers.Indefinite_Vectors can.

That seems like a neat trick, given that a vector is
intended to work like an array, that is, to have a
contiguous block of equal-sized objects. How is the
container going to work?



^ permalink raw reply	[relevance 0%]

* Re: memory management and productivity
  @ 2004-06-21  8:14  5%           ` Martin Krischik
  2004-06-21 15:22  0%             ` Hyman Rosen
  0 siblings, 1 reply; 70+ results
From: Martin Krischik @ 2004-06-21  8:14 UTC (permalink / raw)


Jano wrote:

> It's been so many time since I did C++ that I may be wrong, correct me
> in that case.
> 
> IIRC, in C++ you must destroy (delete?) the object to get the destructor
> called. So, even if you have a carefully built chain of destructors, if
> at some point you forget to destroy the root, you're leaking.
> 
> In Ada, when an object goes out of scope (assuming it has been created
> in the stack and not with the "new" operator), it's automatically
> finished so you have one less thing to care about.

It is the same in Ada as in C++. Both can create object on the heap on
stack. The real difference is that Ada has indefinite objects and as a
result far less object need to be created on the heap.

For example C++ std::vector<> can't store polymorvic objects - Ada soon to
come Ada.Containers.Indefinite_Vectors can.

With Regards

Martin

Container Libraries with support for indefinite Object:

Booch Components: http://adacl.sf.net
Ada.Containers: http://charles.tigris.org.

-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com




^ permalink raw reply	[relevance 5%]

Results 1-70 of 70 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2004-06-17  4:56     memory management and productivity Russ
2004-06-17  8:07     ` Martin Dowie
2004-06-18 23:10       ` Russ
2004-06-19  9:04         ` Martin Dowie
2004-06-21  4:16           ` Russ
2004-06-21  7:29             ` Jano
2004-06-21  8:14  5%           ` Martin Krischik
2004-06-21 15:22  0%             ` Hyman Rosen
2004-06-21 16:47  0%               ` Martin Krischik
2006-09-18 15:24     Basic Explaination of OO in Ada richard.charts
2006-09-18 20:25     ` Jeffrey R. Carter
2006-09-19  3:32       ` Lucretia
2006-09-19 13:56         ` richard.charts
2006-09-19 15:31           ` Ludovic Brenta
2006-09-19 15:56  6%         ` Alex R. Mosteo
2006-09-19 16:06  5%           ` Ludovic Brenta
2006-09-19 16:14  0%             ` Alex R. Mosteo
2006-11-30 23:40     Deallocating list of polymorphic objects? Michael Rohan
2006-12-01  3:52  6% ` Matthew Heaney
2006-12-01  4:11  6% ` Matthew Heaney
2006-12-01  6:12  0%   ` Michael Rohan
2008-09-13 14:18     Array of Strings jedivaughn
2008-09-14  9:45  6% ` Per Sandberg
2009-04-16 13:43     Problems with Scope of aliased Objects patrick.gunia
2009-04-16 15:47     ` Dmitry A. Kazakov
2009-04-16 19:12  4%   ` sjw
2010-08-01 12:17     S-expression I/O in Ada Natacha Kerensikova
2010-08-12 23:26     ` Shark8
2010-08-13  8:56       ` Natacha Kerensikova
2010-08-13 10:30  5%     ` Georg Bauhaus
2010-08-17 17:01     ` Natasha Kerensikova
2010-08-17 19:00  4%   ` Jeffrey Carter
2010-08-18 10:49  0%     ` Natasha Kerensikova
2010-08-18 11:14  0%       ` Ludovic Brenta
2010-09-28  7:37     Limited use for limited with? Maciej Sobczak
2010-09-28  9:18     ` Ludovic Brenta
2010-09-28 12:59       ` Maciej Sobczak
2010-09-28 15:15  4%     ` Ludovic Brenta
2010-09-28 22:04  0%       ` Maciej Sobczak
2010-11-28  3:21     Properties Shark8
2010-11-30  1:49     ` Properties Randy Brukardt
2010-11-30 16:58       ` Properties Charmed Snark
2010-11-30 17:22         ` Properties Dmitry A. Kazakov
2010-11-30 20:27           ` Properties Warren
2010-12-01  8:39             ` Properties Dmitry A. Kazakov
2010-12-01 15:21               ` Properties Warren
2010-12-01 15:59                 ` Properties Dmitry A. Kazakov
2010-12-03  5:53                   ` Properties Shark8
2010-12-03  9:05                     ` Properties Dmitry A. Kazakov
2010-12-03 19:52                       ` Properties Shark8
2010-12-03 21:14  4%                     ` Properties Randy Brukardt
2010-12-04  5:35  0%                       ` Properties Shark8
2010-12-13 15:10  0%                       ` Properties Brian Drummond
2011-03-04 20:58     Little tutorial about streams mockturtle
2011-03-05  1:08  2% ` Shark8
2011-03-19 17:10  4% Order of execution of subprogram parameters Syntax Issues
2011-06-09 17:50     Use of abstract tagged types without access types -- again and complete Prof. Dr. Carl Weierstrass
2011-06-09 20:19     ` Ludovic Brenta
2011-06-09 21:06       ` Randy Brukardt
2011-06-10 15:43  4%     ` Prof. Dr. Carl Weierstrass
2011-06-12 12:05  0%       ` Alex R. Mosteo
2011-12-18 12:34     String_Holder ? Natasha Kerensikova
2011-12-19 11:12  4% ` Martin
2012-10-30 22:03  4% Tasking troubles, unexpected termination Shark8
2012-10-30 23:01     ` Adam Beneschan
2012-10-31  1:05       ` Anh Vo
2012-10-31  2:17  3%     ` Shark8
2012-12-31  0:16     asynchronous task communication Charles Hixson
2012-12-31 12:09     ` Georg Bauhaus
2012-12-31 18:52       ` Charles Hixson
2012-12-31 21:09         ` Niklas Holsti
2013-01-01  3:51           ` Charles Hixson
2013-01-01 12:32             ` Jeffrey Carter
2013-01-01 18:21               ` Charles Hixson
2013-01-01 18:54                 ` Robert A Duff
2013-01-02  7:36                   ` Charles Hixson
2013-01-02  9:55                     ` Dmitry A. Kazakov
2013-01-02 19:02                       ` Charles Hixson
2013-01-02 20:35                         ` Dmitry A. Kazakov
2013-01-03  0:20                           ` Charles Hixson
2013-01-03 22:27                             ` Randy Brukardt
2013-01-05  5:18                               ` Charles Hixson
2013-01-05  8:48                                 ` Niklas Holsti
2013-01-06 22:55                                   ` Charles Hixson
2013-01-07 10:49  3%                                 ` Brian Drummond
2013-03-28 17:34  6% Interresting, possibly buggy behavior in GNAT generics w/ expression function Shark8
2013-04-27 14:09     Depth First Search of a Char_Matrix? Alex
2013-04-27 15:35  3% ` Shark8
2013-04-27 17:25  0%   ` Jeffrey Carter
2013-08-02 16:39     How can I declare a collection of an interface? Graham Stark
2013-08-02 18:28  5% ` Adam Beneschan
2014-08-05 13:06  5% Problem with indefinite discriminant records in container john
2014-08-05 16:05  5% ` Simon Wright
2014-08-05 20:09     A bad counterintuitive behaviour of Ada about OO Victor Porton
2014-08-05 20:59     ` Dmitry A. Kazakov
2014-08-05 21:11       ` Victor Porton
2014-08-06  7:26         ` Dmitry A. Kazakov
2014-08-07  7:41           ` Maciej Sobczak
2014-08-07  8:58             ` J-P. Rosen
2014-08-07  9:40               ` Dmitry A. Kazakov
2014-08-07 11:17                 ` J-P. Rosen
2014-08-07 12:28                   ` Dmitry A. Kazakov
2014-08-07 13:34                     ` J-P. Rosen
2014-08-07 16:10                       ` Dmitry A. Kazakov
2014-08-07 18:14  5%                     ` Robert A Duff
2014-08-07 19:41  0%                       ` Dmitry A. Kazakov
2014-08-07 20:53  0%                         ` Robert A Duff
     [not found]     <8ac0299b-1935-46f9-962a-57fb710e8cf7@googlegroups.com>
2014-10-01 18:16  3% ` Can anyone build AWS on Windows? Björn Lundin
2014-10-03 23:29     array of string Stribor40
2014-10-04  0:50     ` Jerry
2014-10-04  1:07  4%   ` Brad Moore
2015-08-04  2:23  7% Indefinite Containers of Indefinite Private Types Jeffrey R. Carter
2015-08-04  5:40  0% ` Niklas Holsti
2015-08-04 18:56       ` Jeffrey R. Carter
2015-08-07 20:13         ` Bob Duff
2015-08-07 20:45  4%       ` Jeffrey R. Carter
2015-09-08 15:10     working with diferent instances of the same generic interface Aitor Alcrudo Sangros
2015-09-09  6:38     ` Jacob Sparre Andersen
2015-09-09 11:08       ` Aitor Alcrudo Sangros
2015-09-10 12:22  4%     ` Jacob Sparre Andersen
2016-03-20 11:15     Confused about class-wide types Mart van de Wege
2016-03-20 13:18  5% ` Shark8
2016-03-20 13:56  0%   ` Mart van de Wege
2016-03-21 21:54  0%   ` Randy Brukardt
2016-07-31  0:31  4% Is it possible to make a possibly self-referential type using containers? Shark8
2016-07-31  2:41  3% ` Randy Brukardt
2016-07-31  5:36  4% ` Jeffrey R. Carter
2016-07-31  7:00  4% ` Dmitry A. Kazakov
2016-08-20 18:23     Base64 encoding and decoding (preferably public domain) john
2016-08-22  2:48  3% ` Shark8
2016-09-09 20:24  4% Are mutually dependant and possibly recursive types using Containers possible? Shark8
2016-09-09 20:40  0% ` Jeffrey R. Carter
2016-09-21 22:05     New to Ada need help implementing Warshall's algorithm James Brewer
2016-09-23  4:31  5% ` Shark8
2016-09-23 14:54  0%   ` James Brewer
2017-01-25 12:25     Ada.Numerics.Long_Real_Arrays hnptz
2017-01-25 21:29     ` Ada.Numerics.Long_Real_Arrays hnptz
2017-01-26  7:47       ` Ada.Numerics.Long_Real_Arrays Simon Wright
2017-01-26 11:54         ` Ada.Numerics.Long_Real_Arrays hnptz
2017-01-26 14:52  3%       ` Ada.Numerics.Long_Real_Arrays Simon Wright
2017-01-26 15:03  6%         ` Ada.Numerics.Long_Real_Arrays Simon Wright
2017-03-09 13:45  6% Getting the index for an element in mutually referencing containers Mart van de Wege
2017-09-11 21:19  5% Convert between different container types Victor Porton
2017-09-11 21:20  0% ` Victor Porton
2017-10-02 23:29  0%   ` Randy Brukardt
2017-09-11 21:36  0% ` Simon Wright
2017-10-21 21:48  4% Array of Unbounded_String vs Indefinite_Vectors(Natural, String) Victor Porton
2017-10-22  0:51  0% ` Shark8
2017-10-22 10:52  0%   ` Victor Porton
2017-10-22 12:30  0% ` Victor Porton
2017-10-28 11:10  4% Is Ada.Containers.Vectors.Reference_Type a constrained view? Stephen Leake
2017-11-15  0:38  0% ` Randy Brukardt
2017-11-19 20:40     gettext for Ada Victor Porton
2017-11-20 15:40     ` Shark8
2017-11-20 22:43       ` Randy Brukardt
2017-11-21  0:28         ` Shark8
2017-11-22  1:10           ` Randy Brukardt
2017-11-22 15:38             ` Shark8
2017-11-23  8:25               ` G. B.
2017-11-23 16:02  4%             ` Shark8
2018-03-06 19:46     Recursive algebraic data types hnptz
2018-03-06 20:28     ` Randy Brukardt
2018-03-06 20:54  5%   ` Jeffrey R. Carter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox