Re: [fpc-pascal] Traits Proposal

2021-02-13 Thread Ben Grasset via fpc-pascal
This seems possibly a *little* too similar to the existing Interface type
in Object Pascal, however, I *would* really like to see some kind of
functionality that basically amounts to "has the same capabilities as
Interfaces and works on records and objects too, but does NOT require any
kind of heap allocation".

So whether it be this, or just an improvement on the Interfaces we already
have, I'd definitely personally be in favor of something that "works like
Interfaces except minus the negative performance implications."

On Tue, Feb 9, 2021 at 9:27 PM Ryan Joseph via fpc-pascal <
fpc-pascal@lists.freepascal.org> wrote:

> We had talked about this some time ago and it's been rattling around in my
> brain so I wanted to write it down into a formal proposal where we can
> discuss it and hopefully agree upon a syntax. Everything is preliminary and
> tentative but this is a syntax which allows a "composition over
> inheritance" model, also known as "mix-ins" in some languages. That idea is
> similar to multiple inheritance except you have a concrete reference to the
> trait being implemented so you can resolve conflicts easily.
>
> Here's what I have so far. Please feel free to look at it and give any
> feedback.
>
> https://github.com/genericptr/freepascal/wiki/Traits-Proposal
>
> 
>
> type
>   TSomeTrait = trait
> public
>   field: integer;
>   procedure DoThis;
>   end;
>
>   TMyClass = class
> private
>   _trait: TSomeTrait;
> public
>   property someTrait: TSomeTrait implements _trait;
>   end;
>
> var
>   c: TMyClass;
> begin
>   c := TMyClass.Create;
>   c.DoThis;
>   writeln(c.field):
> end;
>
> Regards,
> Ryan Joseph
>
> ___
> fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
>
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] fpcmake packaging

2020-09-26 Thread Ben Grasset via fpc-pascal
What you want is FPMake, not FPCMake. FPCMake is just a generator of GNU
makefiles. As Michael said elsewhere though, FPMake is an API designed
specifically for compiling FPC programs, basically. You write a program
using the API, put it in a file that should always be called "fpmake.pp",
and then either invoke fppkg on it or just literally build it with FPC
yourself and run it (as in like, either "fppkg build" in the directory
where your "fpmake.pp" is, or "fpc ./fpmake.pp && ./fpmake build" in the
directory where your "fpmake.pp" is). Again though, since it is literally
just a program, you can also put any custom logic you want in there.

See here for more info: https://wiki.freepascal.org/FPMake

On Tue, Sep 1, 2020 at 9:05 AM Ryan Joseph via fpc-pascal <
fpc-pascal@lists.freepascal.org> wrote:

> I've never used fpcmake before and instead relied on my own custom build
> system solutions which are a pain to maintain and non-standard which it
> makes extra work configuring the pascal language server I'm using now.
>
> My first question of fpcmake is, can I package application bundles and
> copy resources using it? For example some things I need to do:
>
> - create a directory structure and copy the executable into it
> - copy resource files that may have changed
> - run some shell commands which apple provides for compiling various
> resources files
> - copy a info.plist text file and replace some patterns in the file to
> reflect the build version
>
> Are those the kind of things fpcmake can do or do I need another build
> system for this?
>
> Regards,
> Ryan Joseph
>
> ___
> fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
>
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Generic type conflicts

2019-11-08 Thread Ben Grasset via fpc-pascal
On Fri, Nov 8, 2019 at 11:18 AM Ben Grasset  wrote:

> I know what you mean, and I'm aware, but you actually kind of can to the
> fairly straightforward extent that I'm concerned about with Ryan's patch
> (i.e. simply passing constant results as constraints rather than function
> parameters.)
>

Also, if you were referring specifically to the "making the choice part",
looking at the PDQSort C++ code again, all it was actually doing is
evaluating the *types* involved, not the comparison function itself. Which
would be fairly straightforward to replicate in FPC using something like a
constant TTypeKind constraint.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Generic type conflicts

2019-11-08 Thread Ben Grasset via fpc-pascal
On Fri, Nov 8, 2019 at 11:04 AM Jonas Maebe  wrote:

> You can't. It's the main difference between C++ templates, which is a
> Turing-complete programming language, and generics, which is simply a
> parametrising mechanic.
>

I know what you mean, and I'm aware, but you actually kind of can to the
fairly straightforward extent that I'm concerned about with Ryan's patch
(i.e. simply passing constant results as constraints rather than function
parameters.)
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Generic type conflicts

2019-11-08 Thread Ben Grasset via fpc-pascal
On Fri, Nov 8, 2019 at 1:33 AM Michael Van Canneyt 
wrote:

> As an aside:
> In my opinion (keep in mind I am not a big fan of generics) the above code
> would be a prime example where one should not be using generics, but
> simple overloads.
> If you need to use GetTypeKind in a generic, I think you're on the wrong
> path.
> Use of IsManagedType() in a generic is stretching it, but GetTypeKind() is
> over the line.
>

I agree to an extent that it's not a *huge* problem and that there are
workarounds in many cases, however there's definitely certain things that
simply cannot be achieved in an equally performant way via any alternative
such as normal overloading.

That said, Ryan's currently-in-limbo patch for constant generic parameters
actually itself in theory already provides proper solutions for quite a few
aspects of the general problem, so even as it stands right now we're at
least making progress towards improving the situation I'd say.

For example, I recently did a translation of the fairly well-known
"PDQSort" algorithm from C++ to Pascal:

https://github.com/Akira13641/PasPDQSort

The original C++ version used "constexpr" template parameters to determine
at compile time whether or not the user-provided comparison function was
one for which it should use the "branchless" version of its code for item
partitioning or not, and based on that passed the boolean "true" or "false"
result as another constant template parameter.

The end result of course being that the compiled code is always tuned
precisely to the given comparison function, without any kind of runtime
selection based on non-constant boolean function parameters (which is what
I've currently had to write the "branchless" choice as, defaulting to
"true" unless the user specifies otherwise.)

With Ryan's patch, I'll at least be able to write that choice as a constant
parameter instead, although I'm unaware of any way to replicate actually
having the compiler *make* the choice.

So perhaps what's needed is not even necessarily something like "static if"
support, but rather just more compiler intrinsics along the lines of
GetTypeKind / IsManagedType that evaluate different things and return
constant values, which in combination with Ryan's patch will go a long way
as far as increasing the granularity of control available to users of FPC
as far as this kind of stuff.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Generic type conflicts

2019-11-07 Thread Ben Grasset via fpc-pascal
On Thu, Nov 7, 2019 at 10:23 AM Michael Van Canneyt 
wrote:

> If I understood Sven's example correct, then the compiler does exactly this
> already.
>

It does in the sense of *code generation* for things that are specifically
compiler intrinsics (which I was aware of), but not in a sense that makes
the issue Ryan was posting about here avoidable. Maybe this will explain
what I'm trying to get at a bit better:

program Example;

{$mode ObjFPC}

// Without actually specializing and using GDiv,
// this program compiles fine.

generic function GDiv(const A, B: T): T; inline;
begin
  if GetTypeKind(T) in [tkInteger, tkInt64, tkQWord] then
Result := A div B
  else if GetTypeKind(T) = tkFloat then
Result := A / B
  else
Result := Default(T);
end;

// However, once we do specialize it...

procedure UseGDiv;
begin
  // Example.pas(13,17) Error: Incompatible types: got "Double" expected
"Int64"
  WriteLn(specialize GDiv(1, 2));
  // Example.pas(11,17) Error: Operator is not overloaded: "Double" div
"Double"
  WriteLn(specialize GDiv(1, 2));
end;

// Note: I'm fully aware that having the *normal* if-statement work in such
a way that the
// the above would compile is neither feasible or a good idea. However,
imagine something
// like the following hypothetical version of GDiv, which would rely on the
conditional
// compilation aspect of the scanner to be aware of more than it currently
is, and also
// for the conditional compilation syntax to be somewhat more advanced:

generic function GDiv(const A, B: T): T; inline;
begin
  // Here, we're doing precisely the same kind of thing that is currently
  // possible with SizeOf, Declared, Defined, and so on.
  {$IF GetTypeKind(T) in [tkInteger, tkInt64, tkQWord]}
Result := A div B
  {$ELSEIF GetTypeKind(T) = tkFloat}
Result := A / B
  {$ELSE}
Result := Default(T);
  {$ENDIF}
end;

begin
end.

Of course, implementing that kind of thing in the scanner would likely be
far more difficult than implementing it as something that happens in
"normal" code, via some syntax or perhaps intrinsic that makes it
distinctively a fully-statically-considered conditional, as opposed to a
partially-statically considered one as is the case with normal "if".
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Generic type conflicts

2019-11-07 Thread Ben Grasset via fpc-pascal
On Thu, Nov 7, 2019 at 3:03 AM Sven Barth via fpc-pascal <
fpc-pascal@lists.freepascal.org> wrote:

> If there is no type checking, then it is *not* verified by the compiler.
>

Perhaps "no type checking" was not the write way to put it. A better way to
describe it might be:

Since the compiler *always* knows exactly which type a generic type
constraint currently amounts to, it is clearly capable of properly choosing
specific code paths based on that, if given some kind of
constant-evaluatable boolean condition that is specifically based on
TTypeKind.

In general, it's *exactly* the same concept as something like using SizeOf
in an {$IF} / {$ELSEIF} directive pair (where the compiler does indeed
completely ignore everything in the "false" section):

program Example;

begin
  // You can in fact put stuff that isn't even close to valid code in
whichever block is false for you, below.
  {$IF SizeOf(Pointer) = 4}
WriteLn('The size of a pointer is 4 bytes.');
  {$ELSEIF SizeOf(Pointer) = 8}
WriteLn('The size of a pointer is 8 bytes.');
  {$ENDIF}
end.

Not that it has to do precisely the same thing for a hypothetical
TTypeKind-based choice.

E.G. it could still do the full checking, as the only thing that really
matters is that it does not actively raise error messages only relevant for
Integer under code blocks only entered for tkFloat.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Generic type conflicts

2019-11-06 Thread Ben Grasset via fpc-pascal
On Wed, Nov 6, 2019 at 7:33 PM Ben Grasset  wrote:

> Encouraging typecasting (which cares only about the sizes of the types
> involved, nothing else) at the programmer level is far more error-prone in
> a variety of ways.
>

Also: it's slower in many cases, because it tends to involve "if"
statements that *remain* as if statements in the final generated assembly
code, whereas a static check would allow for simply generating *only* the
code for the path that's actually taken.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Generic type conflicts

2019-11-06 Thread Ben Grasset via fpc-pascal
On Wed, Nov 6, 2019 at 12:44 PM Sven Barth via fpc-pascal <
fpc-pascal@lists.freepascal.org> wrote:

> Pascal has a strong type safety, thus something like the if-expression
> won't be used/allowed to weaken that.
>
> If that means that some things can't be implemented in generics the "easy"
> way, then so be it.
>

I agree that Pascal has strong type safety.

IMO conditional branching based on compile-time constant evaluation, that
cannot fail, does not do anything resembling weakening it, however.

It strengthens it, and has no downsides, because it's verified by the
compiler.

Encouraging typecasting (which cares only about the sizes of the types
involved, nothing else) at the programmer level is far more error-prone in
a variety of ways.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Generic type conflicts

2019-11-06 Thread Ben Grasset via fpc-pascal
On Wed, Nov 6, 2019 at 2:01 AM Sven Barth via fpc-pascal <
fpc-pascal@lists.freepascal.org> wrote:

> A normal if-statements has the same non-evaluation.
>

Not in the way I meant, though.

Like, I thought the difference between "normal if" and "ternary if" was
supposed to be the same as the difference between the existing IfThen()
function and the intrinsic version of IfThen(), on which you based the
"if-then-else" syntax I think.

By which I mean, something similar to the difference between "if" and
"static if" in the D programming language (at least when given things that
are possible to evaluate at compile time, like GetTypeKind is in Pascal).
For example:

import std.stdio;
import std.traits;

// Would not compile, because everything is evaluated fully,
// and in this case the parameters we pass aren't
// compatible with all branches.
void PrintSomething(T)(T value) {
  if (isFloatingPoint!(T)) {
writefln("Floating point value: %f", value * value);
  } else if (isIntegral!(T)) {
writefln("Integral value: %d", value * value);
  } else if (isSomeString!(T)) {
writefln("String value: %s", value ~ value);
  }
}

// Compiles fine, as only the relevant branch for
// a given parameter is evaluated.
void StaticPrintSomething(T)(T value) {
  static if (isFloatingPoint!(T)) {
writefln("Floating point value: %f", value * value);
  }
  else static if (isIntegral!(T)) {
writefln("Integral value: %d", value * value);
  }
  else static if (isSomeString!(T)) {
// "~" does string concatenation in D
writefln("String value: %s", value ~ value ~ value);
  }
}

void main() {
  StaticPrintSomething(1);
  StaticPrintSomething(1.0);
  StaticPrintSomething("hey");
}

The point being that the type-checking is neither useful or necessary in
scenarios where the branch being evaluated is statically known to be
unreachable ahead of time.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Generic type conflicts

2019-11-05 Thread Ben Grasset via fpc-pascal
On Tue, Nov 5, 2019 at 5:24 PM Sven Barth via fpc-pascal <
fpc-pascal@lists.freepascal.org> wrote:

> Does this really work? Cause the compiler should nevertheless typecheck
> the code in the other branch and thus without casts that shouldn't compile.
> Also if it should indeed work, it would also work without the
> if-expression, but with an if-statement.
>

Hm, it actually doesn't quite for that particular example, testing it for
real. It definitely did for a few other generic things I experimented with
though (that were impossible otherwise.) I'll see if I can find the source
files anywhere.

Why would it work the same way as a normal if statement, though? Isn't the
non-evaluation of the false branch pretty much the only point of the
ternary "form"? E.G. you'd specifically use it when you had two branches
that you knew would never *both* be compilable.
You'd be able to do the same thing with an {$IFDEF}, for example, if
{$IFDEFS} specifically carried through across generic specializations.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Generic type conflicts

2019-11-05 Thread Ben Grasset via fpc-pascal
On Sat, Nov 2, 2019 at 11:51 AM Ryan Joseph via fpc-pascal <
fpc-pascal@lists.freepascal.org> wrote:

> Are there any solutions for this currently? I feel like generics need to
> support some compiler directives so different blocks of code can specialize
> different depending on the type.
>

There's one, that works *exactly* like you want (although it's not
currently present in trunk FPC) which is to apply the (still-working) patch
Sven posted in this mailing list thread a few years ago:
https://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg41336.html

It introduces a const-evaluated "ternary if" of the form "Variable := if
Expression else Expression;" where only the true branch is taken into
consideration by the compiler at all.

Combining it with handy compiler intrinsics like GetTypeKind makes stuff
like the following modified version of your code possible:

{$mode objfpc}
{$modeswitch advancedrecords}

program generic_vector_2;

type
  generic TVec2 = record
X, Y: TScalar;
class function Create(const AX, AY: TScalar): TVec2; static; inline;
class operator / (const Left, Right: TVec2): TVec2; inline;
  end;

  class function TVec2.Create(const AX, AY: TScalar): TVec2;
  begin
with Result do begin
  X := AX;
  Y := AY;
end;
  end;

  class operator TVec2./(const Left, Right: TVec2): TVec2;
  begin
// GetTypeKind is evaluated at compile time, so the following works
perfectly with "ternary if".
Result :=
  if GetTypeKind(TScalar) = tkFloat then
TVec2.Create(Left.X / Right.X, Left.Y / Right.Y)
  else
TVec2.Create(Left.X div Right.X, Left.Y div Right.Y);
  end;

type
  TVec2f = specialize TVec2;
  TVec2i = specialize TVec2;

begin
end.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal