Lazarus

Programming => General => Topic started by: Shpend on December 14, 2019, 09:31:38 pm

Title: Unified Pascal syntax
Post by: Shpend on December 14, 2019, 09:31:38 pm
hello guys,

I have come across something in Pascal (FPC), when I started again using more and more OOP.

This is, I have to say, a critic point in FPC, which bases on the structure of modules, like:

functions/procedures, record, classes, units.

More detailed: I would actually love to see that Pascal enforces the developer to write code in the same way, so to speak: Lets say this:

In my head, there shouldnt even be a need for a modeswitch to advanced records, it should be implicitly possibly

Code: Pascal  [Select][+][-]
  1. TSomeData = record
  2. {here in my head, fpc should enforce the visibility section!}
  3. public/private/strict private/protected etc...
  4.   Type
  5.      T1 = ....
  6.      T2 = ....
  7.      T3 = ....
  8.   const
  9.     C1 = ..
  10.     C2 = ...
  11.   var
  12.     V1: T1;
  13.     V2: T2;
  14. end;
  15.  

//this unfortunately, is not enforced so I can also just write all that without the enforced visibilty section, so it is implicitly guest as public which I dont see it as pascalish way, since pascal wants more and clear expression of what u are trying to archieve. So if u want public, fine, then write it also so, like be forced to name the visibilty section. I dont know, I really find these types of enforcements very useful and readable.

Another thing is, as PascalDragon once suggested me to do with my generic stuff is:

Code: Pascal  [Select][+][-]
  1. type
  2.   generic TMultiSet<T> = record
  3.   public type                                                 //why the extra "public type" here
  4.     PMultiSet = ^specialize TMultiSet<T>;
  5.   public
  6.     fField: Byte;
  7.     value: PMultiSet;
  8.   end;
  9.  

This example could also kinda show, that a good structural layout enforcement is really valuable, since saying:

Code: Pascal  [Select][+][-]
  1. type
  2.   generic TMultiSet<T> = record
  3.   public
  4.     type
  5.       PMultiSet = ^specialize TMultiSet<T>;
  6.     var
  7.       fField: Byte;
  8.       value: PMultiSet;
  9.   end;
  10.  

follows the same layout-tree-enforcement everywhere or for instance I am also sadly able to just say:

Code: Pascal  [Select][+][-]
  1. generic TMultiSet<T> = record
  2.   private  //note the missing "var" section
  3.     fField: Byte;
  4.     value: PMultiSet;
  5.  end;
  6.  

These things, and I am not joking now, prevented 2 of my best friends from joining FPC and moving from C even tho they were looking for change, since C is to much of an old-burden for them, both of my friends participated largely in the Cafu Engine development and they kinda liked the overall Idea of FPC/Delphi, so both know C kinda good I wiould assume.

Would like to hear about that, if its something for you to consider or If I should consume less drugs :---D

Best regards

Shpend
Title: Re: Unified Pascal syntax
Post by: jamie on December 14, 2019, 10:51:01 pm
its no surprise you find fpc/Pascal clear to understand, it was generally considered a language to use to teach proper structured programming  :D :D
Title: Re: Unified Pascal syntax
Post by: howardpc on December 14, 2019, 11:02:46 pm
FPC strives to be fully backwards compatible.
So the implicit public visibility of record fields simply aligns Object Pascal with record declarations in Wirth's original Pascal, years before sections of different visibility in records were conceived.
If Object Pascal forced you to add a visibility specifier to all record declarations, all Pascal code from the 1980s and 1990s would become invalid at a stroke.
As it is now, you can make the implicit visibility explicit, if you find that helpful.
Just as some people write
Code: Pascal  [Select][+][-]
  1. TMyClass = class(TObject)
  2. ...
  3. end;
making the ancestor class explicit, rather than writing
Code: Pascal  [Select][+][-]
  1. TMyClass = class
  2. ...
  3. end;
Title: Re: Unified Pascal syntax
Post by: marcov on December 15, 2019, 12:22:36 am
Personally I think too detailed information hiding is counterproductive.

The benefits are in the first order aspects, the rest is micromanaging.

If you go that way, maybe identifiers should have ACLs ?  >:D
Title: Re: Unified Pascal syntax
Post by: Shpend on December 15, 2019, 03:26:46 am
Quote
If Object Pascal forced you to add a visibility specifier to all record declarations, all Pascal code from the 1980s and 1990s would become invalid at a stroke.

first of all, i meant actuall all modular-aspects of pascal, like: Unit, Class, Record, Object everything which has the capability of encapsulation in a wider sense, so like the overall pattern I am striving personally atleast is:

Code: Pascal  [Select][+][-]
  1.  
  2. <ModuleType> =  <Modulename>
  3.   <visibility>           #1. place
  4.     [optional]
  5.       <Type>           # if types needed, always after the visibility section
  6.       .
  7.       .
  8.       .
  9.      <Constantes>    #if constants needed, always after the visibility section
  10.       .
  11.       .
  12.       .
  13.       .
  14.     <Var>              #if variables needed, always after the visibility section
  15.       .
  16.       .
  17.       .  
  18.    //actually would have been a nice "routine" keyword too, to express that here will come numerous routines (functions/procedures)
  19.    <Routines>       #if routines needed, always after the visibility section  
  20.       .
  21.       .
  22.       .
  23.  [optional]
  24.  

The same goes actually for the UNIT too, since a unit has all these things the usual modules (class,record, object) have in common it only adds the "uses" clause on top of it but only with the difference of "interface" and "implementation" which are effectively like private and public. Which I dont know really, why these 2 Accessor-keywords didnt have been introduced by wirth, but probably they came much later, like when OOP started and that was way after that time. But interesstingly enough, within an Unit file, you have to declare both interface and implementation section no matter if you only need like constants in that file , otherwords you dont need implementation at all, it still (as I like it, correctly) forces you to write those out. I and seemingly many others would have enjoyed such a brilliant consistency throughout the entirety of Pascal a lot.
Title: Re: Unified Pascal syntax
Post by: Shpend on December 15, 2019, 03:29:26 am
Personally I think too detailed information hiding is counterproductive.

The benefits are in the first order aspects, the rest is micromanaging.

If you go that way, maybe identifiers should have ACLs ?  >:D

Would you explain that a bit more detailed to a newbie in this area, im not sure I can follow  %)
Title: Re: Unified Pascal syntax
Post by: Shpend on December 15, 2019, 03:53:16 am
another thing (but dont worry, no other programming language offer this currently AFAIK) would be to remove the keywords object and let only record/class available as an OOP-keyword, BUT: here is the clu because you can then do all these things, which are currently done by (records /advanced records; object; class)

with this new model you can do all of that with only class and record because record is implictly an object, even if you only have simple types in it or only types +  some functions, its still internally without the developer seeing it, treated by the compiler as an advanced record but without the need to define a modeswitch for it and if you indeed need the full "object" power then the compiler just implicitly recognize from its definition of what it should be treated as, with all that said, consider the following:



Code: Pascal  [Select][+][-]
  1. //CASE1. If you want a short only data holder, be it simple types, or variant types or bitfields, as long as it only contains raw simple types like how it is done by records right now.
  2.  
  3.   T_Record = record
  4.     a,b,c: byte;
  5.     d: char;
  6.  
  7.     case boolean of
  8.       fieldlist1: (a1, b1, c1: byte);
  9.       fieldlist2: (a2, b2: QWord);  //etc...
  10.   end;
  11.  
  12.   var
  13.     mySimpleRec: T_Record ;
  14.   begin
  15.     mySimpleRec.a := 10;
  16.     mySimpleRec.b := 20;
  17.     mySimpleRec.c := 255; //etc...
  18.   end;
  19.  


Code: Pascal  [Select][+][-]
  1. //CASE2. If you want a short only data holder PLUS routines and or types + const, be it simple types, or variant types or bitfields, like how its done by the [I]{$modeswitch advanced records}[/I]
  2.   T_AdvancedRecord = record
  3.   public
  4.     Type
  5.       TBla = byte;
  6.       TRangeBla = 10..189;
  7.      var
  8.        a,b,c: TBla;
  9.        d: char;
  10.        blarange: TRangeBla ;
  11.     case boolean of
  12.       fieldlist1: (a1, b1, c1: byte);
  13.       fieldlist2: (a2, b2: QWord);  //etc...
  14.  
  15.     //just some crap.. xD
  16.     function Do_1: byte;
  17.     function Do_2: Char;
  18.     procedure Do_3;
  19.   end;
  20.  
  21.   var
  22.     mySimpleRec: T_AdvancedRecord ;
  23.   begin
  24.     mySimpleRec.a := 10;
  25.     mySimpleRec.b := 20;
  26.     mySimpleRec.c := 255; //etc...
  27.     mySimpleRec.blaRange := 189;
  28.     writeln(mySimpleRec.Do_1 + mySimpleRec.a);
  29.   end;
  30.  



Code: Pascal  [Select][+][-]
  1. //CASE3. If you want a fully OOP version with polymorphie, inheritcance and stuff, you could do like this, but with the exception that it will get automatically released by the stackmanager after it leaves its current scope , like how it is done by object right now.
  2.  
  3.   T_Object = record(TAnotherClass, IAnotherInterface1, IAnotherInterface2)
  4.     a: IAnotherInterface1;
  5.     d: char;  
  6.   end;
  7.  
  8.   var
  9.     mySimpleRec: T_Object;
  10.     varOfInterface1: IAnotherInterface ;
  11.   begin
  12.     mySimpleRec.a := varOfInterface1;
  13.     mySimpleRec.b := 'C';
  14.     mySimpleRec.a.DoSomeCallHere();
  15.   end;
  16.  

Yea and class is just remains a class, how it is done currently.
Title: Re: Unified Pascal syntax
Post by: marcov on December 15, 2019, 12:10:11 pm
Personally I think too detailed information hiding is counterproductive.

The benefits are in the first order aspects, the rest is micromanaging.

Informating hiding is hiding identifiers from others scopes (classes/units/whatever). I firmly believe in keeping that simple. (IMHO the whole "strict*" was already worse than the actual problem).  private/protected/public is good enough.

Quote
If you go that way, maybe identifiers should have ACLs ?  >:D

ACL are access control lists, lists like file permissions on windows that list who (and or which group) can access what.
Title: Re: Unified Pascal syntax
Post by: simone on December 15, 2019, 01:28:14 pm
Personally I think too detailed information hiding is counterproductive.

The benefits are in the first order aspects, the rest is micromanaging.

Informating hiding is hiding identifiers from others scopes (classes/units/whatever). I firmly believe in keeping that simple. (IMHO the whole "strict*" was already worse than the actual problem).  private/protected/public is good enough.


I basically agree. The problem is that the object pascal language has a peculiar notion of private (and protected), since a private member of a class is visible not only within the class to which it belongs, but also outside, within the unit where the class itself is defined. This does not happen for example in C++ and Java. Hence the need for the 'strict' keyword to restrict visibility.

Title: Re: Unified Pascal syntax
Post by: MarkMLl on December 15, 2019, 01:31:20 pm
Quote
If you go that way, maybe identifiers should have ACLs ?  >:D
ACL are access control lists, lists like file permissions on windows that list who (and or which group) can access what.

Actually, I do have some sympathy with that one: perhaps an explicit export <identifier> to <unit> or similar.

However it could probably be simulated adequately by having a sensitive class issue access tokens on request, and then checking that that token was being presented (by the correct thread/unit/class) during subsequent operations.

MarkMLl
Title: Re: Unified Pascal syntax
Post by: Shpend on December 15, 2019, 02:02:42 pm
Is anyone of you attracted to the record/class idea I mentioed above?

Like making records implicitly advanced and object-wise, like supporting everything that a class can but is still allocated on the stack.

I feel this bringing a modeswitch into fpc feels very deprecated to me atleast.
Title: Re: Unified Pascal syntax
Post by: marcov on December 15, 2019, 02:10:47 pm
Personally I think too detailed information hiding is counterproductive.

The benefits are in the first order aspects, the rest is micromanaging.

Informating hiding is hiding identifiers from others scopes (classes/units/whatever). I firmly believe in keeping that simple. (IMHO the whole "strict*" was already worse than the actual problem).  private/protected/public is good enough.


I basically agree. The problem is that the object pascal language has a peculiar notion of private (and protected), since a private member of a class is visible not only within the class to which it belongs, but also outside, within the unit where the class itself is defined. This does not happen for example in C++ and Java. Hence the need for the 'strict' keyword to restrict visibility.

That's what I meant with worse than the problem. The addition (and having six levels) is worse than the original problem (three levels with some shortcuts for use within the same unit).

Note that the exceptions are partially rooted in the unit system, a concept that  e.g. Java doesn't have, and C++ is only discussing about in committees. C++ is  30 years back  on that front, so it is logical that they don't support it.
Title: Re: Unified Pascal syntax
Post by: howardpc on December 15, 2019, 02:35:47 pm
Is anyone of you attracted to the record/class idea I mentioed above?

Like making records implicitly advanced and object-wise, like supporting everything that a class can but is still allocated on the stack.

I feel this bringing a modeswitch into fpc feels very deprecated to me atleast.
I think In Delphi mode you don't need an advancedrecords modeswitch to give you advanced records.
FPC is already halfway there with old-style objects whose declarations default to public and are allocated on the stack.
Of course they lack proper inheritance.
Title: Re: Unified Pascal syntax
Post by: Thaddy on December 15, 2019, 03:59:41 pm
Of course they lack proper inheritance.
Since when? KOL or FV are counter-examples. That's a load of Boris. Look how fp is build.
Title: Re: Unified Pascal syntax
Post by: howardpc on December 15, 2019, 06:33:51 pm
Sorry, confused message. 
I meant advanced records currently lack inheritance. Perhaps they always will?
Title: Re: Unified Pascal syntax
Post by: PascalDragon on December 15, 2019, 06:53:42 pm
In my head, there shouldnt even be a need for a modeswitch to advanced records, it should be implicitly possibly
We are reluctant to enable new features by default in mode ObjFPC, cause we're trying to be as backwards compatible as possible. That would also answer the following question:
Is anyone of you attracted to the record/class idea I mentioed above?
No, we're not. There are more important things to work on, namely features like dynamic packages, anonymous functions, extended RTTI, improving optimizations than inventing yet another dialect (because that is all that it would be).

Like making records implicitly advanced and object-wise, like supporting everything that a class can but is still allocated on the stack.
Use the object type for that.

I feel this bringing a modeswitch into fpc feels very deprecated to me atleast.
The mode and modeswitch concept is a very strong point of FPC and easily allows it to incorporate multiple language dialects and to easily add new features without breaking existing code.

Sorry, confused message. 
I meant advanced records currently lack inheritance. Perhaps they always will?
That's the idea. If you need inheritance then use the appropriate type.
Title: Re: Unified Pascal syntax
Post by: 440bx on December 15, 2019, 07:26:49 pm
I meant advanced records currently lack inheritance. Perhaps they always will?
Probably, because adding inheritance to advanced records would result in something that already exists: the old "object"  (or very close to it.)
Title: Re: Unified Pascal syntax
Post by: kupferstecher on December 15, 2019, 11:36:35 pm
From my Pascal experience and understanding I expect Records to be plain data structures and Objects like the Classes to be the real OOP features. So for simplicity I'd rather hope that the advanced records are dropped.

Actually I quite liked using the Object type, especially as singleton. But I'm more and more reluctant because it is not fully compatible with the Class type. Override of methods e.g. is not possible and I stumbled into strange errors time by time. The problem for the missing features is, that in the beginning the object type seems to be enough and later I reach a point where incompatibilities occur, requiring to change to the class type. It's a rare case, but still I always have it in mind when I consider using the Object type. So it would be nice if the Object type would be further developed to be fully orthogonal to the Class type. E.g. a class could be derived from an object (and vice versa?).

On the other hand, the additional effort for just using a class is minimal, so perhaps its the best to constrain oneself to the class type (on systems with OS).
Title: Re: Unified Pascal syntax
Post by: valdir.marcos on December 16, 2019, 06:32:31 am
Personally I think too detailed information hiding is counterproductive.
The benefits are in the first order aspects, the rest is micromanaging.
Informating hiding is hiding identifiers from others scopes (classes/units/whatever). I firmly believe in keeping that simple. (IMHO the whole "strict*" was already worse than the actual problem).  private/protected/public is good enough.
I basically agree. The problem is that the object pascal language has a peculiar notion of private (and protected), since a private member of a class is visible not only within the class to which it belongs, but also outside, within the unit where the class itself is defined. This does not happen for example in C++ and Java. Hence the need for the 'strict' keyword to restrict visibility.
That's what I meant with worse than the problem. The addition (and having six levels) is worse than the original problem (three levels with some shortcuts for use within the same unit).

Note that the exceptions are partially rooted in the unit system, a concept that  e.g. Java doesn't have, and C++ is only discussing about in committees. C++ is  30 years back  on that front, so it is logical that they don't support it.
Interesting.
Title: Re: Unified Pascal syntax
Post by: PascalDragon on December 16, 2019, 09:17:25 am
From my Pascal experience and understanding I expect Records to be plain data structures and Objects like the Classes to be the real OOP features. So for simplicity I'd rather hope that the advanced records are dropped.
No.
1. they are required for Delphi compatibility
2. it's necessary do declare operators, types, constants and such inside a record so that they can be used inside a generic's specialization

Actually I quite liked using the Object type, especially as singleton. But I'm more and more reluctant because it is not fully compatible with the Class type. Override of methods e.g. is not possible and I stumbled into strange errors time by time. The problem for the missing features is, that in the beginning the object type seems to be enough and later I reach a point where incompatibilities occur, requiring to change to the class type. It's a rare case, but still I always have it in mind when I consider using the Object type. So it would be nice if the Object type would be further developed to be fully orthogonal to the Class type. E.g. a class could be derived from an object (and vice versa?).
The object type is the old object system from Turbo Pascal times. As it was quite a bit different from the Delphi class types they do have their different behaviours. Thus it's also not possible to have one inherit from the other, because they present completely different concepts.
Also while we don't consider the object type to be deprecated (like Delphi does) we don't really have an intention to develop it further (though there might be exceptions like this (https://bugs.freepascal.org/view.php?id=36350) feature request).
Title: Re: Unified Pascal syntax
Post by: MarkMLl on December 16, 2019, 10:07:13 am
The object type is the old object system from Turbo Pascal times.

What was that- Turbo pascal 5.5? I no longer have access to my manual collection, but I think it was in an addendum accompanying the TP5 manuals. And then Turbo Pascal for Windows introduced an early OO framework- OWL?

MarkMLl
Title: Re: Unified Pascal syntax
Post by: winni on December 16, 2019, 10:43:23 am
Hi!

Do you mean "Turbo Pascal 5.5 OOP Guide"?

https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=2ahUKEwia_bXp7bnmAhUSyqQKHQbuBXsQFjACegQIBhAC&url=https%3A%2F%2Fedn.embarcadero.com%2Farticle%2Fimages%2F20803%2FTP_55_OOP_Guide.pdf&usg=AOvVaw39XCuNM_YklMBPRqR7qfJ- (https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=2ahUKEwia_bXp7bnmAhUSyqQKHQbuBXsQFjACegQIBhAC&url=https%3A%2F%2Fedn.embarcadero.com%2Farticle%2Fimages%2F20803%2FTP_55_OOP_Guide.pdf&usg=AOvVaw39XCuNM_YklMBPRqR7qfJ-)

Winni
Title: Re: Unified Pascal syntax
Post by: MarkMLl on December 16, 2019, 11:11:33 am
> Do you mean "Turbo Pascal 5.5 OOP Guide"?

Looks about right. So from the copyright that was 1989... 30 years on FPC still doesn't break the core language and library (although things like CRT support are a problem).

MarkMLl
Title: Re: Unified Pascal syntax
Post by: lucamar on December 16, 2019, 02:02:57 pm
What was that- Turbo pascal 5.5? I no longer have access to my manual collection, but I think it was in an addendum accompanying the TP5 manuals.

Borland expanded objects very quickly; every new release from TP 5.5 came with new features: private/public fields/methods, etc. FPC's objects are like the objects in the final TP 7.0
Title: Re: Unified Pascal syntax
Post by: glorfin on December 16, 2019, 02:44:39 pm
From my Pascal experience and understanding I expect Records to be plain data structures and Objects like the Classes to be the real OOP features. So for simplicity I'd rather hope that the advanced records are dropped.
I would agree. I doubt that adding new and new syntactic features make a language really better.
Quote
Override of methods e.g. is not possible...
Why?? There is no key word "override" for old style objects, but you can have a virtual method and, in a heir type, define another method with the same arguments and virtual modifier - and it overrides the old one:
TMyFirstObject = object(TObject)
  .............
  MyMethod(param1:real):real; virtual;
end;

TMySecondObject = object(TMyFirstObject);
  .................
  MyMethod(param1:real):real; virtual;
end;
..................
TMySecondObject.MyMethod;
var
  MyVal:real;
begin
  MyVal := TMyFirstObject.MyMethod(Param1); // call to inherited method
  ..........
end;
Title: Re: Unified Pascal syntax
Post by: Shpend on December 16, 2019, 07:40:07 pm
@PascalDragon

Quote
Thus it's also not possible to have one inherit from the other, because they present completely different concepts.

They may be like this, but the realy issue IMHO is, do they present equaly or kinda equaly the same within memory?
Isnt this the real question if there might be the motivation to make them fully compatible with eachother, since its a very powerful OOP feature if they would.

I know obviously, that a class is stored as a pointer to the date  which itself is on the heap, and object is pure date itself at the stack, but ignoring this for a second, they should be behave the same ,right?
Title: Re: Unified Pascal syntax
Post by: lucamar on December 16, 2019, 07:59:26 pm
I know obviously, that a class is stored as a pointer to the date  which itself is on the heap, and object is pure date itself at the stack, but ignoring this for a second, they should be behave the same ,right?

Not quite, and it depends on quite a lot of things: v.g. whether the object has virtual or dynamic fields/methods, and other things. In fact, AFAIK, most complex types are really pointers, under the hood, i..e the generated code takes the instance variable as pointing someplace (whether heap or stack) where the "real" data resides.

Also, old-style objects are not neccessarily stored in the stack (though they may be): if you use the extended New() and Dispose() to create them, for example, the instance data should be in the heap. Indeed, it couldn't be otherwise: given their size (for other than record-like objects) they would consume the stack fairly quickly.

The difference between old-style objects and classes is not big; it's just enough that to make them "compatible" is not the straight proposition it may sound like.
Title: Re: Unified Pascal syntax
Post by: kupferstecher on December 16, 2019, 10:24:37 pm
Thus it's also not possible to have one inherit from the other, because they present completely different concepts.
Do you mean on implementation/memory side or on syntax side?

Quote
Also while we don't consider the object type to be deprecated (like Delphi does) we don't really have an intention to develop it further.
Yes, I realized that. Except for embedded targets there also seems no need for the object type. But perhaps its also a henn/egg-problem. If there were full compatibility than maybe it would be used more, which could result in a higher motivation for improvements :)

I think of something like this:

Code: Pascal  [Select][+][-]
  1. Type TFoo = object
  2.   Procedure DoSomething;
  3. end;
  4.  
  5. var
  6.   Foo: array[0..5] of TFoo; //Static Memory
  7.   tempFoo: class(TFoo)      //variable of class type (reference)
  8.  
  9. begin
  10.   tempFoo:= Foo[1];
  11.   tempFoo.DoSomething;
  12.   //or even..
  13.   for tempFoo in Foo
  14.   do tempFoo.DoSomething
  15.  
  16. end;

This would allow the use of static memory and still avoid explicit pointer handling, when dealt with references.

Override of methods e.g. is not possible...
Why?? There is no key word "override" for old style objects, but you can have a virtual method and, in a heir type, define another method with the same arguments and virtual modifier - and it overrides the old one:
Thanks! I wasn't aware of that.
Title: Re: Unified Pascal syntax
Post by: marcov on December 16, 2019, 10:32:58 pm
Quote
Code: [Select]
  tempFoo:= Foo[1];
  tempFoo.DoSomething;
  //or even..
  for tempFoo in Foo
  do tempFoo.DoSomething
 
end;

This would allow the use of static memory and still avoid explicit pointer handling, when dealt with references.

Afaik for..in would copy foo
Title: Re: Unified Pascal syntax
Post by: kupferstecher on December 16, 2019, 10:47:31 pm
(Thats hypothetical syntax.)

tempFoo was declared as class type, so it only contains the reference to the instance.

Code: Pascal  [Select][+][-]
  1. var
  2.   tempFoo: class(TFoo)

Internally the data structure of an instance of Class or Object would be the same, only the variable behaviour would be different.
Title: Re: Unified Pascal syntax
Post by: PascalDragon on December 17, 2019, 09:50:27 am
Thus it's also not possible to have one inherit from the other, because they present completely different concepts.
Do you mean on implementation/memory side or on syntax side?
The former. For starters an object might be located on the stack or the heap, calling constructors can be considered optional and they or may not have a pointer to a VMT depending on the inheritance and the presence of virtual methods. In contrast a class instance is always located on the heap, one must call a constructor to instantiate it and they always have a pointer to a VMT. Not to mention that the VMT of the later (https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/rtl/inc/objpash.inc?revision=43418&view=markup#l101) is much more vast than that of objects (https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/rtl-extra/src/inc/objects.pp?revision=40598&view=markup#l1127).
TL;DR: They are simply not compatible and they'll stay that way.
Title: Re: Unified Pascal syntax
Post by: kupferstecher on December 17, 2019, 06:07:34 pm
For starters an object might be located on the stack or the heap, [...]
In contrast a class instance is always located on the heap
Thats clear, but both variables, of type Object and Class carry the memory address of the data block. So regarding the memory access there should be no difference whether its allocated on the stack or heap or whereever else in the RAM.

Quote
[Object...] calling constructors can be considered optional [...]
[Class...] one must call a constructor to instantiate it [...]
Even with Class/Object compatibility this still could stay that way. If the constructor were called from an object type, then the Constructor would be called as plain procedure without reserving memory, as the static memory of an object is reserved already. I think that would be straight forward to use.

Quote
[Object...] and they or may not have a pointer to a VMT depending on the inheritance and the presence of virtual methods. [...]
[Class...] and they always have a pointer to a VMT. Not to mention that the VMT of the later is much more vast than that of objects. [...]
Ok, thats a real incompatibility now. There arises the question if backward compatibility on binary side is always given, or if internal structures could be changed time by time.
Title: Re: Unified Pascal syntax
Post by: PascalDragon on December 18, 2019, 09:53:11 am
For starters an object might be located on the stack or the heap, [...]
In contrast a class instance is always located on the heap
Thats clear, but both variables, of type Object and Class carry the memory address of the data block. So regarding the memory access there should be no difference whether its allocated on the stack or heap or whereever else in the RAM.
Yes, there is a difference. A class can be allocated using a class type and the class that is really instantiated could have a larger size. Let's assume that allocating a class on the stack would work. Then the following code would fail:
Code: Pascal  [Select][+][-]
  1. type
  2.   TMyClass = class
  3.     fMyField: LongInt;
  4.   end;
  5.   TMyClasses = class of TMyClass;
  6.  
  7.   TMySubClass = class(TMyClass)
  8.     fMySubField: LongInt;
  9.   end;
  10.  
  11. procedure Whatever;
  12. var
  13.   o: TMyClass; stack; // this will allocate TMyClass.InstanceSize of memory
  14.   c: TMyClasses;
  15. begin
  16.   c := TMySubClass;
  17.   o := c.Create; // this requires TMySubClass.InstanceSize
  18.   Writeln(TMySubClass(o).fMySubField); // <- BOOM!
  19. end;
  20.  

That's the same reason why you need to allocate object instances on the heap if you want to work with virtual inheritance and such. For class types this is an integral part of the concept and thus combining them essentially reduces classes to objects.
Title: Re: Unified Pascal syntax
Post by: kupferstecher on December 18, 2019, 11:05:27 pm
Firstly let me rewrite your code to my syntax in mind and comment inside. The interface part stays the same.
Code: Pascal  [Select][+][-]
  1. type
  2.   TMyClass = class
  3.     fMyField: LongInt;
  4.   end;
  5.   TMyClasses = class of TMyClass;
  6.  
  7.   TMySubClass = class(TMyClass)
  8.     fMySubField: LongInt;
  9.   end;
  10.  
  11. procedure Whatever;
  12. var
  13.   o: object(TMyClass);  //An instance of TMyClass is allocated on the stack.
  14.                         // Short form for:
  15.                         //  Type TMyObject = object(TMyClass);
  16.                         //  o: TMyObject;
  17.   c: TMyClasses;
  18. begin
  19.   c := TMySubClass;
  20.   o := c.Create;  // This is an unfortunate line of code, as 'o' is already
  21.                   // allocated on the stack and Create results into a second memory
  22.                   // allocation, because it's called by the class type 'c' and not by an
  23.                   // object type, which would just call the procedure Create without
  24.                   // memory allocation. The address of the class type is written
  25.                   // into 'o' which leads into a memory leak (until the procedure is left).
  26.   Writeln(TMySubClass(o).fMySubField); // That would still work, as 'o' references the
  27.                                        // instantiated class and not the original object.
  28. end;
  29.  
As you can see, the object/class mixture in that special case wouldn't result in useful code, but it would still be legit code. In the example the limitations of the object type are already on syntax level as it's a result of the memory allocation (time and place) and of the behaviour of the constructor-call. Thus the compiler wouldn't have to do special checks for which features are allowed or not for object or class type.
But perhaps I'm missing something...


That's the same reason why you need to allocate object instances on the heap if you want to work with virtual inheritance and such.
Can you give an example for that?

The following (hypothetical) code should work with fully static memory:

Code: Pascal  [Select][+][-]
  1. Type TMyObj = object
  2.   Procedure DoSomething; virtual;
  3. end;
  4.  
  5. Type TMySubObj = object(TMyObj);
  6.   Procedure DoSomething; override;
  7. end;
  8.  
  9. var
  10.   obj: TMyObj;
  11.   subObj: TMySubObj;
  12.   vObj: class(TMyObj); // Serves as pointer, doesn't allocate memory
  13. begin
  14.   vObj:= obj;
  15.   vObj.DoSomething; // Calls TMyObj.DoSomething
  16.   vObj:= subObj;
  17.   vObj.DoSomething; // Calls TMySubObj.DoSomething
  18. end;

Quote
For class types this is an integral part of the concept and thus combining them essentially reduces classes to objects.
The class reference feature "class of T..." wouldn't be applicable to objects (that means no "object of T.."), but classes still can have it. I still think objects and classes could behave quite orthogonal without the reduce of any features.
Title: Re: Unified Pascal syntax
Post by: PascalDragon on December 19, 2019, 09:46:18 am
Firstly let me rewrite your code to my syntax in mind and comment inside. The interface part stays the same.
Code: Pascal  [Select][+][-]
  1. type
  2.   TMyClass = class
  3.     fMyField: LongInt;
  4.   end;
  5.   TMyClasses = class of TMyClass;
  6.  
  7.   TMySubClass = class(TMyClass)
  8.     fMySubField: LongInt;
  9.   end;
  10.  
  11. procedure Whatever;
  12. var
  13.   o: object(TMyClass);  //An instance of TMyClass is allocated on the stack.
  14.                         // Short form for:
  15.                         //  Type TMyObject = object(TMyClass);
  16.                         //  o: TMyObject;
  17.   c: TMyClasses;
  18. begin
  19.   c := TMySubClass;
  20.   o := c.Create;  // This is an unfortunate line of code, as 'o' is already
  21.                   // allocated on the stack and Create results into a second memory
  22.                   // allocation, because it's called by the class type 'c' and not by an
  23.                   // object type, which would just call the procedure Create without
  24.                   // memory allocation. The address of the class type is written
  25.                   // into 'o' which leads into a memory leak (until the procedure is left).
  26.   Writeln(TMySubClass(o).fMySubField); // That would still work, as 'o' references the
  27.                                        // instantiated class and not the original object.
  28. end;
  29.  
As you can see, the object/class mixture in that special case wouldn't result in useful code, but it would still be legit code. In the example the limitations of the object type are already on syntax level as it's a result of the memory allocation (time and place) and of the behaviour of the constructor-call. Thus the compiler wouldn't have to do special checks for which features are allowed or not for object or class type.
But perhaps I'm missing something...
First you declare it as "an object", thus it's on the stack and then suddenly there's a heap allocation thanks to the constructor. How is a user to know what is going on now, especially when they're somewhere down in the code? No, that's not a good design.

That's the same reason why you need to allocate object instances on the heap if you want to work with virtual inheritance and such.
Can you give an example for that?

The following (hypothetical) code should work with fully static memory:
I'm not talking about hypothetical code, I'm talking about existing code:

Code: Pascal  [Select][+][-]
  1. uses
  2.   SysUtils;
  3.  
  4. type
  5.   TMyObj = object
  6.     Procedure DoSomething; virtual;
  7.   end;
  8.  
  9.   TMySubObj = object(TMyObj)
  10.     Procedure DoSomething; virtual;
  11.   end;
  12.  
  13. procedure TMyObj.DoSomething;
  14. begin
  15.   Writeln('Obj');
  16. end;
  17.  
  18. procedure TMySubObj.DoSomething;
  19. begin
  20.   Writeln('SubObj');
  21. end;
  22.  
  23. var
  24.   obj: TMyObj;
  25.   subObj: TMySubObj;
  26. begin
  27.   obj.DoSomething;
  28.   Obj:= subObj;
  29.   Obj.DoSomething;
  30. end.
  31.  

The compiler even warns here:
Code: [Select]
PS E:\fpc\git> fpc -FEtestoutput .\fpctests\tobjtest.pp
Free Pascal Compiler version 3.0.4 [2019/10/27] for i386
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling .\fpctests\tobjtest.pp
tobjtest.pp(10,4) Warning: Virtual methods are used without a constructor in "TMyObj"
tobjtest.pp(18,4) Warning: Virtual methods are used without a constructor in "TMySubObj"
tobjtest.pp(39,3) Warning: Variable "obj" does not seem to be initialized
tobjtest.pp(40,9) Warning: Variable "subObj" does not seem to be initialized
Linking testoutput\tobjtest.exe
42 lines compiled, 0.2 sec, 64192 bytes code, 4100 bytes data
4 warning(s) issued

And here's the BOOM:

Code: [Select]
PS E:\fpc\git> .\testoutput\tobjtest.exe
An unhandled exception occurred at $00401544:
EAccessViolation: Access violation
  $00401544

The whole discussion is moot anyway however as we are not going to change that objects and classes are different.
Title: Re: Unified Pascal syntax
Post by: kupferstecher on December 19, 2019, 11:11:05 am
First you declare it as "an object", thus it's on the stack and then suddenly there's a heap allocation thanks to the constructor. How is a user to know what is going on now, especially when they're somewhere down in the code? No, that's not a good design.
It just makes no sense to mix the object and class type within the one line of calling the constructor. The compiler could even cover that by prompting an error, but that are details.

Why they should be compatible:
1. Then its very easy to change between both types
2. Imho there should be a possibility for static allocation of a class
3. The class type could function as easy to use pointers for objects (avoids the cryptic use of real pointers)


I'm not talking about hypothetical code, I'm talking about existing code:
[...]
And here's the BOOM:
I see. But there's an issue:
The allocation of the overridden method is done in the construtor and that means one could define an object and call the Creator of a subclassed object, then the object carries the methods of the subclass. So far so good, but the variables added by the subobject are statically allocated beforehand. The subclassed method now could access memory which actually is not available.
So I wonder what is it good for that the inheritance is not defined by the compiler on compile time and instead waits for the Constructor to be called.

The whole discussion is moot anyway however as we are not going to change that objects and classes are different.
I know. Still I hope that I can give you inspirations when you think about that topics and also this helps me to further understand the language and the internals of the compiler. And finally its just interesting to think about it.
Title: Re: Unified Pascal syntax
Post by: Shpend on December 19, 2019, 04:51:59 pm
As much as I can understand that building new stuff for a compiler (especially if its not driven financially and also not by a central Head aka projectmanager or the like) that its alot of hardwork to be done, to implement such a feature, to be absolutely honest, I only had one particular featurea from C++ in mind which is very powerful (hence they embedded it very early in C++) that you can have everything what a class can but also the option to put it on a stack or heap, but you  alwaays have both, nevermind which exact memory layout it has.

But well, you guys have to set ur priorities and the points you have mentioned earlier, @PascalDragon, are also very much needed for the FPC, so go ahead, I just want to throw the caviet out, allways, when I open up a thread like this, my only intention is to, so to speak, brainstorm with you guys, what can be done in theory if and when you implement it, is another question you have to answer for yourself!
TinyPortal © 2005-2018