* Proposal: Auto-allocation of Indefinite Objects @ 2020-04-03 22:48 Stephen Davies 2020-04-03 23:45 ` Stephen Leake ` (4 more replies) 0 siblings, 5 replies; 47+ messages in thread From: Stephen Davies @ 2020-04-03 22:48 UTC (permalink / raw) Firstly, apologies if this has already been discussed or, more likely, if it's a really stupid idea for some reason that I haven't thought of. My proposal is that it should (sometimes?) be possible to declare objects of indefinite types such as String and have the compiler automatically declare the space for them without the programmer having to resort to access types. Benefits: 1. Easier, especially for newbies/students. 2. Safer due to reduced use of access types. 3. Remove the need to have definite and indefinite verions of generic units. It is the 3rd reason that initially got me thinking about this. It seems excessive to have two versions of packages just because one version can say "Node.Item := New_Item;" but the other has to say "Node.Item_Ptr := new Element_Type'(New_Item);". It's probably not a good idea for auto-allocation to be the default behaviour, so I suggest something like: type Node_Type is record Item : new Element_Type; Prev : Node_Ptr_Type; Next : Node_Ptr_Type; end record; If Element_Type is a definite type in the instantiation then Node.Item will be a normal object of that type. Otherwise, it is implemented as a pointer but the code still treats it as an object. The target of the pointer is allocated on assignment of the object. The pointer cannot be copied to any other object. Assignments of the whole record will perform a deep-copy of the auto-allocated component. The target of the Node.Item pointer can be auto-deallocated when Node goes out of scope or is deallocated. Ok, I've probably missed something obvious and have been wasting my time, but at least I've got plenty of time to waste at the moment. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-04-03 22:48 Proposal: Auto-allocation of Indefinite Objects Stephen Davies @ 2020-04-03 23:45 ` Stephen Leake 2020-04-04 10:54 ` Jeffrey R. Carter 2020-04-04 8:31 ` Dmitry A. Kazakov ` (3 subsequent siblings) 4 siblings, 1 reply; 47+ messages in thread From: Stephen Leake @ 2020-04-03 23:45 UTC (permalink / raw) On Friday, April 3, 2020 at 3:48:43 PM UTC-7, Stephen Davies wrote: > Firstly, apologies if this has already been discussed or, > more likely, if it's a really stupid idea for some reason > that I haven't thought of. > > My proposal is that it should (sometimes?) be possible to declare > objects of indefinite types such as String and have the compiler > automatically declare the space for them without the programmer > having to resort to access types. declare Foo : String := ...; begin ... end; Foo is allocated on the stack; size is taken from the initialization expression. with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; declare Foo : Unbounded_String; -- empty begin Foo := To_Unbounded ("hi"); -- allocated on the heap Foo := Foo & To_Unbounded ("bye"); -- allocation grows end; -- deallocated. -- Stephe ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-04-03 23:45 ` Stephen Leake @ 2020-04-04 10:54 ` Jeffrey R. Carter 2020-04-04 20:55 ` Stephen Davies 0 siblings, 1 reply; 47+ messages in thread From: Jeffrey R. Carter @ 2020-04-04 10:54 UTC (permalink / raw) On 4/4/20 1:45 AM, Stephen Leake wrote: > > with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; > > declare > Foo : Unbounded_String; -- empty > begin > Foo := To_Unbounded ("hi"); -- allocated on the heap > Foo := Foo & To_Unbounded ("bye"); -- allocation grows Foo := Foo & "bye"; Those should be To_Unbounded_String; For an issue related to the OP's idea, consider with System; procedure Boom is type Very_Large_Item is ...; type Very_Large_Index is mod System.Max_Binary_Modulus; type Very_Large_List is array (Very_Large_Index range <>) of Very_Large_Item; Last : constant := ...; List : Very_Large_List (0 .. Last); begin -- Boom ... -- Do some thing useful with List end Boom; There exists a value N > 0 such that Last = N works and Last = N + 1 results in Storage_Error. The actual value of N may vary depending on the compiler, target, and the actual machine on which the program is executed. If you want to handle a List with Last > N, you have to make it an access to Very_Large_List unless you care where it is allocated. There is still a value M which will result in Storage_Error, but on most machines where you'd try to process such a large object, M >> N because on such machines the heap is much larger than the stack. Implicit dereferencing makes this change less painful than it would be without implicit dereferencing, but there are still usually places where explicit dereferencing will be needed, so there is still some pain involved even though you don't care where the object is allocated. It would be nice if there were a compiler option where objects that don't fit on the stack would be automatically allocated on the heap, and automatically deallocated when they go out of scope. Similar arguments can be made for a compiler option where all numeric types would be accepted, with some implemented in terms of the compiler's ability to calculate static expressions exactly, rather than the user having to switch from a numeric type to an unbounded-number pkg. This has the added value that such pkgs usually lose the automated checks that numeric types have. All of these issues have been around for some time, and the ARG is aware of them and has chosen to take no action. That seems unlikely to change. -- Jeff Carter "I'm a vicious jungle beast!" Play It Again, Sam 131 ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-04-04 10:54 ` Jeffrey R. Carter @ 2020-04-04 20:55 ` Stephen Davies 0 siblings, 0 replies; 47+ messages in thread From: Stephen Davies @ 2020-04-04 20:55 UTC (permalink / raw) On 2020-04-03, Stephen Davies wrote: >> >> Item : New String; [ill-thought-out proposal] On 2020-04-04, Stephen Leake wrote: > > [Ada-101 stuff ;-)] On 2020-04-04, Dmitry A. Kazakov wrote: > > This looks interesting to me. There is a huge number of cases I > am using this schema, especially when Item is initialized once. Woohoo, I'm not a complete idiot. On 2020-04-04, Jeffrey R. Carter wrote: > > the ARG is aware of them and has chosen to take no action. > That seems unlikely to change. Oh. :-( ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-04-03 22:48 Proposal: Auto-allocation of Indefinite Objects Stephen Davies 2020-04-03 23:45 ` Stephen Leake @ 2020-04-04 8:31 ` Dmitry A. Kazakov 2020-07-27 7:47 ` Yannick Moy ` (2 subsequent siblings) 4 siblings, 0 replies; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-04-04 8:31 UTC (permalink / raw) On 2020-04-04 00:48, Stephen Davies wrote: > It is the 3rd reason that initially got me thinking about this. > It seems excessive to have two versions of packages just because > one version can say "Node.Item := New_Item;" but the other has to say > "Node.Item_Ptr := new Element_Type'(New_Item);". This is another issue, IMO. The language should support interface inheritance: type Node_Item_Inteface is ...; type Static_Node_Item is new Node_Item_Inteface with record ... type Dynamic_Node_Item is new Node_Item_Inteface with access Some_Implementation; Implementation of an interface per access type. > It's probably not a good idea for auto-allocation to be the default > behaviour, so I suggest something like: > > type Node_Type is record > Item : new Element_Type; > Prev : Node_Ptr_Type; > Next : Node_Ptr_Type; > end record; > > If Element_Type is a definite type in the instantiation then > Node.Item will be a normal object of that type. Otherwise, it is > implemented as a pointer but the code still treats it as an object. > The target of the pointer is allocated on assignment of the object. > The pointer cannot be copied to any other object. Assignments of the > whole record will perform a deep-copy of the auto-allocated component. > The target of the Node.Item pointer can be auto-deallocated when Node > goes out of scope or is deallocated. > > Ok, I've probably missed something obvious and have been wasting my > time, but at least I've got plenty of time to waste at the moment. This looks interesting to me. There is a huge number of cases I am using this schema, especially when Item is initialized once. The major advantage is of course in having a plain String instead of Unbounded_String. No conversions, no space/time penalties. I refrain using Unbounded_String as much as possible. Also there must be a possibility to specify the pool of Item. I frequently place things like Node_Type into an arena pool, soI want the string going there as well. Another case is marshaling such objects, so that the body of Item would not be left behind. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-04-03 22:48 Proposal: Auto-allocation of Indefinite Objects Stephen Davies 2020-04-03 23:45 ` Stephen Leake 2020-04-04 8:31 ` Dmitry A. Kazakov @ 2020-07-27 7:47 ` Yannick Moy 2020-07-27 9:21 ` J-P. Rosen 2020-07-27 17:48 ` Brian Drummond 2020-07-31 9:25 ` Stephen Davies 2020-09-03 4:30 ` linda white 4 siblings, 2 replies; 47+ messages in thread From: Yannick Moy @ 2020-07-27 7:47 UTC (permalink / raw) Hi Stephen, On Saturday, April 4, 2020 at 12:48:43 AM UTC+2, Stephen Davies wrote: > Firstly, apologies if this has already been discussed or, > more likely, if it's a really stupid idea for some reason > that I haven't thought of. Actually, that's something more and more of us would like to see. > My proposal is that it should (sometimes?) be possible to declare > objects of indefinite types such as String and have the compiler > automatically declare the space for them without the programmer > having to resort to access types. I agree with the goal. > Benefits: > > 1. Easier, especially for newbies/students. > 2. Safer due to reduced use of access types. > 3. Remove the need to have definite and indefinite versions of generic units. I agree with 2 only if we can combine this with safe handling of aliasing. It would be terrible to have such a feature lead to unsafe code if you somehow copy the pointer. Also, for strings that's possibly not the only change needed. What you'd like really is to be able to reassign the string to some larger/smaller string, like you do when using Unbounded_String. On 2020-04-04, Jeffrey R. Carter wrote: > > the ARG is aware of them and has chosen to take no action. > That seems unlikely to change. On the other hand, AdaCore has launched a project to collect/discuss ideas/suggestions/problems regarding the evolution of Ada and SPARK: https://github.com/AdaCore/ada-spark-rfcs Feel free to open an Issue there on that topic. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-27 7:47 ` Yannick Moy @ 2020-07-27 9:21 ` J-P. Rosen 2020-07-27 9:49 ` Dmitry A. Kazakov 2020-07-27 17:48 ` Brian Drummond 1 sibling, 1 reply; 47+ messages in thread From: J-P. Rosen @ 2020-07-27 9:21 UTC (permalink / raw) Le 27/07/2020 à 09:47, Yannick Moy a écrit : >> My proposal is that it should (sometimes?) be possible to declare >> objects of indefinite types such as String and have the compiler >> automatically declare the space for them without the programmer >> having to resort to access types. > I agree with the goal. > You have it already. It's called Unbounded_String. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-27 9:21 ` J-P. Rosen @ 2020-07-27 9:49 ` Dmitry A. Kazakov 0 siblings, 0 replies; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-07-27 9:49 UTC (permalink / raw) On 27/07/2020 11:21, J-P. Rosen wrote: > Le 27/07/2020 à 09:47, Yannick Moy a écrit : >>> My proposal is that it should (sometimes?) be possible to declare >>> objects of indefinite types such as String and have the compiler >>> automatically declare the space for them without the programmer >>> having to resort to access types. >> I agree with the goal. >> > You have it already. It's called Unbounded_String. Not really. 1. Unbounded_String is a compromise needed when the string length change during its life. The great majority of cases allocate [and initialize] a string just once. [addressed to be the cases when using a discriminant does not work] 2. There is nothing for arrays that are not strings and for other indefinite types. E.g.: type Node_Type is record Item : new Element_Type'Class; Prev : Node_Ptr_Type; Next : Node_Ptr_Type; end record; 3. There is nothing for serialization and marshaling objects logically containing strings and other indefinite types. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-27 7:47 ` Yannick Moy 2020-07-27 9:21 ` J-P. Rosen @ 2020-07-27 17:48 ` Brian Drummond 2020-07-27 20:02 ` Dmitry A. Kazakov 2020-07-27 20:31 ` Jeffrey R. Carter 1 sibling, 2 replies; 47+ messages in thread From: Brian Drummond @ 2020-07-27 17:48 UTC (permalink / raw) On Mon, 27 Jul 2020 00:47:30 -0700, Yannick Moy wrote: >> My proposal is that it should (sometimes?) be possible to declare >> objects of indefinite types such as String and have the compiler >> automatically declare the space for them without the programmer having >> to resort to access types. In one sense we already have this ... in that we can do this in a Declare block, where stack allocation is a practical implementation. But what about cases where (for whatever reason) we want it allocated on the heap? In another sense we have it as JP Rosen said, for the specific example Unbounded_String. Is there any way we could generalise the (storage, access and lifetime aspects of) Unbounded_String for unconstrained arrays and discriminated records in such a way that Unbounded_String can be a simple instantiation of one of these? But without the full flexibility (or overhead) of controlled types. So, somewhere in between, as: 1. Controlled type | ---2.Unconstrained Array or Discriminated Record | ---3. Unbounded String (instance of 2) 2) can be implemented internally using pointers, but externally appears to be a data object, just like Unbounded_String does, with similar semantics. -- Brian ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-27 17:48 ` Brian Drummond @ 2020-07-27 20:02 ` Dmitry A. Kazakov 2020-07-28 14:28 ` Brian Drummond 2020-07-27 20:31 ` Jeffrey R. Carter 1 sibling, 1 reply; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-07-27 20:02 UTC (permalink / raw) On 27/07/2020 19:48, Brian Drummond wrote: > 2) can be implemented internally using pointers, but externally appears > to be a data object, just like Unbounded_String does, with similar > semantics. No, the point is that Unbounded_String is exactly opposite to what is required. In no case it should appear as an object of a different type! Compare access to string P with unbounded string U: for I in P'Range loop -- This is OK P(J) := 'a' -- This is OK Now would you do: To_String (U) (J) := 'a' -- Garbage! What if the original object must be a class-wide object, task, protected object, limited object etc? Ada's access types delegate all operations to the target object, except assignment. This is the key property that the proposal in my view must retain. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-27 20:02 ` Dmitry A. Kazakov @ 2020-07-28 14:28 ` Brian Drummond 2020-07-28 14:59 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Brian Drummond @ 2020-07-28 14:28 UTC (permalink / raw) On Mon, 27 Jul 2020 22:02:57 +0200, Dmitry A. Kazakov wrote: > On 27/07/2020 19:48, Brian Drummond wrote: > >> 2) can be implemented internally using pointers, but externally appears >> to be a data object, just like Unbounded_String does, with similar >> semantics. > > No, the point is that Unbounded_String is exactly opposite to what is > required. In no case it should appear as an object of a different type! > > Compare access to string P with unbounded string U: > > for I in P'Range loop -- This is OK > P(J) := 'a' -- This is OK > > Now would you do: > > To_String (U) (J) := 'a' -- Garbage! That wasn't the aspect of Unbounded I was getting at. I agree ... garbage. What I meant was that Unbounded doesn't load New, dereferencing, deallocation etc onto the programmer, but hides the access details, and our indefinite type should do the same (the compiler can probably to a better job than the programmer anyway). I'm suggesting something more like the C++ reference, signalling (perhaps by adding a reserved word "indefinite") that fixed size allocation won't work; and implementation is more in line with a controlled type but with system-provided Initialise,Adjust,Finalize providing the required operations (no need for the programmer to provide them). A : String := "hello" -- a definite string P : access String := new String'("hello"); Q : indefinite String := "hello"; ... begin for I in P'Range loop -- This is OK P(J) := 'a'; -- This is OK Q(J) := 'a'; -- also OK. But index out of range would raise Constraint Error ... Q := "hello_world"; -- deallocates, allocates with new bounds ... end; -- deallocate Q here. It follows that "indefinite" cannot also be "aliased" unless we want to implement smart pointers. For simplicity I'd suggest disallowing "aliased indefinite" on the grounds that "access" can (should) be used instead. Records (including tagged, class wide, discriminated) should work the same, but probably with shallow copy on assignment if they contain access types. If there is no re-allocation (no different size assignment) the compiler is free to substitute direct (stack) storage instead of heap allocation and implicit access types. So for example instead of A constant String := "done"; ... loop declare P : String := Get_Line; begin exit when P = A; end; end loop; A constant String := "done"; Q : indefinite String; ... loop Q := Get_Line; exit when Q = A; end loop; the implementation can be either an implicit declare block or an implicit access type. However, where Q has several reassignments within a block, and the compiler can't determine the size, an implicit access type must be used. (If it can, it can warn that "indefinite " is unnecessary). > What if the original object must be a class-wide object, task, protected > object, limited object etc? > > Ada's access types delegate all operations to the target object, except > assignment. This is the key property that the proposal in my view must > retain. Indefinite can also be applied to records (discriminated, class wide, etc) here the size is indeterminate and may vary on reassignment. Assignment would always be shallow copy (where the record contained access types). -- Brian ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-28 14:28 ` Brian Drummond @ 2020-07-28 14:59 ` Dmitry A. Kazakov 2020-07-29 15:33 ` Brian Drummond 0 siblings, 1 reply; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-07-28 14:59 UTC (permalink / raw) On 28/07/2020 16:28, Brian Drummond wrote: > On Mon, 27 Jul 2020 22:02:57 +0200, Dmitry A. Kazakov wrote: > >> On 27/07/2020 19:48, Brian Drummond wrote: >> >>> 2) can be implemented internally using pointers, but externally appears >>> to be a data object, just like Unbounded_String does, with similar >>> semantics. >> >> No, the point is that Unbounded_String is exactly opposite to what is >> required. In no case it should appear as an object of a different type! >> >> Compare access to string P with unbounded string U: >> >> for I in P'Range loop -- This is OK >> P(J) := 'a' -- This is OK >> >> Now would you do: >> >> To_String (U) (J) := 'a' -- Garbage! > > That wasn't the aspect of Unbounded I was getting at. I agree ... garbage. > > What I meant was that Unbounded doesn't load New, dereferencing, > deallocation etc onto the programmer, but hides the access details, and > our indefinite type should do the same (the compiler can probably to a > better job than the programmer anyway). > > I'm suggesting something more like the C++ reference, signalling (perhaps > by adding a reserved word "indefinite") that fixed size allocation won't > work; Equivalent of C++ reference in Ada is renaming. and implementation is more in line with a controlled type but with > system-provided Initialise,Adjust,Finalize providing the required > operations (no need for the programmer to provide them). > > A : String := "hello" -- a definite string > P : access String := new String'("hello"); > Q : indefinite String := "hello"; I think the keyword is misleading. Maybe this: Q : new String := "hello"; And I don't like initialization. It was a mistake to have limited return. The syntax must stress that all initialization is strictly in-place. No copies involved because the pool is fixed. > ... > begin > for I in P'Range loop -- This is OK > P(J) := 'a'; -- This is OK > Q(J) := 'a'; -- also OK. But index out of range would raise > Constraint Error > ... > Q := "hello_world"; -- deallocates, allocates with new bounds > ... > end; -- deallocate Q here. The rule could be "same pool" as of the container. In the case of a block, the pool is the stack. In the case of a record member, the pool is the pool of where the record itself is allocated. So that you could allocate all object in the same pool. > It follows that "indefinite" cannot also be "aliased" unless we want to > implement smart pointers. For simplicity I'd suggest disallowing "aliased > indefinite" on the grounds that "access" can (should) be used instead. It makes sense, but there are use cases for having it aliased: X : indefinite T; Y : indefinite S (X'Access); -- Access discriminant > Records (including tagged, class wide, discriminated) should work the > same, but probably with shallow copy on assignment if they contain access > types. > > If there is no re-allocation (no different size assignment) the compiler > is free to substitute direct (stack) storage instead of heap allocation > and implicit access types. So for example instead of > > A constant String := "done"; > ... > loop > declare > P : String := Get_Line; > begin > exit when P = A; > end; > end loop; > > A constant String := "done"; > Q : indefinite String; > ... > loop > Q := Get_Line; > exit when Q = A; > end loop; I am not comfortable with the semantics of this and with possible implications too. I would keep it simple. > the implementation can be either an implicit declare block or an implicit > access type. However, where Q has several reassignments within a block, > and the compiler can't determine the size, an implicit access type must > be used. (If it can, it can warn that "indefinite " is unnecessary). > >> What if the original object must be a class-wide object, task, protected >> object, limited object etc? >> >> Ada's access types delegate all operations to the target object, except >> assignment. This is the key property that the proposal in my view must >> retain. > > Indefinite can also be applied to records (discriminated, class wide, etc) > here the size is indeterminate and may vary on reassignment. Assignment > would always be shallow copy (where the record contained access types). That would be inconsistent. IMO, it should be a deep copy, provided such a component would not make the type limited, of which I am not sure. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-28 14:59 ` Dmitry A. Kazakov @ 2020-07-29 15:33 ` Brian Drummond 2020-07-29 16:20 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Brian Drummond @ 2020-07-29 15:33 UTC (permalink / raw) On Tue, 28 Jul 2020 16:59:09 +0200, Dmitry A. Kazakov wrote: > On 28/07/2020 16:28, Brian Drummond wrote: >> On Mon, 27 Jul 2020 22:02:57 +0200, Dmitry A. Kazakov wrote: >> >>> On 27/07/2020 19:48, Brian Drummond wrote: >>> >>>> 2) can be implemented internally using pointers, but externally >>>> appears to be a data object, just like Unbounded_String does, with >>>> similar semantics. >>> >>> No, the point is that Unbounded_String is exactly opposite to what is >>> required. In no case it should appear as an object of a different >>> type! >>> >>> Compare access to string P with unbounded string U: >>> >>> for I in P'Range loop -- This is OK >>> P(J) := 'a' -- This is OK >>> >>> Now would you do: >>> >>> To_String (U) (J) := 'a' -- Garbage! >> >> That wasn't the aspect of Unbounded I was getting at. I agree ... >> garbage. >> >> What I meant was that Unbounded doesn't load New, dereferencing, >> deallocation etc onto the programmer, but hides the access details, and >> our indefinite type should do the same (the compiler can probably to a >> better job than the programmer anyway). >> >> I'm suggesting something more like the C++ reference, signalling >> (perhaps by adding a reserved word "indefinite") that fixed size >> allocation won't work; > > Equivalent of C++ reference in Ada is renaming. OK. Not quite sure how complete the correspondence between reference and renaming is, but I can see similarities. >> Q : indefinite String := "hello"; > > I think the keyword is misleading. Maybe this: > > Q : new String := "hello"; Not sure I like. The reader has to make the mental jump from seeing "new" to thinking of this as an indefinite type. There may be a better keyword, open to suggestions, but let's stick to indefinite for now. > And I don't like initialization. Initialisation is unnecessary for indefinite String. It was only used in that example for similarity with previous strings A,P. >> begin >> for I in P'Range loop -- This is OK >> P(J) := 'a'; -- This is OK Q(J) := 'a'; -- also OK. But index >> out of range would raise >> Constraint Error ... >> Q := "hello_world"; -- deallocates, allocates with new bounds >> ... >> end; -- deallocate Q here. > > The rule could be "same pool" as of the container. In the case of a > block, the pool is the stack. In the case of a record member, the pool > is the pool of where the record itself is allocated. So that you could > allocate all object in the same pool. Looks like a good rule. Saves the compiler having to plant deallocations if the whole pool is to be de-allocated. >> It follows that "indefinite" cannot also be "aliased" unless we want to >> implement smart pointers. For simplicity I'd suggest disallowing >> "aliased indefinite" on the grounds that "access" can (should) be used >> instead. > > It makes sense, but there are use cases for having it aliased: > > X : indefinite T; X : aliased indefinite T; > Y : indefinite S (X'Access); -- Access discriminant As elsewhere, "aliased" indicates both to compiler and reader, that the rules are about to get more complicated. Specifically, if X is re- allocated thanks to a different size assignment, all Y must be updated. >> A constant String := "done"; >> Q : indefinite String; >> ... >> loop >> Q := Get_Line; >> exit when Q = A; >> end loop; > > I am not comfortable with the semantics of this and with possible > implications too. I would keep it simple. Interesting. Can you pin down some of that discomfort? It looks simple to me : "indefinite" indicates the size can vary (and the compiler knows whether it used the heap or stack), and in the absence of "aliased" we know there are no copies of the pointer (if heap). But of course my mind isn't wrapped round all the corner cases, and if you are uncomfortable, I'm probably missing a very good reason. >> Indefinite can also be applied to records (discriminated, class wide, >> etc) >> here the size is indeterminate and may vary on reassignment. Assignment >> would always be shallow copy (where the record contained access types). > > That would be inconsistent. IMO, it should be a deep copy, provided such > a component would not make the type limited, of which I am not sure. Honest question : Inconsistent with what? I suggested shallow copy just for simplicity, and for no (ahh) deeper reason. But again, I'm probably missing something. Thank you for your thoughts. I don't know if this is worth developing into an AI. -- Brian ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-29 15:33 ` Brian Drummond @ 2020-07-29 16:20 ` Dmitry A. Kazakov 2020-07-30 13:37 ` Stephen Davies ` (2 more replies) 0 siblings, 3 replies; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-07-29 16:20 UTC (permalink / raw) On 29/07/2020 17:33, Brian Drummond wrote: > On Tue, 28 Jul 2020 16:59:09 +0200, Dmitry A. Kazakov wrote: >>> A constant String := "done"; >>> Q : indefinite String; >>> ... >>> loop >>> Q := Get_Line; >>> exit when Q = A; >>> end loop; >> >> I am not comfortable with the semantics of this and with possible >> implications too. I would keep it simple. > > Interesting. Can you pin down some of that discomfort? It looks simple to > me : > > "indefinite" indicates the size can vary (and the compiler knows whether > it used the heap or stack), and in the absence of "aliased" we know there > are no copies of the pointer (if heap). I don't like compiler relocating objects. If the pool is a stack (or heap organized as a stack) it might be unable to do this. In general, there are two close but not equivalent objectives one is handling indefinite components of records another is a transparent holder object integrated into the language (without generic mess). Your use case is about the latter. My is rather the former. I doubt it is possible to unite both objectives in a single AI. >> That would be inconsistent. IMO, it should be a deep copy, provided such >> a component would not make the type limited, of which I am not sure. > > Honest question : Inconsistent with what? > I suggested shallow copy just for simplicity, and for no (ahh) deeper > reason. But again, I'm probably missing something. If you make a shallow copy of type Node_Type is record Item : new Element_Type; Prev : Node_Ptr_Type; Next : Node_Ptr_Type; end record; you create a dangling pointer should the original node disappear. A deep copy would create a new target for new Item. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-29 16:20 ` Dmitry A. Kazakov @ 2020-07-30 13:37 ` Stephen Davies 2020-07-30 14:23 ` Dmitry A. Kazakov 2020-07-30 17:04 ` Brian Drummond 2020-08-10 0:31 ` Randy Brukardt 2 siblings, 1 reply; 47+ messages in thread From: Stephen Davies @ 2020-07-30 13:37 UTC (permalink / raw) On Wednesday, 29 July 2020 at 17:20:24 UTC+1, Dmitry A. Kazakov wrote: > If you make a shallow copy of > type Node_Type is record > Item : new Element_Type; > Prev : Node_Ptr_Type; > Next : Node_Ptr_Type; > end record; > you create a dangling pointer should the original node disappear. A deep > copy would create a new target for new Item. I see my proposal is being debated again. And Dmitry is arguing my case far better that I could, so I'll probably stay quiet. (though maybe I should try to plant the idea of "Trim_Image" and "Trim_Width" into Dmitry's head ;-)) ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-30 13:37 ` Stephen Davies @ 2020-07-30 14:23 ` Dmitry A. Kazakov 0 siblings, 0 replies; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-07-30 14:23 UTC (permalink / raw) On 30/07/2020 15:37, Stephen Davies wrote: > (though maybe I should try to plant the idea of "Trim_Image" and "Trim_Width" into Dmitry's head ;-)) My head is already filled with X'Image instead of T'Image(X), as stream attributes already are, with optional parameters for width, alignment, base, precision, sign, encoding (e.g. for using UTF-8 superscripts in the floating-point exponent). -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-29 16:20 ` Dmitry A. Kazakov 2020-07-30 13:37 ` Stephen Davies @ 2020-07-30 17:04 ` Brian Drummond 2020-07-30 18:28 ` Dmitry A. Kazakov 2020-08-10 0:31 ` Randy Brukardt 2 siblings, 1 reply; 47+ messages in thread From: Brian Drummond @ 2020-07-30 17:04 UTC (permalink / raw) On Wed, 29 Jul 2020 18:20:24 +0200, Dmitry A. Kazakov wrote: > On 29/07/2020 17:33, Brian Drummond wrote: >> On Tue, 28 Jul 2020 16:59:09 +0200, Dmitry A. Kazakov wrote: > >>>> A constant String := "done"; >>>> Q : indefinite String; >>>> ... >>>> loop >>>> Q := Get_Line; exit when Q = A; >>>> end loop; >>> >>> I am not comfortable with the semantics of this and with possible >>> implications too. I would keep it simple. >> >> Interesting. Can you pin down some of that discomfort? It looks simple >> to me : >> >> "indefinite" indicates the size can vary (and the compiler knows >> whether it used the heap or stack), and in the absence of "aliased" we >> know there are no copies of the pointer (if heap). > > I don't like compiler relocating objects. If the pool is a stack (or > heap organized as a stack) it might be unable to do this. Ah OK, I see it. The compiler should be able to determine if (as in the loop above) the use of Q (the indefinite type) is equivalent to a Declare block (i.e. can be on the stack; new stack frame in each iteration; no relocation ever required) or not. If it cannot prove, it should assume not. In which case allocation is NOT on stack or heap so organised, and it knows before generating code that heap allocation and possible relocation is required. In this latter case the situation is no worse than if the programmers explicitly used an access type and handled the allocations and relocations and frees themselves, but without requiring that level of detail. > In general, there are two close but not equivalent objectives one is > handling indefinite components of records another is a transparent > holder object integrated into the language (without generic mess). > > Your use case is about the latter. My is rather the former. If a record with even one indefinite component is an indefinite record, and therefore embedded in a transparent holder (I like that term), aren't they equivalent? >> Honest question : Inconsistent with what? >> I suggested shallow copy just for simplicity, and for no (ahh) deeper >> reason. But again, I'm probably missing something. > > If you make a shallow copy of > > type Node_Type is record > Item : new Element_Type; > Prev : Node_Ptr_Type; Next : Node_Ptr_Type; > end record; > > you create a dangling pointer should the original node disappear. A deep > copy would create a new target for new Item. You are using "new" to signify Item is indefinite, I think? But the problem is that Prev,Next are copies of the original Prev,Next pointers, so if the original Node_Type is then freed, they are dangling? Thanks, this one I'll have to think about. -- Brian ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-30 17:04 ` Brian Drummond @ 2020-07-30 18:28 ` Dmitry A. Kazakov 2020-08-10 0:39 ` Randy Brukardt 0 siblings, 1 reply; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-07-30 18:28 UTC (permalink / raw) On 30/07/2020 19:04, Brian Drummond wrote: > On Wed, 29 Jul 2020 18:20:24 +0200, Dmitry A. Kazakov wrote: > >> On 29/07/2020 17:33, Brian Drummond wrote: >>> On Tue, 28 Jul 2020 16:59:09 +0200, Dmitry A. Kazakov wrote: >> >>>>> A constant String := "done"; >>>>> Q : indefinite String; >>>>> ... >>>>> loop >>>>> Q := Get_Line; exit when Q = A; >>>>> end loop; >>>> >>>> I am not comfortable with the semantics of this and with possible >>>> implications too. I would keep it simple. >>> >>> Interesting. Can you pin down some of that discomfort? It looks simple >>> to me : >>> >>> "indefinite" indicates the size can vary (and the compiler knows >>> whether it used the heap or stack), and in the absence of "aliased" we >>> know there are no copies of the pointer (if heap). >> >> I don't like compiler relocating objects. If the pool is a stack (or >> heap organized as a stack) it might be unable to do this. > > Ah OK, I see it. > > The compiler should be able to determine if (as in the loop above) the > use of Q (the indefinite type) is equivalent to a Declare block (i.e. can > be on the stack; new stack frame in each iteration; no relocation ever > required) or not. I don't want the compiler deciding where Q is allocated, especially because this could break things: 1. Large object moved to the stack 2. Lock-free code starting using heap lock when moved from the stack. The mechanism should be transparent. I do not like Unbounded_String for many reasons. Fiddling with the heap is one of them. I do not know which heuristic it uses to reduce reallocation and how much extra memory it takes under which circumstances. >> In general, there are two close but not equivalent objectives one is >> handling indefinite components of records another is a transparent >> holder object integrated into the language (without generic mess). >> >> Your use case is about the latter. My is rather the former. > > If a record with even one indefinite component is an indefinite record, > and therefore embedded in a transparent holder (I like that term), aren't > they equivalent? I don't understand this question. >>> Honest question : Inconsistent with what? >>> I suggested shallow copy just for simplicity, and for no (ahh) deeper >>> reason. But again, I'm probably missing something. >> >> If you make a shallow copy of >> >> type Node_Type is record >> Item : new Element_Type; >> Prev : Node_Ptr_Type; Next : Node_Ptr_Type; >> end record; >> >> you create a dangling pointer should the original node disappear. A deep >> copy would create a new target for new Item. > > You are using "new" to signify Item is indefinite, I think? > > But the problem is that Prev,Next are copies of the original Prev,Next > pointers, so if the original Node_Type is then freed, they are dangling? They are supposed to be handled by the doubly-linked list infrastructure, e.g. Prev and Next pointing to the node itself is a precondition for freeing the node. The problem is with the node contents. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-30 18:28 ` Dmitry A. Kazakov @ 2020-08-10 0:39 ` Randy Brukardt 2020-08-10 8:57 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Randy Brukardt @ 2020-08-10 0:39 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:rfv3gf$1bbo$1@gioia.aioe.org... > On 30/07/2020 19:04, Brian Drummond wrote: >> On Wed, 29 Jul 2020 18:20:24 +0200, Dmitry A. Kazakov wrote: >> >>> On 29/07/2020 17:33, Brian Drummond wrote: >>>> On Tue, 28 Jul 2020 16:59:09 +0200, Dmitry A. Kazakov wrote: >>> >>>>>> A constant String := "done"; >>>>>> Q : indefinite String; >>>>>> ... >>>>>> loop >>>>>> Q := Get_Line; exit when Q = A; >>>>>> end loop; >>>>> >>>>> I am not comfortable with the semantics of this and with possible >>>>> implications too. I would keep it simple. >>>> >>>> Interesting. Can you pin down some of that discomfort? It looks simple >>>> to me : >>>> >>>> "indefinite" indicates the size can vary (and the compiler knows >>>> whether it used the heap or stack), and in the absence of "aliased" we >>>> know there are no copies of the pointer (if heap). >>> >>> I don't like compiler relocating objects. If the pool is a stack (or >>> heap organized as a stack) it might be unable to do this. >> >> Ah OK, I see it. >> >> The compiler should be able to determine if (as in the loop above) the >> use of Q (the indefinite type) is equivalent to a Declare block (i.e. can >> be on the stack; new stack frame in each iteration; no relocation ever >> required) or not. > > I don't want the compiler deciding where Q is allocated, especially > because this could break things: > > 1. Large object moved to the stack The compiler is buggy IMHO if this breaks something. Any compiler has to be able to deal with objects that exceed the maximum stack frame, and move those to somewhere that they will fit (or reject completely). Yes, most compilers are buggy this way (including mine in a few cases). So what? > 2. Lock-free code starting using heap lock when moved from the stack. Expecting a compiler not to use the heap is silly in any case (outside of the No_Heap restriction - use that in Janus/Ada and the compiler refuses to do anything outside of elementary types). The compiler is supposed to be making the programmer's life easier, not adding new hurdles. > The mechanism should be transparent. I do not like Unbounded_String for > many reasons. Fiddling with the heap is one of them. I do not know which > heuristic it uses to reduce reallocation and how much extra memory it > takes under which circumstances. That's the idea of such mechanisms. If you really need control, you do not use these abstractions and instead write the stuff yourself explicitly using access types and the like. Otherwise, you use containers and unbounded strings, and they do what they do. There's no free lunch. But the need to be explicit should be very rare - the main problem is programmers with insufficient trust that a compiler will do the right thing. Randy. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-10 0:39 ` Randy Brukardt @ 2020-08-10 8:57 ` Dmitry A. Kazakov 2020-08-20 0:10 ` Randy Brukardt 0 siblings, 1 reply; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-10 8:57 UTC (permalink / raw) On 10/08/2020 02:39, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:rfv3gf$1bbo$1@gioia.aioe.org... >> I don't want the compiler deciding where Q is allocated, especially >> because this could break things: >> >> 1. Large object moved to the stack > > The compiler is buggy IMHO if this breaks something. Any compiler has to be > able to deal with objects that exceed the maximum stack frame, and move > those to somewhere that they will fit (or reject completely). > > Yes, most compilers are buggy this way (including mine in a few cases). So > what? > >> 2. Lock-free code starting using heap lock when moved from the stack. > > Expecting a compiler not to use the heap is silly in any case (outside of > the No_Heap restriction - use that in Janus/Ada and the compiler refuses to > do anything outside of elementary types). The compiler is supposed to be > making the programmer's life easier, not adding new hurdles. > >> The mechanism should be transparent. I do not like Unbounded_String for >> many reasons. Fiddling with the heap is one of them. I do not know which >> heuristic it uses to reduce reallocation and how much extra memory it >> takes under which circumstances. > > That's the idea of such mechanisms. If you really need control, you do not > use these abstractions and instead write the stuff yourself explicitly using > access types and the like. Right, that is my take on the proposal. If I am ready to compromise on #1 and #2, I can use an abstraction hiding pool access. Otherwise I want a language construct being more safe than raw access types. > Otherwise, you use containers and unbounded strings, and they do what they > do. No, from the abstraction point of view they do not. They indeed abstract the memory allocation aspect, but they do that at the cost of *everything* else. Unbounded_String is no string anymore. Container is neither array nor record type. Unbounded_String must be converted forth and back. For containers I must use ugly hacks like iterators to make them resemble arrays and records introducing whole levels of complexity to fight through every time the compiler or I miss something. In most cases I prefer to keep a clear array or record interface at the expense of manual memory management. > There's no free lunch. I think with a better type system there could be a whole banquet. (:-)) -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-10 8:57 ` Dmitry A. Kazakov @ 2020-08-20 0:10 ` Randy Brukardt 2020-08-20 17:49 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Randy Brukardt @ 2020-08-20 0:10 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:rgr267$1o1n$1@gioia.aioe.org... > No, from the abstraction point of view they do not. They indeed abstract > the memory allocation aspect, but they do that at the cost of *everything* > else. Unbounded_String is no string anymore. Container is neither array > nor record type. Unbounded_String must be converted forth and back. For > containers I must use ugly hacks like iterators to make them resemble > arrays and records introducing whole levels of complexity to fight through > every time the compiler or I miss something. > > In most cases I prefer to keep a clear array or record interface at the > expense of manual memory management. > >> There's no free lunch. > > I think with a better type system there could be a whole banquet. (:-)) Maybe. but IMHO a better type system would get rid of arrays and strings altogether and only have containers/records of various sorts. The complexity of having both solving the same problems (not very well in the case of arrays/strings) doesn't buy much. I suspect that a user-defined "." as you've proposed elsewhere would eliminate most of the rest of the problems (and unify everything even further). Randy. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-20 0:10 ` Randy Brukardt @ 2020-08-20 17:49 ` Dmitry A. Kazakov 2020-08-20 20:19 ` Dennis Lee Bieber 2020-08-20 23:30 ` Randy Brukardt 0 siblings, 2 replies; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-20 17:49 UTC (permalink / raw) On 20/08/2020 02:10, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:rgr267$1o1n$1@gioia.aioe.org... >> No, from the abstraction point of view they do not. They indeed abstract >> the memory allocation aspect, but they do that at the cost of *everything* >> else. Unbounded_String is no string anymore. Container is neither array >> nor record type. Unbounded_String must be converted forth and back. For >> containers I must use ugly hacks like iterators to make them resemble >> arrays and records introducing whole levels of complexity to fight through >> every time the compiler or I miss something. >> >> In most cases I prefer to keep a clear array or record interface at the >> expense of manual memory management. >> >>> There's no free lunch. >> >> I think with a better type system there could be a whole banquet. (:-)) > > Maybe. but IMHO a better type system would get rid of arrays and strings > altogether and only have containers/records of various sorts. The complexity > of having both solving the same problems (not very well in the case of > arrays/strings) doesn't buy much. I suspect that a user-defined "." as > you've proposed elsewhere would eliminate most of the rest of the problems > (and unify everything even further). But records and arrays are needed as building blocks of containers. How would you get rid of them? -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-20 17:49 ` Dmitry A. Kazakov @ 2020-08-20 20:19 ` Dennis Lee Bieber 2020-08-20 23:33 ` Randy Brukardt 2020-08-20 23:30 ` Randy Brukardt 1 sibling, 1 reply; 47+ messages in thread From: Dennis Lee Bieber @ 2020-08-20 20:19 UTC (permalink / raw) On Thu, 20 Aug 2020 19:49:44 +0200, "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> declaimed the following: > >But records and arrays are needed as building blocks of containers. How >would you get rid of them? And likely needed for any embedded or low-level work where they are mapped to things like (GP) I/O ports or such... -- Wulfraed Dennis Lee Bieber AF6VN wlfraed@ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-20 20:19 ` Dennis Lee Bieber @ 2020-08-20 23:33 ` Randy Brukardt 2020-08-21 6:45 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Randy Brukardt @ 2020-08-20 23:33 UTC (permalink / raw) "Dennis Lee Bieber" <wlfraed@ix.netcom.com> wrote in message news:mkmtjflufgmatkk3hp25nvk2hoogun1fis@4ax.com... > On Thu, 20 Aug 2020 19:49:44 +0200, "Dmitry A. Kazakov" > <mailbox@dmitry-kazakov.de> declaimed the following: > >> >>But records and arrays are needed as building blocks of containers. How >>would you get rid of them? > > And likely needed for any embedded or low-level work where they are > mapped to things like (GP) I/O ports or such... Yes, a fixed vector container would be needed for interfacing (probably wouldn't use it for anything else). But there's no reason that can't be provided as a container, so long as representation guarentees (esp. Component_Size) are included. Remember that containers (in Ada 202x) have indexing, aggregates, and all of the useful basic operations. The stuff that's missing is the same stuff that adds a vast amount of complexity to Ada (and possibilities for bugs) - hardly anyone would miss it. Randy. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-20 23:33 ` Randy Brukardt @ 2020-08-21 6:45 ` Dmitry A. Kazakov 2020-08-23 4:52 ` Randy Brukardt 0 siblings, 1 reply; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-21 6:45 UTC (permalink / raw) On 21/08/2020 01:33, Randy Brukardt wrote: > "Dennis Lee Bieber" <wlfraed@ix.netcom.com> wrote in message > news:mkmtjflufgmatkk3hp25nvk2hoogun1fis@4ax.com... >> On Thu, 20 Aug 2020 19:49:44 +0200, "Dmitry A. Kazakov" >> <mailbox@dmitry-kazakov.de> declaimed the following: >> >>> >>> But records and arrays are needed as building blocks of containers. How >>> would you get rid of them? >> >> And likely needed for any embedded or low-level work where they are >> mapped to things like (GP) I/O ports or such... > > Yes, a fixed vector container would be needed for interfacing (probably > wouldn't use it for anything else). But there's no reason that can't be > provided as a container, so long as representation guarentees (esp. > Component_Size) are included. Remember that containers (in Ada 202x) have > indexing, aggregates, and all of the useful basic operations. The stuff > that's missing is the same stuff that adds a vast amount of complexity to > Ada (and possibilities for bugs) - hardly anyone would miss it. Really? I would miss array conversions, slices, equivalence of same length index ranges, constrained array subtypes etc. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-21 6:45 ` Dmitry A. Kazakov @ 2020-08-23 4:52 ` Randy Brukardt 2020-08-23 12:28 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Randy Brukardt @ 2020-08-23 4:52 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:rhnqip$bga$1@gioia.aioe.org... > On 21/08/2020 01:33, Randy Brukardt wrote: >> "Dennis Lee Bieber" <wlfraed@ix.netcom.com> wrote in message >> news:mkmtjflufgmatkk3hp25nvk2hoogun1fis@4ax.com... >>> On Thu, 20 Aug 2020 19:49:44 +0200, "Dmitry A. Kazakov" >>> <mailbox@dmitry-kazakov.de> declaimed the following: >>> >>>> >>>> But records and arrays are needed as building blocks of containers. How >>>> would you get rid of them? >>> >>> And likely needed for any embedded or low-level work where they are >>> mapped to things like (GP) I/O ports or such... >> >> Yes, a fixed vector container would be needed for interfacing (probably >> wouldn't use it for anything else). But there's no reason that can't be >> provided as a container, so long as representation guarentees (esp. >> Component_Size) are included. Remember that containers (in Ada 202x) have >> indexing, aggregates, and all of the useful basic operations. The stuff >> that's missing is the same stuff that adds a vast amount of complexity to >> Ada (and possibilities for bugs) - hardly anyone would miss it. > > Really? I would miss array conversions, slices, equivalence of same length > index ranges, constrained array subtypes etc. Those things are mostly useful for making work for programmers. Note that I'm assuming that Strings are a completely separate abstraction - a UTF-8 string is not an array and shouldn't be treated as one. (Indexing of individual characters being very expensive.) Fixed constrained arrays would be available for interfacing (they're not really useful for much else). Note that a bounded vector is allocated statically, so there's no extra cost to using it (unlike an unbounded vector or string). Randy. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-23 4:52 ` Randy Brukardt @ 2020-08-23 12:28 ` Dmitry A. Kazakov 0 siblings, 0 replies; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-23 12:28 UTC (permalink / raw) On 23/08/2020 06:52, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:rhnqip$bga$1@gioia.aioe.org... >> On 21/08/2020 01:33, Randy Brukardt wrote: >>> "Dennis Lee Bieber" <wlfraed@ix.netcom.com> wrote in message >>> news:mkmtjflufgmatkk3hp25nvk2hoogun1fis@4ax.com... >>>> On Thu, 20 Aug 2020 19:49:44 +0200, "Dmitry A. Kazakov" >>>> <mailbox@dmitry-kazakov.de> declaimed the following: >>>> >>>>> >>>>> But records and arrays are needed as building blocks of containers. How >>>>> would you get rid of them? >>>> >>>> And likely needed for any embedded or low-level work where they are >>>> mapped to things like (GP) I/O ports or such... >>> >>> Yes, a fixed vector container would be needed for interfacing (probably >>> wouldn't use it for anything else). But there's no reason that can't be >>> provided as a container, so long as representation guarentees (esp. >>> Component_Size) are included. Remember that containers (in Ada 202x) have >>> indexing, aggregates, and all of the useful basic operations. The stuff >>> that's missing is the same stuff that adds a vast amount of complexity to >>> Ada (and possibilities for bugs) - hardly anyone would miss it. >> >> Really? I would miss array conversions, slices, equivalence of same length >> index ranges, constrained array subtypes etc. > > Those things are mostly useful for making work for programmers. Note that > I'm assuming that Strings are a completely separate abstraction - a UTF-8 > string is not an array and shouldn't be treated as one. (Indexing of > individual characters being very expensive.) That is an implementation detail of a given representation. String of any encoding is an array of characters per definition of string. > Fixed constrained arrays would > be available for interfacing (they're not really useful for much else). I would say it is exactly the opposite. Unconstrained arrays are not very useful because the operation of changing array length is very rare and very expensive (applying your logic). In most cases a fixed array does the work. Note that among the remaining cases, the majority are ones where bounds are still fixed but Ada does not support proper initialization or proper aggregation of. The remainder of that is very small. That small part could, again, be covered by bounded arrays, as you suggested in another post, if Ada supported propagation of constraints in a more effective way than literal discriminants. Presently bounded arrays are practically useless because the place where you must specify the bounds is never the place where you can determine them. > Note > that a bounded vector is allocated statically, so there's no extra cost to > using it (unlike an unbounded vector or string). Maybe, but since there will be arrays anyway, why should I suffer dealing with messy generics? -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-20 17:49 ` Dmitry A. Kazakov 2020-08-20 20:19 ` Dennis Lee Bieber @ 2020-08-20 23:30 ` Randy Brukardt 2020-08-21 6:46 ` Dmitry A. Kazakov 1 sibling, 1 reply; 47+ messages in thread From: Randy Brukardt @ 2020-08-20 23:30 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:rhmd3m$1eql$2@gioia.aioe.org... > On 20/08/2020 02:10, Randy Brukardt wrote: >> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >> news:rgr267$1o1n$1@gioia.aioe.org... >>> No, from the abstraction point of view they do not. They indeed abstract >>> the memory allocation aspect, but they do that at the cost of >>> *everything* >>> else. Unbounded_String is no string anymore. Container is neither array >>> nor record type. Unbounded_String must be converted forth and back. For >>> containers I must use ugly hacks like iterators to make them resemble >>> arrays and records introducing whole levels of complexity to fight >>> through >>> every time the compiler or I miss something. >>> >>> In most cases I prefer to keep a clear array or record interface at the >>> expense of manual memory management. >>> >>>> There's no free lunch. >>> >>> I think with a better type system there could be a whole banquet. (:-)) >> >> Maybe. but IMHO a better type system would get rid of arrays and strings >> altogether and only have containers/records of various sorts. The >> complexity >> of having both solving the same problems (not very well in the case of >> arrays/strings) doesn't buy much. I suspect that a user-defined "." as >> you've proposed elsewhere would eliminate most of the rest of the >> problems >> (and unify everything even further). > > But records and arrays are needed as building blocks of containers. How > would you get rid of them? There's no reason that a compiler couldn't "build-in" a simple bounded vector container as the basic building block. We already do that for things like Ada.Exceptions, Unchecked_Conversion, and Unchecked_Deallocation, so it's no harder to do that for a vector. (Probably would need some sort of fixed vector for interfacing purposes as well, to deal with other language's and/or system's memory layout.) One could do something similar for records, although I would probably leave them as in Ada and just allow user-definition of "." (via a getter/setter pair). Randy. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-20 23:30 ` Randy Brukardt @ 2020-08-21 6:46 ` Dmitry A. Kazakov 2020-08-23 4:48 ` Randy Brukardt 0 siblings, 1 reply; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-21 6:46 UTC (permalink / raw) On 21/08/2020 01:30, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:rhmd3m$1eql$2@gioia.aioe.org... >> On 20/08/2020 02:10, Randy Brukardt wrote: >>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >>> news:rgr267$1o1n$1@gioia.aioe.org... >>>> No, from the abstraction point of view they do not. They indeed abstract >>>> the memory allocation aspect, but they do that at the cost of >>>> *everything* >>>> else. Unbounded_String is no string anymore. Container is neither array >>>> nor record type. Unbounded_String must be converted forth and back. For >>>> containers I must use ugly hacks like iterators to make them resemble >>>> arrays and records introducing whole levels of complexity to fight >>>> through >>>> every time the compiler or I miss something. >>>> >>>> In most cases I prefer to keep a clear array or record interface at the >>>> expense of manual memory management. >>>> >>>>> There's no free lunch. >>>> >>>> I think with a better type system there could be a whole banquet. (:-)) >>> >>> Maybe. but IMHO a better type system would get rid of arrays and strings >>> altogether and only have containers/records of various sorts. The >>> complexity >>> of having both solving the same problems (not very well in the case of >>> arrays/strings) doesn't buy much. I suspect that a user-defined "." as >>> you've proposed elsewhere would eliminate most of the rest of the >>> problems >>> (and unify everything even further). >> >> But records and arrays are needed as building blocks of containers. How >> would you get rid of them? > > There's no reason that a compiler couldn't "build-in" a simple bounded > vector container as the basic building block. That simply replaces the word "array" with four words "simple bounded vector container." The construct is still there and it is still built-in. The syntax and usability are drastically worse, though. > One could do something similar for records, although I would probably leave > them as in Ada and just allow user-definition of "." (via a getter/setter > pair). Ditto. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-21 6:46 ` Dmitry A. Kazakov @ 2020-08-23 4:48 ` Randy Brukardt 2020-08-23 12:29 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Randy Brukardt @ 2020-08-23 4:48 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:rhnqjf$bga$2@gioia.aioe.org... > On 21/08/2020 01:30, Randy Brukardt wrote: ... >> There's no reason that a compiler couldn't "build-in" a simple bounded >> vector container as the basic building block. > > That simply replaces the word "array" with four words "simple bounded > vector container." The construct is still there and it is still built-in. > The syntax and usability are drastically worse, though. ??? The syntax of use is the same (as it is in Ada 2012). Declaration would be an instance, about the same length and wordiness as an array declaration. Yes, junk like slices, settable/retrievable bounds, and built-in operations that are rarely used would be gone, but so would the rather substantial overhead that those things entail. There'd be a lot more flexibility in implementation, which would allow better implementations. Virtually every array that I write has a fixed size (capacity really) and a usage high-water mark (a "length"). Having that generated automatically would be usually better than having to reinvent it literally every time I program something. (And as you've noticed repeatedly, Ada's type abstraction isn't good enough to make it practical to build anything reusable to do that.) >> One could do something similar for records, although I would probably >> leave >> them as in Ada and just allow user-definition of "." (via a getter/setter >> pair). > > Ditto. ??? The basic idea would be to eliminate the huge number of special cases that exist in Ada resolution and essentially make *everything* a subprogram call at it's heart. Ada did that for enumeration literals and that model makes sense for pretty much everything: object usage, indexing, selection, etc. It would be much easier to prove that resolution is doing the right thing (I don't think that would be practically possible for Ada). Randy. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-23 4:48 ` Randy Brukardt @ 2020-08-23 12:29 ` Dmitry A. Kazakov 0 siblings, 0 replies; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-23 12:29 UTC (permalink / raw) On 23/08/2020 06:48, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:rhnqjf$bga$2@gioia.aioe.org... >> On 21/08/2020 01:30, Randy Brukardt wrote: > ... >>> There's no reason that a compiler couldn't "build-in" a simple bounded >>> vector container as the basic building block. >> >> That simply replaces the word "array" with four words "simple bounded >> vector container." The construct is still there and it is still built-in. >> The syntax and usability are drastically worse, though. > > ??? The syntax of use is the same (as it is in Ada 2012). Declaration would > be an instance, That alone disqualifies it in my eyes. > about the same length and wordiness as an array declaration. Plus a dozen of tagged helper types... > Yes, junk like slices, settable/retrievable bounds, and built-in operations > that are rarely used would be gone, but so would the rather substantial > overhead that those things entail. There'd be a lot more flexibility in > implementation, which would allow better implementations. These is a vital part of array interface to me. Moreover I want lost of other junk there, like ranges being proper types, like multidimensional slices/subarrays, indicator sets (to specify array's diagonal) etc. > Virtually every array that I write has a fixed size (capacity really) and a > usage high-water mark (a "length"). Having that generated automatically > would be usually better than having to reinvent it literally every time I > program something. (And as you've noticed repeatedly, Ada's type abstraction > isn't good enough to make it practical to build anything reusable to do > that.) I agree with that, but disagree with the solution. In my view arrays must be 1) generalized, 2) abstracted to support user-defined implementations. The challenge is to have a type system where one could design a 3-band matrix type usable where a dense matrix type is expected. >>> One could do something similar for records, although I would probably >>> leave >>> them as in Ada and just allow user-definition of "." (via a getter/setter >>> pair). >> >> Ditto. > > ??? > > The basic idea would be to eliminate the huge number of special cases that > exist in Ada resolution and essentially make *everything* a subprogram call > at it's heart. Yes, I agree everything must have a corresponding primitive operation. But there are cases when such operations must be static like "." of a record types or implemented per delegation to a generalized implementation like integer or string literals. > Ada did that for enumeration literals and that model makes > sense for pretty much everything: object usage, indexing, selection, etc. It > would be much easier to prove that resolution is doing the right thing (I > don't think that would be practically possible for Ada). I think that not only Ada's, but even C++'s type system, could be expressed by means of a more powerful one. After all it is possible to write a compiler for both... -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-29 16:20 ` Dmitry A. Kazakov 2020-07-30 13:37 ` Stephen Davies 2020-07-30 17:04 ` Brian Drummond @ 2020-08-10 0:31 ` Randy Brukardt 2020-08-10 8:58 ` Dmitry A. Kazakov 2 siblings, 1 reply; 47+ messages in thread From: Randy Brukardt @ 2020-08-10 0:31 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:rfs7k4$c83$1@gioia.aioe.org... > On 29/07/2020 17:33, Brian Drummond wrote: >> On Tue, 28 Jul 2020 16:59:09 +0200, Dmitry A. Kazakov wrote: > >>>> A constant String := "done"; >>>> Q : indefinite String; >>>> ... >>>> loop >>>> Q := Get_Line; >>>> exit when Q = A; >>>> end loop; >>> >>> I am not comfortable with the semantics of this and with possible >>> implications too. I would keep it simple. >> >> Interesting. Can you pin down some of that discomfort? It looks simple to >> me : >> >> "indefinite" indicates the size can vary (and the compiler knows whether >> it used the heap or stack), and in the absence of "aliased" we know there >> are no copies of the pointer (if heap). > > I don't like compiler relocating objects. If the pool is a stack (or heap > organized as a stack) it might be unable to do this. This is not that hard to deal with. Janus/Ada handles discriminant-dependent components of mutable objects this way: they are allocated on the stack, but if they have to be reallocated they move to the heap. I note that the original idea already exists for discriminant-dependent components -- that's a bit more painful to use but hardly difficult. The main issue is that most compilers fail to support these components properly, using some sort of max-size implementation unconditionally rather than switching to a pool-based implementation when the max size is too large. I've never understood why Ada compilers were allowed to make such a limitation (it becomes a major limitation when working on non-embedded programs), while similar limitations on case statements and aggregates are not allowed. Randy. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-10 0:31 ` Randy Brukardt @ 2020-08-10 8:58 ` Dmitry A. Kazakov 2020-08-20 0:13 ` Randy Brukardt 0 siblings, 1 reply; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-10 8:58 UTC (permalink / raw) On 10/08/2020 02:31, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:rfs7k4$c83$1@gioia.aioe.org... >> On 29/07/2020 17:33, Brian Drummond wrote: >>> On Tue, 28 Jul 2020 16:59:09 +0200, Dmitry A. Kazakov wrote: >> >>>>> A constant String := "done"; >>>>> Q : indefinite String; >>>>> ... >>>>> loop >>>>> Q := Get_Line; >>>>> exit when Q = A; >>>>> end loop; >>>> >>>> I am not comfortable with the semantics of this and with possible >>>> implications too. I would keep it simple. >>> >>> Interesting. Can you pin down some of that discomfort? It looks simple to >>> me : >>> >>> "indefinite" indicates the size can vary (and the compiler knows whether >>> it used the heap or stack), and in the absence of "aliased" we know there >>> are no copies of the pointer (if heap). >> >> I don't like compiler relocating objects. If the pool is a stack (or heap >> organized as a stack) it might be unable to do this. > > This is not that hard to deal with. Janus/Ada handles discriminant-dependent > components of mutable objects this way: they are allocated on the stack, but > if they have to be reallocated they move to the heap. What you do if such an object is allocated via pool-specific access type? > I note that the original idea already exists for discriminant-dependent > components -- that's a bit more painful to use but hardly difficult. The > main issue is that most compilers fail to support these components properly, > using some sort of max-size implementation unconditionally rather than > switching to a pool-based implementation when the max size is too large. > I've never understood why Ada compilers were allowed to make such a > limitation (it becomes a major limitation when working on non-embedded > programs), while similar limitations on case statements and aggregates are > not allowed. I think a non-embedded target could use a task-local pool for the purpose. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-10 8:58 ` Dmitry A. Kazakov @ 2020-08-20 0:13 ` Randy Brukardt 2020-08-20 17:49 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Randy Brukardt @ 2020-08-20 0:13 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:rgr27b$1o1n$2@gioia.aioe.org... > On 10/08/2020 02:31, Randy Brukardt wrote: >> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >> news:rfs7k4$c83$1@gioia.aioe.org... >>> On 29/07/2020 17:33, Brian Drummond wrote: >>>> On Tue, 28 Jul 2020 16:59:09 +0200, Dmitry A. Kazakov wrote: >>> >>>>>> A constant String := "done"; >>>>>> Q : indefinite String; >>>>>> ... >>>>>> loop >>>>>> Q := Get_Line; >>>>>> exit when Q = A; >>>>>> end loop; >>>>> >>>>> I am not comfortable with the semantics of this and with possible >>>>> implications too. I would keep it simple. >>>> >>>> Interesting. Can you pin down some of that discomfort? It looks simple >>>> to >>>> me : >>>> >>>> "indefinite" indicates the size can vary (and the compiler knows >>>> whether >>>> it used the heap or stack), and in the absence of "aliased" we know >>>> there >>>> are no copies of the pointer (if heap). >>> >>> I don't like compiler relocating objects. If the pool is a stack (or >>> heap >>> organized as a stack) it might be unable to do this. >> >> This is not that hard to deal with. Janus/Ada handles >> discriminant-dependent >> components of mutable objects this way: they are allocated on the stack, >> but >> if they have to be reallocated they move to the heap. > > What you do if such an object is allocated via pool-specific access type? The whole object goes in that pool. The entire mechanism in Janus/Ada is built around pools - the stack is represented by a pool object as well as various other pools to support the mechanism. >> I note that the original idea already exists for discriminant-dependent >> components -- that's a bit more painful to use but hardly difficult. The >> main issue is that most compilers fail to support these components >> properly, >> using some sort of max-size implementation unconditionally rather than >> switching to a pool-based implementation when the max size is too large. >> I've never understood why Ada compilers were allowed to make such a >> limitation (it becomes a major limitation when working on non-embedded >> programs), while similar limitations on case statements and aggregates >> are >> not allowed. > > I think a non-embedded target could use a task-local pool for the purpose. At the cost of using explicit allocators and effectively leaking memory (most tasks are fairly long-lived, much longer than the majority of objects). Randy. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-20 0:13 ` Randy Brukardt @ 2020-08-20 17:49 ` Dmitry A. Kazakov 2020-08-20 23:25 ` Randy Brukardt 0 siblings, 1 reply; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-20 17:49 UTC (permalink / raw) On 20/08/2020 02:13, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:rgr27b$1o1n$2@gioia.aioe.org... >> On 10/08/2020 02:31, Randy Brukardt wrote: >>> This is not that hard to deal with. Janus/Ada handles >>> discriminant-dependent >>> components of mutable objects this way: they are allocated on the stack, >>> but >>> if they have to be reallocated they move to the heap. >> >> What you do if such an object is allocated via pool-specific access type? > > The whole object goes in that pool. The entire mechanism in Janus/Ada is > built around pools - the stack is represented by a pool object as well as > various other pools to support the mechanism. OK, but then you are back to the problem that you do not know how that pool works. The user pool might require a certain order of objects inside it and your interference with relocation will break it. >>> I note that the original idea already exists for discriminant-dependent >>> components -- that's a bit more painful to use but hardly difficult. The >>> main issue is that most compilers fail to support these components >>> properly, >>> using some sort of max-size implementation unconditionally rather than >>> switching to a pool-based implementation when the max size is too large. >>> I've never understood why Ada compilers were allowed to make such a >>> limitation (it becomes a major limitation when working on non-embedded >>> programs), while similar limitations on case statements and aggregates >>> are >>> not allowed. >> >> I think a non-embedded target could use a task-local pool for the purpose. > > At the cost of using explicit allocators and effectively leaking memory > (most tasks are fairly long-lived, much longer than the majority of > objects). No, I meant that if you used a pool behind the scenes for local objects you could do that task-specific eliminating interlocking. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-20 17:49 ` Dmitry A. Kazakov @ 2020-08-20 23:25 ` Randy Brukardt 2020-08-21 7:08 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Randy Brukardt @ 2020-08-20 23:25 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:rhmd3c$1eql$1@gioia.aioe.org... > On 20/08/2020 02:13, Randy Brukardt wrote: ... >>> What you do if such an object is allocated via pool-specific access >>> type? >> >> The whole object goes in that pool. The entire mechanism in Janus/Ada is >> built around pools - the stack is represented by a pool object as well as >> various other pools to support the mechanism. > > OK, but then you are back to the problem that you do not know how that > pool works. The user pool might require a certain order of objects inside > it and your interference with relocation will break it. Such a pool does not implement the interface as defined in 13.11. It's OK of course to write a pool that depends on implementation-specific properties (I've done it many times), but such a pool is not usable with portable Ada code. If the pool allows any sort of allocation at any time, then it will work just fine with the Janus/Ada implementation. (Of course, you can use a one-size only pool allocation with Janus/Ada, so long as what you are allocating doesn't have discrimiant-dependent components. Janus/Ada has informational messages about such components, so you can do it if you want/need. Probably should have an aspect as well to force an error if a static size is expected.) Note that this is the reason that Ada doesn't support specifying the pool used by a container. It would not be reasonable to restrict the allocations in any way, so implementation-dependent pool designs would not work. >>>> I note that the original idea already exists for discriminant-dependent >>>> components -- that's a bit more painful to use but hardly difficult. >>>> The >>>> main issue is that most compilers fail to support these components >>>> properly, >>>> using some sort of max-size implementation unconditionally rather than >>>> switching to a pool-based implementation when the max size is too >>>> large. >>>> I've never understood why Ada compilers were allowed to make such a >>>> limitation (it becomes a major limitation when working on non-embedded >>>> programs), while similar limitations on case statements and aggregates >>>> are not allowed. >>> >>> I think a non-embedded target could use a task-local pool for the >>> purpose. >> >> At the cost of using explicit allocators and effectively leaking memory >> (most tasks are fairly long-lived, much longer than the majority of >> objects). > > No, I meant that if you used a pool behind the scenes for local objects > you could do that task-specific eliminating interlocking. Whether that would be worthwhile would depend on how expensive the locking is. If a lock-free algorithm was used, it might be cheap enough to not make it worth bothering (the actual heap manipulation usually being more expensive given the free chain searching). [A lock-free algorithm typically using busy-waiting rather than suspension to wait.] Of course, Janus/Ada itself uses the Windows heap for heap management, so the locking is already built-in and not paying for it is not an option. But roll-your-own-heap managers (as Janus/Ada used on CP/M and MS-DOS) have options. Randy. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-20 23:25 ` Randy Brukardt @ 2020-08-21 7:08 ` Dmitry A. Kazakov 2020-08-23 5:03 ` Randy Brukardt 0 siblings, 1 reply; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-21 7:08 UTC (permalink / raw) On 21/08/2020 01:25, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:rhmd3c$1eql$1@gioia.aioe.org... >> On 20/08/2020 02:13, Randy Brukardt wrote: > ... >>>> What you do if such an object is allocated via pool-specific access >>>> type? >>> >>> The whole object goes in that pool. The entire mechanism in Janus/Ada is >>> built around pools - the stack is represented by a pool object as well as >>> various other pools to support the mechanism. >> >> OK, but then you are back to the problem that you do not know how that >> pool works. The user pool might require a certain order of objects inside >> it and your interference with relocation will break it. > > Such a pool does not implement the interface as defined in 13.11. It's OK of > course to write a pool that depends on implementation-specific properties > (I've done it many times), but such a pool is not usable with portable Ada > code. If the pool allows any sort of allocation at any time, then it will > work just fine with the Janus/Ada implementation. It is a different situation. Such pools are not intended as a general purpose pools. But the type is. In my view an implementation of the type provided by compiler must work in all legal cases. Otherwise it is either language of compiler bug. > (Of course, you can use a one-size only pool allocation with Janus/Ada, so > long as what you are allocating doesn't have discrimiant-dependent > components. Janus/Ada has informational messages about such components, so > you can do it if you want/need. Probably should have an aspect as well to > force an error if a static size is expected.) > > Note that this is the reason that Ada doesn't support specifying the pool > used by a container. It would not be reasonable to restrict the allocations > in any way, so implementation-dependent pool designs would not work. > >> No, I meant that if you used a pool behind the scenes for local objects >> you could do that task-specific eliminating interlocking. > > Whether that would be worthwhile would depend on how expensive the locking > is. It could be very expensive on a multi-core architecture. I also think about scenarios when the object is used inside a protected action. I would not like to see any pool interaction in an interrupt handler! -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-21 7:08 ` Dmitry A. Kazakov @ 2020-08-23 5:03 ` Randy Brukardt 2020-08-23 12:28 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Randy Brukardt @ 2020-08-23 5:03 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:rhnrtu$rk2$1@gioia.aioe.org... > On 21/08/2020 01:25, Randy Brukardt wrote: >> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >> news:rhmd3c$1eql$1@gioia.aioe.org... >>> On 20/08/2020 02:13, Randy Brukardt wrote: >> ... >>>>> What you do if such an object is allocated via pool-specific access >>>>> type? >>>> >>>> The whole object goes in that pool. The entire mechanism in Janus/Ada >>>> is >>>> built around pools - the stack is represented by a pool object as well >>>> as >>>> various other pools to support the mechanism. >>> >>> OK, but then you are back to the problem that you do not know how that >>> pool works. The user pool might require a certain order of objects >>> inside >>> it and your interference with relocation will break it. >> >> Such a pool does not implement the interface as defined in 13.11. It's OK >> of >> course to write a pool that depends on implementation-specific properties >> (I've done it many times), but such a pool is not usable with portable >> Ada >> code. If the pool allows any sort of allocation at any time, then it will >> work just fine with the Janus/Ada implementation. > > It is a different situation. Such pools are not intended as a general > purpose pools. But the type is. In my view an implementation of the type > provided by compiler must work in all legal cases. Otherwise it is either > language of compiler bug. There's a third possibility: unrealistic expectations. :-) The only kind of pool that is not general-purpose is one that is necessarily depending on the details of the implementation. Trying to constrain what allocations a compiler can do would ensure that a language could not be implemented efficiently or flexibly. That's not a language I'd want to use. ... > It could be very expensive on a multi-core architecture. I suppose, but that architecture would be lousy for running any multi-tasking or parallel program (since any such program is going to need a significant amount of synchronization). A lock-free algorithm is usually the cheapest possible synchronization on any architecture (it usually includes a spin, but the spin is almost never executed). > .. I also think > about scenarios when the object is used inside a protected action. I would > not like to see any pool interaction in an interrupt handler! Interrupt handlers shouldn't be doing anything other than unblocking tasks. I think it is a mistake to allow anything else (as there are always problems with race conditions if you do so). So no heap possibilities as very little is going on. Randy. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-23 5:03 ` Randy Brukardt @ 2020-08-23 12:28 ` Dmitry A. Kazakov 0 siblings, 0 replies; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-23 12:28 UTC (permalink / raw) On 23/08/2020 07:03, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:rhnrtu$rk2$1@gioia.aioe.org... >> On 21/08/2020 01:25, Randy Brukardt wrote: >>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >>> news:rhmd3c$1eql$1@gioia.aioe.org... >>>> On 20/08/2020 02:13, Randy Brukardt wrote: >>> ... >>>>>> What you do if such an object is allocated via pool-specific access >>>>>> type? >>>>> >>>>> The whole object goes in that pool. The entire mechanism in Janus/Ada >>>>> is >>>>> built around pools - the stack is represented by a pool object as well >>>>> as >>>>> various other pools to support the mechanism. >>>> >>>> OK, but then you are back to the problem that you do not know how that >>>> pool works. The user pool might require a certain order of objects >>>> inside >>>> it and your interference with relocation will break it. >>> >>> Such a pool does not implement the interface as defined in 13.11. It's OK >>> of >>> course to write a pool that depends on implementation-specific properties >>> (I've done it many times), but such a pool is not usable with portable >>> Ada >>> code. If the pool allows any sort of allocation at any time, then it will >>> work just fine with the Janus/Ada implementation. >> >> It is a different situation. Such pools are not intended as a general >> purpose pools. But the type is. In my view an implementation of the type >> provided by compiler must work in all legal cases. Otherwise it is either >> language of compiler bug. > > There's a third possibility: unrealistic expectations. :-) > > The only kind of pool that is not general-purpose is one that is necessarily > depending on the details of the implementation. Trying to constrain what > allocations a compiler can do would ensure that a language could not be > implemented efficiently or flexibly. That's not a language I'd want to use. > > ... >> It could be very expensive on a multi-core architecture. > > I suppose, but that architecture would be lousy for running any > multi-tasking or parallel program (since any such program is going to need a > significant amount of synchronization). A lock-free algorithm is usually the > cheapest possible synchronization on any architecture (it usually includes a > spin, but the spin is almost never executed). > > > .. I also think >> about scenarios when the object is used inside a protected action. I would >> not like to see any pool interaction in an interrupt handler! > > Interrupt handlers shouldn't be doing anything other than unblocking tasks. > I think it is a mistake to allow anything else (as there are always problems > with race conditions if you do so). So no heap possibilities as very little > is going on. Yes, and this is why light-weight implementations are important. You want to take them away while giving no promises, no, actually promising that expecting the alternative to work would be: "an unrealistic expectation." (:-)) -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-27 17:48 ` Brian Drummond 2020-07-27 20:02 ` Dmitry A. Kazakov @ 2020-07-27 20:31 ` Jeffrey R. Carter 1 sibling, 0 replies; 47+ messages in thread From: Jeffrey R. Carter @ 2020-07-27 20:31 UTC (permalink / raw) On 7/27/20 7:48 PM, Brian Drummond wrote: > > Is there any way we could generalise the (storage, access and lifetime > aspects of) Unbounded_String for unconstrained arrays and discriminated > records in such a way that Unbounded_String can be a simple instantiation > of one of these? Ada.Strings.Unbounded can be considered a combination of Ada.Containers.Indefinite_Holders instantiated for String and Ada.Containers.Vectors instantiated with Positive and Character, with some additional operations added. The To_String and To_Unbounded_String operations of Unbounded_String are similar to the Element and Replace_Element operations of Holder, which do not exist for Vector. The indexed operations of Unbounded_String are similar to the indexed operations of Vector, which do not exist for Holder. If Ada.Containers.Vectors had an additional generic formal type type Fixed is array (Index_Type range <>) of Element_Type; and 2 new operations function To_Fixed (From : Vector) return Fixed; function To_Vector (From : Fixed) return Vector; then we wouldn't need Ada.Strings.Unbounded. -- Jeff Carter "Blessed is just about anyone with a vested interest in the status quo." Monty Python's Life of Brian 73 ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-04-03 22:48 Proposal: Auto-allocation of Indefinite Objects Stephen Davies ` (2 preceding siblings ...) 2020-07-27 7:47 ` Yannick Moy @ 2020-07-31 9:25 ` Stephen Davies 2020-07-31 10:20 ` Dmitry A. Kazakov 2020-09-03 4:30 ` linda white 4 siblings, 1 reply; 47+ messages in thread From: Stephen Davies @ 2020-07-31 9:25 UTC (permalink / raw) On Friday, 3 April 2020 at 23:48:43 UTC+1, Stephen Davies wrote: > type Node_Type is record > Item : new Element_Type; > Prev : Node_Ptr_Type; > Next : Node_Ptr_Type; > end record; Perhaps a better way to think of this is as a discriminated record without an explicit discriminant? In which case maybe a different syntax than "new" would be appropriate? ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-31 9:25 ` Stephen Davies @ 2020-07-31 10:20 ` Dmitry A. Kazakov 2020-08-01 11:22 ` Stephen Davies 0 siblings, 1 reply; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-07-31 10:20 UTC (permalink / raw) On 31/07/2020 11:25, Stephen Davies wrote: > On Friday, 3 April 2020 at 23:48:43 UTC+1, Stephen Davies wrote: >> type Node_Type is record >> Item : new Element_Type; >> Prev : Node_Ptr_Type; >> Next : Node_Ptr_Type; >> end record; > > Perhaps a better way to think of this is as a discriminated record without > an explicit discriminant? In which case maybe a different syntax than "new" > would be appropriate? That is right, but it would be a much larger problem to resolve than your original proposal. First, Ada lacks necessary discriminants, e.g. type Node_Type (Descendant : Ada.Tags.Tag) is record Item : Element_Type (Tag => Descendant); Prev : Node_Ptr_Type; Next : Node_Ptr_Type; end record; Here Element_Type is a specific type from Element_Type'Class which tag is Descendant. Second, Ada's object initialization process has no means to determine discriminants. One extra step is missing before a call to allocator to provide constraints of a type. [I proposed a record type T'Constraints that would contain all constraints and no data to be passed to allocator to determine the object constraints and thus its size.] Third, there is still the problem that task components do not work, as well as all other cases when the Rosen trick is used to work-around full multiple inheritance by making record members out of intended parents. All in one, the crude work-around has always been an access type, which your original proposal would handle with much more grace. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-07-31 10:20 ` Dmitry A. Kazakov @ 2020-08-01 11:22 ` Stephen Davies 2020-08-01 12:58 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Stephen Davies @ 2020-08-01 11:22 UTC (permalink / raw) On Friday, 31 July 2020 at 11:20:09 UTC+1, Dmitry A. Kazakov wrote: > On 31/07/2020 11:25, Stephen Davies wrote: > > On Friday, 3 April 2020 at 23:48:43 UTC+1, Stephen Davies wrote: > > Perhaps a better way to think of this is as a discriminated record without > > an explicit discriminant? In which case maybe a different syntax than "new" > > would be appropriate? > That is right, but it would be a much larger problem to resolve than > your original proposal. > First, Ada lacks necessary discriminants ... > Second, Ada's object initialization process has no means to determine > discriminants... > Third, there is still the problem that task components do not work... > All in one, the crude work-around has always been an access type... Maybe I'm missing something but my thought was maybe there is no need for a named discriminant, e.g. type Node_Type (<>) is record Item : Element_Type; Prev : Node_Ptr_Type; Next : Node_Ptr_Type; end record; The rules for such records would be the same as for discriminated ones, except that instead of usages needing to provide values for discriminants, they would need to provide values for indefinite components. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-01 11:22 ` Stephen Davies @ 2020-08-01 12:58 ` Dmitry A. Kazakov 2020-08-01 20:35 ` Stephen Davies 0 siblings, 1 reply; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-01 12:58 UTC (permalink / raw) On 01/08/2020 13:22, Stephen Davies wrote: > On Friday, 31 July 2020 at 11:20:09 UTC+1, Dmitry A. Kazakov wrote: >> On 31/07/2020 11:25, Stephen Davies wrote: >>> On Friday, 3 April 2020 at 23:48:43 UTC+1, Stephen Davies wrote: >>> Perhaps a better way to think of this is as a discriminated record without >>> an explicit discriminant? In which case maybe a different syntax than "new" >>> would be appropriate? >> That is right, but it would be a much larger problem to resolve than >> your original proposal. >> First, Ada lacks necessary discriminants ... >> Second, Ada's object initialization process has no means to determine >> discriminants... >> Third, there is still the problem that task components do not work... >> All in one, the crude work-around has always been an access type... > > Maybe I'm missing something but my thought was maybe there is no > need for a named discriminant, e.g. > type Node_Type (<>) is record > Item : Element_Type; > Prev : Node_Ptr_Type; > Next : Node_Ptr_Type; > end record; > The rules for such records would be the same as for discriminated ones, > except that instead of usages needing to provide values for discriminants, > they would need to provide values for indefinite components. 1. There is no discriminants for cases when Item is T'Class. 2. You cannot get discriminant from the value in the case of Rosen trick. Consider Item being a task with the access to the actual node as its discriminant: type Node_Type; task type Worker (Node : not null access Node_Type) is ...; type Mode_Type is record Item : Worker (Node_Type'Unchecked_Access); Prev : Node_Ptr_Type; Next : Node_Ptr_Type; end record; You cannot initialize Item because you cannot construct Worker without having the node. And you cannot have the node without having Item initialized. 3. Copying is involved. There should be none, especially for limited types. Limited returns are broken per construction and nothing could ever fix them. ------------------------- If the only problem were to deduce discriminants from a value. We could leave Node_Type as-is and simply fix aggregates: type T (L : Natural) is record S : String (1..L); I : Integer; end record; Why not to make this legal? X : T := ("hello!", 123); -- L is deduced from S -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-01 12:58 ` Dmitry A. Kazakov @ 2020-08-01 20:35 ` Stephen Davies 2020-08-01 20:56 ` Dmitry A. Kazakov 0 siblings, 1 reply; 47+ messages in thread From: Stephen Davies @ 2020-08-01 20:35 UTC (permalink / raw) On Saturday, 1 August 2020 at 13:58:10 UTC+1, Dmitry A. Kazakov wrote: > On 01/08/2020 13:22, Stephen Davies wrote: > > type Node_Type (<>) is record > > Item : Element_Type; > > Prev : Node_Ptr_Type; > > Next : Node_Ptr_Type; > > end record; > > The rules for such records would be the same as for discriminated ones, > > except that instead of usages needing to provide values for discriminants, > > they would need to provide values for indefinite components. > 1. There is no discriminants for cases when Item is T'Class. > 2. You cannot get discriminant from the value in the case of Rosen trick... > 3. Copying is involved. There should be none, especially for limited types... I'm mainly talking about situations in which there doesn't need to be a discriminant at all, e.g. when Element_Type is an indefinite non-limited generic parameter. In other words, Node_Type would then also be indefinite, but not discriminated. > Why not to make this legal? > X : T := ("hello!", 123); -- L is deduced from S Maybe that's something that should be fixed anyway, though this is indeed another situation that (both versions of) my proposal would address, by removing (the somewhat redundant) L altogether. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-08-01 20:35 ` Stephen Davies @ 2020-08-01 20:56 ` Dmitry A. Kazakov 0 siblings, 0 replies; 47+ messages in thread From: Dmitry A. Kazakov @ 2020-08-01 20:56 UTC (permalink / raw) On 01/08/2020 22:35, Stephen Davies wrote: > On Saturday, 1 August 2020 at 13:58:10 UTC+1, Dmitry A. Kazakov wrote: >> On 01/08/2020 13:22, Stephen Davies wrote: >>> type Node_Type (<>) is record >>> Item : Element_Type; >>> Prev : Node_Ptr_Type; >>> Next : Node_Ptr_Type; >>> end record; >>> The rules for such records would be the same as for discriminated ones, >>> except that instead of usages needing to provide values for discriminants, >>> they would need to provide values for indefinite components. >> 1. There is no discriminants for cases when Item is T'Class. >> 2. You cannot get discriminant from the value in the case of Rosen trick... >> 3. Copying is involved. There should be none, especially for limited types... > I'm mainly talking about situations in which there doesn't need to be a > discriminant at all, e.g. when Element_Type is an indefinite non-limited > generic parameter. In other words, Node_Type would then also be indefinite, > but not discriminated. In my view all indefinite types are discriminated, though some discriminants are anonymous or represented by attributes, per language design irregularities. E.g. T'Class is discriminated by the type tag. Array bounds must clearly be discriminants etc. Each constraint must be expressed in terms of discriminants. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Proposal: Auto-allocation of Indefinite Objects 2020-04-03 22:48 Proposal: Auto-allocation of Indefinite Objects Stephen Davies ` (3 preceding siblings ...) 2020-07-31 9:25 ` Stephen Davies @ 2020-09-03 4:30 ` linda white 4 siblings, 0 replies; 47+ messages in thread From: linda white @ 2020-09-03 4:30 UTC (permalink / raw) On Saturday, 4 April 2020 04:18:43 UTC+5:30, Stephen Davies wrote: > Firstly, apologies if this has already been discussed or, > more likely, if it's a really stupid idea for some reason > that I haven't thought of. > > My proposal is that it should (sometimes?) be possible to declare > objects of indefinite types such as String and have the compiler > automatically declare the space for them without the programmer > having to resort to access types. > > Benefits: > > 1. Easier, especially for newbies/students. > 2. Safer due to reduced use of access types. > 3. Remove the need to have definite and indefinite verions of generic units. > > It is the 3rd reason that initially got me thinking about this. > It seems excessive to have two versions of packages just because > one version can say "Node.Item := New_Item;" but the other has to say > "Node.Item_Ptr := new Element_Type'(New_Item);". > > It's probably not a good idea for auto-allocation to be the default > behaviour, so I suggest something like: > > type Node_Type is record > Item : new Element_Type; > Prev : Node_Ptr_Type; > Next : Node_Ptr_Type; > end record; > > If Element_Type is a definite type in the instantiation then > Node.Item will be a normal object of that type. Otherwise, it is > implemented as a pointer but the code still treats it as an object. > The target of the pointer is allocated on assignment of the object. > The pointer cannot be copied to any other object. Assignments of the > whole record will perform a deep-copy of the auto-allocated component. > The target of the Node.Item pointer can be auto-deallocated when Node > goes out of scope or is deallocated. > > Ok, I've probably missed something obvious and have been wasting my > time, but at least I've got plenty of time to waste at the moment. ^ permalink raw reply [flat|nested] 47+ messages in thread
end of thread, other threads:[~2020-09-03 4:30 UTC | newest] Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-04-03 22:48 Proposal: Auto-allocation of Indefinite Objects Stephen Davies 2020-04-03 23:45 ` Stephen Leake 2020-04-04 10:54 ` Jeffrey R. Carter 2020-04-04 20:55 ` Stephen Davies 2020-04-04 8:31 ` Dmitry A. Kazakov 2020-07-27 7:47 ` Yannick Moy 2020-07-27 9:21 ` J-P. Rosen 2020-07-27 9:49 ` Dmitry A. Kazakov 2020-07-27 17:48 ` Brian Drummond 2020-07-27 20:02 ` Dmitry A. Kazakov 2020-07-28 14:28 ` Brian Drummond 2020-07-28 14:59 ` Dmitry A. Kazakov 2020-07-29 15:33 ` Brian Drummond 2020-07-29 16:20 ` Dmitry A. Kazakov 2020-07-30 13:37 ` Stephen Davies 2020-07-30 14:23 ` Dmitry A. Kazakov 2020-07-30 17:04 ` Brian Drummond 2020-07-30 18:28 ` Dmitry A. Kazakov 2020-08-10 0:39 ` Randy Brukardt 2020-08-10 8:57 ` Dmitry A. Kazakov 2020-08-20 0:10 ` Randy Brukardt 2020-08-20 17:49 ` Dmitry A. Kazakov 2020-08-20 20:19 ` Dennis Lee Bieber 2020-08-20 23:33 ` Randy Brukardt 2020-08-21 6:45 ` Dmitry A. Kazakov 2020-08-23 4:52 ` Randy Brukardt 2020-08-23 12:28 ` Dmitry A. Kazakov 2020-08-20 23:30 ` Randy Brukardt 2020-08-21 6:46 ` Dmitry A. Kazakov 2020-08-23 4:48 ` Randy Brukardt 2020-08-23 12:29 ` Dmitry A. Kazakov 2020-08-10 0:31 ` Randy Brukardt 2020-08-10 8:58 ` Dmitry A. Kazakov 2020-08-20 0:13 ` Randy Brukardt 2020-08-20 17:49 ` Dmitry A. Kazakov 2020-08-20 23:25 ` Randy Brukardt 2020-08-21 7:08 ` Dmitry A. Kazakov 2020-08-23 5:03 ` Randy Brukardt 2020-08-23 12:28 ` Dmitry A. Kazakov 2020-07-27 20:31 ` Jeffrey R. Carter 2020-07-31 9:25 ` Stephen Davies 2020-07-31 10:20 ` Dmitry A. Kazakov 2020-08-01 11:22 ` Stephen Davies 2020-08-01 12:58 ` Dmitry A. Kazakov 2020-08-01 20:35 ` Stephen Davies 2020-08-01 20:56 ` Dmitry A. Kazakov 2020-09-03 4:30 ` linda white
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox