📜 ⬆️ ⬇️

PAS2JS Transporter from Pascal to JavaScript: Delphi incompatibilities and workarounds

Nowadays, in the pocket of an ordinary person lies a powerful personal computer, which 10-20 years ago could only be dreamed of. And if you have kilometers of debugged Windows code and perfectly working applications and utilities written in Delphi, you probably would like to use this wealth for mobile development. As well as the experience gained during programming under Windows. PAS2JS helps you to combine two worlds: development for Windows and the creation of Web applications and Node.js modules.


Some of the difficulties found from personal experience are discussed in this article.


Why not just learn JavaScript and write Web applications on it?


I learned the javascript language sufficiently. But first, programming for the Web is more than just language skills. Secondly, the ability to write one code for different platforms is priceless. You can debug application modules in Delphi IDE, using its powerful debugger and editor, and then, adding the necessary binding, get a ready-made working application for the site. And when you correct the error or add new functionality to the application for Windows, it will be enough just to recompile the JavaScript modules in PAS2JS .


It should be noted that while PAS2JS does not support all the features of the Delphi language, they are listed on the site . Also, some fragments of seemingly simple PAS2JS code cannot transpose into JavaScript.


Translation difficulties


So, the new PAS2JS package is downloaded from FTP , we try to recompile a simple “Hello world”, and immediately stop at:


uses System.SysUtils; 

Error: can't find unit "System.SysUtils"

Ready-made PAS2JS packages, which can be found in the packages folder, partially duplicate Delphi system units. But they do not have a prefix in the name. The solution is simple: we delete the prefix “System.” From the name of the unit. A program in Delphi is compiled (if not, check the presence of the “System” prefix in the Unit Scope Names, in the Delphi Project | Options | Delphi Compiler menu).


Type reduction in constants


PAS2JS does not support type conversion in constant expressions:


 const CODE_A = Word('a'); 

Error: Constant expression expected

In the case of enumerated types, you can try to change it, so it passes:


 const CODE_A = Ord('a'); 

Also, PAS2JS does not understand the built-in functions of the Lo and Hi languages. In the definition of constants, they can be replaced as follows:


 const LO_BYTE = $1234 and $FF; // Lo($1234); HI_BYTE = $1234 shr 8;// Hi($1234); 

ANSI characters and strings


I hope you have already switched to Unicode strings in your Delphi projects? If you have left part of the strings in ANSI format in order to save memory, they will not be converted to JavaScript: PAS2JS does not know the types AnsiChar, AnsiString, Utf8String and RawByteString. Consider replacing them with Unicode types, or Byte and Array of Byte.


Here is an example of replacing AnsiChar with Byte:


 // Было procedure TestAnsiCharAndByte1; const SMALL_ENG_LETTERS = ['a'..'z']; CAPITAL_ENG_LETTERS = ['A'..'Z']; var ch: AnsiChar; engs: set of AnsiChar; begin engs := SMALL_ENG_LETTERS + CAPITAL_ENG_LETTERS; ch := 'Z'; if ch in engs then Writeln('It''s an English letter'); end; // Стало procedure TestAnsiCharAndByte2; const SMALL_ENG_LETTERS = [Ord('a')..Ord('z')]; CAPITAL_ENG_LETTERS = [Ord('A')..Ord('Z')]; var ch: Byte; engs: set of Byte; begin engs := SMALL_ENG_LETTERS + CAPITAL_ENG_LETTERS; ch := Ord('Z'); if ch in engs then Writeln('It''s an English letter'); end; 

Awkward letter ó


As a curiosity: in Polish there is the letter ó - O kreskowane, Unicode # $ 00F3. For some reason, PAS2JS disliked it, and in some cases can not perceive the line if this letter is included in it:


 var s: string; begin s := #$00F3'abdef'; // Компилируется s := 'abdef'#$017C; // Компилируется s := #$00F3'abdef'#$017C; // Error: Illegal character s := #$00F3; s := s + 'abdef'#$017C; // Так снова компилируется end; 

Case operator


A sudden surprise came up in the case statement, in which PAS2JS refused to accept Russian letters as options:


  ch := 'Я'; case ch of 'А': Writeln('Это "А"'); // Error: Incompatible types: got "Char" expected "Char" (???) 'Б'..'Я': Writeln('Это другая русская буква'); // Error: char expected, but string found end; 

The definition of constants for the desired Russian letters helped:


 const ckbA = #$410; // А ckbB = #$411; // Б ckbYa = #$42F; // Я var ch: Char; begin ch := 'Я'; case ch of ckbA: Writeln('Это "А"'); ckbB..ckbYa: Writeln('Это другая русская буква'); end; 

findings


I managed to compile a small Delphi project for the Web, making relatively small changes to the source code of the program, and for the time saved I wrote this article. Testing has shown that both versions of the program: for Windows and for the Web, work in exactly the same way. This is undoubtedly a success: now I can develop this project, modifying the program in Delphi, and transpiling it into JavaScript using PAS2JS.


As for the minor shortcomings revealed, I am sure they will be quickly eliminated. Since the project PAS2JS - open and free, actively developed by the community Free Pascal .



Source: https://habr.com/ru/post/436920/