Re: [fpc-pascal] Traits Proposal
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
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
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
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
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
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
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
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
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
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
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
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