Jump to content

Stefan Glienke

Members
  • Content Count

    1497
  • Joined

  • Last visited

  • Days Won

    152

Everything posted by Stefan Glienke

  1. If you mean the TArray class with the Sort methods and so on then it's System.Generics.Collections. TArray<T> in System is not a class but a dynamic array declaration.
  2. Stefan Glienke

    Is it bug? (type inference)

    Whatever... all types with TypeKind = tkFloat 🤷‍♂️
  3. Stefan Glienke

    Is it bug? (type inference)

    I don't know what you mean 😉 Yes, I meant decimal type
  4. Stefan Glienke

    Is it bug? (type inference)

    Bug and already reported - all types of typekind = tkFloat getting inferred as Extended - which then causes followup errors: https://quality.embarcadero.com/browse/RSP-25799 https://quality.embarcadero.com/browse/RSP-31289
  5. Stefan Glienke

    Compiler detecting repeated lines?

    No On a more serious note: This would require the compiler to know that the repeated call is to a pure function - GCC for example has such an optimization, clang on the other hand as far as I could find (I did not spend much time) does not.
  6. Stefan Glienke

    Unit testing for beginners

    The benefit is having individual test cases generated which can be executed individually - if you ever messed with conditional breakpoints or pass counters to stop at exactly those args that cause the failure you know what I mean.
  7. Stefan Glienke

    Unit testing for beginners

    If you type "how to unit test and what to test" into google the first page lists a plethora of good articles on the subject
  8. Stefan Glienke

    Hot Reload in Delphi?

    Because hot reload is a modern part of the R in RAD. Stopping, recompiling and getting to the point where you were before the change would be completely unnecessary. Game devs using UE or similar tools have been using this for quite a while.
  9. Stefan Glienke

    Hot Reload in Delphi?

    They cannot even build a stable debugger - how could they ever achieve this.
  10. Stefan Glienke

    CharInSet revisited (again)

    Hence my word of warning You might not want to suffer the same amount of pain as I do
  11. Stefan Glienke

    CharInSet revisited (again)

    This has nothing to do with CharInSet per se but the fact that the Win64 compiler obviously is doing a poor job inlining it. Win32 code looks like this (i modified it slightly using a loop var rather than increasing the PChar): CharInSet.dpr.18: while not CharInSet(cp[i], [#0, #13, #10]) do 004C999C 0FB71446 movzx edx,[esi+eax*2] 004C99A0 6685D2 test dx,dx 004C99A3 740C jz $004c99b1 004C99A5 6683EA0A sub dx,$0a 004C99A9 7406 jz $004c99b1 004C99AB 6683EA03 sub dx,$03 004C99AF 75EA jnz $004c999b CharInSet.dpr.48: while not (cp[i] in [#0, #13, #10]) do 004C9B5B 0FB70C42 movzx ecx,[edx+eax*2] 004C9B5F 6685C9 test cx,cx 004C9B62 740C jz $004c9b70 004C9B64 6683E90A sub cx,$0a 004C9B68 7406 jz $004c9b70 004C9B6A 6683E903 sub cx,$03 004C9B6E 75EA jnz $004c9b5a Caution: if you go down that road you might feel the urge to rewrite half (if not more) of your code that is using RTL functions because the Win64 compiler does some terrible job on many of them. Edit: reported codegen issue: https://quality.embarcadero.com/browse/RSP-35981
  12. I leave that as an exercise to anyone who needs it - I would not want to have it run through the virtual Get and GetObject functions for every iteration. As for "All that hacking"- it's only that one private field access. And even that could be done a little cleaner by using the helper with Self trick. I always use records for enumerators except when I don't 😉
  13. program StringListHelper; {$APPTYPE CONSOLE} uses Classes, System.SysUtils; type TStringListItem = record str: string; obj: TObject; end; TStringListPairs = record private List: TStringList; type TEnumerator = record private List: TStringList; Index: Integer; function GetCurrent: TStringListItem; public function MoveNext: Boolean; property Current: TStringListItem read GetCurrent; end; TStringListAccess = class(TStrings) private FList: TStringItemList; end; public function GetEnumerator: TEnumerator; end; TStringListHelper = class helper for TStringList public function Pairs: TStringListPairs; inline; end; { TStringListPairs.TEnumerator } function TStringListPairs.TEnumerator.GetCurrent: TStringListItem; begin Result := TStringListItem(TStringListAccess(List).FList[Index]); end; function TStringListPairs.TEnumerator.MoveNext: Boolean; begin Inc(Index); Result := Index < List.Count; end; { TStringListHelper } function TStringListHelper.Pairs: TStringListPairs; begin Result.List := Self; end; { TStringListPairs } function TStringListPairs.GetEnumerator: TEnumerator; begin Result.List := List; Result.Index := -1; end; var sl: TStringList; begin sl := TStringList.Create; for var p in sl.Pairs do if p.str = 'foo' then Writeln(p.obj.ClassName); end.
  14. Wrong, string and object are in the same entry - the internal storage of a TStringList has an array of TStringItem which is a record which contains a string and an object. You simply find it like this: function findSomething( const aStringArg : string ) : TObject; var i: Integer; begin i := sl.IndexOf(aStringArg); if i >= 0 then Result := sl.Objects[i] else Result := nil; end; Make this a method in your own TStringListHelper and there you go. If you want easy and fast lookup of objects by string key, then use a dictionary.
  15. Second but without Egyptian begin/end.
  16. Stefan Glienke

    Maximum static memory

    I am sure you did not mean that as it came across because to me it sounded like an insult to any member of Delphi Praxis.
  17. Stefan Glienke

    Calling inherited in Destroy

    Should as in "it would be desirable" but the Delphi compiler does not do that. This is usually achieved by compilers by either automatically inlining calls and then noticing there is nothing in such call hence no call/code to emit at all or by applying WPO or LTO. Both are things the Delphi compiler does not do. The Delphi compiler does not inline inherited calls if the method is virtual which Destroy is.
  18. Most likely a sampling variation - the majority of time is spent on the div instruction inside the loop in the OneLoop routine and that did not change - and is not optimizable in any way. Quickly looking into the code that clang or gcc produce it looks pretty similar so I assume VC++ does the same.
  19. No, that only affects the ability to properly see the content of the list when debugging
  20. Most likely this: https://quality.embarcadero.com/browse/RSP-30870
  21. Stefan Glienke

    How to manage feature changes during release cycle?

    We used to do Git flow but recently changed to GitLab flow. It basically goes like this:
  22. Stefan Glienke

    Why empty dynamic arrays = NIL?

    Nope, depending on the target version I am writing "if StringVar.IsEmpty" 😉
  23. Stefan Glienke

    Why empty dynamic arrays = NIL?

    Fixed it for you: const EmptyArray = nil; var numbers: TArray<Integer>; begin if numbers <> EmptyArray then Writeln('not empty'); end.
  24. Stefan Glienke

    Why empty dynamic arrays = NIL?

    Because a pointer to empty would be quite stupid. While you can technically build an allocated array with a capacity of zero with some hacking the RTL always cleans up the memory as soon as an arrays length becomes 0. Fun fact - checking against nil for the purpose of "is it empty or not" opposed to comparing Length to 0 is slightly faster: procedure test(const a: TBytes); begin if a <> nil then Writeln; if Length(a) > 0 then Writeln; end; CheckArray.dpr.12: begin 0041D57C 53 push ebx 0041D57D 8BD8 mov ebx,eax CheckArray.dpr.13: if a <> nil then 0041D57F 85DB test ebx,ebx 0041D581 740F jz $0041d592 CheckArray.dpr.14: Writeln; 0041D583 A1B4254200 mov eax,[$004225b4] 0041D588 E8CF7DFEFF call @WriteLn 0041D58D E8B270FEFF call @_IOTest CheckArray.dpr.15: if Length(a) > 0 then 0041D592 8BC3 mov eax,ebx 0041D594 85C0 test eax,eax 0041D596 7405 jz $0041d59d 0041D598 83E804 sub eax,$04 0041D59B 8B00 mov eax,[eax] 0041D59D 85C0 test eax,eax 0041D59F 7E0F jle $0041d5b0 CheckArray.dpr.16: Writeln; 0041D5A1 A1B4254200 mov eax,[$004225b4] 0041D5A6 E8B17DFEFF call @WriteLn 0041D5AB E89470FEFF call @_IOTest CheckArray.dpr.17: end; 0041D5B0 5B pop ebx 0041D5B1 C3 ret
  25. Stefan Glienke

    We use DUnitX and it discovers all our silly mistakes before release

    No, I took the state from SourceForge years ago and removed all the cruft that I did not need and refactored some things. Also due to the fragmentation of the project it was kinda hard to see what is actually the most recent one. I just learned that probably your fork is.
×