Recent

Author Topic: Considerations in the decision of adding a feature to the FPC compiler?  (Read 2092 times)

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7613
What Leledumbo says, and that also illustrates that one should be very careful with borrowing features. What it ends up being might be different from how it is in a different language.

The classic example is GC. People compare languages with movable, generational GCs designed into the core, and then say "Yes, but you can also whack a GC under C, so it should also be possible for Pascal". NO, not the SAME  GC :_)

Anyway, radical changes are not considered AT ALL anyway.

And personally, I think the undirected drive to modernization is just a pretext for forcing random language experimentation into a project where it doesn't belong.
« Last Edit: June 12, 2019, 08:43:11 am by marcov »

PascalDragon

  • Hero Member
  • *****
  • Posts: 716
  • Compiler Developer
Quote
Is there some somewhat "formal"/"structured" process that leads to the decision of including/excluding such features ?

No. If a committer wants to commit them, there is sometimes discussion on maillists. Unfortunately IMHO it gets accepted way too often with the argument "you don't have to use it if you don't like it".
I think the recent discussions on fpc-devel showed that we're still not accepting everything and the kitchen sink. ;)

In my opinion the feature list is already too long. It's nearly impossible to know all the possibilities, the syntax options and all side effects of the various features of fpc.
So instead of introducing new features I would suggest to do some tidy up.
E.g.
- The writable typed constant concept as local static variable is counter intuitive, perhaps constants should never be variables.
- Classes, objects, advanced records. Thats one to much.
- Modula-2 syntax for blocks: if ... then ... end; for... do ... end;
- Passing constant values to var parameters should be possible. (Well, this would be backward compatible)
- Parameters as var, out, const, constref... perhaps this could be done better.
- Volatility (I know it was introduced, but as I understand if the compiler really builds on it, this would break existing code)

These are just examples, don't need to discuss them. I also know that there are very good reasons why it is done the way it currently is. Furthermore, breaking backward compatibility is a huge step.
No. Just no. Both compatibility to TP/Delphi and backwards compatibility are important core concepts of FPC (though the Delphi compatibility got quite a chink with Delphi introducing inline variables %) ) and thus we won't restructure core concepts only because some think that it's too much. Those people can always start a new compiler, cause that's what it would be essentially.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 635
Half my projects end up written in a different language, simply because the lack of support for the library or target. Like bigint, iOS or embedded. Mac is still not complete. And the installation still fails half the time (especially on Linux).

Ok, not as sexy as adding stuff to the environment you actively use to code, but if you want to grow support for the language, the most important feature is that you can start coding your new project right away. If it takes days or weeks of effort before you can start, most people take an alternative development platform. And the few who do make the effort end up as part of the dev team.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8114
  • Programming + Glam Metal + Tae Kwon Do = Me
but, I think of Nim as a macro language itself since it doesn't compile to native code, it produces C. 
If you take a look at the generated C code, or how it's generated, it's far from other compilers that transpiles to C, where the C code is usually still human readable. The author treats C like an abstract architecture, hence the generated C code looks more assembly-ish than C converted code.

440bx

  • Hero Member
  • *****
  • Posts: 1273
but, I think of Nim as a macro language itself since it doesn't compile to native code, it produces C. 
If you take a look at the generated C code, or how it's generated, it's far from other compilers that transpiles to C, where the C code is usually still human readable. The author treats C like an abstract architecture, hence the generated C code looks more assembly-ish than C converted code.
I'm not familiar enough with Nim to evaluate it properly but, the fact that a separate compiler is involved in the process of getting executable code makes me uncomfortable.  That additional compiler is, at least potentially, another source of problems.
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8114
  • Programming + Glam Metal + Tae Kwon Do = Me
I'm not familiar enough with Nim to evaluate it properly but, the fact that a separate compiler is involved in the process of getting executable code makes me uncomfortable.  That additional compiler is, at least potentially, another source of problems.
Indeed, it was a source of attraction by supporting multiple C compilers. It actually has more than 1 backend, the compiler can generate C, C++, Objective-C and JavaScript. Much like FPC with HL codegen backend only plus Pas2JS.

Akira1364

  • Hero Member
  • *****
  • Posts: 539
In general, I think there's certainly a difference between mere syntax extensions and things that make it possible to write better-optimized code than you could previously.

Personally I'm hoping to see some more movement on getting the generic constants feature, shown here: https://bugs.freepascal.org/view.php?id=35140 merged sometime soon.

Thaddy

  • Hero Member
  • *****
  • Posts: 9285
Well, the only thing I really miss is anonymous methods because I have a lot of dual code base between Delphi and FPC.
But that is already in progress. Freepascal has already so many features above and beyond that I can understand the hesitation to add new features that extend the language once more.
also related to equus asinus.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7613
And gettypekind in generics.

Akira1364

  • Hero Member
  • *****
  • Posts: 539
Well, the only thing I really miss is anonymous methods because I have a lot of dual code base between Delphi and FPC.
But that is already in progress.

It's been in progress for a lot longer than it should have been, I think. Blaise seems to keep disappearing for long stretches of time and then reappearing.

And gettypekind in generics.

I'm pretty sure it works in generics at least in trunk. You can't currently use it in constants or within scanner conditionals though, which you can in Delphi. That said, I actually have a patch I've been working on that enables this, and also adds Delphi-compatible IsManagedType and IsConstValue intrinsics that I might submit soon. (FWIW, adding those intrinsics was actually... very easy, as the compiler has internal methods that provide basically exactly the required functionality.)
« Last Edit: June 21, 2019, 03:36:11 pm by Akira1364 »

Thaddy

  • Hero Member
  • *****
  • Posts: 9285
Anonymous methods are not easy to implement. Be graceful some people take the effort. And note: the way Delphi does it with hidden interfaces is not optimal.
Although notationally easy it has a performance hit.
« Last Edit: June 20, 2019, 04:28:21 pm by Thaddy »
also related to equus asinus.

Akira1364

  • Hero Member
  • *****
  • Posts: 539
And note: the way Delphi does it with hidden interfaces is not optimal.
Although notationally easy it has a performance hit.

I'm aware. I think this is also how the FPC implementation works, unfortunately. Hopefully at some point after it's initially implemented, it can be reworked in a more optimal way for situations where no variables need to be captured and forwarded.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7613
I'm pretty sure it works in generics at least in trunk. You can't currently use it in constants or within scanner conditionals though, which you can in Delphi. That said, I actually have a patch I've been working on that enables this, and also adds Delphi-compatible IsMangagedType and IsConstValue intrinsics that I might submit soon. (FWIW, adding those intrinsics was actually... very easy, as the compiler has internal methods that provide basically exactly the required functionality.)

My bad. I indeed meant ismanagedtype and not gettypekind and specialization time elimination of other branches

PascalDragon

  • Hero Member
  • *****
  • Posts: 716
  • Compiler Developer
I'm pretty sure it works in generics at least in trunk. You can't currently use it in constants or within scanner conditionals though, which you can in Delphi. That said, I actually have a patch I've been working on that enables this, and also adds Delphi-compatible IsMangagedType and IsConstValue intrinsics that I might submit soon. (FWIW, adding those intrinsics was actually... very easy, as the compiler has internal methods that provide basically exactly the required functionality.)

My bad. I indeed meant ismanagedtype and not gettypekind and specialization time elimination of other branches
The specialization time elimination is already done by the compiler if it can do it (so once IsManagedType and IsConstValue are supported that should be immediately picked up as well; GetTypeKind already does that correctly, cause I explicitely tested that):
Code: Pascal  [Select]
  1. generic function GenSwapEndian<T>(aValue: T): T; inline;
  2. begin
  3.   case SizeOf(aValue) of
  4.     1:
  5.       Result := aValue;
  6.     2:
  7.       Result := SwapEndian(UInt16(aValue));
  8.     4:
  9.       Result := SwapEndian(UInt32(aValue));
  10.     8:
  11.       Result := SwapEndian(UInt64(aValue));
  12.   end;
  13. end;
  14.  
  15. procedure Test;
  16. var
  17.   u8: UInt8;
  18.   u16: UInt16;
  19.   u32: UInt32;
  20.   u64: UInt64;
  21. begin
  22.   specialize GenSwapEndian<UInt8>(u8);
  23.   specialize GenSwapEndian<UInt16>(u16);
  24.   specialize GenSwapEndian<UInt32>(u32);
  25.   specialize GenSwapEndian<UInt64>(u64);
  26. end;
  27.  
The assembler code of Test then looks like this (unlike Delphi we also inline correctly  :-[ ):
Code: [Select]
.section .text.n_p$thelloworld_$$_test,"x"
.balign 16,0x90
.globl P$THELLOWORLD_$$_TEST
P$THELLOWORLD_$$_TEST:
# [42] begin
pushl %ebp
movl %esp,%ebp
leal -24(%esp),%esp
# Var u8 located at ebp-4, size=OS_8
# Var u16 located at ebp-8, size=OS_16
# Var u32 located at ebp-12, size=OS_32
# Var u64 located at ebp-24, size=OS_64
# [43] specialize GenSwapEndian<UInt8>(u8);
movb -4(%ebp),%al
# [44] specialize GenSwapEndian<UInt16>(u16);
movzwl -8(%ebp),%eax
shrl $8,%eax
movzwl -8(%ebp),%edx
shll $8,%edx
orl %edx,%eax
# [45] specialize GenSwapEndian<UInt32>(u32);
movl -12(%ebp),%eax
shll $8,%eax
andl $-16711936,%eax
movl -12(%ebp),%edx
shrl $8,%edx
andl $16711935,%edx
orl %edx,%eax
roll $16,%eax
# [46] specialize GenSwapEndian<UInt64>(u64);
pushl -20(%ebp)
pushl -24(%ebp)
call SYSTEM_$$_SWAPENDIAN$QWORD$$QWORD
# [47] end;
movl %ebp,%esp
popl %ebp
ret