Jump to content

Mahdi Safsafi

Members
  • Content Count

    38
  • Joined

  • Last visited

Community Reputation

14 Good

About Mahdi Safsafi

  • Birthday 02/12/1993

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Mahdi Safsafi

    Passing back a string from an external program

    @David Heffernan You can use LoadLibrary with exe file ! The only things is that you need to keep an eye on initialisation.
  2. Mahdi Safsafi

    Passing back a string from an external program

    You don't need to convert Program2 into DLL. Just exports your functions and consume them directly from Program1 (just like DLL). // ========================================== Program1 ========================================== program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, WinApi.Windows; const Program2 = 'Project2.exe'; type TGetProgram2Result = function(Param1, Param2: Integer): string; var LIB: HMODULE; GetProgram2Result: TGetProgram2Result = nil; s: string = ''; begin try LIB := LoadLibrary(Program2); @GetProgram2Result := GetProcAddress(LIB, 'GetProgram2Result'); s := GetProgram2Result(5, 2); Writeln(s); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. // ========================================== Program2 ========================================== program Project2; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, WinApi.Windows; function GetProgram2Result(Param1, Param2: Integer): string; begin Result := Format('%d+%d=%d', [Param1, Param2, Param1 + Param2]); end; // ------------- EXPORTS ------------- exports GetProgram2Result; begin try Writeln('This is Program2'); Writeln(GetProgram2Result(5, 2)); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
  3. In addition to what @Stefan Glienke pointed out, there is a problem with your prototypes, your function does not change aQuality param so why you're passing it by value ? Also you're adding extra-no-sense comparison : if aQuality = rsPoor then Result := 0 // you may remove this one ! ... else Result := 0; // rsPoor covered here !
  4. Mahdi Safsafi

    Relaxed JSON

    Are you sure about that ?
  5. Mahdi Safsafi

    EmptyString constant

    For me, I found it useful in the following cases: - The Sync mode utility works great with EmptyStr. - I edit a lot of my pas files manually using Notepad, so I just select one EmptyStr and I can clearly see all places where the EmptyStr was implemented. - Last thing, it's a mind trick, I pay much more attention for arguments that use EmptyStr. Blabla(... , EmptyStr); // focus on that call. Blabla(... , ''); // usually I ignore it.
  6. Mahdi Safsafi

    How do you organize units, forms?

    Didn't know that GExperts implements such functionality. Does it sort function implementation too ?
  7. Mahdi Safsafi

    Funny Code in System.Types

    Not just the cast ... Result.X := Result.X !
  8. Mahdi Safsafi

    Funny Code in System.Types

    Wow: Result.x := SmallInt(Result.x);
  9. Mahdi Safsafi

    Delphi inline and function evaluation

    of course ! But you know : the MSVC's output didn't impressed me since I was expecting to get such result(especially with the constexpr specifier). However, Delphi did ! I never thought that it can do function evaluation on the fly.
  10. Hello guys, I always thought that the Delphi compiler takes the inlined function and TRIES to insert it (without making a call instruction) where the call to that function occurs. However for some circumstances it can do better ! it TRIES to evaluate the function (just like constexpr in c++) ! Here is an example : program Console1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; function Max(a, b: Integer): Integer; inline; begin if (a > b) then Result := a else Result := b; end; var a: Integer = 5; b: Integer = 9; i: Integer; begin Writeln('--------------------------------'); i := Max(5, 9); // evaluated Writeln(Format('max=%d', [i])); i := Max(a, b); // not evaluated Writeln(Format('max=%d', [i])); Writeln('--------------------------------'); Readln; end. After compiling the above example (x64, Release mode), the compiler generates the following code: //------------------------------------------------------ Delphi ------------------------------------------------------------ 0000000000428510 | 48:8B0D 59880000 | mov rcx,qword ptr ds:[430D70] | 0000000000428517 | 48:8D15 6E010000 | lea rdx,qword ptr ds:[42868C] | rdx:EntryPoint, 000000000042868C:L"--------------------------------" 000000000042851E | E8 2DEFFDFF | call <console1.sub_407450> | 0000000000428523 | 48:89C1 | mov rcx,rax | rax:EntryPoint 0000000000428526 | E8 85F0FDFF | call <console1.sub_4075B0> | 000000000042852B | E8 60D4FDFF | call <console1.sub_405990> | 0000000000428530 | B8 09000000 | mov eax,9 | eax:EntryPoint, 9:'\t' 0000000000428535 | 8905 3D420100 | mov dword ptr ds:[43C778],eax | eax:EntryPoint 000000000042853B | 8B05 37420100 | mov eax,dword ptr ds:[43C778] | eax:EntryPoint 0000000000428541 | 8945 28 | mov dword ptr ss:[rbp+28],eax | eax:EntryPoint 0000000000428544 | C645 30 00 | mov byte ptr ss:[rbp+30],0 | 0000000000428548 | 48:8D4D 38 | lea rcx,qword ptr ss:[rbp+38] | 000000000042854C | 48:8D15 89010000 | lea rdx,qword ptr ds:[<sub_4286DC>] | rdx:EntryPoint, 00000000004286DC:L"max=%d" 0000000000428553 | 4C:8D45 28 | lea r8,qword ptr ss:[rbp+28] | 0000000000428557 | 4D:33C9 | xor r9,r9 | r9:EntryPoint 000000000042855A | E8 C16AFFFF | call <console1.sub_41F020> | 000000000042855F | 48:8B0D 0A880000 | mov rcx,qword ptr ds:[430D70] | 0000000000428566 | 48:8B55 38 | mov rdx,qword ptr ss:[rbp+38] | rdx:EntryPoint 000000000042856A | E8 E1EEFDFF | call <console1.sub_407450> | 000000000042856F | 48:89C1 | mov rcx,rax | rax:EntryPoint 0000000000428572 | E8 39F0FDFF | call <console1.sub_4075B0> | 0000000000428577 | E8 14D4FDFF | call <console1.sub_405990> | 000000000042857C | 8B05 72860000 | mov eax,dword ptr ds:[430BF4] | eax:EntryPoint 0000000000428582 | 3B05 70860000 | cmp eax,dword ptr ds:[430BF8] | eax:EntryPoint 0000000000428588 | 7E 08 | jle console1.428592 | 000000000042858A | 8B05 64860000 | mov eax,dword ptr ds:[430BF4] | eax:EntryPoint 0000000000428590 | EB 06 | jmp console1.428598 | 0000000000428592 | 8B05 60860000 | mov eax,dword ptr ds:[430BF8] | eax:EntryPoint 0000000000428598 | 8905 DA410100 | mov dword ptr ds:[43C778],eax | eax:EntryPoint 000000000042859E | 8B05 D4410100 | mov eax,dword ptr ds:[43C778] | eax:EntryPoint 00000000004285A4 | 8945 28 | mov dword ptr ss:[rbp+28],eax | eax:EntryPoint 00000000004285A7 | C645 30 00 | mov byte ptr ss:[rbp+30],0 | 00000000004285AB | 48:8D4D 20 | lea rcx,qword ptr ss:[rbp+20] | 00000000004285AF | 48:8D15 26010000 | lea rdx,qword ptr ds:[<sub_4286DC>] | rdx:EntryPoint, 00000000004286DC:L"max=%d" 00000000004285B6 | 4C:8D45 28 | lea r8,qword ptr ss:[rbp+28] | 00000000004285BA | 4D:33C9 | xor r9,r9 | r9:EntryPoint 00000000004285BD | E8 5E6AFFFF | call <console1.sub_41F020> | 00000000004285C2 | 48:8B0D A7870000 | mov rcx,qword ptr ds:[430D70] | 00000000004285C9 | 48:8B55 20 | mov rdx,qword ptr ss:[rbp+20] | rdx:EntryPoint 00000000004285CD | E8 7EEEFDFF | call <console1.sub_407450> | 00000000004285D2 | 48:89C1 | mov rcx,rax | rax:EntryPoint 00000000004285D5 | E8 D6EFFDFF | call <console1.sub_4075B0> | 00000000004285DA | E8 B1D3FDFF | call <console1.sub_405990> | 00000000004285DF | 48:8B0D 8A870000 | mov rcx,qword ptr ds:[430D70] | 00000000004285E6 | 48:8D15 9F000000 | lea rdx,qword ptr ds:[42868C] | rdx:EntryPoint, 000000000042868C:L"--------------------------------" 00000000004285ED | E8 5EEEFDFF | call <console1.sub_407450> | 00000000004285F2 | 48:89C1 | mov rcx,rax | rax:EntryPoint 00000000004285F5 | E8 B6EFFDFF | call <console1.sub_4075B0> | 00000000004285FA | E8 91D3FDFF | call <console1.sub_405990> | 00000000004285FF | 48:8B0D 9A880000 | mov rcx,qword ptr ds:[430EA0] | 0000000000428606 | E8 45E6FDFF | call <console1.sub_406C50> | 000000000042860B | E8 80D3FDFF | call <console1.sub_405990> | 0000000000428610 | 90 | nop | You can see that the compiler was able to evaluate the first expression "i := Max(5, 9);" and just generated one single instruction "mov eax, 9". For the second call "i := Max(a, b);" the compiler didn't make any evaluation and it just inlined the function. This is really impressive ! the first call was completely evaluated at the compiling time. I also tested the above example with MSVC and the result was quite different (I was expecting that before running my debugger): #include "pch.h" #include <iostream> inline int max(int a, int b) { return a > b ? a : b; } constexpr int max2(int a, int b) { return a > b ? a : b; } int a = 5; int b = 9; int i; int main() { printf("--------------------------------\n"); i = max(5, 9); // evaluated printf("max=%d\n", i); i = max(a, b); // evaluated printf("max=%d\n", i); i = max2(5, 9); // evaluated printf("max=%d\n", i); i = max2(a, b); // evaluated printf("max=%d\n", i); printf("--------------------------------\n"); } //------------------------------------------------------ CPP ------------------------------------------------------------ 00007FF7DB431070 | 48:83EC 28 | sub rsp,28 | consoleapplication4.cpp:19 00007FF7DB431074 | 48:8D0D 85110000 | lea rcx,qword ptr ds:[7FF7DB432200] | consoleapplication4.cpp:20, 00007FF7DB432200:"--------------------------------\n" 00007FF7DB43107B | E8 90FFFFFF | call <consoleapplication4.printf> | 00007FF7DB431080 | BA 09000000 | mov edx,9 | consoleapplication4.cpp:24, 9:'\t' 00007FF7DB431085 | C705 91250000 09000000 | mov dword ptr ds:[<i>],9 | 9:'\t' 00007FF7DB43108F | 48:8D0D 92110000 | lea rcx,qword ptr ds:[7FF7DB432228] | 00007FF7DB432228:"max=%d\n" 00007FF7DB431096 | E8 75FFFFFF | call <consoleapplication4.printf> | 00007FF7DB43109B | BA 09000000 | mov edx,9 | consoleapplication4.cpp:26, 9:'\t' 00007FF7DB4310A0 | C705 76250000 09000000 | mov dword ptr ds:[<i>],9 | 9:'\t' 00007FF7DB4310AA | 48:8D0D 77110000 | lea rcx,qword ptr ds:[7FF7DB432228] | 00007FF7DB432228:"max=%d\n" 00007FF7DB4310B1 | E8 5AFFFFFF | call <consoleapplication4.printf> | 00007FF7DB4310B6 | BA 09000000 | mov edx,9 | consoleapplication4.cpp:28, 9:'\t' 00007FF7DB4310BB | C705 5B250000 09000000 | mov dword ptr ds:[<i>],9 | 9:'\t' 00007FF7DB4310C5 | 48:8D0D 5C110000 | lea rcx,qword ptr ds:[7FF7DB432228] | 00007FF7DB432228:"max=%d\n" 00007FF7DB4310CC | E8 3FFFFFFF | call <consoleapplication4.printf> | 00007FF7DB4310D1 | BA 09000000 | mov edx,9 | consoleapplication4.cpp:30, 9:'\t' 00007FF7DB4310D6 | C705 40250000 09000000 | mov dword ptr ds:[<i>],9 | 9:'\t' 00007FF7DB4310E0 | 48:8D0D 41110000 | lea rcx,qword ptr ds:[7FF7DB432228] | 00007FF7DB432228:"max=%d\n" 00007FF7DB4310E7 | E8 24FFFFFF | call <consoleapplication4.printf> | 00007FF7DB4310EC | 48:8D0D 0D110000 | lea rcx,qword ptr ds:[7FF7DB432200] | consoleapplication4.cpp:31, 00007FF7DB432200:"--------------------------------\n" 00007FF7DB4310F3 | E8 18FFFFFF | call <consoleapplication4.printf> | 00007FF7DB4310F8 | 33C0 | xor eax,eax | consoleapplication4.cpp:32 00007FF7DB4310FA | 48:83C4 28 | add rsp,28 | 00007FF7DB4310FE | C3 | ret | Note that MSVC also generated a very short routine compared to what Delphi generated!
  11. Mahdi Safsafi

    Discussion: JSON and templates

    Yeah that's good too ! and maybe I can use function just like template too.
  12. Mahdi Safsafi

    Discussion: JSON and templates

    Child or Children that is not the question !
  13. Hello guys, I started this thread with hope to get advises and feedback. I have a large complex data (splitted into fields and many of those fields share common properties) that must be saved on files. XML was the best choice but since I need to edit those files manually … it’s out of question to use XML (it just not user friendly). Neither YAML was(I’m not a big fun of languages that use space and tab) ! So I found my self using JSON. But I got many issues : my files got very big(because there is no reference/template support) and not mentioning that I was desperately lacking for comments. So I decided to write a custom language that inherits all JSON spec and provides additional supports for reference and templates. Here is an example : # templates: # --------- class TPerson<Name, Sex>{ name: Name, sex : Sex, } class TMan<Name> : TPerson<Name, "male">; class TWoman<Name>: TPerson<Name, "female">; class TChild<Name, Sex, Father, Mother> : TPerson<Name, Sex>{ father: Father, mother: Mother, } class TBoy<Name, Father, Mother> : TChild<Name, "male", Father, Mother>; class TGirl<Name, Father, Mother> : TChild<Name, "female", Father, Mother>; class TFamily<Name, Father, Mother, Childs>{ name : Name, father: Father, mother: Mother, childs: Childs, } # references: # ---------- def mike : TMan<"mike">; def mira : TWoman<"mira">; def jaky : TBoy<"jaky", mike, mira>; def lila : TGirl<"lila", mike, mira>; # public (just like json): [TFamily<"FamilyName", mike, mira, [jaky, lila]>] After my language runs the above example, actually it’s able to generate a Perl object that supports reference so if I change the father name of the first child in run-time … the father’s name will change for all fields: my $file = 'test.xjson'; my $parser = XJSON::Parser->new(); my $xjson = $parser->parse($file); $xjson->[0]->{childs}->[0]->{father}->{name} = "NotMike"; # mike's name changed for all fields. And converting it to JSON will dump the following: [ { "name" : "FamilyName", "father" : { "name" : "mike", "sex" : "male" }, "childs" : [ { "name" : "jaky", "sex" : "male", "mother" : { "sex" : "female", "name" : "mira" }, "father" : { "name" : "mike", "sex" : "male" } }, { "name" : "lila", "sex" : "female", "father" : { "name" : "mike", "sex" : "male" }, "mother" : { "sex" : "female", "name" : "mira" } } ], "mother" : { "sex" : "female", "name" : "mira" } } ] Right now, my language is draft and many things are implemented in a no proper way. I may rewrite it in C and consume it from Perl and probably Pascal. So what do you think guys about the language ? and any idea about improving it ? and if you were at my situation what kind of solution you may think to use ?
  14. Glad to see that my explanation was helpful.
  15. I think that the syntax was always there and I use it a lot. I found it more useful especially it provides a compiler check about the indexing type. This code : NodeNames: array [TInfoType] of string = ('itProject', 'itContacts', 'itWorker', 'itWorkers'); Is exactly equivalent to this one : NodeNames2: array [Ord(Low(TInfoType)) .. Ord(High(TInfoType))] of string = ('itProject', 'itContacts', 'itWorker', 'itWorkers'); Note that you can also use range: NodeNames3: array [itContacts .. itWorkers] of string = ('itContacts', 'itWorker','itWorkers');
×