pas2js/ru: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: pas2js/ru
| Old | New | Line | |
|---|---|---|---|
| 1 | + | # Pas2js: что это? | |
| 2 | + | ||
| 3 | + | ## Компилятор | |
| 4 | + | ||
| 5 | + | Pas2js - это транспилер(транскомпилятор) \[кода\] [[Pascal]] в [[JavaScript/ru|JavaScript]]. Он парсит Object Pascal и выдает JavaScript. JavaScript в настоящее время имеет уровень ECMAScript 5 и должен запускаться в любом браузере или в Node.js (цель "nodejs"). Доступен в 3 формах: | |
| 6 | + | ||
| 7 | + | - как библиотека | |
| 8 | + | - как программа командной строки | |
| 9 | + | - как веб-сервер | |
| 10 | + | ||
| 11 | + | Он транскомпилирует \[код\] из фактических исходников Pascal, у него нет промежуточных файлов .ppu. Это означает, что все исходники должны быть всегда доступны. | |
| 12 | + | ||
| 13 | + | Через определения внешних классов компилятор может использовать классы JavaScript: | |
| 14 | + | ||
| 15 | + | - Все классы, доступные во время выполнения JavaScript и в браузере, доступны через модули импорта (сравнимо с модулями windows или unix для собственного компилятора). | |
| 16 | + | - Для Node.js доступна базовая поддержка среды выполнения nodejs. | |
| 17 | + | - Доступен модуль импорта для jQuery (libjquery) | |
| 18 | + | ||
| 19 | + | ## RTL | |
| 20 | + | ||
| 21 | + | Для работы сгенерированного кода требуется небольшой файл JavaScript: rtl.js. Он определяет объект RTL. Этот объект запустит код Object Pascal, если вы включите вызов `rtl.run()` на странице [[HTML]]. | |
| 22 | + | ||
| 23 | + | ```html4strict | |
| 24 | + | <script type="application/javascript"> | |
| 25 | + | rtl.run() | |
| 26 | + | </script> | |
| 27 | + | ``` | |
| 28 | + | ||
| 29 | + | pas2js может автоматически включить этот файл в сгенерированный вывод, например так: | |
| 30 | + | ||
| 31 | + | pas2js -Jc -Jirtl.js -Tbrowser hello.pas | |
| 32 | + | ||
| 33 | + | Для `nodejs` компилятор вставит вызов `rtl.run()` автоматически в конец сгенерированного файла Javascript. | |
| 34 | + | ||
| 35 | + | Существует базовый Object Pascal RTL, также доступны несколько модулей из пакетов FPC. | |
| 36 | + | ||
| 37 | + | - system | |
| 38 | + | - sysutils | |
| 39 | + | - Math | |
| 40 | + | - strutils | |
| 41 | + | - rtlconst | |
| 42 | + | - classes | |
| 43 | + | - contnrs | |
| 44 | + | - DB (да, TDataset) | |
| 45 | + | - fpcunit testsuite | |
| 46 | + | - custapp | |
| 47 | + | - restconnection | |
| 48 | + | - js (системные объекты javascript) | |
| 49 | + | - web (объекты, предоставляемые браузером) | |
| 50 | + | - libjquery (JQuery также доступен) | |
| 51 | + | - nodejs (среда выполнения базового узла) | |
| 52 | + | - typinfo | |
| 53 | + | - objpas | |
| 54 | + | - browserconsole (поддержка writeln) | |
| 55 | + | - dateutils | |
| 56 | + | - browserapp | |
| 57 | + | - nodejsapp | |
| 58 | + | ||
| 59 | + | # Где его взять | |
| 60 | + | ||
| 61 | + | Компилятор pas2js и RTL - естественно - с открытым исходным кодом и могут быть загружены и использованы свободно. | |
| 62 | + | ||
| 63 | + | ## Снапшоты | |
| 64 | + | ||
| 65 | + | Снапшоты содержат двоичные файлы для Windows (32 и 64-разрядная версия), Linux (64-разрядная версия) и MacOS. | |
| 66 | + | ||
| 67 | + | Снапшоты загружены в | |
| 68 | + | ||
| 69 | + | - <ftp://ftpmaster.freepascal.org/fpc/contrib/pas2js> | |
| 70 | + | ||
| 71 | + | Каждая версия имеет каталог с номером версии. Список изменений можно найти на странице журнала изменений [[Pas2JS Version Changes]] | |
| 72 | + | ||
| 73 | + | ## SVN | |
| 74 | + | ||
| 75 | + | ``` bash | |
| 76 | + | svn co https://svn.freepascal.org/svn/projects/pas2js/trunk pas2js | |
| 77 | + | ``` | |
| 78 | + | ||
| 79 | + | Вам нужен [[FPC]] 3.0.4 или старше, чтобы скомпилировать его. | |
| 80 | + | ||
| 81 | + | Перейдите в каталог и соберите его с помощью: | |
| 82 | + | ||
| 83 | + | ``` bash | |
| 84 | + | make clean all | |
| 85 | + | ``` | |
| 86 | + | ||
| 87 | + | Это создаст *compiler/utils/pas2js/pas2js* (Windows: compiler\utils\pas2js\pas2js.exe) | |
| 88 | + | ||
| 89 | + | # Как использовать pas2js | |
| 90 | + | ||
| 91 | + | Аргументы командной строки в основном остаются такими же, как аргументы командной строки FPC. Сообщения об ошибках также в том же формате. | |
| 92 | + | ||
| 93 | + | Компилятору необходим доступ ко всем источникам, поэтому вам необходимо указать путь к источникам всех используемых модулей. | |
| 94 | + | ||
| 95 | + | Что касается компилятора FPC, поддерживается файл конфигурации, который имеет тот же синтаксис, что и файл конфигурации FPC. Обратите внимание, что снапшоты и версия svn уже содержат файл pas2js.cfg по умолчанию с путями поиска модулей (-Fu) для rtl и fcl. | |
| 96 | + | ||
| 97 | + | По сути, команда такая же, как и в любой командной строке FPC. Единственное, что отличается - это цель: '-Tbrowser' или '-Tnodeejs' | |
| 98 | + | ||
| 99 | + | Вот полный список аргументов командной строки: [[pas2js command line arguments|аргументы командной строки]]. | |
| 100 | + | ||
| 101 | + | ## для браузера | |
| 102 | + | ||
| 103 | + | Рассмотрим классику: | |
| 104 | + | ||
| 105 | + | ``` pascal | |
| 106 | + | program hello; | |
| 107 | + | ||
| 108 | + | begin | |
| 109 | + | Writeln('Hello, world!'); | |
| 110 | + | end. | |
| 111 | + | ``` | |
| 112 | + | ||
| 113 | + | Да, writeln поддерживается. Вот как это скомпилировать: | |
| 114 | + | ||
| 115 | + | pas2js -Jc -Jirtl.js -Tbrowser hello.pas | |
| 116 | + | ||
| 117 | + | После успешной компиляции код можно запустить в браузере, открыв в браузере html-файл со следующим содержимым: | |
| 118 | + | ||
| 119 | + | ```html4strict | |
| 120 | + | <html> | |
| 121 | + | <head> | |
| 122 | + | <meta charset="utf-8"/> | |
| 123 | + | <script type="application/javascript" src="hello.js"></script> | |
| 124 | + | </head> | |
| 125 | + | <body> | |
| 126 | + | <script type="application/javascript"> | |
| 127 | + | rtl.run(); | |
| 128 | + | </script> | |
| 129 | + | </body> | |
| 130 | + | </html> | |
| 131 | + | ``` | |
| 132 | + | ||
| 133 | + | Необходимые файлы: | |
| 134 | + | ||
| 135 | + | - hello.html | |
| 136 | + | - hello.js | |
| 137 | + | ||
| 138 | + | Независимо от того, открыт ли hello.html двойным щелчком по нему в проводнике или помещен на сервер и открыт с помощью URL, это не имеет значения. | |
| 139 | + | ||
| 140 | + | Вывод отображается в консоли веб-разработчика браузера. Включив модуль browserconsole, это будет видно на странице браузера: | |
| 141 | + | ||
| 142 | + | ``` pascal | |
| 143 | + | program hello; | |
| 144 | + | ||
| 145 | + | uses browserconsole; | |
| 146 | + | ||
| 147 | + | begin | |
| 148 | + | Writeln('Hello, world!'); | |
| 149 | + | end. | |
| 150 | + | ``` | |
| 151 | + | ||
| 152 | + | ## для NodeJS | |
| 153 | + | ||
| 154 | + | pas2js -Tnodejs hello.pas | |
| 155 | + | ||
| 156 | + | После успешной компиляции код можно запустить на узле с помощью следующей команды. | |
| 157 | + | ||
| 158 | + | nodejs hello.js | |
| 159 | + | ||
| 160 | + | > **Note:** в MacOS это "node hello.js" | |
| 161 | + | ||
| 162 | + | # Supported syntax elements | |
| 163 | + | ||
| 164 | + | В основном, поддерживается синтаксис [[Delphi]] 7. Это включает RTTI. Более подробный список можно найти в источниках файла [translation.html](https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/utils/pas2js/docs/translation.html?view=co). | |
| 165 | + | ||
| 166 | + | - режим [[Mode Delphi|Delphi]] и [[Mode ObjFPC|ObjFPC]] | |
| 167 | + | - [[Program]], [[Unit|Units]], пространства имен | |
| 168 | + | - инициализация модуля, но не финализация | |
| 169 | + | - [[Var]], [[Const]], [[Type]] | |
| 170 | + | - string (unicodestring), char (widechar), [[Boolean]], [[Double]], [[Byte]], [[Shortint]], [[Word]], [[Smallint]], longword, [[Longint]], nativeint(int53), nativeuint(int52), currency | |
| 171 | + | - resourcestrings | |
| 172 | + | - [[Pointer]] (как ссылка на класс, массив, запись, указатель записи, интерфейс, но без арифметики указателя) | |
| 173 | + | - [[Record]] (но не variant records) | |
| 174 | + | - [[Function|Functions]], [[Procedure|Procedures]], вложенные, анонимные функции | |
| 175 | + | - типы функций: of object, reference to (закрытые) | |
| 176 | + | - аргументы функций: default, const, var, out | |
| 177 | + | - [[If]]-then-else | |
| 178 | + | - [[For]]-do | |
| 179 | + | - [[Repeat]]-until | |
| 180 | + | - [[While]]-do | |
| 181 | + | - [[With]]-do | |
| 182 | + | - try-finally | |
| 183 | + | - try-except | |
| 184 | + | - enums | |
| 185 | + | - sets | |
| 186 | + | - arrays static, dynamic, open, multi dimensionals | |
| 187 | + | - String like array operations: *a:=\[1,2,3\]+\[1,1\];* | |
| 188 | + | - class type, visibility, virtual, override, abstract, overload, properties, class properties, class var, class const, constructor, destructor | |
| 189 | + | - class-of | |
| 190 | + | - вложенные классы | |
| 191 | + | - интерфейсы: CORBA, COM, delegations, method resolution, reference counting, TVirtualInterface | |
| 192 | + | - внешние классы, переменные, константы | |
| 193 | + | - Энумератор for..in..do | |
| 194 | + | - Псевдоним типа, например, type TTranslateString = type string; | |
| 195 | + | - RTTI | |
| 196 | + | - asm блок для встраивания в JavaScript напрямую | |
| 197 | + | - директивы компилятора (e.g. \$ifdef, \$if, \$define, \$modeswitch, \$R+) | |
| 198 | + | - проверка времени компиляции и времени выполнения | |
| 199 | + | ||
| 200 | + | Есть некоторые конструкции, которые естественно не поддерживаются и никогда не будут поддерживаться: | |
| 201 | + | ||
| 202 | + | - Все, что связано с указателями памяти и арифметикой указателей. | |
| 203 | + | - Variant records | |
| 204 | + | ||
| 205 | + | Подробно о поддерживаемых элементах и переходе с Pascal на JavaScript: [translation](https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/utils/pas2js/docs/translation.html?view=co). | |
| 206 | + | ||
| 207 | + | # Планируемые языковые особенности | |
| 208 | + | ||
| 209 | + | По сути, идея состоит в том, чтобы вывести транспайлер pas2js на тот же уровень, что и FPC или Delphi. Это означает, что необходимо добавить следующее: | |
| 210 | + | ||
| 211 | + | - Продвинутые записи(records) | |
| 212 | + | - Проверка во время выполнения: переполнение(overflow) -Co, \$Q | |
| 213 | + | - Обобщения(дженерики) | |
| 214 | + | - Тип помощников(helpers) | |
| 215 | + | - Массив констант | |
| 216 | + | ||
| 217 | + | Излишне говорить, что все, что требует прямого доступа к памяти, не будет поддерживаться. | |
| 218 | + | ||
| 219 | + | # Другие не реализованные функции | |
| 220 | + | ||
| 221 | + | - Атрибуты | |
| 222 | + | - Перечисления с пользовательскими значениями | |
| 223 | + | - Глобальные свойства | |
| 224 | + | - Futures | |
| 225 | + | - Помощники(helpers) для типов, классов, записей | |
| 226 | + | - Inline | |
| 227 | + | - Библиотека | |
| 228 | + | - Объекты | |
| 229 | + | - Перегрузка оператора | |
| 230 | + | - Арифметика указателей | |
| 231 | + | - Ресурсы | |
| 232 | + | - Расширение RTTI, \$RTTI | |
| 233 | + | - Вариантные записи(records) | |
| 234 | + | - Варианты(variants) | |
| 235 | + | ||
| 236 | + | # Интеграция pas2js в Lazarus | |
| 237 | + | ||
| 238 | + | Lazarus понимает концепцию внешних классов, используемую pas2js, поэтому автозавершение кода будет работать. | |
| 239 | + | ||
| 240 | + | Начиная с Lazarus 1.9, среда IDE может использовать pas2js.exe в качестве обычного компилятора. | |
| 241 | + | ||
| 242 | + | Интеграция описана здесь: [[lazarus pas2js integration/ru|Интеграция pas2JS в Lazarus]]. Он все еще находится в стадии разработки, но планируется глубокая интеграция с Lazarus. | |
| 243 | + | ||
| 244 | + | # Импорт классов Javascript | |
| 245 | + | ||
| 246 | + | Чтобы импортировать класс javascript, нужно написать обычное определение класса, которое имитирует класс Javascript. Можно использовать свойства. Многие примеры можно найти в модулях JS, web, nodejs и libjquery. | |
| 247 | + | ||
| 248 | + | Вот простой пример: | |
| 249 | + | ||
| 250 | + | ``` pascal | |
| 251 | + | TJSFunction = class external name 'Function'(TJSObject) | |
| 252 | + | private | |
| 253 | + | Flength: NativeInt external name 'length'; | |
| 254 | + | Fprototyp: TJSFunction external name 'prototyp'; | |
| 255 | + | public | |
| 256 | + | name: String; | |
| 257 | + | property prototyp: TJSFunction read Fprototyp; | |
| 258 | + | property length: NativeInt read Flength; | |
| 259 | + | function apply(thisArg: TJSObject; const ArgArray: TJSValueDynArray): JSValue; varargs; | |
| 260 | + | function bind(thisArg: TJSObject): JSValue; varargs; | |
| 261 | + | function call(thisArg: TJSObject): JSValue; varargs; | |
| 262 | + | end; | |
| 263 | + | ``` | |
| 264 | + | ||
| 265 | + | \[Приведенный выше код\] объявляет объект `TJSFunction`: в Javascript функции являются объектами. | |
| 266 | + | ||
| 267 | + | - "`external name 'Function'`" означает, что вы объявляете класс Javascript, где именем класса Javascript является 'Function'. | |
| 268 | + | - `(TJSObject)` означает, что он наследуется от `TJSObject` и внешнего класса. Там не должно быть типа предка. | |
| 269 | + | - Поля объявлены так же, как в Паскале. | |
| 270 | + | - Чтобы объявить поля только для чтения, можно использовать хитрость: объявите поле с использованием модификатора `external name "thename"` и объявите свойство только для чтения с тем же именем (см. length declaration) | |
| 271 | + | - `Varargs` может использоваться, чтобы указать, что функция принимает любое количество аргументов. | |
| 272 | + | - `JSValue` может использоваться для указания неизвестного типа. Это более или менее эквивалентно типу Variant. | |
| 273 | + | ||
| 274 | + | # Создание простых объектов JS с новой функцией | |
| 275 | + | ||
| 276 | + | Некоторые функции JS-фреймворка ожидают JS-объект в качестве параметра. Вот как это сделать в Pascal, используя функцию *new* из модуля *JS*: | |
| 277 | + | ||
| 278 | + | ``` javascript | |
| 279 | + | // JavaScript: | |
| 280 | + | DoIt({name:"Fred", id:3, size:4.3}); | |
| 281 | + | ``` | |
| 282 | + | ||
| 283 | + | ``` pascal | |
| 284 | + | // Pascal; | |
| 285 | + | DoIt(new(['name','Fred', 'id',3, 'size',4.3])); | |
| 286 | + | ``` | |
| 287 | + | ||
| 288 | + | Вы можете вложить его для создания субобъектов: | |
| 289 | + | ||
| 290 | + | ``` javascript | |
| 291 | + | // JavaScript: | |
| 292 | + | DoIt({name:"Fred", size:{width:3,height:2}}); | |
| 293 | + | ``` | |
| 294 | + | ||
| 295 | + | ``` pascal | |
| 296 | + | // Pascal; | |
| 297 | + | DoIt(new(['name','Fred', 'size',new(['width',3, 'height',2])])); | |
| 298 | + | ``` | |
| 299 | + | ||
| 300 | + | Вы можете использовать `TJSArray._of` для создания JS-массивов "на лету": | |
| 301 | + | ||
| 302 | + | ``` javascript | |
| 303 | + | // JavaScript: | |
| 304 | + | DoIt({numbers:[1,2,3]}); | |
| 305 | + | ``` | |
| 306 | + | ||
| 307 | + | ``` pascal | |
| 308 | + | // Pascal; | |
| 309 | + | DoIt(new(['numbers',TJSArray._of(1,2,3)])); | |
| 310 | + | ``` | |
| 311 | + | ||
| 312 | + | # Отладка | |
| 313 | + | ||
| 314 | + | Сгенерированный исходный код Javascript, конечно, видим и доступен отладке в браузере. | |
| 315 | + | ||
| 316 | + | Более того, транспайлер может генерировать файл-маппер (прим.перев: это минифицированный/объединённый файл, связанный с файлами, из которых он получился), что означает, что вы сможете увидеть и отладить код Pascal в браузере (будет работать не \[абсолютно\] все, но многое. Это зависит \[еще\] и от браузера.) | |
| 317 | + | ||
| 318 | + | файл-маппер может быть сгенерирован с использованием параметра командной строки | |
| 319 | + | ||
| 320 | + | -Jm | |
| 321 | + | ||
| 322 | + | Проще всего включать исходники Pascal в файл-маппер | |
| 323 | + | ||
| 324 | + | -Jminclude | |
| 325 | + | ||
| 326 | + | You can tell the compiler to store all file names relative to a local base directory: Вы можете указать компилятору хранить все имена файлов в \[путях\] относительно локального базового каталога: | |
| 327 | + | ||
| 328 | + | -Jmbasedir=DirName | |
| 329 | + | ||
| 330 | + | И вы можете сохранять URL-адрес на карте, поэтому браузер будет использовать URL/вышеуказанное-относительное-имя-файла, чтобы получать исходный код: | |
| 331 | + | ||
| 332 | + | -Jmsourceroot=URL | |
| 333 | + | ||
| 334 | + | # Баги | |
| 335 | + | ||
| 336 | + | Пожалуйста, сообщайте об ошибках в багтрекере FPC в категории *pas2js*: <http://bugs.freepascal.org> | |
| 337 | + | ||
| 338 | + | # Примеры | |
| 339 | + | ||
| 340 | + | - Приложение для отслеживания времени: (исходный код: <https://www.devstructor.com/demos/pas2js-time/source.zip>) | |
| 341 | + | - Рисование и анимация на холсте: <http://ragnemalm.se/images/santa/santa.html> (исходный код: <http://ragnemalm.se/images/santa/>) | |
| 342 | + | - WebGL: <https://github.com/genericptr/Pas2JS-WebGL#pas2js-webgl> | |
| 343 | + | ||
| 344 | + | # Виджеты Lazarus | |
| 345 | + | ||
| 346 | + | Конечная цель, конечно, - запустить LCL в Всемирной сети. Обсуждения по этой теме делегированы на отдельной странице. [[pas2js widgetsets]] | |
| 347 | + | ||
| 348 | + | # ЧаВо | |
| 349 | + | ||
| 350 | + | ## Почему простая программа "hello world" такая большая? | |
| 351 | + | ||
| 352 | + | Это в основном связано с использованием rtl.js. Файл rtl.js содержит код для паскалевских модулей, классов, RTTI, наборов, проверок диапазона и т.д., и написан с учетом больших WebApp, а не для сценариев с несколькими строками кода. | |
| 353 | + | ||
| 354 | + | 1. Вы можете использовать Javascript [[pas2js minifier|minifier ("минимизатор")]], чтобы уменьшить созданный Javascript | |
| 355 | + | 2. Вы можете создать свой собственный "минимизатор" rtl.js, удалив все ненужные вам функции. В конечном итоге это будет сделано автоматически pas2js. | |
| 356 | + | ||
| 357 | + | ## Почему \[нежелательно\] применение asm-вставок? | |
| 358 | + | ||
| 359 | + | Asm-вставки полезны для вещей, которые вы не можете сделать с \[помощью\] pas2js. Но есть некоторые недостатки: pas2js не разбирает JS. Он также не проверяет синтаксис и не знает, на какие идентификаторы Паскаля ссылается код. Это означает, что любой идентификатор, доступный только блоку asm, будет удален оптимизатором pas2js. | |
| 360 | + | ||
| 361 | + | Поэтому всегда старайтесь делать это на Паскале. Помните, что вы можете типизировать значения в JSValue, объекты в TJSObject, массивы в TJSArray, строки в TJSString и т.д., чтобы использовать почти все функции JS. | |
| 362 | + | ||
| 363 | + | ## Почему не парсятся(разбираются) asm-вставки? | |
| 364 | + | ||
| 365 | + | Любой анализатор JS времени компиляции может выполнять только проверку синтаксиса и анализировать только простые JS. Но так как простой JS может быть лучше написан на Паскале, это несколько бессмысленно и поэтому имеет низкий приоритет. | |
| 366 | + | ||
| 367 | + | --- | |
| 368 | + | *From the Free Pascal wiki, page "pas2js/ru", as it stood on 2022-05-28 after a change by FTurtle, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
